Opencv

您所在的位置:网站首页 图像的梯度图像是什么图形 Opencv

Opencv

2024-07-09 02:13| 来源: 网络整理| 查看: 265

本篇记录学习图像梯度的计算。查找图像渐变,边缘等将学习以下函数:cv2.Sobel(),cv2.Scharr(),cv2.Laplacian()等 原理:

梯度简单来说就是求导。OpenCV 提供了三种不同的梯度滤波器,或者说高通滤波器: Sobel,Scharr 和 Laplacian。 Sobel, Scharr 其实就是求一阶或二阶导数。 Scharr 是对 Sobel(使用小的卷积核求解求解梯度角度时)的优化。 Laplacian 是求二阶导数。

Sobel 算子和 Scharr 算子:

Sobel 算子是高斯平滑与微分操作的结合体,所以它的抗噪声能力很好。我们可以设定求导的方向( xorder 或 yorder)。

      G_{X}=\begin{bmatrix} -1 &0 &+1 \\ -2&0 &+2\\ -1&0 &+1 \end{bmatrix}\ast A     G_{Y}=\begin{bmatrix} -1& -2 &-1 \\ 0&0 & 0\\ +1& +2 &+1 \end{bmatrix}\ast A       

水平梯度=右-左;垂直梯度=下-上。我们以下图为例进行展示:

在opencv3中,看老师视频会讲到要取绝对值运算,即要用到cv.convertScaleAbs()函数,因为水平梯度=右-左,如图

因此输出应该是只有左半部分一个半圆弧,右边会被截断。但是我在使用opencv4进行计算的时候,发现左右都有一个圆弧,(猜测原因是opencv4进行了改进)代码及结果如下:

垂直梯度运算同样opencv3和人 opencv4运算结果不一样。

但是,如果图像深度和原图像保持一致,即cv.Sobel(src, -1,1, 0, ksize=3)函数的第二个参数填入 -1,结果就会出现截断情况,如图所示:

在进行梯度运算是水平和垂直要分别进行计算,最后在进行合成,用公式:G=\sqrt{G_{X}^{2}+G_{Y}^{2}},不建议进行一块运算,原因如下图:

整体运算:

分开运算-->再合成:

# -*- coding:utf-8 -*- # Author : MMagicLoren # @Email : [email protected] # @Time : 2019/10/13 15:59 # @File : 图像梯度计算.py # @Project : Workspace import cv2 as cv def sobel_demo(image): grad_x = cv.Sobel(src, cv.CV_64F, 1, 0, ksize=3) gradx = cv.convertScaleAbs(grad_x) grad_y = cv.Sobel(src, cv.CV_64F, 0, 1, ksize=3) grady = cv.convertScaleAbs(grad_y) gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0) cv.imshow("grad_x", grad_x) # 将src图片放入该创建的窗口中 cv.imshow("grad_y", grad_y) # 将src图片放入该创建的窗口中 cv.imshow("gradxy", gradxy) # 将src图片放入该创建的窗口中 if __name__ == '__main__': src = cv.imread("F:/Pycharm/opencv_exercises-master/images/circular.png") # 读入图片放进src中 cv.namedWindow("input image", cv.WINDOW_AUTOSIZE) # 创建窗口, 窗口尺寸自动调整 cv.imshow("input image", src) sobel_demo(src) cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口 cv.destroyAllWindows()

还可以设定使用的卷积核的大小( ksize)。如果 ksize=-1,会使用 3x3 的 Scharr 滤波器,它的的效果要比 3x3 的 Sobel 滤波器好(而且速度相同,所以在使用 3x3 滤波器时应该尽量使用 Scharr 滤波器)。 3x3 的 Scharr 滤波器卷积核如下:G_{X}=\begin{bmatrix} -3 & 0 &3 \\ -10 & 0 &10 \\ -3&0 & 3 \end{bmatrix}        G_{Y}=\begin{bmatrix} -3 & -10&-3 \\ 0 & 0 &0 \\ 3&10 & 3 \end{bmatrix}

# -*- coding:utf-8 -*- # Author : MMagicLoren # @Email : [email protected] # @Time : 2019/10/13 15:59 # @File : 图像梯度计算.py # @Project : Workspace import cv2 as cv def scharr_demo(image): scharr_x = cv.Scharr(src, cv.CV_64F, 1, 0) scharrx = cv.convertScaleAbs(scharr_x) scharr_y = cv.Scharr(src, cv.CV_64F, 0, 1) scharry = cv.convertScaleAbs(scharr_y) scharrxy = cv.addWeighted(scharrx, 0.5, scharry, 0.5, 0) # cv.imshow("grad_x", grad_x) # 将src图片放入该创建的窗口中 # cv.imshow("grad_y", grad_y) # 将src图片放入该创建的窗口中 cv.imshow("gradxy", scharrxy) # 将src图片放入该创建的窗口中 if __name__ == '__main__': src = cv.imread("F:/Pycharm/opencv_exercises-master/images/CrystalLiu1.jpg") # 读入图片放进src中 cv.namedWindow("input image", cv.WINDOW_AUTOSIZE) # 创建窗口, 窗口尺寸自动调整 cv.imshow("input image", src) # sobel_demo(src) scharr_demo(src) cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口 cv.destroyAllWindows()

可见scharr算子对线条更加敏感,对图像描述的更细致。

laplacian算子:

laplacian算子在实际应用中很少单独用到,都是结合一些其他的函数共同使用。

G=\begin{bmatrix} 0 &1 &0 \\ 1& -4 &1\\ 0& 1 &0 \end{bmatrix}

# -*- coding:utf-8 -*- # Author : MMagicLoren # @Email : [email protected] # @Time : 2019/10/13 15:59 # @File : 图像梯度计算.py # @Project : Workspace import cv2 as cv def laplacian_demo(image): laplacian = cv.Laplacian(src, cv.CV_64F) laplacian = cv.convertScaleAbs(laplacian) cv.imshow("laplacian", laplacian) # 将src图片放入该创建的窗口中 if __name__ == '__main__': src = cv.imread("F:/Pycharm/opencv_exercises-master/images/CrystalLiu1.jpg") # 读入图片放进src中 cv.namedWindow("input image", cv.WINDOW_AUTOSIZE) # 创建窗口, 窗口尺寸自动调整 cv.imshow("input image", src) # sobel_demo(src) # scharr_demo(src) laplacian_demo(src) cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口 cv.destroyAllWindows()

 

我们也可以自己定义一个拉普拉斯算子进行计算,看看效果如何。定义算子为:

G=\begin{bmatrix} 1 &1 &1 \\ 1& -8 &1 \\ 1& 1 & 1 \end{bmatrix}

# -*- coding:utf-8 -*- # Author : MMagicLoren # @Email : [email protected] # @Time : 2019/10/13 15:59 # @File : 图像梯度计算.py # @Project : Workspace import cv2 as cv import numpy as np def laplacian_demo(image): # laplacian = cv.Laplacian(src, cv.CV_64F) kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1, ]]) dst = cv.filter2D(src, cv.CV_64F, kernel=kernel) laplacian = cv.convertScaleAbs(dst) cv.imshow("laplacian", laplacian) # 将src图片放入该创建的窗口中 if __name__ == '__main__': src = cv.imread("F:/Pycharm/opencv_exercises-master/images/CrystalLiu1.jpg") # 读入图片放进src中 cv.namedWindow("input image", cv.WINDOW_AUTOSIZE) # 创建窗口, 窗口尺寸自动调整 cv.imshow("input image", src) # sobel_demo(src) # scharr_demo(src) laplacian_demo(src) cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口 cv.destroyAllWindows()

可见自定义的算子也是对原始算子的一个增强。

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3