基于Python的OpenCV图像处理7

May 19,2017   3643 words   14 min


图像形态学处理

在OpenCV中实现形态学处理很简单,一般情况下对二值图像进行操作。函数一般基本需要输入 两个参数:待处理图像和结构化元素(又称卷积核)用于决定操作性质。两个基本的形态学操作是 腐蚀和膨胀。他们的变体构成了开运算、闭运算、梯度等等。

1.腐蚀

所谓腐蚀是指,卷积核沿着图像滑动,如果与卷积核对应的所有像素值都是1,那么中心元素保持 原来的像素值,否则为0。如下所示,是一个3×3的卷积模板,对应像素与模板依次进行与运算。如下图所示。 这样的操作就会导致所有前景物体会变小,整幅图像的白色区域会减少。这对于去除白噪声很有用, 也可以用来断开两个连接在一起的物体等。
在OpenCV中,使用cv2.erode()函数实现腐蚀。代码如下:

# coding=utf-8
import numpy as np
import cv2

img = cv2.imread("E:\\05193.png")

# 这里我们定义了一个5×5,元素值全为1的卷积核
kernel = np.ones((5, 5), np.uint8)

# 第一个参数是待处理图像
# 第二个参数是我们定义的卷积核
# 第三个参数是腐蚀次数,可省略,默认为1
ero = cv2.erode(img, kernel, iterations=1)

cv2.imshow("img", img)
cv2.imshow("ero", ero)
cv2.waitKey(0)

处理后的对比效果如下。可以看到两个矩形中间原本连接的白线被腐蚀掉了。

2.膨胀

与腐蚀相反,原图像中,与卷积核对应的像素值只要有一个是1,那么新的中心元素的像素值就是1。 所以这个操作会增加图像中的白色区域(前景)。一般在去噪声时先用腐蚀,再用膨胀。因为腐蚀 在去掉白噪声的同时,也会使前景对象变小。所以需要再对它进行膨胀。膨胀可以用来连接两个分开的物体。 示意图如下: 可以看到,由于卷积核对应的像素中有两个不是0,所以新的中心像素的值即为1。腐蚀和膨胀类似于逻辑判断 中的与和或运算。腐蚀是将模板与原始图像进行“与”运算,只有原始图像对应像素全为1,新的中心像素才为1。 膨胀是将模板与原始图像进行“或”运算,只要原始图像对应的像素中有一个为1,那么新的中心像素值即为1。
在OpenCV中,使用函数cv2.dilate()实现,代码如下:

# coding=utf-8
import numpy as np
import cv2

img = cv2.imread("E:\\05194.png")

# 这里我们定义了一个5×5,元素值全为1的卷积核
kernel = np.ones((5, 5), np.uint8)

# 第一个参数是待处理图像
# 第二个参数是我们定义的卷积核
# 第三个参数是膨胀次数,可省略,默认为1
dilate = cv2.dilate(img, kernel, iterations=1)

cv2.imshow("img", img)
cv2.imshow("dilate", dilate)
cv2.waitKey(0)

结果如下:

3.开运算

所谓开运算,是先进行腐蚀,再进行膨胀的运算。它可以用来去除噪声。开运算在OpenCV中有专门的函数可以实现, 当然我们也可以自己组合实现。代码如下:

# coding=utf-8
import numpy as np
import cv2

img = cv2.imread("E:\\05196.png")

kernel = np.ones((5, 5), np.uint8)

# 方法一 自己组合实现开运算,先腐蚀再膨胀
erode = cv2.erode(img, kernel, iterations=1)
dilate = cv2.dilate(erode, kernel, iterations=1)

# 方法二,直接使用内置函数,其中第二个参数指定的是操作类型
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

cv2.imshow("img", img)
cv2.imshow("erode", erode)
cv2.imshow("dilate", dilate)
cv2.imshow("open", opening)
cv2.waitKey(0)

实现后的效果如下: 可以看到,原图里的”五角星”噪声已经被去除掉了。而且我们自己实现的开运算和内置函数最后的结果是相同的。

4.闭运算

与开运算对应,闭运算是先膨胀,再腐蚀。它常被用来填充前景物体中的小洞,或者前景物体上的小黑点。代码如下:

# coding=utf-8
import numpy as np
import cv2

img = cv2.imread("E:\\05197.png")

kernel = np.ones((5, 5), np.uint8)

# 方法一 自己组合实现闭运算,先膨胀再腐蚀
dilate = cv2.dilate(img, kernel, iterations=1)
erode = cv2.erode(dilate, kernel, iterations=1)

# 方法二,直接使用内置函数,其中第二个参数指定的是操作类型
close = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

cv2.imshow("img", img)
cv2.imshow("erode", erode)
cv2.imshow("dilate", dilate)
cv2.imshow("close", close)
cv2.waitKey(0)

效果如下所示,漏洞基本被补上了。

5.形态学梯度

其实就是一幅图像膨胀与腐蚀的区别,这样结果看上去就像是前景物体的轮廓。

# coding=utf-8
import numpy as np
import cv2

img = cv2.imread("E:\\05193.png")

kernel = np.ones((5, 5), np.uint8)

# 第二个参数指定的是操作类型
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

cv2.imshow("gradient", gradient)
cv2.waitKey(0)

6.礼帽

原始图像与进行开运算之后得到的图像的差。

# coding=utf-8
import numpy as np
import cv2

img = cv2.imread("E:\\05193.png")

kernel = np.ones((5, 5), np.uint8)

# 第二个参数指定的是操作类型
open = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)

cv2.imshow("img", img)
cv2.imshow("open", open)
cv2.imshow("tophat", tophat)
cv2.waitKey(0)

7.黑帽

原始图像与进行闭运算后的图像的差。

# coding=utf-8
import numpy as np
import cv2

img = cv2.imread("E:\\05193.png")

kernel = np.ones((5, 5), np.uint8)

# 第二个参数指定的是操作类型
close = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

cv2.imshow("img", img)
cv2.imshow("close", close)
cv2.imshow("blackhat", blackhat)
cv2.waitKey(0)

8.结构化元素

在前面我们使用Numpy构建的卷积核都是正方形的,但有时我们需要构建一个圆形或椭圆形的卷积核。 为实现这种要求,OpenCV提供cv2.getStructuringElement()。参数为核的形状与大小。

# 普通矩形卷积核
k1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
print k1, k1.dtype

# 椭圆(圆)形卷积核
k2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
print k2, k2.dtype

# 十字形卷积核
k3 = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
print k3, k3.dtype

对应输出结果如下:

[[1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]] uint8
 
[[0 0 1 0 0]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [0 0 1 0 0]] uint8
 
[[0 0 1 0 0]
 [0 0 1 0 0]
 [1 1 1 1 1]
 [0 0 1 0 0]
 [0 0 1 0 0]] uint8

本文作者原创,未经许可不得转载,谢谢配合

返回顶部