肉眼识别即颜色变化强度大的地方,对于计算机而言就是像素点梯度方向像素变化率很大的地方。
首先我们先说一下,什么是高斯噪声?高斯噪声就是它的概率密度函数服从高斯分布(即正态分布)的一类噪声。其在图像当中常表现为能引起较强视觉效果的孤立像素点或像素块。噪声的出现会给图像带来干扰,让图像变得不清楚。
高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。消除图像在数字化过程中产生或者混入的噪声。
二维高斯分布:
假定中心点的坐标是(0,0),那么取距离它最近的8个点坐标,为了计算,需要设定σ的值。假定σ=1,则高斯滤波核计算如下:
有表中数据可得到结论:中心的值最大,越往外侧值约小。
再归一化处理:我们还要确保这九个值加起来为1(高斯滤波核的特性),这9个点的权重总和等于0.7792,因此给上面9个值还要分别除以0.7792,得到最终的高斯滤波核的值。
具体计算方法:
与对应位相乘得到结果为1.58左右则将原来3的位置改为1。然后依次向左向下移动小橘框与滤波核进行计算。(加外围一排的原因是为了保持计算完后)
注:在原图加一层的做法是为了使在计算后得到与原图大小相同的图。通俗的讲就是,原图大小是5x5的,在外围加了一层变为了6x6,计算结束后又变成了原图5x5的大小。
高斯滤波的作用:原图的灰度强度变化是很大的(225旁边是2,4,差值很大)通过高斯滤波之后,差值变小了,说明图变平滑多了
Sobel计算方法大致与高斯相同,对应位相乘,但计算卷积因子Gx,Gy是固定不变的。
举例:
与Gx对应位相乘,中间一竖行乘不起作用,其余位与Gx相乘会发现是右边一列的值减去左边一列的值。即乘 + 乘,即算出水平方向的梯度dx,同样方法算出垂直方向的梯度dy。最终梯度及其方向计算方法如图:
具体计算方法如下(对应位相乘):
梯度值最终结果为:
非极大值抑制就是是一种去除非极大值的算法,常用于计算机视觉中的边缘检测、物体识别等。可以将sobel计算的边界变细。
在中心像素点的梯度方向方向选三个点,(8领域表示法,表示中间像素的8个方向)如果中间点值最大则暂且认为其是边缘点,如果中间点值不是最大则此是边缘点。举例:若选择一个中间点,其梯度方向为了90°,则看图中4,2,5三个点,比较2是否是局部最大值(极值点),如果是则2为边缘点,如果不是则不是边缘点。因为是在sobel的基础上选择领域中最大的,因此边界变细。
举例:g1,g2,g3,g4,c都为离散的像素点(c点的8邻域),如何判断c点是其中最大的像素点?
在c点的梯度方向(边的垂直方向)做一条线,交点可能没有像素点,则设两个交点为dTmp1,dTmp1,用线性差值法算出两交点像素值,与c点像素值比较,如果c点是最大值则保留c点,否则抛弃。
阈值minvalue, 阈值maxvalue(一般minvalue设为50,maxvalue为3倍的minvalue)
若像素小于阈值minvalue或者大于阈值maxvalue的点扔掉。
若介于minvalue与maxvalue之间,需要分情况,如果像素点在主边缘上则保留,如果与主边缘没有相连则扔掉。
# 读入图像
import cv2
img = cv2.imread("E:/PycharmProjects/doutula/baidutup/pic/lixian_2.jpg")
lenna = cv2.imread("E:/PycharmProjects/doutula/baidutup/pic/lixian_2.jpg",0)
cv2.imshow("lixian", img)
cv2.imshow("huidu", lenna)
# 图像降噪
lenna = cv2.GaussianBlur(lenna, (5, 5), 0)
# Canny边缘检测,低阈值50,高阈值150
canny = cv2.Canny(lenna, 50, 150)
cv2.imshow("canny", canny)
cv2.waitKey()
结果显示:
用栈来完成,确定出一定是边的像素点,然后遍历这些一定是边的像素点的8邻域,看是否存在灰度值在minvalue与maxvalue之间可能是边的像素点。如果此像素点可能是边并且又在肯定是边的像素点的8邻域内,则将其标记为一定是边的像素点,压入栈中。将这些一定是边的像素点连接起来就是边缘。