20. 图像的形态学操作-腐蚀、膨胀、开运算、闭运算、顶帽和黑帽、形态学梯度

1. 形态学操作

形态学操作其实就是改变物体的形状,比如腐蚀就是”变瘦”,膨胀就是”变胖”。

形态学操作一般作用于二值图,来连接相邻的元素或分离成独立的元素。

常见的形态学操作有:腐蚀、膨胀、开运算、闭运算、顶帽和黑帽、形态学梯度。

2. 图像的腐蚀和膨胀

2.1 腐蚀(erode)-cv2.erode()

腐蚀和膨胀是相反的操作,腐蚀是求局部最小值的操作。腐蚀操作会使图像中的高亮区逐渐减小。

20. 图像的形态学操作-腐蚀、膨胀、开运算、闭运算、顶帽和黑帽、形态学梯度_第1张图片20. 图像的形态学操作-腐蚀、膨胀、开运算、闭运算、顶帽和黑帽、形态学梯度_第2张图片20. 图像的形态学操作-腐蚀、膨胀、开运算、闭运算、顶帽和黑帽、形态学梯度_第3张图片

                          原图                                                                 腐蚀                                                        腐蚀后结果

操作过程和卷积类似,只看卷积核中为1的部分对应的原图中的值,当1所对应的区域有0时,这个中心位置就为0

从图中可以看出,0的位置变得更多,腐蚀操作的结果就是让暗的区域变大。

2.2 膨胀(dilate)-cv2.dilate()

膨胀就是求局部最大值的操作。从数学角度来说,就是将图像与核进行卷积,计算核B覆盖区域的像素点的最大值,并把这个最大值赋值给参考点指定的元素。这样就会使图像中的高亮区域逐渐增长。膨胀和腐蚀的操作正好相反,膨胀操作的结果就是让亮的区域变大。

2.3 腐蚀和膨胀的主要功能

(1)消除噪声

(2)分割出独立的图像元素,在图像中连接相邻的元素

(3)寻找图像中的极大值或者极小值区域

(4)求出图像的梯度

腐蚀和膨胀作用在二值图上。在实际的图像去噪中,通常是先腐蚀后膨胀,即所谓的开运算。其效果相比单一操作要好许多。

2.4 实现代码

import cv2 as cv
import numpy as np

"""
形态学操作是根据图像形状进行的简单操作。一般情况下对二值化图像进行的操作。
需要输入两个参数,一个是原始图像,第二个被称为结构化元素或 核,它是用来决定操作的性质的。
两个基本的形态学操作是腐蚀和膨胀。他们 的变体构成了开运算,闭运算,梯度等
"""

def erode_demo(image):
    
    print(image.shape)
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow("binary", binary)

    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    dst = cv.erode(binary, kernel=kernel)
    cv.imshow("erode_demo", dst)


def dilate_demo(image):
    
    print(image.shape)
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow("binary", binary)

    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    dst = cv.dilate(binary, kernel=kernel)
    cv.imshow("dilate_demo", dst)


def main():
    src = cv.imread("../images/01.jpg")
    # erode_demo(src)
    # dilate_demo(src)

    # 彩色图像腐蚀,膨胀
    img = cv.imread("../images/lena.jpg")
    cv.imshow("img", img)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    # dst = cv.dilate(img, kernel=kernel)
    dst = cv.erode(img, kernel=kernel)
    cv.imshow("dilate", dst)
    cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
    cv.destroyAllWindows()  # 关闭所有窗口


if __name__ == '__main__':
    main()

3. 开运算和闭运算

3.1 开运算

开运算是先腐蚀后膨胀。主要用于消除小物体,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积,同时抑制比结构元小的亮细节;也可以提取水平和垂直的线(比如,要检测垂直线,将cv2.getStructuringElement()中的核大小弄成(1, x) 这种形式)。(二值化后前景为白色,背景为黑色)

3.2 闭运算

闭运算是先膨胀后腐蚀。用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积,同时抑制比结构元小的暗细节。

3.3 函数实现-cv2.morphologyEx()

  • 参数:cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel)
  • 参数说明: 1. 二值化后的图像 2.形态学操作 3. 卷积核大小

3.4 代码

def open_demo(image):
    print(image.shape)
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    cv.imshow("binary", binary)
    """
    在前面的例子中我们使用Numpy构建了结构化元素,它是正方形的。
    但有时我们需要构建一个椭圆形 / 圆形的核。为了实现这种要求,提供了OpenCV
    函数cv2.getStructuringElement()。你只需要告诉他你需要的核的形状和大小。
    """
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    dst = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel=kernel)
    cv.imshow("open_demo", dst)

def close_demo(image):
    print(image.shape)
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow("binary", binary)

    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    dst = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel=kernel)
    cv.imshow("close_demo", dst)

4. 顶帽、黑帽和形态学梯度

4.1 顶帽-tophat

顶帽就是源图像和开运算得到的图像之间的差值图像。

4.2 黑帽-blackhat

黑帽就是闭运算得到的图像和源图像之间的差值图像。

我觉得黑帽和顶帽其实就是找出那些噪音点。

4.3 形态学梯度

                                                                           

20. 图像的形态学操作-腐蚀、膨胀、开运算、闭运算、顶帽和黑帽、形态学梯度_第4张图片

4.4 实现代码

def hat_binary_demo(image):                            # 对二值图像进行顶帽、黑帽操作
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))         # 获取结构元素
    # dst = cv.morphologyEx(binary, cv.MORPH_BLACKHAT, kernel=kernel)    # 黑帽操作
    dst = cv.morphologyEx(binary, cv.MORPH_TOPHAT, kernel=kernel)      # 顶帽操作
    cv.imshow("top_hat_demo", dst)


def hat_gray_demo(image):                            # 对灰度图像进行顶帽、黑帽操作
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))         # 获取结构元素
    # dst = cv.morphologyEx(gray, cv.MORPH_BLACKHAT, kernel=kernel)    # 黑帽操作
    dst = cv.morphologyEx(gray, cv.MORPH_TOPHAT, kernel=kernel)      # 顶帽操作
    cimg = np.array(gray.shape, np.uint8)
    cimg = 100
    dst = cv.add(dst, cimg)

    cv.imshow("top_hat_demo", dst)

def gradient_demo(image):
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    dm = cv.dilate(image, kernel)
    cm = cv.erode(image, kernel)
    dst1 = cv.subtract(image, cm)
    dst2 = cv.subtract(dm, image)
    cv.imshow("internal gradient", dst1)
    cv.imshow("external gradient", dst2)

 

你可能感兴趣的:(opencv基础知识,python,opencv,计算机视觉)