OpenCV的边缘计算
基于梯度的检测器
梯边缘,顶边缘,坡边缘
有限差分
最简单的梯度算子
$$
gx=f(x+1,y)-f(x,y) \
gy=f(x,y+1)-f(x,y)
$$
Sobel算子
对于具有噪声的图有很好的效果
$$
gx=\frac{1}{8}\left[ \begin{matrix} -1 & 0 & 1 \ -2 & 0 & 2 \ -1 & 0 & 1 \end{matrix} \right]\
gy=\frac{1}{8}\left[ \begin{matrix} 1 & 2 & 1 \ 0 & 0 & 0 \ -1 & -2 & -1 \end{matrix} \right]
$$
基于曲率的检测器
缺点,对于薄边缘在精准定位边缘没有优势
Marr-Hildreth
$$
gx-g(x-1)=f(x+1,y)-f(x,y) -(f(x,y)-f(x-1,y) )=f(x+1,y)-f(x-1,y)-2f(x,y)
$$
高斯的拉普拉斯滤波器LoG
考虑四边的核
$$
\frac{1}{8}\left[ \begin{matrix} 0 & -1 & 0 \ -1 & 4 & -1 \ 0 & -1 & 0 \end{matrix} \right]
$$
考虑全部八个方向
$$
\frac{1}{8}\left[ \begin{matrix} -1 & -1 & -1 \ -1 & 8 & -1 \ -1 & -1 & -1 \end{matrix} \right]
$$
Canny边缘检测
canny的四步法
使用低通滤波器抑制噪声
计算梯度幅度和方向图
对梯度幅度图使用非极大值抑制
运用迟滞和连通分析检测边缘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using namespace cv;
using namespace std;
int main() {
Mat srcImage, grayImage;
srcImage = imread("Lena.png");
imshow("Lena.png", srcImage);
Mat srcImage1 = srcImage.clone();
//图形转换:
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
Mat dstImage, edge;
//均值滤波
blur(srcImage1, grayImage, Size(3, 3));
imshow("grayImage.png", grayImage);
GaussianBlur(grayImage, grayImage, Size(5, 5), 0.8);
/*
边缘检测
低于阈值1的像素点会被认为不是边缘;
高于阈值2的像素点会被认为是边缘;
在阈值1和阈值2之间的像素点,若与第2步得到的边缘像素点相邻,则被认为是边缘,否则被认为不是边缘。
*/
Canny(grayImage, edge, 150, 100, 3);
dstImage.create(srcImage1.size(), srcImage1.type());
dstImage = Scalar::all(0);
/*
image.copyTo(imageROI)。作用是把image的内容复制粘贴到imageROI上;
image.copyTo(imageROI,mask)。 作用是把mask和image重叠以后把mask中像素值为0(black)的点对应的image中的点变为透明,而保留其他点。
*/
srcImage1.copyTo(dstImage, edge);
imwrite("canny.jpg", dstImage);
imshow("canny.jpg", dstImage);
waitKey(0);
return 0;
}
fast算子
计算步骤
从图片中选取一个坐标点,获取该点的像素值,接下来判定该点是否为特征点.
选取一个以选取点坐标为圆心的半径等于三的Bresenham圆(一个计算圆的轨迹的离散算法,得到整数级的圆的轨迹点),一般来说,这个圆上有16个点
现在选取一个阈值,假设为t,关键步骤,假设这16个点中,有N个连续的像素点,他们的亮度值与中心点的像素值的差大于或者小于t,那么这个点就是一个特征点.(n的取值一般取值12或者9,实验证明9可以取得更好的效果,因为可以获取更多的特征点,后面进行处理时,数据样本额相对多一些).
加入每个轨迹点都需要遍历的话,那么需要的时间比较长,有一种比较简单的方法可以选择,那就是仅仅检查在位置1,9,5和13四个位置的像素,首先检测位置1和位置9,如果它们都比阈值暗或比阈值亮,再检测位置5和位置13,该满足判断条件。如果不满足中心点不可能是一个角点。对于所有点做上面这一部分初步的检测后,符合条件的将成为候选的角点,我们再对候选的角点,做完整的测试,即检测圆上的所有点.
但是,这种检测方法会带来一个问题,就是造成特征点的聚簇效应,多个特征点在图像的某一块重复高频率的出现,FAST算法提出了一种非极大值抑制的办法来消除这种情况,具体办法如下
对所有检测到的角点构建一个打分函数。就是像素点与周围16个像素点差值的绝对值之和。
考虑两个相邻的角点,并比较它们的值。
值较低的角点将会被删除。
1 |
|
1 | enum struct DrawMatchesFlags |
Harris算子
步骤如下:
生成梯度图像gx,gy
一个颜色块A,A1到A9 3x3,一个颜色块B,B1到B9 3x3 w x(Ai-Bi)的平方。w是权值比如A5到Ai的距离。
得到两个特征值下x,y如果两个值都很小,没有特征。如果一个很大就存在一条边,都很大,这个点有一个角点。
c++的实现
1 |
|