美文网首页
opencv-python sobel边缘检测结果图数据类型问题

opencv-python sobel边缘检测结果图数据类型问题

作者: 1037号森林里一段干木头 | 来源:发表于2021-04-07 16:06 被阅读0次

    简介:本篇文章主要关注sobel边缘检测后的图像数据类型与后续计算和显示的关系问题。
    sobel参考链接

    1.代码

    import os
    import cv2 as cv
    import numpy as np
    import matplotlib.pyplot as plt
    
    def showImage(img, winName="image", waitKey=1, destroyMode=0):
        if img is None:
            print("in showImage: the input image is None!\n")
            return -1
        cv.namedWindow(winName, 0)
        cv.imshow(winName, img)
        cv.waitKey(waitKey)
        if destroyMode != 0:
            cv.destroyWindow(winName)
    
    
    def sobel_x(img,ksize=3):
        if img is None:
            return img
        #注:ddepth参数如果用CV_8U的话,负数的梯度会被直接置零,丢失从wight-to-black的梯度
        return cv.Sobel(img,cv.CV_64F,1,0,ksize=ksize)
    
    
    def sobel_y(img,ksize=3):
        if img is None:
            return img
        # 注:ddepth参数如果用CV_8U的话,负数的梯度会被直接置零,丢失从wight-to-black的梯度
        return cv.Sobel(img,cv.CV_64F,0,1,ksize=ksize)
    
    
    def sobel_xy(img,ksize=3,gamma=0):
        if img is None:
            return img
        # 注:ddepth参数如果用CV_8U的话,负数的梯度会被直接置零,丢失从wight-to-black的梯度
        sobel_x = cv.Sobel(img,cv.CV_64F,1,0,ksize=ksize)
        sobel_y = cv.Sobel(img,cv.CV_64F,0,1,ksize=ksize)
        sobel_xy = cv.addWeighted(sobel_x,0.5,sobel_y,0.5,gamma)
        return sobel_xy
    
    if __name__ == "__main__":
        imagePath = "G:\\imageData\\del.png"
        img = readImage(imagePath)
        showImage(img,winName="image",waitKey=1)
    
        #sobel_x
        sobel_x = sobel_x(img,3)
        #sobel_x的数据类型是double类型的,转为uint8时会被截断,显示时出现很多白班
        #
        showImage(sobel_x,"sobel_x",0)
    
        #sobel_y
        sobel_y = sobel_y(img,3)
        showImage(sobel_y,"sobel_y",0)
    
        #sobel_xy
        sobel_xy = sobel_xy(img,3)
        showImage(sobel_xy,"sobel_xy",0)
    
    

    2.数据类型实验

    • 在opencv-python中函数原型如下
      dst = cv.Sobel( src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]] )
      其中第二个参数ddepth表示的是结果图用多少位深度保存结果,因为opencv中sobel计算的结果从暗到亮是正数,从亮到暗是负数,如果用CV_8U格式(即8位无符号整型)则所有负数都会被置零,也就是从亮到暗的梯度会丢失。

    • 把上面代码中所有cv.sobel(img,cv.CV_64F,.....)的参数cv.CV_64F换为cv.CV_8U后,从图像上看就如下图:


      image.png

      这里的结果显示,从左到右,从上到下,只有从暗到亮的地方的梯度(正数)被保留下来了,从亮到暗的梯度(负数)都损失了。所以sobel算子做边缘提取时还是只能用CV_64F、CV_32F等更多位数的格式保存结果图。

    3.显示CV_64F格式的图片

    CV_64F的数据格式在显示时会有问题,对返回的CV_64F格式的结果图直接用cv.imshow显示如下

    image.png
    这里的结果表明opencv在显示的时候,CV_64F格式的图片超过255的都被截断了,负数都置为零,看起来就像是二值化的。为了正常显示,需要用cv.convertScaleAbs()函数把图的格式转换一下。
    cv.convertScaleAbs()函数包含三个操作:
    • 取绝对值
    • 尺度缩放
    • 映射到8bits 空间


      image.png

      修改1.中代码

    if __name__ == "__main__":
        imagePath = "G:\\imageData\\del.png"
        img = readImage(imagePath)
        showImage(img,winName="image",waitKey=1)
    
        #sobel_x
        sobel_x = sobel_x(img,3)
        #sobel_x的数据类型是double类型的,转为uint8时会被截断,显示时出现很多白班
        #负数部分不会显示,用cv.convertScaleAbs转换
        sobel_x = cv.convertScaleAbs(sobel_x)
        showImage(sobel_x,"sobel_x",0)
    
        #sobel_y
        sobel_y = sobel_y(img,3)
        sobel_y = cv.convertScaleAbs(sobel_y)
        showImage(sobel_y,"sobel_y",0)
    
        #sobel_xy
        sobel_xy = sobel_xy(img,3)
        sobel_xy = cv.convertScaleAbs(sobel_xy)
        showImage(sobel_xy,"sobel_xy",0)
    

    结果


    image.png

    相关文章

      网友评论

          本文标题:opencv-python sobel边缘检测结果图数据类型问题

          本文链接:https://www.haomeiwen.com/subject/zelukltx.html