传统CV算法——边缘算子与图像金字塔算法介绍
边缘算子
图像梯度算子 - Sobel
Sobel算子是一种用于边缘检测的图像梯度算子,它通过计算图像亮度的空间梯度来突出显示图像中的边缘。Sobel算子主要识别图像中亮度变化快的区域,这些区域通常对应于边缘。它是通过对图像进行水平和垂直方向的差分运算来实现的,具体来说:
- ddepth:输出图像的深度,通常设置为
cv2.CV_64F
来避免负数被截断。 - dx 和 dy 分别指定了水平和垂直方向的导数阶数,比如
dx=1, dy=0
就是对水平方向求一阶导数,用于检测垂直边缘;而dx=0, dy=1
对应的是对垂直方向求一阶导数,用于检测水平边缘。 - ksize 是Sobel算子的大小,它决定了滤波器的大小。ksize越大,滤波器覆盖的像素就越多,边缘检测就越模糊。常见的ksize值有1, 3, 5, 7。特别地,ksize=-1时会应用3x3的Scharr滤波器,它比3x3的Sobel滤波器有更好的结果。
在实践中,Sobel算子通过卷积框架应用于图像,分别计算x和y方向上的梯度,然后根据需要可能会结合这两个方向的梯度来得到边缘的完整表示。
dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
- ddepth:图像的深度
- dx和dy分别表示水平和竖直方向
- ksize是Sobel算子的大小
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('pie.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow("img",img)
cv2.waitKey()
cv2.destroyAllWindows()
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
cv_show(sobelx,'sobelx')
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
cv_show(sobely,'sobely')
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show(sobelxy,'sobelxy')
灰度化处理
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
cv_show(img,'img')
cv2.convertScaleAbs()
函数主要作用是将梯度转换成可视化的形式。在进行Sobel边缘检测后,如果直接输出梯度结果,可能会因为数据类型的问题(比如负值)而不能正确显示。这个函数首先对输入的梯度值进行绝对值处理,然后将数据类型转换为无符号8位整型(uint8
),这样就可以正常显示为图像了。这个步骤是图像处理中常用的一种方式,用来将处理后的数据转化为图像处理软件或显示设备可以接受的格式。
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show(sobelxy,'sobelxy')
图像梯度-Scharr算子
不同算子的差异
分别为sobel 、 Scharr、laplacian
#不同算子的差异
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show(res,'res')
Canny边缘检测
-
使用高斯滤波器,以平滑图像,滤除噪声。
-
计算图像中每个像素点的梯度强度和方向。
-
应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
-
应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
-
通过抑制孤立的弱边缘最终完成边缘检测。
cv2.Canny()
函数实现的是Canny边缘检测算法,这是一种非常流行且有效的图像边缘检测方法。该函数需要两个阈值作为参数,用来控制边缘检测的灵敏度。较低的阈值可以捕获更多的边缘(但可能包括一些噪声),而较高的阈值只捕获最显著的边缘。这个算法的步骤包括使用高斯滤波器去除图像噪声、计算图像的梯度强度和方向、应用非极大值抑制(NMS)来消除边缘响应的假阳性以及应用双阈值检测和边缘连接。最终,它输出一个二值图像,显示了检测到的边缘。
img=cv2.imread("lena.jpg",cv2.IMREAD_GRAYSCALE)
v1=cv2.Canny(img,80,150)
v2=cv2.Canny(img,50,100)
res = np.hstack((v1,v2))
cv_show(res,'res')
对车辆采用canny算子
img=cv2.imread("car.png",cv2.IMREAD_GRAYSCALE)
v1=cv2.Canny(img,120,250)
v2=cv2.Canny(img,50,100)
res = np.hstack((v1,v2))
cv_show(res,'res')
图像金字塔
高斯金字塔
高斯金字塔主要用于图像的多尺度表示。在计算机视觉和图像处理中,高斯金字塔通过逐步降低图像的分辨率并应用高斯滤波来生成图像的一系列缩小版本。这个过程包括两个基本操作:降采样和平滑。首先,原始图像被高斯滤波器平滑处理,然后每个方向上每隔一个像素进行采样,从而创建出更小尺寸的图像。
高斯金字塔的应用包括但不限于:
- 图像压缩:通过降低图像分辨率的方式减少存储空间需求。
- 图像融合:在进行图像拼接或HDR图像合成时,金字塔可以帮助在不同尺度上平滑地融合图像。
- 物体检测和识别:使用图像金字塔可以在不同的尺度上检测物体,提高检测的精度和鲁棒性。
通过这种方式,高斯金字塔能够在不同的分辨率层次上处理图像,适用于多种不同的图像处理任务。
img=cv2.imread("AM.png")
cv_show(img,'img')
print (img.shape)
上采样
up=cv2.pyrUp(img)
cv_show(up,'up')
print (up.shape)
下采样
down=cv2.pyrDown(img)
cv_show(down,'down')
print (down.shape)
继续上采样
up2=cv2.pyrUp(up)
cv_show(up2,'up2')
print (up2.shape)
原图与经过图像金字塔后处理的图
拉普拉斯金字塔
down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv_show(l_1,'l_1')