#include "core/image/Morph.h" #include "core/image/ImageTools.h" #include #include #include using namespace std; namespace NICE { // little helper function static inline size_t getHistRank(const Histogram& hist, const size_t& rank) { uint sum = 0; for(Histogram::const_iterator i=hist.begin(); i!=hist.end(); ++i) { sum += *i; if(sumhist_max)?hist_val:hist_max; ++i; } while(i<=isize); i=-isize; do { hist_val = src.getPixelQuick(x-isize-1,y+i); --hist[hist_val]; if((hist_val-hist_max)==0) if(hist[hist_max]==0) while(hist[hist_max]==0) --hist_max; ++i; } while(i<=isize); return hist_max; } static inline Ipp32s medianNext(const Ipp8u& hist_val, Histogram& hist, int& hist_temp, int& hist_med, uint& hist_lower, uint& hist_upper, bool add=true) { if(add) { ++hist[hist_val]; if(hist_med<0) { hist_lower = hist_upper = 0; hist_med = hist_val; } else if(hist_val < hist_med) ++hist_lower; else if(hist_val > hist_med) ++hist_upper; } else { --hist[hist_val]; if(hist_val < hist_med) --hist_lower; else if(hist_val > hist_med) --hist_upper; } if(hist_lower>hist[hist_med]+hist_upper) { hist_temp = hist_med-1; while(hist[hist_temp]==0) --hist_temp; hist_lower -= hist[hist_temp]; hist_upper += hist[hist_med]; hist_med = hist_temp; } else if(hist_upper>=hist[hist_med]+hist_lower) { hist_temp = hist_med+1; while(hist[hist_temp]==0) ++hist_temp; hist_upper -= hist[hist_temp]; hist_lower += hist[hist_med]; hist_med = hist_temp; } return hist_med; } // // // // // Ranking Operations Image* rank(const Image& src, const uint& size, const uint& rank, Image* dst) { if( rank>((2*size+1)*(2*size+1)) || rank<1 ) fthrow(ImageException,"Rank smaller 1 or bigger than (2*size+1)x(2*size+1) not allowed."); Image* result = createResultBuffer(src, dst); copyBorder ( src, size, size, dst ); int isize = size; uint msize = 2*isize+1; const Image *imgSub = NULL; Histogram hist; int xstart = size+1; int xend = src.width()-isize; int ystart = size; int yend = src.height()-isize; Image::Pixel *p; for(int y=ystart; ygetPixelPointerXY(isize,y); *p++ = getHistRank(hist, rank); for(int x=xstart; xgetPixelPointerXY(1,1), result->getStepsize(), ROIsize); } else { IppiSize maskSize = {(int)(2*size+1), (int)(2*size+1)}; Ipp8u *pMask = new Ipp8u[(2*size+1)*(2*size+1)]; ippiSet_8u_C1R(1,pMask,2*size+1,maskSize); ret = ippiErode_8u_C1R(src.getPixelPointerXY(anchor.x, anchor.y), src.getStepsize(), result->getPixelPointerXY(anchor.x, anchor.y), result->getStepsize(), ROIsize, pMask, maskSize, anchor); } if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP int isize = size; int xstart = size+1; int xend = src.width()-isize; Histogram hist(256); int hist_min, hist_val; const Image::Pixel* pSrc; Image::Pixel* pDst; for(int y=size; y::max(); for(int sy=-isize; sy<=isize; ++sy) { for(int sx=-isize; sx<=+isize; ++sx,++pSrc) { hist_val = src.getPixelQuick(size+sx,y+sy); ++hist[hist_val]; if(hist_valgetPixelPointerXY(isize,y); *pDst = hist_min; ++pDst; pSrc = src.getPixelPointerXY(xstart,y); for(int x=xstart; xgetPixelPointerXY(anchor.x, anchor.y), result->getStepsize(), ROIsize, maskSize, anchor); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP int isize = size; int xstart = size+1; int xend = src.width()-isize; Histogram hist(256); int hist_med, hist_temp; uint hist_lower = 0; uint hist_upper = 0; const Image::Pixel* pSrc; Image::Pixel* pDst; for(int y=size; ygetPixelPointerXY(isize,y); *pDst = hist_med; ++pDst; for(int x=xstart; xgetPixelPointerXY(anchor.x, anchor.y), result->getStepsize(), ROIsize); else { IppiSize maskSize = {(int)(2*size+1), (int)(2*size+1)}; Ipp8u *pMask = new Ipp8u[(2*size+1)*(2*size+1)]; ippiSet_8u_C1R(1,pMask,2*size+1,maskSize); ret = ippiDilate_8u_C1R(src.getPixelPointerXY(anchor.x, anchor.y), src.getStepsize(), result->getPixelPointerXY(anchor.x, anchor.y), result->getStepsize(), ROIsize, pMask, maskSize, anchor); } if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP int isize = size; int xstart = size+1; int xend = src.width()-isize; Histogram hist(256); int hist_max, hist_val; const Image::Pixel* pSrc; Image::Pixel* pDst; for(int y=size; y::min(); for(int sy=-isize; sy<=isize; ++sy) for(int sx=-isize; sx<=+isize; ++sx,++pSrc) { hist_val = src.getPixelQuick(size+sx,y+sy); ++hist[hist_val]; if(hist_val>hist_max) hist_max = hist_val; } pDst = result->getPixelPointerXY(isize,y); *pDst = hist_max; ++pDst; // now the rest of the line pSrc = src.getPixelPointerXY(xstart,y); for(int x=xstart; x(structureElement.cols()/2); int anchory = static_cast(structureElement.rows()/2); min.x = std::numeric_limits::max(); min.y = std::numeric_limits::max(); max.x = std::numeric_limits::min(); max.y = std::numeric_limits::min(); IntMatrix *pRes = new IntMatrix(entries,2); size_t aPos = 0; for(size_t j=0; jentries || rank<1 ) fthrow(ImageException,"Rank smaller 1 or bigger than nonzero entries in the structureElement are not allowed."); Histogram hist(256); IppiPoint min,max; IntMatrix* strucList = getStructureList(structureElement, min, max); int xstart = -min.x; int xend = src.width()-max.x; int i; Image::Pixel* p; for(int y=-min.y; ygetPixelPointerXY(xstart,y); for(int x=xstart; xrows()-1; do { ++hist[src(x+(*strucList)(i,0), y+(*strucList)(i,1))]; --i; } while(i>=0); *p = getHistRank(hist,rank); } } // clean up delete strucList; return result; }; Image* median(const Image& src, const CharMatrix& structureElement, Image* dst) { Image* result = createResultBuffer(src, dst); size_t nonZero = getNonZeroElements(structureElement); return rank(src, structureElement, ((nonZero%2==0)?nonZero/2:nonZero/2+1), result); } Image* erode(const Image& src, const CharMatrix& structureElement, Image* dst) { Image* result = createResultBuffer(src, dst); copyBorder ( src, structureElement.cols()/2, structureElement.rows()/2, dst ); #ifdef NICE_USELIB_IPP // temporary bugfix: do not use IPP (bug on 64bit systems) //#define NICE_USELIB_IPP_ERODE #endif #ifdef NICE_USELIB_IPP_ERODE IppiPoint anchor = {structureElement.cols()/2, structureElement.rows()/2}; IppiSize maskSize = {structureElement.cols() , structureElement.rows()}; IppiSize ROIsize = {src.width()-structureElement.cols()-1, src.height()-structureElement.rows()-1}; MatrixT sEl(structureElement.cols(), structureElement.rows()); for(uint j=0; jgetPixelPointerXY(anchor.x,anchor.y), result->getStepsize(), ROIsize, sEl.getDataPointer(), maskSize, anchor); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP_ERODE result = rank(src, structureElement, 1, dst); #endif // NICE_USELIB_IPP_ERODE return result; } Image* dilate(const Image& src, const CharMatrix& structureElement, Image* dst) { Image* result = createResultBuffer(src, dst); copyBorder ( src, structureElement.cols()/2, structureElement.rows()/2, dst ); #ifdef NICE_USELIB_IPP IppiPoint anchor = {(int)(structureElement.cols()/2), (int)(structureElement.rows()/2)}; IppiSize maskSize = {(int)(structureElement.cols()), (int)(structureElement.rows())}; IppiSize ROIsize = {(int)(src.width()-structureElement.cols()-1), (int)(src.height()-structureElement.rows()-1)}; MatrixT sEl(structureElement.rows(), structureElement.cols()); for(uint j=0; jset(0.0); IppStatus ret = ippiDilate_8u_C1R(src.getPixelPointerXY(anchor.x,anchor.y), src.getStepsize(), result->getPixelPointerXY(anchor.x,anchor.y), result->getStepsize(), ROIsize, sEl.getDataPointer(), maskSize, anchor); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP result = rank(src, structureElement, getNonZeroElements(structureElement), dst); #endif // NICE_USELIB_IPP return result; } Image* opening(const Image& src, const CharMatrix& structureElement, Image* dst) { Image* temp = new Image(src.width(), src.height()); temp = erode(src, structureElement, temp); Image* result = createResultBuffer(src.width(), src.height(), dst); result = dilate(*temp, structureElement, result); // clean up delete temp; return result; } Image* closing(const Image& src, const CharMatrix& structureElement, Image* dst) { Image* temp = new Image(src.width(), src.height()); temp = dilate(src, structureElement, temp); Image* result = createResultBuffer(src.width(), src.height(), dst); result = erode(*temp, structureElement, result); // clean up delete temp; return result; } // // // // // IP Operations // // // // // void rankingIP(Image& src, const uint& rank) { if( rank>9 || rank<1 ) fthrow(ImageException,"Rank is out of range."); Histogram hist(256); Image::Pixel* p; Ipp8u* buffer = new Ipp8u[src.width()]; buffer[0] = buffer[src.width()-1] = 0; Ipp8u* temp = new Ipp8u[2]; // init buffer with the first image line (y=1) hist = 0; for(int j=-1; j<=+1; ++j) for(int i=-1; i<=+1; ++i) ++hist[src(1+i,1+j)]; buffer[1] = getHistRank(hist, rank); p = src.getPixelPointerXY(2,1); for(int x=2; x::max(); for(int y=0; y<=2; ++y) for(int x=0; x<=2; ++x) { hist_val = src.getPixelQuick(x,y); hist_min = (hist_val::max(); for(int j=-1; j<=1; ++j) for(int i=-1; i<=1; ++i) { hist_val = src(1+i,y+j); hist_min = (hist_val::min(); for(int y=0; y<=2; ++y) for(int x=0; x<=2; ++x) { hist_val = src(x,y); if(hist_val>hist_max) hist_max = hist_val; ++hist[hist_val]; } buffer[1] = hist_max; // init buffer for(int x=2; x::min(); for(int j=-1; j<=1; ++j) for(int i=-1; i<=1; ++i) { hist_val = src(1+i,y+j); if(hist_val>hist_max) hist_max = hist_val; ++hist[hist_val]; } temp[0] = hist_max; temp[1] = dilateNext(src,hist,1,hist_val,hist_max,2,y); // rest of line p = src.getPixelPointerXY(1,y-1); for(int x=3; x<=src.width()-2; ++x) { dilateNext(src,hist,1,hist_val,hist_max,x,y); *p = buffer[x-2]; ++p; buffer[x-2] = temp[0]; temp[0] = temp[1]; temp[1] = hist_max; } // write buffer *p = buffer[src.width()-3]; ++p; *p = buffer[src.width()-2]; ++p; buffer[src.width()-3] = temp[0]; buffer[src.width()-2] = temp[1]; } // copy buffer to last line memcpy(src.getPixelPointerXY(1,src.height()-2), &buffer[1], src.width()-2); // clean up delete[] buffer; delete[] temp; #endif } void openingIP(Image& src) { erodeIP(src); dilateIP(src); } void closingIP(Image& src) { dilateIP(src); erodeIP(src); } // // // // // Matching Operations // // // // // Image* hitAndMiss(const Image& src, const CharMatrix& structureElement, Image* dst) { Image* result = createResultBuffer(src, dst); Image* temp = erode(src, structureElement); // invert the structure element and source image CharMatrix* invStructure = new CharMatrix(structureElement.rows(), structureElement.cols()); for(size_t j=0; jinvert(); result = erode(*invSrc, *invStructure); // do an and-combination const Image::Pixel *pSrc; Image::Pixel *pDst; for(int y=0; yheight(); ++y) { pSrc = temp->getPixelPointerY(y); pDst = result->getPixelPointerY(y); for(int x=0; xwidth(); ++x,++pSrc,++pDst) *pDst = (*pSrc==*pDst && *pSrc!=0)?255:0; } // cleanUp delete invStructure; delete invSrc; delete temp; return result; } } // namespace NICE