图像梯度
一、Sobel算子
-
矩阵
-
Gx 是中心点的右边减去左边
-
Gy 是中心点的下边减去上边
1. 使用方法
-
注意
上面的乘法是阵列(卷积)乘法不是矩阵乘法,就是对应元素相乘后相加
import cv2
import matplotlib
import matplotlib.pyplot as plt #取别名(用于绘图展示)
import numpy as np #取别名,下面是notepad专用,立即显示图像
%matplotlib inline
def cv_show(name, img): #定义函数用于显示图片,此处name为窗口名,img为cv2调用imread方法的返回值
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def winds(images, scale):
for i in range(len(images)):
images[i] = cv2.resize(images[i], (0, 0), fx = scale, fy = scale)
images[i][ :,-2:] = 255
res = np.hstack(images)
cv_show('Compare', res)
img = cv2.imread('sys.jpg')
cv_show('sys', img)
2. dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
-
参数解释:
- src即为待处理图片
- ddepth:图像的深度,维数
- dx和dy分别表示水平和垂直方向,这个不要与resize里面的方法弄混
- ksize是Sobel算子的大小
-
注意:
计算得出负数结果或者超过了 K 比特上限时会进行截断:取为 0 或 (2^k - 1)
round = cv2.imread('round.png')
sobel_x = cv2.Sobel(round, cv2.CV_64F, 1, 0, ksize = 3)
#ksize是矩阵大小,扫描左右而不扫描上下,也就是x轴方向:dx = 1,dy = 0
cv_show('Sobel', sobel_x)
白到黑是正数,黑到白就是负数了,所有的负数都会被截断成0,所以要取绝对值
sobel_x1 = cv2.Sobel(round, cv2.CV_64F, 1, 0, ksize = 3)
sobel_x1 = cv2.convertScaleAbs(sobel_x1) #取绝对值
res = np.hstack([sobel_x, sobel_x1])
cv_show('Compare_x', res)
sobel_y = cv2.Sobel(round, cv2.CV_64F, dx=0, dy=1, ksize = 3)
sobel_y1 = cv2.convertScaleAbs(sobel_y)
res = np.hstack([sobel_y, sobel_y1])
cv_show('Compare_y',res)
效果对比:
winds([round, sobel_x, sobel_x1, sobel_y, sobel_y1], 0.7)
再分别求完,x和y的值之后,求和
sobelxy = cv2.addWeighted(sobel_x1, 0.5, sobel_y1, 0.5, 0)
cv_show('Compare',sobelxy)
最好不要直接计算,分别计算再求和
sobelxy = cv2.Sobel(round, cv2.CV_64F, 1, 1, ksize = 3)
cv_show('Direct_Compute', sobelxy)
效果对比:
winds([round, sobelxy, sobelxy_direct], 1.2)
3. 再走一遍流程
tg = cv2.imread('tgcf.png',cv2.IMREAD_GRAYSCALE) #不要忘本
cv_show('Gray', tg)
## 分别计算
tgx0 = cv2.Sobel(tg, cv2.CV_64F, 1, 0, ksize = 3)
tgx1 = cv2.convertScaleAbs(tgx0) #记住这个绝对值函数
tgy0 = cv2.Sobel(tg, cv2.CV_64F, 0, 1, ksize = 3)
tgy1 = cv2.convertScaleAbs(tgy0)
res = cv2.addWeighted(tgx1, 0.5, tgy1, 0.5, 0)
cv_show('compare',res)
## 整体计算:不好,轮廓重复
sobelxy = cv2.Sobel(tg, cv2.CV_64F, 1, 1, ksize = 3)
sobelxy1 = cv2.convertScaleAbs(sobelxy)
cv_show('Compare', sobelxy1)
- 效果对比:
winds([tg, indirect, direct],0.7)
二、Scharr算子
- 由运算方式可知,与Sobel极其类似,但是上下和左右的所占权值不一样了
- 对线条更加敏感,边缘信息更多
三、Laplacian算子
- 对噪音点比较敏感
- 边缘信息不明显
img = cv2.imread('tgcf.png', cv2.IMREAD_GRAYSCALE)
cv_show('Tg', img)
# kernel = np.ones((3, 3), np.uint8) #kernel滤波器大小
sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize = 3)
sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize = 3)
sobelxy = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)
## 在输出之前一定要再进行一次取绝对值操作
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show('Test', sobelxy)
Scharr_x = cv2.Scharr(img,cv2.CV_64F, 1, 0) #Scharr没有ksize属性,这是固定的吗?
Scharr_y = cv2.Scharr(img,cv2.CV_64F, 0, 1)
Scharrxy = cv2.addWeighted(Scharr_x, 0.5, Scharr_y, 0.5, 0)
Scharrxy = cv2.convertScaleAbs(Scharrxy)
cv_show('Test', Scharrxy)
La = cv2.Laplacian(img,cv2.CV_64F) #Laplacian没有ksize和dx、dy,神奇!因为拉普拉斯算子已经固定啦
La = cv2.convertScaleAbs(La)
cv_show('Test', La)
# res = np.hstack([sobelxy, Scharrxy, La])
# cv_show('Compare', res)
images = [img, sobelxy, Scharrxy, La]
titles = ['Origin', 'Sobel', 'Scharr', 'Laplacian']
for i in range(4):
plt.subplot(1, 4 , i+1)
plt.imshow(images[i], 'gray') #此处的后面参数不是弹窗名,而是图像类型
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
# for i in range(7):
# plt.subplot(2, 4 , i + 1), # 前面是行数,后面是列数,i+1的值应该在 [1 - 行*列] 之间
# plt.imshow(images[i], 'gray')
# plt.title(titles[i])
# plt.xticks([]), plt.yticks([])
# plt.show()
- 效果展示:
winds(images,0.5)