在学习B站教学视频的时候记录的笔记
OpenCV+TensorFlow】迪哥带你做项目!深度学习+计算机视觉实战 纯实战教学 技能点加满
如何理解梯度,以圆形pie.png为例,如果以圆形内部一点为例。画意竖线,很明显竖线两边都是白色没有变化也就没有梯度。如图:
那么梯度会出现在哪呢?很显然是边界附近,如图:
红线左边是黑色,右边是白色,梯度变化肯定是最大的。那么随便点一个点,如果找到此点的梯度呢?其实这就是边缘检测了。
如果计算目标点左边是什么,右边又是什么呢?参考之前的形态学操作,都是创建一个特点的矩阵然后与目标点进行运算。
上面的公式就是计算过程Gx水平方向的梯度计算核矩阵,Gy是竖直方向的梯度计算核矩阵,A为目标点。
实际操作可以调用cv2.Sobel(src,)ddepth,dx,dy,ksize)
ddepth 图像深度(一般为-1表示输入深度和输出深度是一样的)
dx和dy分别表示水平和竖直方向
ksize是Sobel算子的大小
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
cv2.imshow('sobelx',sobelx)
cv2.waitKey(0)
cv2.destroyAllWindows()
ddepth = cv2.CV_64F 表示支持负数。dx=1,dy=0表示计算是水平方向。ksize=3为Sobel算子大小为3.
从图像来看,只有边界有梯度。但为什么左侧边界有,右侧却没有呢,原因是计算过程为右侧-左侧。
圆形左侧边界的左侧是黑色0,右侧是白色255,计算结果255-0=255。同理圆形右侧计算是0-255=0(小于0归零)。如果需要圆形右侧也显示可以把计算过程的归零改成取绝对值。代码如下:
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
注意:从结果来看,sobelx本身是带负数的,只是显示的时候会进行归零操作。
再计算竖直方向,代码如下:
#竖直方向
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
cv2.imshow('sobely',sobely)
cv2.waitKey(0)
cv2.destroyAllWindows()
分别计算x和y,再修改
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv2.imshow('sobelxy',sobelxy)
cv2.waitKey(0)
cv2.destroyAllWindows()
同时计算x和y
sobelxy = cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv2.imshow('sobelxy',sobelxy)
cv2.waitKey(0)
cv2.destroyAllWindows()
从效果来看,直接计算不如分别计算再求和效果好。
再次使用lena进行测试
img = cv2.imread('H:\Peronal\lena.jpg')
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv2.imshow('sobelxy',sobelxy)
cv2.waitKey(0)
cv2.destroyAllWindows()
可以看出来,图像的轮廓已经被标识出来了。
再测试下直接计算的效果。
sobelxy = cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv2.imshow('sobelxy',sobelxy)
cv2.waitKey(0)
cv2.destroyAllWindows()
可以看出来,直接计算不如分别计算再求和。
整体计算方式与sobel一致,只是算子数值不同。
laplacian算子涉及到二次导数,因此对噪音点比较敏感,使用的时候效果不是很好。需要与其他处理搭配使用。
三种算子对比代码如下:
img = cv2.imread('H:\Peronal\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))
cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()