图片的腐蚀以及膨胀

腐蚀:

  图像的腐蚀和膨胀都是相对于像素值高(白色方向)说的,腐蚀简单的说就是白色”被腐蚀“了,也就是像素值低(黑色方向)的变多,白色变少。

  腐蚀的原理是利用一个内核对图像进行卷积(扫描),内核中有一个点被定义为锚点,然后提取内核覆盖区域的像素最小值(黑色方向)来替换锚点位置的像素值,所以扫描过后黑色变多。

Mat img = imread("img.jpg");

    imshow("src", img);

    Mat erodeElement = getStructuringElement(MORPH_RECT, Size(10, 10)); // 获得内核

    erode(img, img, erodeElement); // 腐蚀函数

    imshow("erode", img);
    
    waitKey(0);

膨胀:

​ 和腐蚀一样,也是相对于白色来说,膨胀就是像素值高的(白色方向)变多了(膨胀了),和腐蚀相反,膨胀是提取内核区域的最大值(白色方向)来替换锚点位置的像素值。

Mat img = imread("img.jpg");

    imshow("src", img);

    Mat dilateElement = getStructuringElement(MORPH_RECT, Size(10, 10)); // 获得内核

    dilate(img, img, dilateElement); // 膨胀函数

    imshow("dilate", img);
import cv2 as cv
import numpy as np
 
def erode(img):
    gray=cv.cvtColor(img,cv.COLOR_RGB2GRAY)
    ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    #获得结构元素
    #第一个参数:结构元素形状,这里是矩形
    #第二个参数:结构元素大小
    kernel=cv.getStructuringElement(cv.MORPH_RECT,(5,5))
    #执行腐蚀
    dst=cv.erode(binary,kernel)
    cv.imshow("erode",dst)
 
def dilate(img):
    gray=cv.cvtColor(img,cv.COLOR_RGB2GRAY)
    ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    #获得结构元素
    #第一个参数:结构元素形状,这里是矩形
    #第二个参数:结构元素大小
    kernel=cv.getStructuringElement(cv.MORPH_RECT,(5,5))
    #执行膨胀
    dst=cv.dilate(binary,kernel)
    cv.imshow("dilate",dst)
 
 
src=cv.imread('num.jpg')
cv.imshow('def',src)
erode(src)
dilate(src)
cv.waitKey(0)
cv.destroyAllWindows()

目标

  • 了解形态学操作的概念
  • 学习膨胀、腐蚀、开运算和闭运算等形态学操作
  • OpenCV函数:cv2.erode(), cv2.dilate(), cv2.morphologyEx()

教程

啥叫形态学操作

形态学操作其实就是改变物体的形状,比如腐蚀就是”变瘦”,膨胀就是”变胖”,看下图就明白了:

img

形态学操作一般作用于二值化图,来连接相邻的元素或分离成独立的元素。腐蚀和膨胀是针对图片中的白色部分!

腐蚀

腐蚀的效果是把图片”变瘦”,其原理是在原图的小区域内取局部最小值。因为是二值化图,只有0和255,所以小区域内有一个是0该像素点就为0:

img

这样原图中边缘地方就会变成0,达到了瘦身目的(小胖福利(●ˇ∀ˇ●))

OpenCV中用cv2.erode()函数进行腐蚀,只需要指定核的大小就行:

img = cv2.imread('j.bmp', 0)
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.erode(img, kernel)  # 腐蚀

这个核也叫结构元素,因为形态学操作其实也是应用卷积来实现的。结构元素可以是矩形/椭圆/十字形,可以用cv2.getStructuringElement()来生成不同形状的结构元素,比如:

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 矩形结构
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # 椭圆结构
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))  # 十字形结构

img

膨胀

膨胀与腐蚀相反,取的是局部最大值,效果是把图片”变胖”:

dilation = cv2.dilate(img, kernel)  # 膨胀

开/闭运算

先腐蚀后膨胀叫开运算(因为先腐蚀会分开物体,这样容易记住),其作用是:分离物体,消除小区域。这类形态学操作用cv2.morphologyEx()函数实现:

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 定义结构元素

img = cv2.imread('j_noise_out.bmp', 0)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)  # 开运算

闭运算则相反:先膨胀后腐蚀(先膨胀会使白色的部分扩张,以至于消除/”闭合”物体里面的小黑洞,所以叫闭运算)

img = cv2.imread('j_noise_in.bmp', 0)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)  # 闭运算

img

经验之谈:很多人对开闭运算的作用不是很清楚(好吧,其实是比较容易混◑﹏◐),但看上图↑,不用怕:如果我们的目标物体外面有很多无关的小区域,就用开运算去除掉;如果物体内部有很多小黑洞,就用闭运算填充掉。

接下来的3种形态学操作并不常用,大家有兴趣可以看看(因为较短,没有做成番外篇):

其他形态学操作

  • 形态学梯度:膨胀图减去腐蚀图,dilation - erosion,这样会得到物体的轮廓:
img = cv2.imread('school.bmp', 0)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

img

  • 顶帽:原图减去开运算后的图:src - opening
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
  • 黑帽:闭运算后的图减去原图:closing - src
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

小结

  • 形态学操作就是改变物体的形状,如腐蚀使物体”变瘦”,膨胀使物体”变胖”
  • 先腐蚀后膨胀会分离物体,所以叫开运算,常用来去除小区域物体
  • 先膨胀后腐蚀会消除物体内的小洞,所以叫闭运算。开/闭理解了之后很容易记忆噢(⊙o⊙)
# ex2tron's blog:
# http://ex2tron.wang

import cv2
import numpy as np

# 1.腐蚀与膨胀
img = cv2.imread('j.bmp', 0)
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.erode(img, kernel)  # 腐蚀
dilation = cv2.dilate(img, kernel)  # 膨胀

cv2.imshow('erosion/dilation', np.hstack((img, erosion, dilation)))
cv2.waitKey(0)


# 2.定义结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 矩形结构
print(kernel)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # 椭圆结构
print(kernel)

kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))  # 十字形结构
print(kernel)

# 3.开运算与闭运算
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 定义结构元素

# 开运算
img = cv2.imread('j_noise_out.bmp', 0)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

cv2.imshow('opening', np.hstack((img, opening)))
cv2.waitKey(0)

# 闭运算
img = cv2.imread('j_noise_in.bmp', 0)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

cv2.imshow('closing', np.hstack((img, closing)))
cv2.waitKey(0)


# 4.形态学梯度
img = cv2.imread('school.bmp', 0)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

cv2.imshow('morphological gradient', np.hstack((img, gradient)))
cv2.waitKey(0)


# 5.顶帽
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('top hat', np.hstack((img, tophat)))
cv2.waitKey(0)


# 6.黑帽
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('black hat', np.hstack((img, blackhat)))
cv2.waitKey(0)

参考网址:

https://www.cnblogs.com/whlook/p/6476826.html

https://blog.csdn.net/jacke121/article/details/75331799

https://www.cnblogs.com/Undo-self-blog/p/8436389.html

https://blog.csdn.net/gangzhucoll/article/details/78917011

https://www.jianshu.com/p/05ef50ac89ac

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦