目录
1.图像梯度-sobel算子
计算图像梯度:
- 首先分成水平梯度和垂直梯度
- 水平梯度就是右减左,垂直梯度就是下减上
- 水平梯度表示Gx,垂直梯度表示Gy,分别与图像进行内积。就相当于卷积的过程。
首先读取一张灰度图像:
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
img = cv2.imread('image/pie.png',cv2.IMREAD_GRAYSCALE)
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
cv_show(img,'original')
sobel梯度函数:
dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
- ddepth:图像的深度,默认值为-1
- dx和dy分别表示水平和竖直方向
- ksize是Sobel算子的大小
计算dx梯度:
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) #dx=1就算dx
cv_show(sobelx,'sobelx')
由图像可以看到为什么它只显示左边的梯度,而右边的梯度不显示呢?
那是因为计算dx时,是右减左,所以计算右边半圆梯度的时候,计算结果为负数。在OpenCV中,它会自动把负数进行截断,变成0,所以右半圆就变成了黑色,只能显示左半圆。
下面取绝对值看一下:
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
cv_show(sobelx,'sobelx')
现在它就全部显示啦!
计算dy梯度:(和dx梯度一样,这里我就直接计算绝对值了)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
cv_show(sobely,'sobely')
最后计算总梯度:
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')
2.图像梯度-scharr算子和laplacian算子
scharr算子:
laplacian算子:
img = cv2.imread('image/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) #sobel算子
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) #scharr算子
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian) #laplacian算子
res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show(res,'res')
原图展示:
这样我们就可以看到三个算子之间不同的差异,可以看到scharr算子更加的详细。
2.边缘检测
-
使用高斯滤波器,以平滑图像,滤除噪声。
-
计算图像中每个像素点的梯度强度和方向。
-
应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
-
应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
-
通过抑制孤立的弱边缘最终完成边缘检测。
1.高斯滤波器
2.梯度和方向
3.非极大值抑制
4.双阈值检测
在这里我取了一个偏大的双阈值和一个偏小的双阈值
img=cv2.imread("image/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')
可以看到阈值为(50, 100)比(80, 150)更加详细。