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

news2024/11/17 23:28:27

文章目录

  • 一、阈值处理
    • 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 plt

x=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 plt

img = 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 plt

imgOpen=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.coloradmin.cn/o/1270410.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

认识并初步使用shell脚本

目录 一、什么是Shell脚本 二、变量与运算 三、逻辑判断 四、循环 五、函数 六、中断与继续 一、什么是Shell脚本 在前面学习了Linux的基本指令,而shell脚本其实就是是这些命令的集合。 那么为什么需要shell脚本呢? 因为可以用来实现一些复杂的操…

git丢弃本地操作,强制使用线上最新代码

借鉴:弃用本地分支所有代码,获取远程分支最新代码_git获取远程最新分支_小中.的博客-CSDN博客 1.问题:git pull结果发现本地仓库比线上代码提前l两个commit。本地未进行任何操作。需要直接使用线上最新代码。ps:Author都是某同事。 2.操作: …

旅游网站的技术SEO:技巧与最佳实践

技术SEO在旅游网站中的作用 旅游网站都是关于用户体验和参与度的。但是,在开始处理这些参数之前,您需要努力使用户登陆您的网站。这意味着你需要让你的网站在搜索引擎结果页面(SERP)中排名。 一旦你在搜索引擎结果中获得曝光&am…

什么是PDM图纸管理系统?PDM图纸管理系统主要功能有哪些?

PDM (Product Data Management) 图纸管理系统 是用于管理企业内部图纸和相关文件的软件系统。它提供了一个集中存储、组织和跟踪图纸和文件的平台,以确保团队成员能够轻松访问、共享和更新所需的工程设计和制造数据。 彩虹PDM系统|PDM产品数据管理系统|BOM管理|工艺…

记录仿钉钉审批流(将MySQL换成Oracle)走过的坑

需求:实现审批流程 在Gitee上发现了一个功能还OK的项目,于是就clone下来了(如下图) 原项目用MySQL很好启动,B站上作者还录制了视频,可以去学习 这里主要记录将MySQL换成Oracle出现的问题 首先&#xff0c…

详解API开发【电商平台API封装商品详情SKU数据接口开发】

1、电商API开发 RESTful API的设计 RESTful API是一种通过HTTP协议发送和接收数据的API设计风格。它基于一些简单的原则,如使用HTTP动词来操作资源、使用URI来标识资源、使用HTTP状态码来表示操作结果等等。在本文中,我们将探讨如何设计一个符合RESTfu…

Embassy 库下载代码示例

解决方案: swift import Embassy let downloader Downloader() // 使用代理主机和端口 downloader.useProxy(proxyHost: ") // 下载 URL 的内容 let content downloader.download(from: "") // 输出下载的内容 print(content) 这个程序首先…

STM32 Nucleo-64 boards 外设资源引脚对应关系图

STM32 Nucleo-64 boards 外设资源引脚对应关系图 1. STM32 NUCLEO-F103RB1.1 串口对应关系图1.2 I2C对应关系图【参考博文】1. STM32 NUCLEO-F103RB 1.1 串口对应关系图 1.2 I2C对应关系图 注意:STM32 NUCLEO-F103RB

清早送朋友的阳光早安问候语祝福,愿你好运同行

1、早上好!送上清晨第一缕阳光,伴随着燕舞蝶飞的风声,给您最温馨的问候。让心情放飞,让梦想翱翔,让生命绽放。祝您每天都充满能量,前程似锦! ​ 2、平凡就是幸福,简单就是快乐&…

塑料注塑件自动化光学测量蓝光自动化三维检测解决方案-CASAIM-IS(2ND)

一、背景介绍 在塑料制品的生产过程中,注塑件的质量对于产品的整体质量和性能至关重要。然而,通过使用三坐标、卡尺、千分尺等量具,对工件进行单点或人工检测其加工精度,对复杂形位公差检测目前比较难取得数据,无法快…

基于Java SSM框架实现高校二手交易平台系统项目【项目源码+论文说明】

基于java的SSM框架实现高校二手交易平台系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个高校二手交易平台,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将…

基于three.js生成动态波浪背景效果

文章目录 前言一、安装three二、新建waves.js文件三、引入waves.js文件比查看效果如有启发,可点赞收藏哟~ 前言 基于three.js生成动态波浪背景效果 一、安装three npm i three -S二、新建waves.js文件 注意geometry.setAttribute和geometry.addAttribute和在不同…

一,vue3 解构 获取值 双向绑定 二。数据监听 双向绑定 三。冒泡排序

一&#xff0c;vue3 解构 获取值 双向绑定 <template><nav><!-- 按钮 --><!-- 绑定事件的弹框 v-on --><button click"submit">弹出</button><br><!-- 、双向绑定 --><input v-model"num" place…

Java(十)(网络编程,UDP,TCP)

目录 网络编程 两种软件架构 网络通信的三要素 IP IPv4的地址分类 特殊IP 端口号 协议 用UDP协议发送数据 用UDP接收数据 TCP接收和发送数据 TCP通信--支持与多个客户端同时通信 网络编程 可以让设备中的程序与网络上其他设备的程序进行数据交互(实现网络通信) 两…

TA-Lib学习研究笔记(二)——Overlap Studies下

TA-Lib学习研究笔记&#xff08;二&#xff09;——Overlap Studies下 &#xff08;11&#xff09;SAR - Parabolic SAR 抛物线指标 函数名&#xff1a;SAR 名称&#xff1a; 抛物线指标 简介&#xff1a;抛物线转向也称停损点转向&#xff0c;是利用抛物线方式&#xff0c;随…

【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能

文章目录 ⭐⭐⭐Spring核心源码分析自定义Spring框架⭐⭐⭐一、Spring使用回顾二、Spring核心功能结构1、Spring核心功能2、bean概述 三、Spring IOC相关接口分析1、BeanFactory解析2、BeanDefinition解析3、BeanDefinitionReader解析4、BeanDefinitionRegistry解析5、创建容器…

【Linux】tar 命令使用

tar 命令 tar&#xff08;英文全拼&#xff1a;tape archive &#xff09;命令用于备份文件。tar 是用来建立&#xff0c;还原备份文件的工具程序&#xff0c;它可以加入&#xff0c;解开备份文件内的文件。 著者 由约翰吉尔摩和杰伊芬拉森撰写。 语法 tar [选项] [压缩后文…

【Lustre相关】功能实践-03-文件级冗余(FLR)

一、前言 DDN-03.11-File Level Redundancy (FLR) Category:FLR 1、功能介绍 在文件级冗余&#xff08;File Level Redundancy&#xff0c;FLR&#xff09;特性出现之前&#xff0c;Lustre文件系统数据冗余完全依赖于后端存储设备&#xff08;如RAID6&#xff09;。 Lustre在L…

【数据挖掘】国科大刘莹老师数据挖掘课程作业 —— 第二次作业

Written Part 1. 给定包含属性&#xff5b;Height, Hair, Eye&#xff5d;和两个类别&#xff5b;C1, C2&#xff5d;的数据集。构建基于信息增益&#xff08;info gain&#xff09;的决策树。 HeightHairEyeClass1TallBlondBrownC12TallDarkBlueC13TallDarkBrownC14ShortDark…

C++输出100以内的素数

以下是一个简单的C程序&#xff0c;用于输出100以内的所有素数&#xff1a; #include <iostream>using namespace std;int main() { int num, i, flag 0; for(num 2; num < 100; num) { flag 0; for(i 2; i < num/2; i) { if(…