图像求导、边缘检测、分割
Canny边缘检测算子是一种多级检测算法。1986年由John F. Canny提出,同时提出了边缘检测的三大准则:
- 低错误率的边缘检测:检测算法应该精确地找到图像中的尽可能多的边缘,尽可能的减少漏检和误检。
- 最优定位:检测的边缘点应该精确地定位于边缘的中心。
- 图像中的任意边缘应该只被标记一次,同时图像噪声不应产生伪边缘。
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 算法思路:
- 初始化参数空间,将参数空间矩阵每一个像素置0;
- 遍历图像当中不为0的像素点,记录所有经过该像素点直线的直线参数,将参数空间中对应该直线参数的像素值加1;
- 根据先验知识,分析参数矩阵,获取参数矩阵某些峰值作为检测结果。
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()