图像求导、边缘检测、分割

Canny边缘检测算子是一种多级检测算法。1986年由John F. Canny提出,同时提出了边缘检测的三大准则:

  1. 低错误率的边缘检测:检测算法应该精确地找到图像中的尽可能多的边缘,尽可能的减少漏检和误检。
  2. 最优定位:检测的边缘点应该精确地定位于边缘的中心。
  3. 图像中的任意边缘应该只被标记一次,同时图像噪声不应产生伪边缘。

 

 

1.sobel算子

Sobel导数并不是真正的导数,因为Sobel算子定义在一个离散的空间上。Sobel算子真正表示的是多项式拟合。

 

Sobel(imGray,imgSobeled,-1,0,1);

 

 

2.Priwitt滤波器

 

 

3.Scharr滤波器:相较于Sobel精度更高

 

Scharr(imGray,imScharred,-1,0,1);

 

4.拉普拉斯核——真正的轮廓识别

 

Laplacian(imGray,imLaped,-1,1);

 

 

 

 

 分别对应:原图,Sobel/Scharr滤波,Laplacian变换

 

 

 

5.Canny边缘检测

 

Canny边缘检测算法可以分为以下5个步骤:

  • 1) 高斯模糊 - GaussianBlur
  • 2) 灰度转换 - cvtColor
  • 3) 计算梯度 - Sobel/Scharr
  • 4) 非最大信号抑制
  • 5) 高低阈值输出二值图像

 

 

    Mat dx,dy;
    blur(imGray,blurImage,cv::Size(3,3));
    Scharr(blurImage,dx,CV_16S,1,0);
    Scharr(blurImage,dy,CV_16S,0,1);
    Canny(dx,dy,imCannyed,100,150);

 

6.hough变换

6.1 算法思路:

  1. 初始化参数空间,将参数空间矩阵每一个像素置0;
  2. 遍历图像当中不为0的像素点,记录所有经过该像素点直线的直线参数,将参数空间中对应该直线参数的像素值加1;
  3. 根据先验知识,分析参数矩阵,获取参数矩阵某些峰值作为检测结果。

6.2 OpenCV接口:

  • Hough变换主要优点是能容忍特征边界描述中的间隙,并且相对不受图像噪声的影响。
  • SHT,标准hough变换
  • MHT,多尺度hough变换,对SHT的细化,精度更高
  • PPHT,渐进概率hough变换,计算直线及其延长线——只要峰值够高,只要花很少的时间即可,可大幅提高速度
void HoughLines( InputArray image,   // image:输入图像
                 OutputArray lines,  //lines:检测到的直线(表示其实为直线参数(θ,p)集合)
                 double rho,       //rho:像素每次迭代的大小(即每一次选取像素的过程跳跃多少,一般设置为1)
                 double theta,     //theta:角度累加器的大小(即选取的直线参数θ的变化),一般为CV_PI/180
                 int threshold,    //thresold:阈值大小(即每个参数对至少经过的像素点数)   
                 double srn = 0, double stn = 0,
                 double min_theta = 0, double max_theta = CV_PI );

 C++程序实现参考:https://github.com/ljwcdtj/HoughTransform

6.3 缺点

  • 巨量的计算,难以达到实时性
  • 解决思路:
  • 裁剪原始图像,缩小搜索范围
  • 平方根,正弦,余弦计算的查表化
  • “多尺度”搜索策略,即先对原图抽样数据进行粗搜索定位,再对原图在一定的角度范围内进行搜索
  • 先验知识(直线走向,长度等限制)的使用以及一些多线程/并行计算策略

6.4 参考:https://blog.csdn.net/ljwcdtj/article/details/89091060

 

7.距离变换(有标记、无标记)

  • 用于细化字符的轮廓和查找物体质心(中心)。参考:https://blog.csdn.net/z827997640/article/details/80461240

 7.1 算法思路

按照某种距离(如:D4距离或D8距离)对大小为M×N的图像中的区域块作距离变换,算法过程如下:

 

 

 

  • 1、建立一个大小为M×N的数组F,作如下的初始化:将区域块中的元素设置为0,其余元素设置为无穷;
  • 2、利用掩模1(mask1),左上角开始,从左往右,从上往下遍历数组,将掩模中P点对应的元素的值作如下更新:

  • 3、利用掩模2(mask2),右下角开始,从右往左,从下往上遍历数组,将掩模中P点对应的元素的值作如下更新:

  • 4、最终得到的更新后的数组即为距离变换的结果。

7.2 opencv接口

void distanceTransform( InputArray src, 
              OutputArray dst,
                        int distanceType,
               int maskSize,
               int dstType=CV_32F);

InputArray src:输入图像,一般为二值图像;
OutputArray dst:输出的图像,距离变换结果;
int distanceType:用于距离变换的距离类型(欧氏距离:DIST_L2 = 2;$D_4$距离:DIST_L1 = 1;$D_8$距离:DIST_C = 3等);
int mask_size:距离变换掩模的大小,一般为3或5;
int dstType:输出图像的数据类型,可以为CV_8U或CV_32F。

7.3 应用 

  • 骨架抽取
  • 用距离变换的方式来实现匹配,配合倒角距离变换(Chamfer Distance Transform)可以达到快速匹配的效果。(对旋转、缩放是无效的)

 

 7.4 参考:

https://zhuanlan.zhihu.com/p/38917770

https://www.2cto.com/kf/201701/586976.html

 

8.分割

8.1 漫水填充

  • cv::floodFill()

8.2 分水岭算法

  • 无单独背景蒙版时,需要分割图像:图中的线转化成“山”,平坦区域转化成“谷”用以分割
  • 使用者/算法先标记对象或背景的一部分
  • cv::watershed()

8.3 Grabcuts算法

  • 使用者/算法在待分割对象周围提供一个矩形框,其外部即为背景
  • cv::grabCut()

8.4 Mean-shift分割

  • 基于颜色分布峰值进行分割
  • 通过滑动窗口找到最高密度块,
  • cv::pyrMeanShiftFiltering()

 

posted @ 2019-12-03 16:12  寒江小筑  阅读(1126)  评论(0编辑  收藏  举报