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函数就自适应确定门限。
转自:http://bixiaoxu.blog.163.com/blog/static/197727347201341345012574/

你可能感兴趣的:(opencv,自适应,canny,边沿检测)