现在的位置: 首页 > 综合 > 正文

canny变换中的自适应阈值方法实现

2018年04月01日 ⁄ 综合 ⁄ 共 1610字 ⁄ 字号 评论关闭

在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!

抱歉!评论已关闭.