使用Python,OpenCV进行形态学操作

Posted 程序媛一枚~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用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进行形态学操作的主要内容,如果未能解决你的问题,请参考以下文章

2. OpenCV-Python——阈值平滑处理形态学操作

OpenCV最详细入门-python(代码全部可以直接运行)

python+opencv图像形态学处理详细解释(膨胀腐蚀开闭运算礼帽和黑猫)

OpenCV图像处理应用(面向Python)之形态学操作

OpenCV图像处理应用(面向Python)之形态学操作

使用Python,OpenCV进行基本的图像处理——提取红色圆圈轮廓并绘制