小强学Python+OpenCV之-1.6形态学运算

对于内核的应用,上节说可以进行平滑,模糊,边缘检测等操作。这节,我们就来点实例看一下,内核在图像处理过程中都有哪些作用。

小强学Python+OpenCV之-1.6形态学运算_第1张图片
5.jpg

侵蚀

对上面的图像进行侵蚀操作后是这样的。


小强学Python+OpenCV之-1.6形态学运算_第2张图片
image.png

代码如下:

# 导入库
import argparse
import cv2
 
# 构造参数解析器
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())
 
# 加载图像
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("Original", image)
 
# 对图像进行侵蚀操作(迭代不同的次数)
for i in range(0, 3):
    eroded = cv2.erode(gray.copy(), None, iterations=i + 1)
    cv2.imshow("Eroded {} times".format(i + 1), eroded)
    cv2.waitKey(0)

上面的结果是使用3×3结构元素(内核)对原图像分别进行了1次,2次,3次侵蚀之后的样子。
erode的第二个参数是结构元素(内核),如果是None,则默认选择3×3的结构元素(内核)
erode的第三个参数是迭代次数。

膨胀(扩张)

膨胀与侵蚀动作相反,对上面的图像进行膨胀操作后是这样的。


小强学Python+OpenCV之-1.6形态学运算_第3张图片
image.png

代码如下:

# 关闭所有的窗口,并显示原图像
cv2.destroyAllWindows()
cv2.imshow("Original", image)
 
# 对原图像进行扩张操作
for i in range(0, 3):
    dilated = cv2.dilate(gray.copy(), None, iterations=i + 1)
    cv2.imshow("Dilated {} times".format(i + 1), dilated)
    cv2.waitKey(0)

上面的结果是使用3×3结构元素(内核)对原图像分别进行了1次,2次,3次扩张操作之后的样子。
dilate函数的参数意义与erode函数是相同的。

由上面的两个基本操作结合前面几节课的内容,我们还可以形成一些更加有用的处理操作。比如:
开运算(侵蚀+扩张)
闭运算(扩张+侵蚀)
梯度运算(开运算^闭运算)
白帽运算(开运算^原图像)
黑帽运算(闭运算^原图像)
下面我们来一一看一下。

开运算

小强学Python+OpenCV之-1.6形态学运算_第4张图片
image.png

代码如下:

# 关闭所有的窗口,并显示原图像
cv2.destroyAllWindows()
cv2.imshow("Original", image)
kernelSizes = [(3, 3), (5, 5), (7, 7)]
 
# 对原图像分别进行结构元素(内核)大小分别为(3, 3), (5, 5), (7, 7)的开运算
for kernelSize in kernelSizes:
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, kernelSize)
    opening = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
    cv2.imshow("Opening: ({}, {})".format(kernelSize[0], kernelSize[1]), opening)
    cv2.waitKey(0)

闭运算

小强学Python+OpenCV之-1.6形态学运算_第5张图片
image.png

代码如下:

# 关闭所有的窗口,并显示原图像
cv2.destroyAllWindows()
cv2.imshow("Original", image)
 
# 对原图像分别进行结构元素(内核)大小分别为(3, 3), (5, 5), (7, 7)的闭运算
for kernelSize in kernelSizes:
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, kernelSize)
    closing = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel)
    cv2.imshow("Closing: ({}, {})".format(kernelSize[0], kernelSize[1]), closing)
    cv2.waitKey(0)

上面的两个运算中,开运算可以看出它的作用是可以去除图像中的小斑点。闭运算看不出有什么效果。但两都组合就可以得到比较在用的作用-梯度运算(开运算^闭运算)

梯度运算

小强学Python+OpenCV之-1.6形态学运算_第6张图片
image.png

可以看出,梯度运算可以计算出图像的轮廓。代码如下:

# 关闭所有的窗口,并显示原图像
cv2.destroyAllWindows()
cv2.imshow("Original", image)
 
# 对原图像分别进行结构元素(内核)大小分别为(3, 3), (5, 5), (7, 7)的梯度运算
for kernelSize in kernelSizes:
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, kernelSize)
    gradient = cv2.morphologyEx(gray, cv2.MORPH_GRADIENT, kernel)
    cv2.imshow("Gradient: ({}, {})".format(kernelSize[0], kernelSize[1]), gradient)
    cv2.waitKey(0)

白帽,黑帽运算

小强学Python+OpenCV之-1.6形态学运算_第7张图片

可以看到黑帽和白帽运算好像有点意思了。代码如下:
我们新建一个python文件hats.py

# 导入库
import argparse
import cv2
 
# 构建参数解析器
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())
 
# 加载图像
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
# 构造结构元素(内核),并应用黑帽运算
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 5))
blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel)
 
# 应用白帽运算
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
 
# 输出图像
cv2.imshow("Original", image)
cv2.imshow("Blackhat", blackhat)
cv2.imshow("Tophat", tophat)
cv2.waitKey(0)

总结

我们学习了几个比较有用的图像运算算法:
侵蚀
扩张
开运算(侵蚀+扩张)
闭运算(扩张+侵蚀)
梯度运算(开运算^闭运算)
白帽运算(开运算^原图像)
黑帽运算(闭运算^原图像)。
其实这几种算法也是利用前面几节课中的内核的概念以及数学运算。通常对于图像做预处理操作。

我们在最后的黑白帽运算中用的图像是车牌的图像。其实,可以想像一下,如果我们真的要识别车牌,还真就得用这种基础的算法去对图像做一些预先的处理。大胆猜测一下车牌识别的方法:比如先去识别图像中的蓝色区域,然后得到的矩形与原图像做与运算,得到车牌区域。然后再对得到的图像进行黑白帽运算,然后再二值化,然后再做梯度或开闭运算,即可分解出车牌中的字母及数字。

你可能感兴趣的:(小强学Python+OpenCV之-1.6形态学运算)