1、主要参考
(1)官网:https://docs.opencv.org/
(2)https://www.cnblogs.com/aiguona/p/9394263.html
(3)比较好:https://blog.csdn.net/weixin_45939019/article/details/104410567
2、主要函数
(1)主要函数,python
cv.Sobel( src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]] ) -> dst
C++中的定义
C++: void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, intborderType=BORDER_DEFAULT )
(2)官网定义截图
(3)主要参数
- src – 输入图像。
- dst – 输出图像,与输入图像同样大小,拥有同样个数的通道。
- ddepth –
- 输出图片深度;下面是输入图像支持深度和输出图像支持深度的关系:
- src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F
- src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F
- src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F
- src.depth() = CV_64F, ddepth = -1/CV_64F
- 当 ddepth为-1时, 输出图像将和输入图像有相同的深度。输入8位图像则会截取顶端的导数。
- xorder – x方向导数运算参数。
- yorder – y方向导数运算参数。
- ksize – Sobel内核的大小,可以是:1,3,5,7。
- scale – 可选的缩放导数的比例常数。
- delta – 可选的增量常数被叠加到导数中。
- borderType – 用于判断图像边界的模式。
3、原理
sobel算子的原理是根据边缘形成的不同原因,对图像的各像素点进行求微分或者二阶微分,从而可以检测出变化明显的点。边缘检测大大减少了源图像的数据量,剔除了与目标不相干的信息,保留了图像重要的结构属性。边缘检测算子利用图像边缘的突变性质来检测边缘的。
主要摘自官网https://docs.opencv.org/和https://blog.csdn.net/weixin_45939019/article/details/104410567
使用sobel算子计算图像导数。sobel算子是一种计算不同方向上梯度的工具。原理是使用卷积核对图像进行处理。
(1)水平方向的算子。如果想计算x方向梯度,我们就需要这样的一个卷积核
以卷积核的中心为中心,将卷积核与图像上像素值一一对应,卷积核上的数字相当于系数。利用如下公式即可计算出卷积核中心的x方向梯度。
(2)垂直方向的算子。如果想要计算y方向的梯度,卷积核应该是这样的,公式也是同理。
我们求得了某一像素x方向和y方向的梯度,那么该像素的梯度容易得出:
但是这个公式比较难算,所以我们也可直接把这个公式化作(PS:不一定是下面操作,不一定推荐):
4、代码测试
3.1正常测试
(1)X和Y各自倒数,最后相加看看
import cv2 as cv
# import numpy as np
if __name__ == '__main__':
src = cv.imread("d:/lenargb.bmp")
src = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)
h, w = src.shape[:2]
x_grad = cv.Sobel(src, cv.CV_32F, 1, 0)
y_grad = cv.Sobel(src, cv.CV_32F, 0, 1)
x_grad = cv.convertScaleAbs(x_grad)
cv.imshow("Xgradient", x_grad)
y_grad = cv.convertScaleAbs(y_grad)
cv.imshow("Ygradient", y_grad)
dst = cv.add(x_grad, y_grad, dtype=cv.CV_16S)
dst = cv.convertScaleAbs(dst)
cv.imshow("gradient", dst)
cv.waitKey(0)
cv.destroyAllWindows()
(2)原图
(3)X方向的导数,因为导数有正负,这里偷懒取了绝对值显示
(4)Y方向的导数,因为导数有正负,这里偷懒取了绝对值显示
(5)X和Y叠加后的结果
3.2非正常参数设置测试
(1)将X和Y的参数同时设置为1
xy_grad = cv.Sobel(src, cv.CV_32F, 1, 1)
(2)完整测试代码
import cv2 as cv
# import numpy as np
if __name__ == '__main__':
src = cv.imread("d:/lenargb.bmp")
src = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)
h, w = src.shape[:2]
x_grad = cv.Sobel(src, cv.CV_32F, 1, 0)
y_grad = cv.Sobel(src, cv.CV_32F, 0, 1)
x_grad = cv.convertScaleAbs(x_grad)
cv.imshow("Xgradient", x_grad)
y_grad = cv.convertScaleAbs(y_grad)
cv.imshow("Ygradient", y_grad)
dst = cv.add(x_grad, y_grad, dtype=cv.CV_16S)
dst = cv.convertScaleAbs(dst)
cv.imshow("gradient", dst)
xy_grad = cv.Sobel(src, cv.CV_32F, 1, 1)
xy_grad = cv.convertScaleAbs(xy_grad)
cv.imshow("XYgradient", xy_grad)
cv.waitKey(0)
cv.destroyAllWindows()
(3)测试结果和XY分布计算后累加的比起来差好多,不行!