在OpenCV中自适应确定canny算法的分割门限

在OpenCV中用canny算子进行边缘检测速度很快,不过有点不爽的就是高低阈值需要输入。在matlab中,如果不指定阈值的话,由函数自适应确定,因此仿照matlab中的做法,对canny函数进行了修改,以便当用户没有指定高低阈值时,由函数自适应确定阈值。 我在OpenCv原码库中增加了一个函数,用于确定高低阈值。 // 仿照matlab,自适应求高低两个门限

CV_IMPL void AdaptiveFindThreshold(CvMat *dx, CvMat *dy, double *low, double *high)

{

CvSize size;

IplImage *imge=0;

int i,j;

CvHistogram *hist;

int hist_size = 255;

float range_0[]={0,256};

float* ranges[] = { range_0 };

double  PercentOfPixelsNotEdges = 0.7;

size = cvGetSize(dx);

imge = cvCreateImage(size, IPL_DEPTH_32F, 1);

// 计算边缘的强度, 并存于图像中

float maxv = 0;

for(i = 0; i < size.height; i++ )

{

 const short* _dx = (short*)(dx->data.ptr + dx->step*i);

       const short* _dy = (short*)(dy->data.ptr + dy->step*i);

 float* _image = (float *)(imge->imageData + imge->widthStep*i);

 for(j = 0; j < size.width; j++)

 {

  _image[j] = (float)(abs(_dx[j]) + abs(_dy[j]));

  maxv = maxv < _image[j] ? _image[j]: maxv;

 }

  }

 

 // 计算直方图

range_0[1] = maxv;

hist_size = (int)(hist_size > maxv ? maxv:hist_size);

hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);

cvCalcHist( &imge, hist, 0, NULL );

int total = (int)(size.height * size.width * PercentOfPixelsNotEdges);

float sum=0;

int icount = hist->mat.dim[0].size;

 

float *h = (float*)cvPtr1D( hist->bins, 0 );

for(i = 0; i < icount; i++)

{

 sum += h[i];

 if( sum > total )

  break; 

}

// 计算高低门限

*high = (i+1) * maxv / hist_size ;

*low = *high * 0.4;

cvReleaseImage( &imge );

cvReleaseHist(&hist);

}

 

在把cvCanny函数进行以下修改。

在函数体中,当程序用两个sobel算子计算完水平和垂直两个方向的梯度强度过后加入以下代码

// 自适应确定阈值

if(low_thresh == -1 && high_thresh == -1)

{

 AdaptiveFindThreshold(dx, dy, &low_thresh, &high_thresh);

}

 

这样,在调用cvCanny函数时,指定高低门限为-1,则cvCanny函数就自适应确定门限。 最后,别忘了重新编译cv库,对lib和dll库进行更新。 that's all!

你可能感兴趣的:(算法,image,null,matlab,dll,float)