• OpenCV 09(形态学)


    一、形态学

    形态学指一系列处理图像 形状特征图像处理技术.

    • 形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。
    • 这些处理方法基本是对二进制图像进行处理, 即黑白图像
    • 卷积核决定着图像处理后的效果


    形态学常用基本操作有:

        - 膨胀和腐蚀
        - 开运算
        - 闭运算
        - 顶帽
        - 黑帽

    1.1 图像全局二值化 

    二值化: 将图像的每个像素变成两种值, 比如0,  255

    0和255:0是黑色,255是白色

    01: 0是黑色,1是白色

    - threshold(src, thresh, maxval, type[, dst])

      - src 最好是灰度图

      - thresh: 阈值

      - maxval: 最大值, 最大值不一定是255

      - type: 操作类型.常见操作类型如下:

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('./dog.jpeg')
    4. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    5. # 返回两个结果, 一个是阈值, 另一个是处理后的图片
    6. ret, dst = cv2.threshold(gray, 80, 255, cv2.THRESH_BINARY)
    7. cv2.imshow('dog', np.hstack((gray, dst)))
    8. cv2.waitKey(0)
    9. cv2.destroyAllWindows()

    1.2 自适应阈值二值化

    在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。当时这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。

    adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)**
     这种方法需要我们指定六个参数,返回值只有一个。

     • **Adaptive Method**- 指定计算阈值的方法。
     – **cv2.ADPTIVE_THRESH_MEAN_C**:阈值取自相邻区域的平均值
     – **cv2.ADPTIVE_THRESH_GAUSSIAN_C**:阈值取值相邻区域的加权和,权重为一个高斯窗口。 
     • **Block Size** - 邻域大小(用来计算阈值的区域大小)。
     • **C** - 这就是是一个常数,阈值就等于的平均值或者加权平均值减去这个常数。

    1. # 因为光线问题, 全局二值化导致有部分地方看不见了.这时就需要自适应阈值二值化了.
    2. import cv2
    3. import numpy as np
    4. img = cv2.imread('./math.png')
    5. cv2.namedWindow('img', cv2.WINDOW_NORMAL)
    6. cv2.resizeWindow('img', 1920, 1080)
    7. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    8. # 自适应阈值二值化只返回一个值, 即二值化后的结果
    9. dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 3, 0)
    10. cv2.imshow('img', np.hstack((gray, dst)))
    11. cv2.waitKey(0)
    12. cv2.destroyAllWindows()

     

    1.3  腐蚀操作

     腐蚀操作也是用卷积核扫描图像, 只不过腐蚀操作的卷积一般都是1, 如果卷积核内所有像素点都是白色, 那么锚点即为白色. 

    - 大部分时候腐蚀操作使用的都是全为1的卷积核.

    - erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

      - iterations是腐蚀操作的迭代次数, 次数越多, 腐蚀操作执行的次数越多, 腐蚀效果越明显

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('./msb.png')
    4. kernel = np.ones((3, 3), np.uint8)
    5. dst = cv2.erode(img, kernel, iterations=2)
    6. cv2.imshow('img', np.hstack((img, dst)))
    7. cv2.waitKey(0)
    8. cv2.destroyAllWindows()

     

     

    1.4 获取形态学卷积核

    - opencv提供了获取卷积核的api.不需要我们手工创建卷积核.
    - getStructuringElement(shape, ksize[, anchor])

      - shape是指卷积核的形状, 注意不是指长宽, 是指卷积核中1形成的形状.
        - MORPH_RECT 卷积核中的1是矩形, 常用.
        - MORPH_ELLIPSE 椭圆
        - MORPH_CROSS 十字

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('./j.png')
    4. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    5. dst = cv2.erode(img, kernel, iterations=2)
    6. cv2.imshow('img', np.hstack((img, dst)))
    7. cv2.waitKey(0)
    8. cv2.destroyAllWindows()

    1.5 膨胀操作

    膨胀是腐蚀的相反操作, 基本原理是只要保证卷积核的锚点是非0值, 周边无论是0还是非0值, 都变成非0值.

    - dilate(img, kernel, iterations=1)

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('./j.png')
    4. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    5. dst = cv2.dilate(img, kernel, iterations=2)
    6. cv2.imshow('img', np.hstack((img, dst)))
    7. cv2.waitKey(0)
    8. cv2.destroyAllWindows()

     

    1.6 开运算

     开运算和闭运算都是腐蚀和膨胀的基本应用. 

    - 开运算 = 腐蚀 + 膨胀
    - morphologyEx(img, MORPH_OPEN, kernel)

      - MORPH_OPEN 表示形态学的开运算
      - kernel 如果噪点比较多, 会选择大一点的kernel, 如果噪点比较小, 可以选择小点的kernel

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('./dotj.png')
    4. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    5. # 腐蚀
    6. # dst = cv2.erode(img, kernel, iterations=2)
    7. # # 膨胀
    8. # dst = cv2.dilate(dst, kernel, iterations=2)
    9. # 直接调用opencv提供的开运算api
    10. dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=2)
    11. cv2.imshow('img', np.hstack((img, dst)))
    12. cv2.waitKey(0)
    13. cv2.destroyAllWindows()

    1.7 闭运算

    - 闭运算 = 膨胀 + 腐蚀

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('./dotinj.png')
    4. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    5. dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=2)
    6. cv2.imshow('img', np.hstack((img, dst)))
    7. cv2.waitKey(0)
    8. cv2.destroyAllWindows()

    1.8 形态学梯度

    - 梯度 = 原图  -  腐蚀
    - 腐蚀之后原图边缘变小了, 原图 - 腐蚀 就可以得到腐蚀掉的部分, 即边缘.

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('./j.png')
    4. # 注意调节kernel大小以获得更清晰的边缘
    5. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    6. dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel, iterations=1)
    7. cv2.imshow('img', np.hstack((img, dst)))
    8. cv2.waitKey(0)
    9. cv2.destroyAllWindows()

    1.9 顶帽运算

    - 顶帽 = 原图 - 开运算
    - 开运算的效果是去除图像外的噪点, 原图 - 开运算就得到了去掉的噪点.

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('./tophat.png')
    4. # 注意调整kernel以保留小图形
    5. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (19, 19))
    6. dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel, iterations=1)
    7. cv2.imshow('img', np.hstack((img, dst)))
    8. cv2.waitKey(0)
    9. cv2.destroyAllWindows()

     

    1.10 黑帽操作

    - 黑帽 = 原图 - 闭运算
    - 闭运算可以将图形内部的噪点去掉, 那么原图 - 闭运算的结果就是图形内部的噪点.

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('./dotinj.png')
    4. # 注意调节kernel大小以获得更清晰的边缘
    5. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
    6. dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel, iterations=1)
    7. cv2.imshow('img', np.hstack((img, dst)))
    8. cv2.waitKey(0)
    9. cv2.destroyAllWindows()

  • 相关阅读:
    jenkins安装
    OpenCV_CUDA_VS编译安装
    JavaScript-DOM
    linux ubuntu中配置nfs共享存储服务
    [LeetCode周赛复盘] 第 91 场双周赛补20221015
    指令的类型
    初识linux(1)
    多角度的模板匹配
    SSM+医保业财一体化管理系统 毕业设计-附源码151023
    基于Dijkstra、A*和动态规划的移动机器人路径规划(Matlab代码实现)
  • 原文地址:https://blog.csdn.net/peng_258/article/details/132774908