static UNUSED IplImage* test_find_edges_hist(IplImage *im) { int w = im->width; int h = im->height; CvSize small_size = {w / 8, h / 8}; CvPoint middle = {w/2, h/2}; IplImage *small = cvCreateImage(small_size, IPL_DEPTH_8U, 1); /*for quicker histogram */ IplImage *mask = cvCreateImage(cvGetSize(im), IPL_DEPTH_8U, 1); IplImage *green = cvCreateImage(cvGetSize(im), IPL_DEPTH_8U, 1); cvSplit(im, NULL, green, NULL, NULL); cvResize(green, small, CV_INTER_NN); //small = green; int hist_size[] = {255}; float range[] = {0, 255}; float *ranges[] = {range}; CvHistogram* hist = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1); cvCalcHist(&small, hist, 0, NULL); int pixels = small->width * small->height; int min_black = pixels / 8; int max_black = pixels / 2; int totals[256] = {0}; int best_d = pixels + 1; int best_t = 0; int total = 0; for (int i = 0; i < 255; i++){ int v = (int)cvQueryHistValue_1D(hist, i + 2); total += v; totals[i] = total; if (total > min_black){ if (i > 5){ int diff = totals[i] - totals[i - 5]; if (diff < best_d){ best_d = diff; best_t = i; } if (total >= max_black){ break; } } } } best_t -= 2; printf("found best threshold %d -- %d pixel change at %d/%d pixels\n", best_t, best_d, totals[best_t], pixels); cvCmpS(green, best_t, mask, CV_CMP_GT); IplImage *mask2 = cvCreateImage(cvGetSize(im), IPL_DEPTH_8U, 1); memset(mask2->imageData, 255, w*h); floodfill_mono_superfast(mask, mask2, middle); return mask2; }
IplImage* BinarizeImageFilter::process(const IplImage* im, IplImage* buffer /*= NULL*/) { if (im == NULL) return NULL; assert (im->nChannels == 1); if (buffer == NULL) { buffer = cvCreateImage(cvGetSize(im), 8, 1); } else { assert(buffer->nChannels = 1 && buffer->width == im->width && buffer->height == im->height); } cvCmpS(im, threshold, buffer, cmpOp); return buffer; }
void run() { int key; IplImage *mask = cvCreateImage( cvGetSize(img_gui), 8, 1 ); IplImage *display = cvCreateImage( cvGetSize(img_gui), 8, 3 ); IplImage *fgcolor = cvCloneImage( img_gui), *bgcolor = cvCloneImage( img_gui); cvSet( fgcolor, cvScalar( 255, 0, 0)), cvSet( bgcolor, cvScalar( 0, 255, 255)); // gui int swmin = _swmin; int swmax = std::max( std::max( img_gui->width, img_gui->height) / 8, 1); int swstep = std::max( std::min( img_gui->width, img_gui->height) / 100, 1); int swdefault = std::min( std::max( std::min( img_gui->width, img_gui->height) / 32, swmin), swmax); strokewidth = swdefault; RenderMsg( display); cvNamedWindow( "working space" ); cvNamedWindow( "trimap" ); cvShowImage( "working space" , display ); cvShowImage( "trimap" , usr); cvSetMouseCallback( "working space", DrawStroke); cvSetMouseCallback( "trimap", DrawStroke); while(1) { key = cvWaitKey(5); if(key=='q') break; else if(key=='w') { stroketype++; stroketype = stroketype % 3; printf("%d\n", stroketype); } else if( key == 'd') // decrease stroke width strokewidth = ( strokewidth - swstep < swmin) ? swmin : strokewidth - swstep; else if( key == 'a') // increase stroke width strokewidth = ( strokewidth + swstep > swmax) ? swmax : strokewidth + swstep; else if( key == 'u' && flashOnlyImg_gui!=NULL ) { T += T_step; FlashMatting::GenerateTrimap( flashOnlyImg_gui, usr, T); } else if( key == 'i' && flashOnlyImg_gui!=NULL ) { T -= T_step; FlashMatting::GenerateTrimap( flashOnlyImg_gui, usr, T); } // display cvCopy( img_gui, display ); cvCmpS( usr, _strokeColor[_strokebg], mask, CV_CMP_EQ); cvOr( img_gui, bgcolor, display, mask); cvCmpS( usr, _strokeColor[_strokefg], mask, CV_CMP_EQ); cvOr( img_gui, fgcolor, display, mask); cvConvertScale( display, display, 0.7); //cvCmpS( usr, _strokeColor[_strokeu], mask, CV_CMP_EQ); //cvCopy( img_gui, display, mask); RenderMsg( display); cvShowImage( "working space", display); cvShowImage( "trimap" , usr); } cvReleaseImage( &display ); cvDestroyAllWindows(); }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------ CvMat *tgso (CvMat &tmap, int ntex, double sigma, double theta, CvMat &tsim, int useChi2) { CvMat *roundTmap=cvCreateMat(tmap.rows,tmap.cols,CV_32FC1); CvMat *comp=cvCreateMat(tmap.rows,tmap.cols,CV_32FC1); for (int i=0;i<tmap.rows;i++) for (int j=0;j<tmap.cols;j++) cvSetReal2D(roundTmap,i,j,cvRound(cvGetReal2D(&tmap,i,j))); cvSub(&tmap,roundTmap,comp); if (cvCountNonZero(comp)) { printf("texton labels not integral"); cvReleaseMat(&roundTmap); cvReleaseMat(&comp); exit(1); } double min,max; cvMinMaxLoc(&tmap,&min,&max); if (min<1 && max>ntex) { char *msg=new char[50]; printf(msg,"texton labels out of range [1,%d]",ntex); cvReleaseMat(&roundTmap); cvReleaseMat(&comp); exit(1); } cvReleaseMat(&roundTmap); cvReleaseMat(&comp); double wr=floor(sigma); //sigma=radius (Leo) CvMat *x=cvCreateMat(1,wr-(-wr)+1, CV_64FC1); CvMat *y=cvCreateMat(wr-(-wr)+1,1, CV_64FC1); CvMat *u=cvCreateMat(wr-(-wr)+1,wr-(-wr)+1, CV_64FC1); CvMat *v=cvCreateMat(wr-(-wr)+1,wr-(-wr)+1, CV_64FC1); CvMat *gamma=cvCreateMat(u->rows,v->rows, CV_64FC1); // Set x,y directions for (int j=-wr;j<=wr;j++) { cvSetReal2D(x,0,(j+wr),j); cvSetReal2D(y,(j+wr),0,j); } // Set u,v, meshgrids for (int i=0;i<u->rows;i++) { cvRepeat(x,u); cvRepeat(y,v); } // Compute the gamma matrix from the grid for (int i=0;i<u->rows;i++) for (int j=0;j<u->cols;j++) cvSetReal2D(gamma,i,j,atan2(cvGetReal2D(v,i,j),cvGetReal2D(u,i,j))); cvReleaseMat(&x); cvReleaseMat(&y); CvMat *sum=cvCreateMat(u->rows,u->cols, CV_64FC1); cvMul(u,u,u); cvMul(v,v,v); cvAdd(u,v,sum); CvMat *mask=cvCreateMat(u->rows,u->cols, CV_8UC1); cvCmpS(sum,sigma*sigma,mask,CV_CMP_LE); cvConvertScale(mask,mask,1.0/255); cvSetReal2D(mask,wr,wr,0); int count=cvCountNonZero(mask); cvReleaseMat(&u); cvReleaseMat(&v); cvReleaseMat(&sum); CvMat *sub=cvCreateMat(mask->rows,mask->cols, CV_64FC1); CvMat *side=cvCreateMat(mask->rows,mask->cols, CV_8UC1); cvSubS(gamma,cvScalar(theta),sub); cvReleaseMat(&gamma); for (int i=0;i<mask->rows;i++){ for (int j=0;j<mask->cols;j++) { double n=cvmGet(sub,i,j); double n_mod = n-floor(n/(2*M_PI))*2*M_PI; cvSetReal2D(side,i,j, 1 + int(n_mod < M_PI)); } } cvMul(side,mask,side); cvReleaseMat(&sub); cvReleaseMat(&mask); CvMat *lmask=cvCreateMat(side->rows,side->cols, CV_8UC1); CvMat *rmask=cvCreateMat(side->rows,side->cols, CV_8UC1); cvCmpS(side,1,lmask,CV_CMP_EQ); cvCmpS(side,2,rmask,CV_CMP_EQ); int count1=cvCountNonZero(lmask), count2=cvCountNonZero(rmask); if (count1 != count2) { printf("Bug: imbalance\n"); } CvMat *rlmask=cvCreateMat(side->rows,side->cols, CV_32FC1); CvMat *rrmask=cvCreateMat(side->rows,side->cols, CV_32FC1); cvConvertScale(lmask,rlmask,1.0/(255*count)*2); cvConvertScale(rmask,rrmask,1.0/(255*count)*2); cvReleaseMat(&lmask); cvReleaseMat(&rmask); cvReleaseMat(&side); int h=tmap.rows; int w=tmap.cols; CvMat *d = cvCreateMat(h*w,ntex,CV_32FC1); CvMat *coltemp = cvCreateMat(h*w,1,CV_32FC1); CvMat *tgL = cvCreateMat(h,w, CV_32FC1); CvMat *tgR = cvCreateMat(h,w, CV_32FC1); CvMat *temp = cvCreateMat(h,w,CV_8UC1); CvMat *im = cvCreateMat(h,w, CV_32FC1); CvMat *sub2 = cvCreateMat(h,w,CV_32FC1); CvMat *sub2t = cvCreateMat(w,h,CV_32FC1); CvMat *prod = cvCreateMat(h*w,ntex,CV_32FC1); CvMat reshapehdr,*reshape; CvMat* tgL_pad = cvCreateMat(h+rlmask->rows-1,w+rlmask->cols-1,CV_32FC1); CvMat* tgR_pad = cvCreateMat(h+rlmask->rows-1,w+rlmask->cols-1,CV_32FC1); CvMat* im_pad = cvCreateMat(h+rlmask->rows-1,w+rlmask->cols-1,CV_32FC1); CvMat *tg=cvCreateMat(h,w,CV_32FC1); cvZero(tg); if (useChi2 == 1){ CvMat* temp_add1 = cvCreateMat(h,w,CV_32FC1); for (int i=0;i<ntex;i++) { cvCmpS(&tmap,i+1,temp,CV_CMP_EQ); cvConvertScale(temp,im,1.0/255); cvCopyMakeBorder(tgL,tgL_pad,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2),IPL_BORDER_CONSTANT); cvCopyMakeBorder(tgR,tgR_pad,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2),IPL_BORDER_CONSTANT); cvCopyMakeBorder(im,im_pad,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2),IPL_BORDER_CONSTANT); cvFilter2D(im_pad,tgL_pad,rlmask,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2)); cvFilter2D(im_pad,tgR_pad,rrmask,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2)); cvGetSubRect(tgL_pad,tgL,cvRect((rlmask->cols-1)/2,(rlmask->rows-1)/2,tgL->cols,tgL->rows)); cvGetSubRect(tgR_pad,tgR,cvRect((rlmask->cols-1)/2,(rlmask->rows-1)/2,tgR->cols,tgR->rows)); cvSub(tgL,tgR,sub2); cvPow(sub2,sub2,2.0); cvAdd(tgL,tgR,temp_add1); cvAddS(temp_add1,cvScalar(0.0000000001),temp_add1); cvDiv(sub2,temp_add1,sub2); cvAdd(tg,sub2,tg); } cvScale(tg,tg,0.5); cvReleaseMat(&temp_add1); } else{// if not chi^2 for (int i=0;i<ntex;i++) { cvCmpS(&tmap,i+1,temp,CV_CMP_EQ); cvConvertScale(temp,im,1.0/255); cvCopyMakeBorder(tgL,tgL_pad,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2),IPL_BORDER_CONSTANT); cvCopyMakeBorder(tgR,tgR_pad,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2),IPL_BORDER_CONSTANT); cvCopyMakeBorder(im,im_pad,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2),IPL_BORDER_CONSTANT); cvFilter2D(im_pad,tgL_pad,rlmask,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2)); cvFilter2D(im_pad,tgR_pad,rrmask,cvPoint((rlmask->cols-1)/2,(rlmask->rows-1)/2)); cvGetSubRect(tgL_pad,tgL,cvRect((rlmask->cols-1)/2,(rlmask->rows-1)/2,tgL->cols,tgL->rows)); cvGetSubRect(tgR_pad,tgR,cvRect((rlmask->cols-1)/2,(rlmask->rows-1)/2,tgR->cols,tgR->rows)); cvSub(tgL,tgR,sub2); cvAbs(sub2,sub2); cvTranspose(sub2,sub2t); reshape=cvReshape(sub2t,&reshapehdr,0,h*w); cvGetCol(d,coltemp,i); cvCopy(reshape,coltemp); } cvMatMul(d,&tsim,prod); cvMul(prod,d,prod); CvMat *sumcols=cvCreateMat(h*w,1,CV_32FC1); cvSetZero(sumcols); for (int i=0;i<prod->cols;i++) { cvGetCol(prod,coltemp,i); cvAdd(sumcols,coltemp,sumcols); } reshape=cvReshape(sumcols,&reshapehdr,0,w); cvTranspose(reshape,tg); cvReleaseMat(&sumcols); } //Smooth the gradient now!! tg=fitparab(*tg,sigma,sigma/4,theta); cvMaxS(tg,0,tg); cvReleaseMat(&im_pad); cvReleaseMat(&tgL_pad); cvReleaseMat(&tgR_pad); cvReleaseMat(&rlmask); cvReleaseMat(&rrmask); cvReleaseMat(&im); cvReleaseMat(&tgL); cvReleaseMat(&tgR); cvReleaseMat(&temp); cvReleaseMat(&coltemp); cvReleaseMat(&sub2); cvReleaseMat(&sub2t); cvReleaseMat(&d); cvReleaseMat(&prod); return tg; }
int main(int argc, char* argv[]) { if( argc != 3 ) { fprintf(stderr, "Usage: %s panorender.png photo.jpg\n", argv[0]); return 1; } IplImage* pano = cvLoadImage( argv[1], CV_LOAD_IMAGE_COLOR); assert(pano); IplImage* img = cvLoadImage( argv[2], CV_LOAD_IMAGE_COLOR); assert(img); CvMat* pano_edges; CvMat* img_edges; { pano_edges = extractEdges(pano, PANO); cvThreshold( pano_edges, pano_edges, 200.0, 0, CV_THRESH_TOZERO ); // the non-edge areas of the panorama should be dont-care areas. I implement // this by // x -> dilate ? x : mean; // another way to state the same thing: // !dilate -> mask // cvSet(mean) #define DILATE_R 9 #define EDGE_MINVAL 180 IplConvKernel* kernel = cvCreateStructuringElementEx( 2*DILATE_R + 1, 2*DILATE_R + 1, DILATE_R, DILATE_R, CV_SHAPE_ELLIPSE, NULL); CvMat* dilated = cvCreateMat( pano->height, pano->width, CV_8UC1 ); cvDilate(pano_edges, dilated, kernel, 1); CvScalar avg = cvAvg(pano_edges, dilated); cvCmpS(dilated, EDGE_MINVAL, dilated, CV_CMP_LT); cvSet( pano_edges, avg, dilated ); cvReleaseMat(&dilated); cvReleaseStructuringElement(&kernel); } { img_edges = extractEdges(img, PHOTO); cvSmooth(img_edges, img_edges, CV_GAUSSIAN, 13, 13, 0.0, 0.0); } CvPoint offset = alignImages( img_edges, pano_edges ); printf("offset: x,y: %d %d\n", offset.x, offset.y ); cvReleaseMat ( &pano_edges ); cvReleaseMat ( &img_edges ); cvReleaseImage( &pano ); cvReleaseImage( &img ); return 0; }
CV_IMPL double cvThreshold( const void* srcarr, void* dstarr, double thresh, double maxval, int type ) { CvHistogram* hist = 0; CV_FUNCNAME( "cvThreshold" ); __BEGIN__; CvSize roi; int src_step, dst_step; CvMat src_stub, *src = (CvMat*)srcarr; CvMat dst_stub, *dst = (CvMat*)dstarr; CvMat src0, dst0; int coi1 = 0, coi2 = 0; int ithresh, imaxval, cn; bool use_otsu; CV_CALL( src = cvGetMat( src, &src_stub, &coi1 )); CV_CALL( dst = cvGetMat( dst, &dst_stub, &coi2 )); if( coi1 + coi2 ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" ); if( !CV_ARE_CNS_EQ( src, dst ) ) CV_ERROR( CV_StsUnmatchedFormats, "Both arrays must have equal number of channels" ); cn = CV_MAT_CN(src->type); if( cn > 1 ) { src = cvReshape( src, &src0, 1 ); dst = cvReshape( dst, &dst0, 1 ); } use_otsu = (type & ~CV_THRESH_MASK) == CV_THRESH_OTSU; type &= CV_THRESH_MASK; if( use_otsu ) { float _ranges[] = { 0, 256 }; float* ranges = _ranges; int hist_size = 256; void* srcarr0 = src; if( CV_MAT_TYPE(src->type) != CV_8UC1 ) CV_ERROR( CV_StsNotImplemented, "Otsu method can only be used with 8uC1 images" ); CV_CALL( hist = cvCreateHist( 1, &hist_size, CV_HIST_ARRAY, &ranges )); cvCalcArrHist( &srcarr0, hist ); thresh = cvFloor(icvGetThreshVal_Otsu( hist )); } if( !CV_ARE_DEPTHS_EQ( src, dst ) ) { if( CV_MAT_TYPE(dst->type) != CV_8UC1 ) CV_ERROR( CV_StsUnsupportedFormat, "In case of different types destination should be 8uC1" ); if( type != CV_THRESH_BINARY && type != CV_THRESH_BINARY_INV ) CV_ERROR( CV_StsBadArg, "In case of different types only CV_THRESH_BINARY " "and CV_THRESH_BINARY_INV thresholding types are supported" ); if( maxval < 0 ) { CV_CALL( cvSetZero( dst )); } else { CV_CALL( cvCmpS( src, thresh, dst, type == CV_THRESH_BINARY ? CV_CMP_GT : CV_CMP_LE )); if( maxval < 255 ) CV_CALL( cvAndS( dst, cvScalarAll( maxval ), dst )); } EXIT; } if( !CV_ARE_SIZES_EQ( src, dst ) ) CV_ERROR( CV_StsUnmatchedSizes, "" ); roi = cvGetMatSize( src ); if( CV_IS_MAT_CONT( src->type & dst->type )) { roi.width *= roi.height; roi.height = 1; src_step = dst_step = CV_STUB_STEP; } else { src_step = src->step; dst_step = dst->step; } switch( CV_MAT_DEPTH(src->type) ) { case CV_8U: ithresh = cvFloor(thresh); imaxval = cvRound(maxval); if( type == CV_THRESH_TRUNC ) imaxval = ithresh; imaxval = CV_CAST_8U(imaxval); if( ithresh < 0 || ithresh >= 255 ) { if( type == CV_THRESH_BINARY || type == CV_THRESH_BINARY_INV || ((type == CV_THRESH_TRUNC || type == CV_THRESH_TOZERO_INV) && ithresh < 0) || (type == CV_THRESH_TOZERO && ithresh >= 255) ) { int v = type == CV_THRESH_BINARY ? (ithresh >= 255 ? 0 : imaxval) : type == CV_THRESH_BINARY_INV ? (ithresh >= 255 ? imaxval : 0) : type == CV_THRESH_TRUNC ? imaxval : 0; cvSet( dst, cvScalarAll(v) ); EXIT; } else { cvCopy( src, dst ); EXIT; } } if( type == CV_THRESH_BINARY || type == CV_THRESH_BINARY_INV ) { if( icvCompareC_8u_C1R_cv_p && icvAndC_8u_C1R_p ) { IPPI_CALL( icvCompareC_8u_C1R_cv_p( src->data.ptr, src_step, (uchar)ithresh, dst->data.ptr, dst_step, roi, type == CV_THRESH_BINARY ? cvCmpGreater : cvCmpLessEq )); if( imaxval < 255 ) IPPI_CALL( icvAndC_8u_C1R_p( dst->data.ptr, dst_step, (uchar)imaxval, dst->data.ptr, dst_step, roi )); EXIT; } } else if( type == CV_THRESH_TRUNC || type == CV_THRESH_TOZERO_INV ) { if( icvThreshold_GTVal_8u_C1R_p ) { IPPI_CALL( icvThreshold_GTVal_8u_C1R_p( src->data.ptr, src_step, dst->data.ptr, dst_step, roi, (uchar)ithresh, (uchar)(type == CV_THRESH_TRUNC ? ithresh : 0) )); EXIT; } } else { assert( type == CV_THRESH_TOZERO ); if( icvThreshold_LTVal_8u_C1R_p ) { ithresh = cvFloor(thresh+1.); ithresh = CV_CAST_8U(ithresh); IPPI_CALL( icvThreshold_LTVal_8u_C1R_p( src->data.ptr, src_step, dst->data.ptr, dst_step, roi, (uchar)ithresh, 0 )); EXIT; } } icvThresh_8u_C1R( src->data.ptr, src_step, dst->data.ptr, dst_step, roi, (uchar)ithresh, (uchar)imaxval, type ); break; case CV_32F: if( type == CV_THRESH_TRUNC || type == CV_THRESH_TOZERO_INV ) { if( icvThreshold_GTVal_32f_C1R_p ) { IPPI_CALL( icvThreshold_GTVal_32f_C1R_p( src->data.fl, src_step, dst->data.fl, dst_step, roi, (float)thresh, type == CV_THRESH_TRUNC ? (float)thresh : 0 )); EXIT; } } else if( type == CV_THRESH_TOZERO ) { if( icvThreshold_LTVal_32f_C1R_p ) { IPPI_CALL( icvThreshold_LTVal_32f_C1R_p( src->data.fl, src_step, dst->data.fl, dst_step, roi, (float)(thresh*(1 + FLT_EPSILON)), 0 )); EXIT; } } icvThresh_32f_C1R( src->data.fl, src_step, dst->data.fl, dst_step, roi, (float)thresh, (float)maxval, type ); break; default: CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); } __END__; if( hist ) cvReleaseHist( &hist ); return thresh; }
/* Wrapper function for distance transform group */ CV_IMPL void cvDistTransform( const void* srcarr, void* dstarr, int distType, int maskSize, const float *mask, void* labelsarr ) { cv::Ptr<CvMat> temp; cv::Ptr<CvMat> src_copy; cv::Ptr<CvMemStorage> st; float _mask[5] = {0}; CvMat srcstub, *src = (CvMat*)srcarr; CvMat dststub, *dst = (CvMat*)dstarr; CvMat lstub, *labels = (CvMat*)labelsarr; CvSize size; //CvIPPDistTransFunc ipp_func = 0; //CvIPPDistTransFunc2 ipp_inp_func = 0; src = cvGetMat( src, &srcstub ); dst = cvGetMat( dst, &dststub ); if( !CV_IS_MASK_ARR( src ) || (CV_MAT_TYPE( dst->type ) != CV_32FC1 && (CV_MAT_TYPE(dst->type) != CV_8UC1 || distType != CV_DIST_L1 || labels)) ) CV_Error( CV_StsUnsupportedFormat, "source image must be 8uC1 and the distance map must be 32fC1 " "(or 8uC1 in case of simple L1 distance transform)" ); if( !CV_ARE_SIZES_EQ( src, dst )) CV_Error( CV_StsUnmatchedSizes, "the source and the destination images must be of the same size" ); if( maskSize != CV_DIST_MASK_3 && maskSize != CV_DIST_MASK_5 && maskSize != CV_DIST_MASK_PRECISE ) CV_Error( CV_StsBadSize, "Mask size should be 3 or 5 or 0 (presize)" ); if( distType == CV_DIST_C || distType == CV_DIST_L1 ) maskSize = !labels ? CV_DIST_MASK_3 : CV_DIST_MASK_5; else if( distType == CV_DIST_L2 && labels ) maskSize = CV_DIST_MASK_5; if( maskSize == CV_DIST_MASK_PRECISE ) { icvTrueDistTrans( src, dst ); return; } if( labels ) { labels = cvGetMat( labels, &lstub ); if( CV_MAT_TYPE( labels->type ) != CV_32SC1 ) CV_Error( CV_StsUnsupportedFormat, "the output array of labels must be 32sC1" ); if( !CV_ARE_SIZES_EQ( labels, dst )) CV_Error( CV_StsUnmatchedSizes, "the array of labels has a different size" ); if( maskSize == CV_DIST_MASK_3 ) CV_Error( CV_StsNotImplemented, "3x3 mask can not be used for \"labeled\" distance transform. Use 5x5 mask" ); } if( distType == CV_DIST_C || distType == CV_DIST_L1 || distType == CV_DIST_L2 ) { icvGetDistanceTransformMask( (distType == CV_DIST_C ? 0 : distType == CV_DIST_L1 ? 1 : 2) + maskSize*10, _mask ); } else if( distType == CV_DIST_USER ) { if( !mask ) CV_Error( CV_StsNullPtr, "" ); memcpy( _mask, mask, (maskSize/2 + 1)*sizeof(float)); } /*if( !labels ) { if( CV_MAT_TYPE(dst->type) == CV_32FC1 ) ipp_func = (CvIPPDistTransFunc)(maskSize == CV_DIST_MASK_3 ? icvDistanceTransform_3x3_8u32f_C1R_p : icvDistanceTransform_5x5_8u32f_C1R_p); else if( src->data.ptr != dst->data.ptr ) ipp_func = (CvIPPDistTransFunc)icvDistanceTransform_3x3_8u_C1R_p; else ipp_inp_func = icvDistanceTransform_3x3_8u_C1IR_p; }*/ size = cvGetMatSize(src); /*if( (ipp_func || ipp_inp_func) && src->cols >= 4 && src->rows >= 2 ) { int _imask[3]; _imask[0] = cvRound(_mask[0]); _imask[1] = cvRound(_mask[1]); _imask[2] = cvRound(_mask[2]); if( ipp_func ) { IPPI_CALL( ipp_func( src->data.ptr, src->step, dst->data.fl, dst->step, size, CV_MAT_TYPE(dst->type) == CV_8UC1 ? (void*)_imask : (void*)_mask )); } else { IPPI_CALL( ipp_inp_func( src->data.ptr, src->step, size, _imask )); } } else*/ if( CV_MAT_TYPE(dst->type) == CV_8UC1 ) { icvDistanceATS_L1_8u( src, dst ); } else { int border = maskSize == CV_DIST_MASK_3 ? 1 : 2; temp = cvCreateMat( size.height + border*2, size.width + border*2, CV_32SC1 ); if( !labels ) { CvDistTransFunc func = maskSize == CV_DIST_MASK_3 ? icvDistanceTransform_3x3_C1R : icvDistanceTransform_5x5_C1R; func( src->data.ptr, src->step, temp->data.i, temp->step, dst->data.fl, dst->step, size, _mask ); } else { CvSeq *contours = 0; CvPoint top_left = {0,0}, bottom_right = {size.width-1,size.height-1}; int label; st = cvCreateMemStorage(); src_copy = cvCreateMat( size.height, size.width, src->type ); cvCmpS( src, 0, src_copy, CV_CMP_EQ ); cvFindContours( src_copy, st, &contours, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); cvZero( labels ); for( label = 1; contours != 0; contours = contours->h_next, label++ ) { CvScalar area_color = cvScalarAll(label); cvDrawContours( labels, contours, area_color, area_color, -255, -1, 8 ); } cvCopy( src, src_copy ); cvRectangle( src_copy, top_left, bottom_right, cvScalarAll(255), 1, 8 ); icvDistanceTransformEx_5x5_C1R( src_copy->data.ptr, src_copy->step, temp->data.i, temp->step, dst->data.fl, dst->step, labels->data.i, labels->step, size, _mask ); } } }
/* Wrapper function for distance transform group */ CV_IMPL void cvDistTransform( const void* srcarr, void* dstarr, int distType, int maskSize, const float *mask, void* labelsarr, int labelType ) { float _mask[5] = {0}; CvMat srcstub, *src = (CvMat*)srcarr; CvMat dststub, *dst = (CvMat*)dstarr; CvMat lstub, *labels = (CvMat*)labelsarr; src = cvGetMat( src, &srcstub ); dst = cvGetMat( dst, &dststub ); if( !CV_IS_MASK_ARR( src ) || (CV_MAT_TYPE( dst->type ) != CV_32FC1 && (CV_MAT_TYPE(dst->type) != CV_8UC1 || distType != CV_DIST_L1 || labels)) ) CV_Error( CV_StsUnsupportedFormat, "source image must be 8uC1 and the distance map must be 32fC1 " "(or 8uC1 in case of simple L1 distance transform)" ); if( !CV_ARE_SIZES_EQ( src, dst )) CV_Error( CV_StsUnmatchedSizes, "the source and the destination images must be of the same size" ); if( maskSize != CV_DIST_MASK_3 && maskSize != CV_DIST_MASK_5 && maskSize != CV_DIST_MASK_PRECISE ) CV_Error( CV_StsBadSize, "Mask size should be 3 or 5 or 0 (presize)" ); if( distType == CV_DIST_C || distType == CV_DIST_L1 ) maskSize = !labels ? CV_DIST_MASK_3 : CV_DIST_MASK_5; else if( distType == CV_DIST_L2 && labels ) maskSize = CV_DIST_MASK_5; if( maskSize == CV_DIST_MASK_PRECISE ) { icvTrueDistTrans( src, dst ); return; } if( labels ) { labels = cvGetMat( labels, &lstub ); if( CV_MAT_TYPE( labels->type ) != CV_32SC1 ) CV_Error( CV_StsUnsupportedFormat, "the output array of labels must be 32sC1" ); if( !CV_ARE_SIZES_EQ( labels, dst )) CV_Error( CV_StsUnmatchedSizes, "the array of labels has a different size" ); if( maskSize == CV_DIST_MASK_3 ) CV_Error( CV_StsNotImplemented, "3x3 mask can not be used for \"labeled\" distance transform. Use 5x5 mask" ); } if( distType == CV_DIST_C || distType == CV_DIST_L1 || distType == CV_DIST_L2 ) { icvGetDistanceTransformMask( (distType == CV_DIST_C ? 0 : distType == CV_DIST_L1 ? 1 : 2) + maskSize*10, _mask ); } else if( distType == CV_DIST_USER ) { if( !mask ) CV_Error( CV_StsNullPtr, "" ); memcpy( _mask, mask, (maskSize/2 + 1)*sizeof(float)); } CvSize size = cvGetMatSize(src); if( CV_MAT_TYPE(dst->type) == CV_8UC1 ) { icvDistanceATS_L1_8u( src, dst ); } else { int border = maskSize == CV_DIST_MASK_3 ? 1 : 2; cv::Ptr<CvMat> temp = cvCreateMat( size.height + border*2, size.width + border*2, CV_32SC1 ); if( !labels ) { CvDistTransFunc func = maskSize == CV_DIST_MASK_3 ? icvDistanceTransform_3x3_C1R : icvDistanceTransform_5x5_C1R; func( src->data.ptr, src->step, temp->data.i, temp->step, dst->data.fl, dst->step, size, _mask ); } else { cvZero( labels ); if( labelType == CV_DIST_LABEL_CCOMP ) { CvSeq *contours = 0; cv::Ptr<CvMemStorage> st = cvCreateMemStorage(); cv::Ptr<CvMat> src_copy = cvCreateMat( size.height+border*2, size.width+border*2, src->type ); cvCopyMakeBorder(src, src_copy, cvPoint(border, border), IPL_BORDER_CONSTANT, cvScalarAll(255)); cvCmpS( src_copy, 0, src_copy, CV_CMP_EQ ); cvFindContours( src_copy, st, &contours, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(-border, -border)); for( int label = 1; contours != 0; contours = contours->h_next, label++ ) { CvScalar area_color = cvScalarAll(label); cvDrawContours( labels, contours, area_color, area_color, -255, -1, 8 ); } } else { int k = 1; for( int i = 0; i < src->rows; i++ ) { const uchar* srcptr = src->data.ptr + src->step*i; int* labelptr = (int*)(labels->data.ptr + labels->step*i); for( int j = 0; j < src->cols; j++ ) if( srcptr[j] == 0 ) labelptr[j] = k++; } } icvDistanceTransformEx_5x5_C1R( src->data.ptr, src->step, temp->data.i, temp->step, dst->data.fl, dst->step, labels->data.i, labels->step, size, _mask ); } } }