一、图像的梯度处理
1、Sobel算子
梯度可以按照x方向或者y方向求梯度,其实就是在看像素点的差异变化情况,比如黑白物体的交界,其像素值变化差异是非常大的。
求梯度计算使用的函数就叫做Sobel算子,可以分为水平梯度与竖直梯度。
简单点说,Sobel算子是一种特殊的卷积核,可以用于图像的边缘检测。自定义一个水平及竖直方向的sobel算子:
# 水平sobel算子
Sobel_x = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])# 竖直方向的sobel算子
Sobel_y = np.array([[-1,-2,-1],[0,0,0],[1,2,1]])
可以看到使用sobel算子进行卷积计算的时候,就是将中间像素点的一圈像素进行相应的加减操作。
如果是位于同一颜色内的像素点进行卷积操作,那么运算结果就会等于0,因为左右值都是相同的。
opencv里的函数:
dst = cv.Sobel(src, ddepth, dx, dy, ksize)
ddepth:表示传入图像的深度(颜色通道个数)
src:传入图像
dx和dy分别表示水平方向和竖直方向
ksize:表示sobel算子的大小
cv.CV_64F:表示将运算结果使用更大的存储方式存储,因为可能出现负数
代码实现sobel算子:
deff_sobel():
img = cv.imread("car_red.jpg", cv.IMREAD_GRAYSCALE)# 水平sobel算子
Sobel_x = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])# 竖直方向的sobel算子
Sobel_y = np.array([[-1,0,-2],[0,0,0],[1,0,2]])
dst = cv.Sobel(img, cv.CV_64F, dx=1, dy=0, ksize=3)
cv.imshow("zero", dst)
cv.waitKey(0)
cv.destroyAllWindows()
运行结果如图:
结果并不理想,这是由于右值减去左值的结果并不是一直为正,有的时候就负数,opencv会自动把负数进行截断取0操作,因此这个时候就要把负数改变为正数。
deff_sobel():
img = cv.imread("car_red.jpg", cv.IMREAD_GRAYSCALE)# 水平sobel算子
Sobel_x = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])# 竖直方向的sobel算子
Sobel_y = np.array([[-1,0,-2],[0,0,0],[1,0,2]])
dst = cv.Sobel(img, cv.CV_64F,1,0, ksize=3)# 这条代码将正负取绝对值
dst = cv.convertScaleAbs(dst)
cv.imshow("zero", dst)
cv.waitKey(0)
cv.destroyAllWindows()
边界比较清晰:
同时,使用水平或者竖直方向得到的结果也是有差异的。所以可以对水平方向和竖直方向都进行Sobel算子计算,然后将得到的两幅梯度图再进行相加,就可以得到完整的轮廓图像。
代码:
deff_sobel():
img = cv.imread("car_red.jpg", cv.IMREAD_GRAYSCALE)# 水平sobel算子
Sobel_x = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])# 竖直方向的sobel算子
Sobel_y = np.array([[-1,0,-2],[0,0,0],[1,0,2]])
dst_x = cv.Sobel(img, cv.CV_64F,1,0, ksize=3)
dst_y = cv.Sobel(img, cv.CV_64F,0,1, ksize=3)
dst_y = cv.convertScaleAbs(dst_y)
dst_x = cv.convertScaleAbs(dst_x)
dst = cv.addWeighted(dst_x,0.5, dst_y,0.5,0)
cv.imshow("zero", dst)
cv.waitKey(0)
cv.destroyAllWindows()
结果:
Scharr算子:与Sobel算子相比,数值更大,对结果的差异更加敏感。
laplacian算子:对噪音点更敏感
# 水平Scharr算子
Scharr = np.array([[-3,0,3],[-10,0,10],[-3,0,3]])# laplacian算子
laplacian = np.array([[0,1,0],[1,-4,1],[0,1,0]])
函数体:
# 参数与Sobel算子类似
cv2.Scharr(src, dx, dy....)# 拉普拉斯算子不区分x, y方向。因此没有dx, dy参数
cv2.Laplacian(src...)
版权归原作者 NewSuNess 所有, 如有侵权,请联系我们删除。