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/
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的要求是编写一个通过自适应值滤波加局部自适应阈值建立阈值矩阵对Canny算法改进的程序,以下是一份可能符合您要求的Python程序: ```python import cv2 import numpy as np # 读取图像 img = cv2.imread('input.jpg', 0) # 自适应值滤波 def adaptive_median_filter(img, size): height, width = img.shape result = np.zeros((height, width), dtype=np.uint8) for i in range(height): for j in range(width): filter_size = 3 while filter_size <= size: offset = filter_size // 2 roi = img[max(0, i-offset):min(height, i+offset+1), max(0, j-offset):min(width, j+offset+1)] median = np.median(roi) if img[i, j] > median and median > np.min(roi) and median < np.max(roi): result[i, j] = img[i, j] break else: filter_size += 2 else: result[i, j] = median return result # 局部自适应阈值 def local_adaptive_threshold(img, ksize, c): img_mean = cv2.blur(img, (ksize, ksize)) img_sub = img - img_mean img_sub_mean = cv2.blur(img_sub * img_sub, (ksize, ksize)) img_std = np.sqrt(img_sub_mean) return img_mean - c * img_std # Canny算法改进 def canny_improved(img, threshold_matrix): img_median = adaptive_median_filter(img, 7) img_threshold = cv2.compare(img_median, threshold_matrix, cv2.CMP_GT) return cv2.Canny(img_threshold, 100, 200) # 建立阈值矩阵 threshold_matrix = local_adaptive_threshold(img, 3, 0.1) # 显示结果 cv2.imshow('Input', img) cv2.imshow('Output', canny_improved(img, threshold_matrix)) cv2.waitKey(0) cv2.destroyAllWindows() ``` 该程序使用OpenCV库实现了自适应值滤波和局部自适应阈值,然后建立阈值矩阵,并将处理后的图像和阈值矩阵输入到Canny算法,得到改进后的边缘检测结果。您可以将程序的`input.jpg`替换为您想要处理的图像,然后运行程序查看结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值