四时宝库

程序员的知识宝库

opencv(4)--边缘检测Sobel(opencv边缘检测 让轮廓闭合)

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方向导数运算参数。
  • ksizeSobel内核的大小,可以是: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分布计算后累加的比起来差好多,不行!

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接