使用Python,OpenCV进行形态学操作
Posted 程序媛一枚~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Python,OpenCV进行形态学操作相关的知识,希望对你有一定的参考价值。
使用Python,OpenCV进行形态学操作)
这篇博客将介绍如何使用Python,OpenCV应用形态学操作。
包括:
- 腐蚀(Erosion)
- 膨胀(Dilation)
- 打开(Opening)
- 闭合(Closing)
- 形态梯度(Morphological gradient)
- 黑帽(Black hat)
- 白帽(Top hat (also called “White hat”))
形态学操作是应用于灰度或二值图像的图像处理变换。这些操作需要一个结构元素,用于定义应用该操作的像素的邻域。更具体地说,可以使用形态学操作应用于图像内部的形状和结构,以调整输出图像。(例如增加/减少图像中的物体大小,打开/缩小物体之间的间隙)
形态学运算通常被用作更强大的计算机视觉解决方案(如OCR、自动车牌识别(ANPR)和条形码检测)的预处理步骤。 巧妙地使用形态学运算可以避免更复杂(和计算昂贵)的机器学习和深度学习算法。(比如图像中的条码检测,仅使用形态学操作就可以完成~)
1. 效果图
原图 VS 腐蚀1 VS 腐蚀2 VS 腐蚀3 VS 腐蚀4次效果图如下:
可以看到,随着腐蚀迭代次数的增加,越来越多的徽标被腐蚀掉。
腐蚀对于从图像中移除小斑点或断开两个连接的组件是最有用的。
原图 VS 膨胀1 VS 膨胀2 VS 膨胀3次效果图如下:
可以看到应用了3次迭代的膨胀,徽标中所有字母的间隙都已接和。
膨胀会扩大前景区域。当连接对象的断开部分时,膨胀特别有用。
打开操作类似于腐蚀操作,去掉小斑点的同时可能会“打开”图像上的孔,如下图所示:
当我们使用大小为5的内核时×5.小而随机的斑点几乎完全消失了。当它达到一个7大小的内核时,打开操作不仅去除了所有的随机斑点,而且还“打开”了字母“s”,“n”和字母“a”上的孔。
闭合是打开的相反操作,闭合是膨胀后的腐蚀。闭合用于闭合对象内部的孔或将组件连接在一起。
可以看到闭合操作开始桥接徽标中字母之间的间隙。
形态学操作效果图如下:
形态学操作可以使得徽标的轮廓清晰地显示出来。
白帽操作效果图如下:
白帽子🎩形态学操作是原始(灰度/单通道)输入图像和开口之间的差异。
白帽操作用于在深色背景上显示图像的明亮区域。白帽/黑帽操作符都更适合灰度图像,而不是二进制图像。
在深色背景下亮的右侧区域(即白帽)是如何清晰显示的,可以清楚地看到汽车的车牌区域已经显示出来。注意车牌字符本身并没有被包括在内。这是因为车牌字符在浅色背景下是深色的。
可以应用黑帽操作效果图如下:
黑帽操作用于从较亮的背景找出较暗的区域;
要显示车牌字符,需要首先通过白帽操作分割出车牌本身,然后应用黑帽操作符(或阈值)来提取单个车牌字符(可能使用诸如轮廓检测之类的方法)。
2. 原理
结构元素看作是内核或掩码的一种类型。和内核一样,可以是任意大小的邻域。
- cv2.erode:腐蚀对于移除图像中的小斑点或断开两个连接对象的连接非常有用;
- cv2.diplate:膨胀会增大前景对象的大小,特别适用于将图像的断开部分连接在一起;
- cv2.morphologyEx(cv2.MORPH_GRADIENT) 形态梯度是膨胀和腐蚀之间的区别。它有助于确定图像特定对象的轮廓;
- cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)应用白帽操作(允许从较暗的背景找出较亮的区域)
- cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel)应用黑帽操作(允许从较亮的背景找出较暗的区域)
3. 源码
3.1 制作logo源码
import cv2
import numpy as np
zeros = np.zeros((100, 400), dtype="uint8")
image = cv2.merge([zeros, zeros, zeros])
cv2.putText(image, "Shining Seminar ~ ", (60, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 3)
cv2.imshow("image", image)
cv2.imwrite("seminar.jpg", image)
cv2.waitKey(0)
img = np.ones((600, 800, 4)) * (0, 0, 0, 0)
list = ["cv2.FONT_HERSHEY_SIMPLEX",
"cv2.FONT_HERSHEY_COMPLEX",
"cv2.FONT_HERSHEY_COMPLEX_SMALL",
"cv2.FONT_HERSHEY_DUPLEX",
"cv2.FONT_HERSHEY_PLAIN",
"cv2.FONT_HERSHEY_SCRIPT_COMPLEX",
"cv2.FONT_HERSHEY_SCRIPT_SIMPLEX",
"cv2.FONT_HERSHEY_SIMPLEX",
"cv2.FONT_HERSHEY_TRIPLEX",
"cv2.FONT_ITALIC"
]
height = 80
fonti = 0
for font in list:
# 遍历所有字体,找到最好看的一种~
cv2.putText(img, str(fonti) + " Shining Seminar ~ ", (60, height), fonti, 1, (255, 255, 255), 3)
if (fonti == 16):
break
fonti = fonti + 1
if (fonti == 8):
fonti = 16
height = height + 60
cv2.imshow("0image", img)
cv2.waitKey(0)
3.2 腐蚀膨胀打开闭合形态梯度源码
# USAGE
# python morphological_ops.py --image pyimagesearch_logo.png
# 应用OpenCV的形态学操作,包括腐蚀、膨胀、打开、关闭和形态学梯度。
# 导入必要的包
import argparse
import cv2
# 构建命令行参数及解析
# --image 输入图像路径
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=False, default="seminar.jpg",
help="path to input image")
args = vars(ap.parse_args())
# 加载图像,转换为灰度图,并展示
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("Original", image)
# 腐蚀
# 就像河水冲刷河岸腐蚀土壤一样,图像中的腐蚀会“腐蚀”前景对象并使其变小。简单地说,图像中物体边界附近的像素将被丢弃,“腐蚀”掉。
# 腐蚀的工作原理是定义一个结构元素,然后将这个结构元素从左到右、从上到下滑动到输入图像。
# 只有当结构元素内的所有像素都大于0时,输入图像中的前景像素才会被保留。否则,像素被设置为0(即背景)。
# cv2.erode:腐蚀对于移除图像中的小斑点或断开两个连接对象的连接非常有用。
# 应用一系列腐蚀
for i in range(0, 3):
# 随着腐蚀数量的增加,前景标志将开始“腐蚀”和消失。
# - image 要执行腐蚀的图像
# - None 默认3*3,也可提供
# - iterations 迭代次数,随着迭代次数的增加,将看到越来越多的徽标被蚕食。
eroded = cv2.erode(gray.copy(), None, iterations=i + 1)
cv2.imshow("Eroded {} times".format(i + 1), eroded)
# cv2.waitKey(0)
# 膨胀
# 腐蚀的反面是膨胀。就像腐蚀会腐蚀前景像素一样,膨胀会使前景像素增长。膨胀会增大前景对象的大小,特别适用于将图像的断开部分连接在一起。
# cv2.diplate:膨胀,就像腐蚀一样,也利用结构元素-如果结构元素中的任何像素大于0,则结构元素的中心像素p被设置为白色。
# 我们使用进行膨胀
# 关闭所有窗口,展示原始图
cv2.waitKey(0)
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组内核
cv2.destroyAllWindows()
cv2.imshow("Original", image)
kernelSizes = [(3, 3), (5, 5), (7, 7)]
# 遍历内核大小
for kernelSize in kernelSizes:
# 应用打开操作从当前内核大小构建矩形内核
# 根据内核构建结构元素,cv2.MORPH_RECT:矩形 ,也可以是cv2.MORPH_CROSS 十字型、cv2.MORPH_ELLIPSE 椭圆等
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)
# 关闭所有窗口
cv2.destroyAllWindows()
cv2.imshow("Original", image)
# 遍历内核
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)
# 形态梯度是膨胀和腐蚀之间的区别。它有助于确定图像特定对象的轮廓:
# 关闭所有窗口
cv2.destroyAllWindows()
cv2.imshow("Original", image)
# 遍历内核
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)
cv2.destroyAllWindows()
3.3 白帽黑帽操作源码
# USAGE
# python morphological_hats.py --image bmcp.jpg
# 使用OpenCV应用黑帽子和顶帽子/白帽子操作。
# 导入必要的包
import argparse
import cv2
# 构建命令行参数及解析
import imutils
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=False, default="byd.jpg",
help="path to input image")
args = vars(ap.parse_args())
# 加载输入图像并转换为灰度图
image = cv2.imread(args["image"])
image = imutils.resize(image, width=400)
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进行形态学操作的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV最详细入门-python(代码全部可以直接运行)