opencv-python图像处理 —-图像梯度、Sobel算子

一、图像的梯度处理
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算子:

def f_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操作,因此这个时候就要把负数改变为正数。

def f_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算子计算,然后将得到的两幅梯度图再进行相加,就可以得到完整的轮廓图像。
代码:

def f_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...)

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>