我在Vscode学OpenCV 图像处理一(阈值处理、形态学操作【连通性,腐蚀和膨胀,开闭运算,礼帽和黑帽,内核】)

图像处理一

  • 一、阈值处理
    • 1.1 OpenCV 提供了函数` cv2.threshold()`和函数` cv2.adaptiveThreshold(),`用于实现阈值处理
      • 1.1.1. cv2.threshold():
        • (1)在函数`cv2.threshold()`中,参数`threshold_type`用于指定阈值处理的方式。它有以下几种可选的阈值类型:
        • (2)代码
        • (3)图像部分
      • 1.1.2. cv2.adaptiveThreshold():
    • 1.2 Otsu 处理
  • 二、形态学操作
    • 2.1 连通性
      • 2.1.1 邻接种类
      • 2.1.2 连通种类(3种)
    • 2.2 腐蚀和膨胀
      • 2.2.1 膨胀(Dilation):`cv2.dilate`
        • (1)函数原型以及使用方式
        • (2)Py中常用的3个参数
        • (3) 理解膨胀的效果
      • 2.2.2 腐蚀(Erosion): `cv2.erode`
        • (1)函数原型以及使用方式
        • (2)Py中常用的3个参数
        • (3)理解腐蚀的效果
      • 2.2.3 腐蚀和膨胀代码以及图片演示
        • (1)普通的
        • (2)三张照片
      • 2.2.4 形态学梯度:膨胀与腐蚀之差
        • 或者函数
    • 2.3 开闭运算
      • 2.3.1 开运算 opening
      • 2.3.2 闭运算 closing
      • 2.3.3 通用形态学函数
        • (1)常用的参数:
        • (2)完整的
        • (3)注意事项
      • 2.3.4 代码以及演示
    • 2.4 礼帽和黑帽
      • 2.4.1 礼帽运算 (Top-Hat Transformation)
      • 2.4.2 黑帽运算 (Black-Hat Transformation)
      • 2.4.3 代码以及图片演示
    • 2.5 核函数
      • 细微变化

一、阈值处理

阈值:指的是某一个范围内,不可逾越,不能低于的值。

例如,设定阈值为127,然后:
 将图像内所有像素值大于 127 的像素点的值设为 255。
 将图像内所有像素值小于或等于 127 的像素点的值设为 0。

在这里插入图片描述

1.1 OpenCV 提供了函数 cv2.threshold()和函数 cv2.adaptiveThreshold(),用于实现阈值处理

cv2.threshold() 和 cv2.adaptiveThreshold() 是 OpenCV 中用于实现阈值处理的两个函数,它们之间有以下区别:

1.1.1. cv2.threshold():

这个函数是全局阈值处理方法。它将输入图像转换为二进制图像,将像素值与用户提供的阈值进行比较,并根据比较结果将像素设置为给定的最大值或最小值。语法如下:

retval, threshold_image = cv2.threshold(src, threshold_value, max_value, threshold_type)

其中:

  • retval 代表返回的阈值。
  • threshold_image 代表阈值分割结果图像,与原始图像具有相同的大小和类型。
  • src:输入图像,单通道灰度图像的,8 位或 32 位浮点型数值。
  • threshold_value:阈值,用于将像素值与之比较。
  • max_value:当像素值大于阈值时,设置的像素值。
  • threshold_type:阈值类型,用于指定阈值处理的方式。

在这里插入图片描述

(1)在函数cv2.threshold()中,参数threshold_type用于指定阈值处理的方式。它有以下几种可选的阈值类型:
  • cv2.THRESH_BINARY:如果像素值大于阈值,设置为最大值,否则设置为0。

在 8 位图像中,最大值是 255。因此,在对 8 位灰度图像进行二值化时,如果将阈值设定
为 127,那么:
 所有大于 127 的像素点会被处理为 255。
 其余值会被处理为 0。

  • cv2.THRESH_BINARY_INV:与cv2.THRESH_BINARY相反,如果像素值大于阈值,设置为0,否则设置为最大值。

反二值化阈值处理针对像素点的处理方式为:
 对于灰度值大于阈值的像素点,将其值设定为 0。
 对于灰度值小于或等于阈值的像素点,将其值设定为 255。

  • cv2.THRESH_TRUNC:如果像素值大于阈值,设置为阈值,否则保持不变。

截断阈值化处理:
例如,阈值选取为 127,则截断阈值化处理时:
 对于像素值大于 127 的像素点,其像素值将被设定为 127。
 对于像素值小于或等于 127 的像素点,其像素值将保持改变。

  • cv2.THRESH_TOZERO:如果像素值大于阈值,保持不变,否则设置为0。

低阈值零处理
例如,阈值选取为 127,则:
 对于像素值大于 127 的像素点,其像素值将保持改变。
 对于像素值小于或等于 127 的像素点,其像素值将被设定为 0。

  • cv2.THRESH_TOZERO_INV:与cv2.THRESH_TOZERO相反,如果像素值大于阈值,设置为0,否则保持不变。

超阈值零处理
例如,阈值选取为 127,则:
 对于像素值大于 127 的像素点,其值将被设定为 0。
 对于像素值小于或等于 127 的像素点,其值将保持改变。

这些阈值类型可以根据具体的应用需求选择。例如,如果要将图像转换为二进制图像(黑白图像),可以使用cv2.THRESH_BINARYcv2.THRESH_BINARY_INV。如果只想保留图像中较亮的部分,并将其他部分设为黑色,可以使用cv2.THRESH_TRUNC

(2)代码
# 二值化阈值处理会将原始图像处理为仅有两个值的二值图像,
import numpy as np
import cv2 as cv
import matplotlib.pyplot as pltx=np.random.randint(0,256,size=(4,4),dtype=np.uint8)
x

在这里插入图片描述

ret,dst=cv.threshold(x,thresh=127,maxval=255,type=cv.THRESH_BINARY)
ret=127.0
dst

在这里插入图片描述

(3)图像部分

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
反二值
在这里插入图片描述

1.1.2. cv2.adaptiveThreshold():

这个函数是自适应阈值处理方法。它根据图像不同区域的统计特性自适应地选择阈值进行像素分割。语法如下:

这种方法允许在图像的不同区域使用不同的阈值,从而提高对局部变化的适应性

threshold_image = cv2.adaptiveThreshold(src, max_value, adaptive_method, threshold_type, block_size, constant)

其中:

  • src:输入图像,单通道灰度图像。
  • max_value:当像素值大于阈值时,设置的像素值。
  • adaptive_method:自适应阈值算法,可选值包括cv2.ADAPTIVE_THRESH_MEAN_C和cv2.ADAPTIVE_THRESH_GAUSSIAN_C。
  • threshold_type:阈值类型,用于指定阈值处理的方式。
  • block_size:计算阈值时使用的像素领域大小。
  • constant:从计算的均值或加权均值中减去的常数。

 cv2.ADAPTIVE_THRESH_MEAN_C:邻域所有像素点的权重值是一致的。
 cv2.ADAPTIVE_THRESH_GAUSSIAN_C:与邻域各个像素点到中心点的距离有关,通
过高斯方程得到各个点的权重值。
总结:

  • cv2.threshold() 是一种全局的阈值处理方法,适用于图像中的大部分区域。它对整个图像应用相同的阈值。
  • cv2.adaptiveThreshold() 是一种自适应的阈值处理方法,适用于图像中具有不同光照条件和对比度的不同区域。它根据图像的局部特性来选择阈值。

1.2 Otsu 处理

在图像处理中,阈值化是将灰度图像转换为二值图像的过程,其中根据某个阈值将像素分为两个类别:背景和前景。通常情况下,我们可以手动选择一个阈值进行二值化。但对于不同图像,选择合适的阈值可能会很困难。

Otsu处理通过最小化类别内方差和最大化类别间方差来自动确定最佳阈值。它利用图像的直方图信息,找到能够最好地区分前景和背景的阈值。这使得Otsu处理能够更好地适应不同图像的特性,并产生更准确的结果。

使用OpenCV中的cv2.THRESH_OTSU标志,可以轻松应用Otsu处理来确定图像的最佳阈值,并将图像进行二值化。

import cv2
import numpy as np
from matplotlib import pyplot as pltimg = cv2.imread('Pic/cc.jpg', 0)# 使用Otsu's方法进行阈值处理
ret, otsu_thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 使用cv2.THRESH_BINARY进行阈值处理
_, binary_thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)# 使用cv2.THRESH_TRUNC进行阈值处理
_, trunc_thresh = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)# 使用cv2.THRESH_TOZERO进行阈值处理
_, tozero_thresh = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)# 绘制结果图像
plt.subplot(221), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(binary_thresh, cmap='gray')
plt.title('cv2.THRESH_BINARY'), plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.imshow(otsu_thresh, cmap='gray')
plt.title('cv2.THRESH_BINARY + cv2.THRESH_OTSU'), plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(tozero_thresh, cmap='gray')
plt.title('cv2.THRESH_TOZERO'), plt.xticks([]), plt.yticks([])plt.show()

在这里插入图片描述

二、形态学操作

形态学(英语morphology,德语morphologie )的范畴来自希腊语morphe,歌德在自己的生物学研究中倡导得最早,歌德由于不满意自然科学中过分的理性分析倾向,才有这样的规划与设想。
【意为“形状”或“结构”。在图像处理和计算机视觉领域中,形态学通常指的是对图像中对象的形状和结构进行分析和处理的一组数学方法。】

形态学操作的目标是通过改变图像的形状和结构来提取关键信息,如去除噪声、连接对象、分离对象等。形态学操作基于图像中的集合论和拓扑学概念,其中形状和结构是通过一种称为“结构元素”的模板进行操作的。结构元素是一个小的、预定义的形状,类似于滤波器,它在图像上移动并与图像的相应部分进行比较。

形态学操作在图像处理中具有广泛的应用,尤其是在图像分割、特征提取和对象识别等任务中。腐蚀和膨胀是形态学操作的基本构建块,而开运算和闭运算则是这些基本操作的组合,用于解决更复杂的问题。还有形态学梯度(Morphological Gradient)运算、顶帽运算(礼帽运算)、黑帽运算击中击不中等不同形式的操作。这些操作对于处理具有不同形状、大小和方向的对象的图像非常有用。

形态学处理在视觉检测、文字识别、医学图像处理、图像压缩编码等领域都有非常重要的应用。

2.1 连通性

在图像处理和计算机视觉中,"连通性"是指像素之间的连接性或相互关联的性质。它涉及到图像中的区域、对象或像素集合之间的连接关系。

判断两个像素是否连通的条件:
(1)位置相邻: 两个像素必须在空间上是相邻的,即它们在图像中的位置是相邻的。
(2)灰度值相同或相似: 对于灰度图像,两个像素的灰度值通常需要相同或相似。

2.1.1 邻接种类

因为图像中,我们常说的像素是其最小的不可分割的单位。它代表了图像在某区域的信息,它所包含的信息关乎到颜色以及灰度值的大小,而正是这小方块的排列才组成了我们看到的计算机视觉上的“信息”。

  1. 4-邻接
    在4-邻接中,一个像素的邻接像素包括其上、下、左、右四个方向的像素。这意味着一个像素与它上下左右相邻的四个像素是邻接的。

    像素p(x,y)的4邻域是: (x+1,y); (x-1,y); (x,y+1); (x,y-1),用N4(p)表示像素p的4邻接
    
0  1  0
1  x  1   (x表示中心像素)
0  1  0
  1. 8-邻接

. 在8-邻接中,一个像素的邻接像素包括其上、下、左、右四个方向的像素,以及对角线方向的四个像素。这意味着一个像素与它上下左右和对角线方向上相邻的八个像素是邻接的。

像素p(x,y)的8邻域是: 4邻域的点 +D邻域的点,用Ng(p)表示像素p的8邻域连通性是描述区域和边界的重要概念
1  1  1
1  x  1   (x表示中心像素)
1  1  1
  1. “D-邻接”

通常指的是对角线邻接,即在一个像素的周围,除了上、下、左、右的四个方向,还包括对角线方向上的四个方向。这与8-邻接不同,8-邻接同时考虑了上下左右和对角线方向的邻接像素,而D-邻接则专指对角线方向。

像素pix,y)的D邻域是:对角上的点(x+1,y+1); (x+1,y-1); (x-1,y+1); (x-1,y-1),用Np(p)表示像素p的D邻域

在D-邻接中,一个像素的邻接像素包括以下八个方向:

1  0  1
0  x  0   (x表示中心像素)
1  0  1

2.1.2 连通种类(3种)

  1. 4连通: 两个像素p和q被称为4连通,如果q在p的4邻域(上、下、左、右)中。

  2. 8连通: 两个像素p和q被称为8连通,如果q在p的8邻域(包括对角线方向)中。

  3. m连通: m连通是一种混合联通定义。两个像素p和q被称为m连通,如果以下条件之一成立:

    • q在p的4邻域中(4联通条件)。
    • q在p的D邻域中,同时p的4邻域与q的4邻域没有相交(即没有共同的像素,或者说两者之间没有值V的像素)。

这种混合连通性的定义允许通过4联通和8联通的条件来判断两个像素是否相连,同时引入了一些其他限制,以确保连接是有效的。m联通性的定义在一些图像处理任务中可能更灵活,允许更大的灵活性。

2.2 腐蚀和膨胀

这两个操作可以通过以下方式来理解:

腐蚀: 就像沙滩上的海水慢慢侵蚀沙堆,使其变小。
膨胀: 就像在沙堆上添加一些沙子,使其变得更大。’

腐蚀(Erosion)和膨胀(Dilation)是形态学操作中的两个基本操作,它们常常用于图像处理中的前景和背景的调整,以及对象的形状和结构的改变。这两种操作通常与结构元素(structuring element)一起使用。

2.2.1 膨胀(Dilation):cv2.dilate

  • 操作原理: 通过滑动结构元素,将图像中的高亮区域扩张,使得效果图中的高亮区域比原图更大。
  • 效果: 连接相邻的高亮区域,填充小的间隙,使图像中的白色区域增加。
  • 本质: 是求局部最大值的操作。
(1)函数原型以及使用方式
cv.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

cv.dilate 是 OpenCV 库中用于图像膨胀的函数之一。膨胀是形态学操作的一种,它通过移动结构元素(也称为核或内核)在图像上的所有像素上,将像素值置为其邻域内的最大值。这有助于扩大物体,连接物体的断开部分,并强调物体的边缘。

下面是 cv.dilate 函数的一般形式和参数说明:

  • src: 输入图像,通常为灰度图像。
  • kernel: 结构元素(内核),它是在图像上移动的小矩阵。它可以是矩形、椭圆、十字形等形状。可以使用 cv.getStructuringElement() 来创建不同形状和大小的结构元素。
  • dst: 输出图像,与输入图像具有相同的类型和大小。如果未提供,则函数会修改原始图像。
  • anchor: 结构元素的锚点。它指示结构元素的中心位置,通常位于结构元素的中心。默认值为 (-1, -1),表示锚点位于结构元素的中心。
  • iterations: 膨胀的迭代次数。默认为 1。
  • borderType: 图像边界处理类型。默认为 cv.BORDER_CONSTANT,表示用常数填充边界。可以使用其他选项,如 cv.BORDER_REPLICATEcv.BORDER_REFLECT
  • borderValue: 在使用常数填充边界时所用的常数值,默认为 0。

以下是一个简单的例子:

import cv2 as cv
import numpy as np# 读取图像
image = cv.imread('example.jpg', cv.IMREAD_GRAYSCALE)# 创建一个 3x3 的矩形结构元素
kernel = np.ones((3, 3), np.uint8)# 进行膨胀操作
dilated_image = cv.dilate(image, kernel, iterations=1)# 显示原始图像和膨胀后的图像
cv.imshow('Original Image', image)
cv.imshow('Dilated Image', dilated_image)
cv.waitKey(0)
cv.destroyAllWindows()

在这个例子中,cv.dilate 函数使用了一个 3x3 的矩形结构元素,对输入图像进行了一次膨胀操作。你可以根据需要调整结构元素的大小和形状,以及迭代次数,来获得不同的效果。

(2)Py中常用的3个参数
import cv2 as cv
cv.dilate(img,kernel,iterations)

kernel - 核结构
iterations - 膨胀次数,默认为1

(3) 理解膨胀的效果

膨胀操作与腐蚀相反,它可以使物体的边界向外膨胀一定的距离,将与物体接触的背景点合并到物体中,
以此来增大目标并添补目标中的孔洞。

	增大目标并添补孔洞:膨胀操作可以填充物体中的小孔洞或细小空洞。
当物体内部存在一些细小的空隙或孔洞时,膨胀操作会使物体的边界向外膨胀,将与这些孔洞相邻的背景像素合并到物体中,从而填补这些孔洞,使得目标变得更大且更完整将背景点合并到物体中:膨胀操作会扩张物体边界,使物体的边界向外延伸一定的距离。
在这个过程中,原本与物体接触的背景区域的像素会被合并到物体中。这意味着物体的边界会变得更加光滑,原本与背景接触的一些像素点会被认为是物体的一部分,从而扩大了物体的尺寸。

2.2.2 腐蚀(Erosion): cv2.erode

  • 操作原理: 通过滑动结构元素,将图像中的高亮区域缩小,使得效果图中的高亮区域比原图更小。
  • 效果: 消除小的对象、细小的结构和噪声,使图像中的白色区域减小。
  • 本质: 是求局部最小值的操作。
(1)函数原型以及使用方式

cv.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

腐蚀是一种形态学操作,它通过移动结构元素(也称为核或内核)在图像上的所有像素上,将像素值置为其邻域内的最小值。这有助于消除图像中的小物体,平滑物体边界,并缩小或消除物体。

下面是 cv.erode 函数的一般形式和参数说明:

cv.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src: 输入图像,通常为灰度图像。
  • kernel: 结构元素(内核),它是在图像上移动的小矩阵。它可以是矩形、椭圆、十字形等形状。可以使用 cv.getStructuringElement() 来创建不同形状和大小的结构元素。
  • dst: 输出图像,与输入图像具有相同的类型和大小。如果未提供,则函数会修改原始图像。
  • anchor: 结构元素的锚点。它指示结构元素的中心位置,通常位于结构元素的中心。默认值为 (-1, -1),表示锚点位于结构元素的中心。
  • iterations: 腐蚀的迭代次数。默认为 1。
  • borderType: 图像边界处理类型。默认为 cv.BORDER_CONSTANT,表示用常数填充边界。可以使用其他选项,如 cv.BORDER_REPLICATEcv.BORDER_REFLECT
  • borderValue: 在使用常数填充边界时所用的常数值,默认为 0。
import cv2 as cv
import numpy as np# 读取图像
image = cv.imread('example.jpg', cv.IMREAD_GRAYSCALE)# 创建一个 3x3 的矩形结构元素
kernel = np.ones((3, 3), np.uint8)# 进行腐蚀操作
eroded_image = cv.erode(image, kernel, iterations=1)# 显示原始图像和腐蚀后的图像
cv.imshow('Original Image', image)
cv.imshow('Eroded Image', eroded_image)
cv.waitKey(0)
cv.destroyAllWindows()

在这个例子中,cv.erode 函数使用了一个 3x3 的矩形结构元素,对输入图像进行了一次腐蚀操作。你可以根据需要调整结构元素的大小和形状,以及迭代次数,来获得不同的效果。

(2)Py中常用的3个参数
import cv2 as cv
cv.erode(img,kernel,iterations)

kernel - 核结构
iterations - 腐蚀次数,默认为1

(3)理解腐蚀的效果
	消除边界点:腐蚀操作会将物体边界的像素“侵蚀”,也就是将物体边界向内部缩小一定的距离。
这会导致物体边界的像素被消除或减少,从而使物体整体变小。缩小目标:可以通过腐蚀来减小物体的大小以去除不必要的细节。消除小噪声点:小的噪声点会被消除掉,因为它们被看作是物体边界的一部分,随着边界的腐蚀而消失。

2.2.3 腐蚀和膨胀代码以及图片演示

(1)普通的

在这里插入图片描述


import numpy as  np
import cv2 as cv
import matplotlib.pyplot as plt#1.读取图像img = cv.imread("img/test_img.jpg")
#2.Kernel 核结构
kernel = np.ones((5, 5), np.uint8)
#3.图像的腐蚀和膨胀
erpsion = cv.erode(img, kernel)
dilate = cv.dilate(img, kernel)fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(10, 8), dpi=100)
axes[0].imshow(img[:, :, ::-1])
axes[0].set_title("原图")axes[1].imshow(erpsion[:, :, ::-1])
axes[1].set_title("腐蚀")axes[2].imshow(dilate[:, :, ::-1])
axes[2].set_title("膨胀")plt.show()
(2)三张照片

这是三张不同的,用于对比,其中的圈住的并非OpenCV标注,是我自己为了对比,做的记号
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


import numpy as  np
import cv2 as cv
import matplotlib.pyplot as plt#1.读取图像img = cv.imread("img/work1127.jpg")
## 腐蚀和膨胀针对于高亮区域进行的                                                                          
# img = cv.imread("img/useCvOpenxx.jpg")
# img = cv.imread("img/usecvClose.jpg")
#2.Kernel 核结构
kernel = np.ones((5, 5), np.uint8)
#3.图像的腐蚀和膨胀
erpsion = cv.erode(img, kernel)
dilate = cv.dilate(img, kernel)fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(10, 8), dpi=100)
axes[0].imshow(img[:, :, ::-1])
axes[0].set_title("原图")axes[1].imshow(erpsion[:, :, ::-1])
axes[1].set_title("腐蚀")axes[2].imshow(dilate[:, :, ::-1])
axes[2].set_title("膨胀")plt.show()

2.2.4 形态学梯度:膨胀与腐蚀之差

在这里插入图片描述

import numpy as  np
import cv2 as cv
import matplotlib.pyplot as plt
#1.读取图像
## 腐蚀和膨胀针对于高亮区域进行的                                                                          
img = cv.imread("img/usecvClose.jpg")
#2.Kernel 核结构
kernel = np.ones((5, 5), np.uint8)
#3.图像的腐蚀和膨胀
erpsion = cv.erode(img, kernel)
dilate = cv.dilate(img, kernel)plt.imshow(dilate-erpsion)
plt.show()
或者函数

通过将函数 cv2.morphologyEx()的操作类型参数 op 设置为“cv2.MORPH_GRADIENT”,可以实现形态学梯度运算。其语法结构如下:

result = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

在这里插入图片描述

2.3 开闭运算

开运算和闭运算是将腐蚀和膨胀按照一定的次序进行处理。 但这两者并不是可逆的,即先开后闭并不能得到原来的图像。

2.3.1 开运算 opening

开运算是先腐蚀后膨胀。 其作用是:分离物体,消除小区域。 特点:消除噪点,去除小的干扰块,而不影响原来的图像。

开运算:先进行腐蚀,再进行膨胀。它能够消除小的噪声和干扰,分离物体,
并且不影响原始图像的结构。这种操作特别适用于去除小物体、光滑边界和减少细小细节

2.3.2 闭运算 closing

闭运算与开运算相反,是先膨胀后腐蚀,、
作用是消除“闭合”物体里面的孔洞
特点:可以填充闭合区域。

闭运算:先进行膨胀,再进行腐蚀。闭运算通常用于填充物体内部的孔洞或者连接物体之间的间断部分。
它能够关闭物体内部的小空洞,填充闭合区域,并且保持物体的整体形状

2.3.3 通用形态学函数

(1)常用的参数:
import cv2 as cv
cv.morphologyEx(src, op, kernel)

src: 要处理的图像
op: 处理方式:若进行开运算,则设为cv.MORPH_OPEN,
若进行闭运算,则设为cv.MORPH_CLOSE
Kernel: 核结构

(2)完整的

形态学操作是图像处理中的一种基础操作,它包括腐蚀、膨胀、开运算、闭运算等。在 OpenCV 中,有一个通用的形态学操作函数 cv.morphologyEx,可以执行不同形式的形态学操作,包括腐蚀、膨胀、开运算、闭运算等。

cv.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src: 输入图像,通常为灰度图像。

  • op: 形态学操作的类型,可以是以下之一:

    • cv.MORPH_ERODE: 腐蚀
    • cv.MORPH_DILATE: 膨胀
    • cv.MORPH_OPEN: 开运算
    • cv.MORPH_CLOSE: 闭运算
    • cv.MORPH_GRADIENT: 梯度运算
    • cv.MORPH_TOPHAT: 顶帽运算
    • cv.MORPH_BLACKHAT: 黑帽运算
  • kernel: 结构元素(内核),它是在图像上移动的小矩阵。可以使用 cv.getStructuringElement() 来创建不同形状和大小的结构元素。

  • dst: 输出图像,与输入图像具有相同的类型和大小。如果未提供,则函数会修改原始图像。

  • anchor: 结构元素的锚点。它指示结构元素的中心位置,通常位于结构元素的中心。默认值为 (-1, -1),表示锚点位于结构元素的中心。

  • iterations: 操作的迭代次数。默认为 1。

  • borderType: 图像边界处理类型。默认为 cv.BORDER_CONSTANT,表示用常数填充边界。可以使用其他选项,如 cv.BORDER_REPLICATEcv.BORDER_REFLECT

  • borderValue: 在使用常数填充边界时所用的常数值,默认为 0。

以下是一个简单的例子,演示如何使用 cv.morphologyEx 函数进行开运算:

import cv2 as cv
import numpy as np# 读取图像
image = cv.imread('example.jpg', cv.IMREAD_GRAYSCALE)# 创建一个 3x3 的矩形结构元素
kernel = np.ones((3, 3), np.uint8)# 进行开运算
opened_image = cv.morphologyEx(image, cv.MORPH_OPEN, kernel)# 显示原始图像和开运算后的图像
cv.imshow('Original Image', image)
cv.imshow('Opened Image', opened_image)
cv.waitKey(0)
cv.destroyAllWindows()

通过调整操作类型和结构元素,你可以执行其他形态学操作,如膨胀、闭运算等。

(3)注意事项

在这里插入图片描述

在实例中,具有两次迭代的打开操作(#MORPH_OPEN)相当于apply依次为:
侵蚀->侵蚀->扩张->扩张(而不是侵蚀->扩张->侵蚀->扩张)。

2.3.4 代码以及演示

在这里插入图片描述

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt# 读取两张图像
imgCvOpen = cv.imread("img/useCvOpenxx.jpg")
imgCvClose = cv.imread("img/usecvClose.jpg")# 创建核结构(这里创建了一个10x10的全为1的二维数组,作为形态学运算的核结构)
kernel = np.ones((10, 10), np.uint8)# 执行开运算和闭运算
# 开运算:消除周围的噪点
cvOpen = cv.morphologyEx(imgCvOpen, cv.MORPH_OPEN, kernel)
# 闭运算:填充闭合区域的孔洞
cvClose = cv.morphologyEx(imgCvClose, cv.MORPH_CLOSE, kernel)# 使用 Matplotlib 显示图像
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8))# 显示原始图像和处理后的图像
axes[0, 0].imshow(imgCvOpen[:, :, ::-1])
axes[0, 0].set_title("imgCvOpen原图Img")
axes[0, 1].imshow(cvOpen[:, :, ::-1])
axes[0, 1].set_title("cvOpenImg")axes[1, 0].imshow(imgCvClose[:, :, ::-1])
axes[1, 0].set_title("imgCvClose原图Img")
axes[1, 1].imshow(cvClose[:, :, ::-1])
axes[1, 1].set_title("cvCloseImg")plt.show()

2.4 礼帽和黑帽

礼帽运算(Top Hat)和黑帽运算(Black Hat)是形态学操作的两种特殊形式,它们通常用于图像的细节增强和物体检测。

2.4.1 礼帽运算 (Top-Hat Transformation)

原图像与“开运算“的结果图之差

dst=tophat(src,element)=src-open(src,element)

在这里插入图片描述

礼帽运算是原始图像与开运算之差,其中开运算通常用于去除图像中的噪声。礼帽运算突出了图像中的细小亮区域,有助于强调一些细节。

礼帽运算是原始图像与开运算结果之差的操作,

数学表达为 dst = tophat(src, element) = src - open(src, element)
它能突出比原图周围更亮的区域,
强调了图像中边缘或细小亮度变化的区域。
在背景相对较亮,而微小物品或特定区域比较暗的情况下,使用礼帽运算能够帮助提取这些微小暗区域,
这种操作与选择的核大小相关。

2.4.2 黑帽运算 (Black-Hat Transformation)

为”闭运算“的结果图与原图像之差。

dst=blackhat(src,element)=close(src,element)-src

在这里插入图片描述
黑帽运算是闭运算与原始图像之差,其中闭运算通常用于填充图像中的空洞。黑帽运算突出了图像中的细小暗区域,有助于强调一些细节。

黑帽运算是闭运算结果与原始图像之差的操作,

数学表达为 dst = blackhat(src, element) = close(src, element) - src。
它能够突出比原图周围更暗的区域,强调了图像中边缘或细小暗区域的存在。
在背景相对较暗,但是存在微小暗区域或者噪声时,使用黑帽运算能够帮助分离这些暗区域,
同样,这种操作与所选择的核大小相关。

2.4.3 代码以及图片演示


import numpy as np
import cv2 as cv
import matplotlib.pyplot as pltimgOpen=cv.imread("img/useCvOpenxx.jpg")
imgClose=cv.imread("img/usecvClose.jpg")#核结构
kernel=np.ones((10,10),dtype=np.uint8)#礼帽和黑帽
cvOpen1=cv.morphologyEx(imgOpen,cv.MORPH_TOPHAT,kernel)
cvClose1=cv.morphologyEx(imgClose,cv.MORPH_BLACKHAT,kernel)# 显示
fig,axes=plt.subplots(nrows=2,ncols=3,figsize=(10,8))
axes[0,0].imshow(imgOpen)
axes[0,0].set_title("imgOpen")
axes[0, 1].imshow(cvOpen[:, :, ::-1])
axes[0, 1].set_title("cvOpenImg")
axes[0,2].imshow(cvOpen1)
axes[0,2].set_title("cvOpen1")axes[1,0].imshow(cvClose1)
axes[1,0].set_title("imgClose1")
axes[1, 1].imshow(cvClose[:, :, ::-1])
axes[1, 1].set_title("cvCloseImg")
axes[1,2].imshow(cvClose1)
axes[1,2].set_title("cvClose1")
plt.show()

在这里插入图片描述

2.5 核函数

在形态学操作中,核函数(也称为结构元素或内核)是一个小的矩阵,用于定义形态学操作的形状和大小。不同的核函数会产生不同的效果,因此选择适当的核函数对于获得期望的形态学效果非常重要。

在 OpenCV 中,可以使用 cv.getStructuringElement() 函数来创建不同形状和大小的核函数。这个函数返回指定形状和大小的二值矩阵,用于作为形态学操作的核函数。

下面是 cv.getStructuringElement() 函数的一般形式:

cv.getStructuringElement(shape, ksize[, anchor])
  • shape: 结构元素的形状,可以是以下之一:
    • cv.MORPH_RECT:矩形结构元素
    • cv.MORPH_CROSS:十字形结构元素
    • cv.MORPH_ELLIPSE:椭圆形结构元素
  • ksize: 结构元素的大小,通常是一个元组 (rows, cols),指定行数和列数。
  • anchor: 结构元素的锚点。它指示结构元素的中心位置,通常位于结构元素的中心。默认值为 (-1, -1),表示锚点位于结构元素的中心。

以下是一些例子,演示如何创建不同形状和大小的核函数:

import cv2 as cv
import numpy as np# 创建一个 3x3 的矩形结构元素
rect_kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))# 创建一个 5x5 的十字形结构元素
cross_kernel = cv.getStructuringElement(cv.MORPH_CROSS, (5, 5))# 创建一个 7x7 的椭圆形结构元素
ellipse_kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (7, 7))

这些核函数可以用于形态学操作,比如腐蚀、膨胀、开运算、闭运算等。例如,你可以将这些核函数传递给 cv.erodecv.dilatecv.morphologyEx 等函数中的 kernel 参数。

细微变化

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties# 读取图像
image = cv.imread('img/useCvOpenxx.jpg', cv.IMREAD_GRAYSCALE)# 创建不同形状和大小的核函数
rect_kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
cross_kernel = cv.getStructuringElement(cv.MORPH_CROSS, (5, 5))
ellipse_kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (7, 7))# 进行腐蚀操作
eroded_rect = cv.erode(image, rect_kernel)
eroded_cross = cv.erode(image, cross_kernel)
eroded_ellipse = cv.erode(image, ellipse_kernel)# 进行膨胀操作
dilated_rect = cv.dilate(image, rect_kernel)
dilated_cross = cv.dilate(image, cross_kernel)
dilated_ellipse = cv.dilate(image, ellipse_kernel)# 设置中文字体
font = FontProperties(fname=r"C:\Windows\Fonts\simsun.ttc", size=12)# 显示原始图像和不同核函数下的腐蚀结果和膨胀结果
plt.figure(figsize=(12, 8))plt.subplot(3, 3, 1), plt.imshow(image, cmap='gray'), plt.title('原始图像', fontproperties=font)plt.subplot(3, 3, 2), plt.imshow(eroded_rect, cmap='gray'), plt.title('矩形核腐蚀', fontproperties=font)
plt.subplot(3, 3, 3), plt.imshow(dilated_rect, cmap='gray'), plt.title('矩形核膨胀', fontproperties=font)plt.subplot(3, 3, 5), plt.imshow(eroded_cross, cmap='gray'), plt.title('十字核腐蚀', fontproperties=font)
plt.subplot(3, 3, 6), plt.imshow(dilated_cross, cmap='gray'), plt.title('十字核膨胀', fontproperties=font)plt.subplot(3, 3, 8), plt.imshow(eroded_ellipse, cmap='gray'), plt.title('椭圆核腐蚀', fontproperties=font)
plt.subplot(3, 3, 9), plt.imshow(dilated_ellipse, cmap='gray'), plt.title('椭圆核膨胀', fontproperties=font)plt.show()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/212182.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

应用程序中实现用户隐私合规和数据保护合规的处理方案及建议

随着移动互联网的发展,用户隐私合规和数据保护合规已经成为应用开发过程中不可忽视的重要环节。为了帮助开发者实现隐私和数据保护合规,本文将介绍一些处理方案和建议。 图片来源:应用程序中实现用户隐私合规和数据保护合规的处理方案及建议 …

Spring IOC,DI原理保姆级带你了解如,让面试官感到你的魅力

Spring IOC,DI原理保姆级带你了解如,让面试官感到你的魅力 一,什么是IOC 1.开始:Spring IoC容器的创建。 容器初始化:初始化IoC容器,包括加载配置文件、解析配置文件等。 加载XML/Java配置文件&#xff1…

『Jmeter超级干货』| Linux下Jmeter安装配置、脚本设计执行、监控及报告完整过程

『Jmeter超级干货』| Linux下Jmeter安装配置、脚本设计执行、监控及报告完整过程 1 JDK安装部署1.1 JDK下载1.2 JDK配置 2 Jmeter安装部署2.1 Jmeter下载2.2 Jmeter安装2.3 Jmeter相关目录配置2.4 Jmeter启动配置2.5 检查并启动 3 Jmeter汉化3.1 临时修改3.2 永久修改 4 准备测…

快照读通过MVCC解决不可重复读当前读通过间隙锁解决幻读

简介 Multi-Version Concurrency Control 多版本并发控制,MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程语言中实现事务内存。 *往期知识不做重点 事务具有4个特征,分别是原子性、一致性、隔…

毕设:《基于hive的音乐数据分析系统的设计与实现》

文章目录 环境启动一、爬取数据1.1、歌单信息1.2、每首歌前20条评论1.3、排行榜 二、搭建环境1.1、搭建JAVA1.2、配置hadoop1.3、配置Hadoop环境:YARN1.4、MYSQL1.5、HIVE(数据仓库)1.6、Sqoop(关系数据库数据迁移) 三、hadoop配置内存四、导…

用 PHP和html做一个简单的注册页面

用 PHP和html做一个简单的注册页面 index.html的设计 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title…

【Proteus】绘制简单的电路图

参考书籍&#xff1a;微机原理与接口技术——基于8086和Proteus仿真&#xff08;第3版&#xff09;&#xff08;作者&#xff1a;顾晖等&#xff09;&#xff0c;p111 1.放置元件 以8086为例&#xff1a; 确保处于元件模式&#xff0c;点击对应的按钮&#xff1a; 在元件库中…

【离散数学】——期末刷题题库(等价关系与划分)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

邮政单号查询,邮政快递物流查询,并进行提前签收分析

批量查询邮政快递单号的物流信息&#xff0c;并将提前签收件分析筛选出来。 所需工具&#xff1a; 一个【快递批量查询高手】软件 邮政快递单号若干 操作步骤&#xff1a; 步骤1&#xff1a;运行【快递批量查询高手】软件&#xff0c;第一次使用的朋友记得先注册&#xff0c…

JAVA全栈开发 MySql详解

一、数据库 1.数据储存在哪里&#xff1f; 硬盘、网盘、U盘、光盘、内存&#xff08;临时存储&#xff09; 数据持久化 使用文件来进行存储&#xff0c;数据库也是一种文件&#xff0c;像excel &#xff0c;xml 这些都可以进行数据的存储&#xff0c;但大量数据操作&#x…

商家门店小程序怎么做?门店小程序的优势和好处

生活服务类商家在当前数字化时代&#xff0c;越来越认识到门店小程序的重要性。门店小程序不仅为商家提供了一个在线展示的窗口&#xff0c;更为其打造了一个与消费者直接互动的平台。有了门店小程序&#xff0c;商家可以更加便捷地管理商品信息、订单流程&#xff0c;同时还能…

网络机房的功能有哪些?

网络机房的功能主要包括&#xff1a; 信息存储和管理&#xff1a;机房作为信息系统的核心&#xff0c;需要提供可靠的存储和管理能力&#xff0c;包括服务器、存储设备、备份系统等硬件设备&#xff0c;以及数据备份、数据迁移、容灾等管理方法和技术。网络连接和通信&#xf…

北京市经信局局长姜广智带队调研三六零 强调大模型应与行业结合

12月6日&#xff0c;北京市经济和信息化局局长姜广智、副局长王磊带队走访调研三六零集团&#xff0c;就共促城市级数字安全基础设施项目落地&#xff0c;打造引领行业发展标杆项目&#xff0c;推动大模型落地应用赋能产业、行业发展等话题进行交流。360集团创始人周鸿祎接待来…

【数据结构】二叉树---C语言版

二叉树 一、树的概念及结构1.树的概念2.树的相关概念3.树的表示4.树在实际中的应用 二、二叉树的概念及结构1.二叉树的概念2.满二叉树3.完全二叉树4.二叉树的性质5.二叉树的储存结构 三、二叉树的遍历1.前序遍历2.中序遍历3.后序遍历4.层序遍历 四、手撕二叉树&#xff08;务必…

Linux-代码实现通过system v共享内存实现的进程间的通信

一.makefile编写 .PHONY:all all:processa processbprocessa : processa.ccg -o $ $^ -g -stdc11 processb : processb.ccg -o $ $^ -g -stdc11.PHONY:clean clean:rm -rf processa processb 二.创建system v共享内存 1.系统调用接口 key&#xff1a;a.key是一个数值…

【Java系列】函数式接口编程

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

数据结构之栈

作者简介&#xff1a; zoro-1&#xff0c;目前大二&#xff0c;正在学习Java&#xff0c;数据结构等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; 数据结构之栈 概念特性常用方法栈模拟实现接口实现…

OSHI-操作系统和硬件信息库

文章目录 引言一、快速入门1.1 OSHI的简介1.2 引入依赖1.3 涉及的包&#xff08;package&#xff09;1.4 涉及的核心类 二、操作系统信息&#xff1a;OperatingSystem2.1 总揽2.2 文件系统信息&#xff1a;FileSystem2.3 网络参数信息&#xff1a;NetworkParams2.4 进程信息&am…

C++ 函数详解

目录 函数概述 函数的分类 函数的参数 函数的调用 函数的嵌套调用 函数的链式访问 函数声明和定义 函数递归 函数概述 函数——具有某种功能的代码块。 一个程序中我们经常会用到某种功能&#xff0c;如两数相加&#xff0c;如果每次都在需要用到时实现&#xff0c;那…

状态机的练习:按键控制led灯

设计思路&#xff1a; 三个按键控制led输出。 三个按键经过滤波(消抖)&#xff0c;产生三个按键标志信号。 三个led数据的产生模块&#xff08;流水&#xff0c;跑马&#xff0c;闪烁模块&#xff09;&#xff0c;分别产生led信号。 这六路信号&#xff08;三路按键信号&am…