void applyMorphology(IPLImagePlane &src, IPLImagePlane &dst, int iterations, const std::vector<bool> &kernel, CB progressCallback) { int kernelOffset = (int)sqrt((float)kernel.size()) / 2; for (int i = 0; i < iterations; ++i) { #pragma omp parallel for default(shared) for (int y = 0; y < src.height(); ++y) { for (int x = 0; x < src.width(); ++x) { //TODO: Speed up this routine //There would be several possibilities such as usage of SIMD techniques //or the reduction of the source image (e.g. to unsigned char) bool cancel = false; auto &pixelValue = dst.p(x,y); int i = 0; for( int ky=-kernelOffset; !cancel && ky<=kernelOffset; ky++ ) { for( int kx=-kernelOffset; !cancel && kx<=kernelOffset; kx++ ) { if ( x+kx < 0 || x+kx >= src.width() || y+ky < 0 || y+ky >= src.height()) continue; auto &p = src.p(x+kx,y+ky); bool mask = kernel[i++]; bool pixel = p == (float)T; cancel = mask && pixel; } } pixelValue = cancel? T : F; } progressCallback(); } std::swap(src,dst); } std::swap(src,dst); }
bool IPLCanvasSize::processInputData(IPLImage* image , int, bool) { // delete previous result delete _result; _result = NULL; int width = image->width(); int height = image->height(); _result = new IPLImage(image->type(), width, height); // get properties int new_width = getProcessPropertyInt("width"); int new_height = getProcessPropertyInt("height"); IPLColor color = getProcessPropertyColor("color"); int anchor = getProcessPropertyInt("anchor"); _result = new IPLImage(image->type(), new_width, new_height); int progress = 0; int maxProgress = image->height() * image->getNumberOfPlanes(); int nrOfPlanes = _result->getNumberOfPlanes(); //Anchor:Top Left|Top|Top Right|Left|Center|Right|Bottom Left|Bottom|Bottom Right // Top Left int offset_x = 0; int offset_y = 0; if(anchor == 1) { // Top offset_x = (new_width-width) * 0.5; offset_y = 0; } else if(anchor == 2) { // Top Right offset_x = new_width-width; offset_y = 0; } else if(anchor == 3) { // Left offset_x = 0; offset_y = (new_height-height) * 0.5; } else if(anchor == 4) { // Center offset_x = (new_width-width) * 0.5; offset_y = (new_height-height) * 0.5; } else if(anchor == 5) { // Right offset_x = new_width-width; offset_y = (new_height-height) * 0.5; } else if(anchor == 6) { // Bottom Left offset_x = 0; offset_y = new_height-height; } else if(anchor == 7) { // Bottom offset_x = (new_width-width) * 0.5; offset_y = new_height-height; } else if(anchor == 8) { // Bottom Right offset_x = new_width-width; offset_y = new_height-height; } if(nrOfPlanes == 1) { addWarning("For grayscale images, the red slider is used as background value."); } #pragma omp parallel for for( int planeNr=0; planeNr < nrOfPlanes; planeNr++ ) { IPLImagePlane* plane = image->plane( planeNr ); IPLImagePlane* newplane = _result->plane( planeNr ); ipl_basetype background = 0.0; if(planeNr == 0) background = color.red(); else if(planeNr == 1) background = color.green(); if(planeNr == 2) background = color.blue(); for(int y=0; y<new_height; y++) { // progress notifyProgressEventHandler(100*progress++/maxProgress); for(int x=0; x<new_width; x++) { int from_x = x - offset_x; int from_y = y - offset_y; // check if inside source image if(from_x < 0 || from_y < 0 || from_x > plane->width() || from_y > plane->height()) { newplane->p(x, y) = background; } else { newplane->p(x, y) = plane->p(from_x, from_y); } } } } return true; }
bool IPLConvolutionFilter::processInputData(IPLImage* image , int, bool useOpenCV) { // delete previous result delete _result; _result = NULL; int width = image->width(); int height = image->height(); // get properties _kernel = getProcessPropertyVectorInt("kernel"); _divisor = getProcessPropertyInt("divisor"); _offset = getProcessPropertyDouble("offset"); _normalize = getProcessPropertyBool("normalize"); _borders = getProcessPropertyInt("borders"); if(_normalize) { int sum = 0; for(size_t i=0; i<_kernel.size(); i++) { sum += _kernel[i]; } _divisor = (sum != 0 ? sum : 1); } if (_divisor == 0) { addError("Invalid divisor: 0"); return false; } float divFactor = 1.0f/_divisor; int kernelWidth = (int)sqrt((float)_kernel.size()); int kernelOffset = kernelWidth / 2; int progress = 0; int maxProgress = image->height() * image->getNumberOfPlanes(); if (!useOpenCV) { _result = new IPLImage( image->type(), width, height ); #pragma omp parallel for default(shared) for( int planeNr=0; planeNr < image->getNumberOfPlanes(); planeNr++ ) { IPLImagePlane* plane = image->plane( planeNr ); IPLImagePlane* newplane = _result->plane( planeNr ); for(int y=0; y<plane->height(); y++) { // progress notifyProgressEventHandler(100*progress++/maxProgress); for(int x=0; x<plane->width(); x++) { float sum = 0; int i = 0; for( int ky=-kernelOffset; ky<=kernelOffset; ky++ ) { for( int kx=-kernelOffset; kx<=kernelOffset; kx++ ) { int h = _kernel[i++]; if( h ) { if(_borders == 0) { // Crop borders sum += plane->cp(x+kx, y+ky) * h; } else if(_borders == 1) { // Extend borders sum += plane->bp(x+kx, y+ky) * h; } else { // Wrap borders sum += plane->wp(x+kx, y+ky) * h; } } } } sum = sum * divFactor + _offset; sum = (sum>1.0) ? 1.0 : (sum<0) ? 0.0 : sum; // clamp to 0.0 - 1.0 newplane->p(x,y) = sum; } } } } else { notifyProgressEventHandler(-1); cv::Mat src = image->toCvMat(); cv::Mat dst; cv::Mat kernel(kernelWidth, kernelWidth, CV_32FC1 ); int i = 0; for( int y=0; y < kernelWidth; y++ ) for( int x=0; x < kernelWidth; x++ ) kernel.at<float>(cv::Point(x,y)) = _kernel[i++]; kernel *= divFactor; static const int BORDER_TYPES[3] = { cv::BORDER_CONSTANT, cv::BORDER_REPLICATE, cv::BORDER_WRAP }; cv::filter2D(src, dst, -1, kernel, cv::Point(-1,-1), _offset, BORDER_TYPES[_borders]); _result = new IPLImage(dst); } return true; }