当前位置: 首页 > news >正文

我在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)三张照片

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


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()

在这里插入图片描述

相关文章:

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

文章目录 一、阈值处理1.1 OpenCV 提供了函数 cv2.threshold()和函数 cv2.adaptiveThreshold(),用于实现阈值处理1.1.1. cv2.threshold():(1)在函数cv2.threshold()中,参数threshold_type用于指定阈值处理的方式。它有以下几种可选的阈值类型…...

Yolov8实现瓶盖正反面检测

一、模型介绍 模型基于 yolov8n数据集采用SKU-110k,这数据集太大了十几个 G,所以只训练了 10 轮左右就拿来微调了 基于原木数据微调:训练 200 轮的效果 10 轮SKU-110k 20 轮原木 200 轮瓶盖正反面 微调模型下载地址https://wwxd.lanzouu.co…...

GAN:WGAN前作

WGAN前作:有原则的方法来训练GANs 论文:https://arxiv.org/abs/1701.04862 发表:ICLR 2017 本文是wgan三部曲的第一部。文中并没有引入新的算法,而是标是朝着完全理解生成对抗网络的训练动态过程迈进理论性的一步。 文中基本是…...

数据库应用:MongoDB 文档与索引管理

目录 一、理论 1.MongoDB文档管理 2.MongoDB索引管理 二、实验 1.MongoDB文档管理 2.MongoDB索引管理(索引添加与删除) 3.MongoDB索引管理(全文索引) 4.MongoDB索引管理(多列索引) 5.MongoDB索引管…...

Python批处理PDF文件,PDF附件轻松批量提取

PDF附件是指在PDF文档中嵌入的其他文件,如图像、表格、音频、视频或其他文档。这些附件可以与PDF文档一起存储、传输和共享,为文档提供了更丰富的内容和更多的功能。通过添加附件,我们可以将相关文件和信息捆绑在一起,使其更易于管…...

Python可迭代对象排序:深入排序算法与定制排序

更多Python学习内容:ipengtao.com 排序在计算机科学中是一项基础而关键的操作,而Python提供了强大的排序工具来满足不同场景下的排序需求。本文将深入探讨Python中对可迭代对象进行排序的方法,涵盖基础排序算法、sorted函数的应用、以及定制排…...

基于matlab的图像去噪算法设计与实现

摘 要 随着我们生活水平的提高,科技产品飞速更新换代,在信息传输中,图像传输所占的比重越来越大。但自然噪声会在图像传输时干扰其传输过程,甚至会使图片不能表达其原来的意义。去噪处理就是为了去除图像中的噪声,从而…...

NFTScan 正式上线 Starknet NFTScan 浏览器和 NFT API 数据服务

2023 年 11 月 30 号,NFTScan 团队正式对外发布了 Starknet NFTScan 浏览器,将为 Starknet 生态的 NFT 开发者和用户提供简洁高效的 NFT 数据搜索查询服务。NFTScan 作为全球领先的 NFT 数据基础设施服务商,Starknet 是继 Bitcoin、Ethereum、…...

2023年亚太杯APMCM数学建模大赛A题水果采摘机器人的图像识别

2023年亚太杯APMCM数学建模大赛 A题 水果采摘机器人的图像识别 原题再现 中国是世界上最大的苹果生产国,年产量约3500万吨。同时,中国也是世界上最大的苹果出口国,世界上每两个苹果中就有一个是中国出口的,世界上超过六分之一的…...

mysql which is not in SELECT list; this is incompatible with DISTINCT解决方案

mysql报错Expression #1 of ORDER BY clause is not in SELECT list, references column ‘xxx’ which is not in SELECT list; this is incompatible with DISTINCT解决方案: 这是在 mysql5.7 版本,DISTINCT 与 order by 在一起用时则会报3065错误。因…...

linux /proc 文件系统

/proc系统是一个伪文件系统,它只存在内存当中,而不占用外存空间,以文件系统的方式为内核与进程提供通信的接口。 /proc目录下有很多以数字命名的目录,每个数字代表进程号PID它们是进程目录。系统中当前运行的每一个进程在/proc下都…...

java开发之个微群聊自动添加好友

请求URL: http://域名/addRoomMemberFriend 请求方式: POST 请求头Headers: Content-Type:application/jsonAuthorization:login接口返回 参数: 参数名必选类型说明wId是String登录实例标识chatRoom…...

Git .gitignore 忽略文件不生效解决方法

.gitignore 匹配规则 *.sample    # 忽略所有 .sample 结尾的文件 !lib.sample    # 但 lib.sample 除外 /TODO    # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO build/    # 忽略 build/ 目录下的所有文件 doc/*.txt    # 会…...

【Java】16. HashMap

16. HashMap public static String find3(String key) {Map<String, String> map Map.of("bright", "小明","white", "小白","black", "小黑");return map.get(key); }Map.of 用来创建不可变的 Map&#…...

KMP基础架构

前言 Kotlin可以用来开发全栈, 我们所熟悉的各个端几乎都支持(除了鸿蒙) 而我们要开发好KMP项目需要一个好的基础架构,这样不仅代码更清晰,而且能共享更多的代码 正文 我们可以先将KMP分为前端和服务端 它们两端也能共享一些代码,比如接口声明,bean类,基础工具类等 前端和…...

递归实现选择排序.

思路: 1.定位数组中的最大元素或最小元素 2.将其与第一个元素交换位置 3.接着将剩余未排序的元素中的最大值或最小值与第二个元素交换位置 4.以此类推,直到排序完成 示例: [ 8, 5, 1, 9, 3 ] //原始数组 [ 1, 5, 8, 9, 3 ] //3与8交换 [ 1, 3, 8, 9, 5 ] //3与5交换 [ 1,…...

Node.js【文件系统模块、路径模块 、连接 MySQL、nodemon、操作 MySQL】(三)-全面详解(学习总结---从入门到深化)

目录 Node.js 文件系统模块&#xff08;二&#xff09; Node.js 文件系统模块&#xff08;三&#xff09; Node.js 文件系统模块&#xff08;四&#xff09; Node.js 路径模块 Node.js 连接 MySQL Node.js nodemon Node.js 操作 MySQL Node.js 应用 Node.js 文件系统模块…...

公司的销售经理面临哪些压力和挑战?

公司的销售经理面临哪些压力和挑战&#xff1f; 作为公司的销售经理&#xff0c;通常会面临以下挑战和压力&#xff1a; 1. 销售目标难以达成。销售经理需要承担销售目标&#xff0c;这通常是一项艰巨的任务。他们需要制定销售策略&#xff0c;与客户建立联系&#xff0c;并确保…...

【Linux系统编程】如何创建进程(什么是fork函数?进程创建的原理是什么?)

目录 一、前言 二、 进程创建的初次了解&#xff08;创建进程的原理&#xff09; 三、什么是fork函数&#xff1f; &#x1f4a6;初识fork函数 &#x1f4a6;fork函数的四个为什么&#xff1f; ⭐为什么fork()要给子进程返回0&#xff0c;给父进程返回子进程pid&#xff…...

【opencv】计算机视觉基础知识

目录 前言 1、什么是计算机视觉 2、图片处理基础操作 2.1 图片处理&#xff1a;读入图像 2.2 图片处理&#xff1a;显示图像 2.3 图片处理&#xff1a;图像保存 3、图像处理入门基础 3.1 图像成像原理介绍 3.2 图像分类 3.2.1 二值图像 3.2.2灰度图像 3.2.3彩色图像…...

Node——Node.js简介

Node.js是一个基于Chrome V8引擎的JavaScript运行时环境&#xff0c;它能够让JavaScript脚本运行在服务端&#xff0c;这使得JavaScript成为与PHP、Python等服务端语言平起平坐的脚本语言。 1、认识Node.js Node.js是当今网站开发中非常流行的一种技术&#xff0c;它以简单易…...

小型洗衣机什么牌子好又便宜?性价比迷你洗衣机推荐

由于日常所穿的内衣裤由于各种原因&#xff0c;时间一久就很容易产生细菌&#xff0c;而且和其他大件的衣物一起混洗&#xff0c;很容易造成细菌的交叉感染&#xff0c;积攒起来洗就更不卫生了&#xff0c;留在内衣裤上的分泌物会继续滋生细菌&#xff0c;比如闷热的环境下念珠…...

INFINI Easysearch 与华为鲲鹏完成产品兼容互认证

何为华为鲲鹏认证 华为鲲鹏认证是华为云围绕鲲鹏云服务&#xff08;含公有云、私有云、混合云、桌面云&#xff09;推出的一项合作伙伴计划&#xff0c;旨在为构建持续发展、合作共赢的鲲鹏生态圈&#xff0c;通过整合华为的技术、品牌资源&#xff0c;与合作伙伴共享商机和利…...

将linux服务器 设置成 proxy.SOCKS5 服务器

gpt: 如果你想在 Linux 服务器上设置一个 SOCKS5 代理服务器&#xff0c;你可以使用一些现有的工具&#xff0c;比如 Shadowsocks、Dante、或者其他支持 SOCKS5 协议的软件。下面是一个使用 Dante 的简单示例&#xff1a; 1. **安装 Dante&#xff1a;** bash sudo apt-g…...

无mac电脑生成uniapp云打包私钥证书的攻略

uniapp顾名思义是一个跨平台的开发工具&#xff0c;大部分uniapp的开发者&#xff0c;其实并没有mac电脑来开发&#xff0c;但是生成ios的证书&#xff0c;官网的教程却是需要mac电脑的&#xff0c;那么有没有办法无需mac电脑即可生成uniapp云打包的私钥证书呢&#xff1f; 下…...

py 启动默认浏览器

要在Python中启动默认浏览器&#xff0c;可以使用第三方库如webbrowser或pyperclip&#xff0c;也可以使用操作系统特定的命令行调用。以下是几个不同的方法&#xff1a; 使用webbrowser库&#xff1a; import webbrowser webbrowser.open("http://example.com")这…...

scala可变参数列表使用

在Scala中&#xff0c;可以使用可变参数列表&#xff08;varargs&#xff09;来定义一个函数&#xff0c;以接受可变数量的参数。示例如下&#xff1a; def printArgs(args: String*): Unit {args.foreach(println) }// 使用可变参数列表 printArgs("Hello", "…...

经验分享:JMeter控制RPS

一、前言 ​ RPS (Request Per Second)一般用来衡量服务端的吞吐量&#xff0c;相比于并发模式&#xff0c;更适合用来摸底服务端的性能。我们可以通过使用 JMeter 的常数吞吐量定时器来限制每个线程的RPS。对于RPS&#xff0c;我们可以把他理解为我们的TPS&#xff0c;我们就…...

JavaScript中的for循环你用对了吗?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript-for循环 目录 循环结构 循环思想&#xff08;三要素&#xff09; 实现…...

WordPress(10)解决中文连接问题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、修改的前后二、自定义结构讲明三、修改方法前言 提示:这里可以添加本文要记录的大概内容: 1.中文连接如:http://www.lplovemm.love/2023/11/12/测试 2.这种连接在提交sitemap收录的时…...