zoukankan      html  css  js  c++  java
  • opencv边缘检测sobel算子

    人眼怎么识别图像边缘?

    比如有一幅图,图里面有一条线,左边很亮,右边很暗,那人眼就很容易识别这条线作为边缘.也就是像素的灰度值快速变化的地方.

    sobel算子


    对于f(t),其导数f'(t)反映了每一处的变化趋势.在变化最快的位置其导数最大. sobel算子的思路就是模拟求一阶导数.

    sobel算子是一个离散差分算子.它计算图像像素点亮度值的近似梯度.
    图像是二维的,即沿着宽度/高度两个方向.
    我们使用两个卷积核对原图像进行处理:

    • 水平方向

      很好理解,原始像素灰度值-->(右边像素值-左边像素值),反映了水平方向的变化情况.

    • 垂直方向

    这样的话,我们就得到了两个新的矩阵,分别反映了每一点像素在水平方向上的亮度变化情况和在垂直方向上的亮度变换情况.

    综合考虑这两个方向的变化,我们使用

    反映某个像素的梯度变化情况.
    有时候为了简单起见,也直接用绝对值相加替代.

    opencv里可以使用了如下的卷积核,可以"放大像素的变化情况".

    可以参考这个函数Scharr

    opencv实现

    import cv2 as cv
    def test():
        src = cv.imread("/home/sc/disk/keepgoing/opencv_test/sidetest.jpeg")
        src = cv.GaussianBlur(src, (3, 3), 0)
        gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
        grad_x = cv.Sobel(gray, -1, 1, 0, ksize=3)
        grad_y = cv.Sobel(gray, -1, 0, 1, ksize=3)
        
        grad  = cv.addWeighted(grad_x, 0.5, grad_y, 0.5, 0)
        
        cv.imshow("origin",src)
        cv.imshow("grad",grad)
        cv.waitKey()
        
    test()
    

    首先是高斯模糊去噪.某种意义上说高斯模糊是和sobel相反的过程.高斯模糊平滑了某点像素与周边像素的差异.那为什么还要先高斯去噪呢?

    噪声就是像素的强度相对于真值有个突变。从时域上讲,通过高斯滤波能让一个像素的强度与周围的点相关,就减小了突变的影响;从频域上讲,突变引入了高频分量,而高斯滤波器可以滤除高频分量。

    高斯去噪是为了防止把噪点也检测为边缘.

    然后计算grad_x,grad_y.即对原图做水平方向/垂直方向的sobel卷积核卷积

        grad_x = cv.Sobel(gray, -1, 1, 0, ksize=3)
        grad_y = cv.Sobel(gray, -1, 0, 1, ksize=3)
    

    sobel api

    注意区分c++版本和python版本api. 在上述代码中,第二个参数-1代表我们希望输出的图像矩阵和原图有同样的depth,第3/4个参数分别代表在x/y方向做一阶差分.取值0或1.
    ksize必须为奇数.

    tips:通常我们使用( xorder = 1, yorder = 0, ksize = 3) or ( xorder = 0, yorder = 1, ksize = 3)来计算水平/垂直方向的一阶差分矩阵.ksize=3用的是标准sobel卷积核.如果ksize传入FILTER_SCHARR,则使用的是如下卷积核:

    最后将两个矩阵叠加,综合考虑水平和垂直方向的像素灰度值变化强度.得到边缘.

     grad  = cv.addWeighted(grad_x, 0.5, grad_y, 0.5, 0)
    

    完整代码处理效果如下

    ksize采用cv.FILTER_SCHARR效果如下:

        grad_x = cv.Sobel(gray, -1, 1, 0, ksize=cv.FILTER_SCHARR)
        grad_y = cv.Sobel(gray, -1, 0, 1, ksize=cv.FILTER_SCHARR)
    

  • 相关阅读:
    WinForm控件常用设置(转)
    EF Core性能优化(一)
    如何更改已经释放的(released)传输请求(TR)的描述
    在新窗口调用Tcode[ABAP4_CALL_TRANSACTION]
    [代码]如何取得表/结构的列名字(cl_abap_structdescr)
    [代码]创建.ZIP压缩文件[CL_ABAP_ZIP]
    如何在表维护视图(maintenance view)上添加自定义按钮(SM30)
    [代码]基于动态内表的ALV
    物料单位转换函数[MD_CONVERT_MATERIAL_UNIT]
    拆分全路径名得到路径+文件名[STPU1_EXTRACT_FILENAME]
  • 原文地址:https://www.cnblogs.com/sdu20112013/p/11608469.html
Copyright © 2011-2022 走看看