OpenCV快速入门:图像形态学操作

文章目录

  • 前言
  • 一、图像形态学基础
    • 1.1 背景介绍
    • 1.2 像素距离
      • 1.2.1 什么是像素距离?
      • 1.2.2 常见的像素距离度量方法
      • 1.2.3 计算像素距离的代码实现
    • 1.3 图像连通性
      • 1.3.1 什么是图像连通性?
      • 1.3.2 连通类型
      • 1.3.3 连通组件标记
      • 1.3.4 连通性在图像处理中的应用
    • 1.4 结构元素
      • 1.4.1 什么是结构元素?
      • 1.4.2 结构元素的类型
        • 1.4.2.1 矩形结构元素
        • 1.4.2.2 圆形结构元素
        • 1.4.2.3 十字形结构元素
        • 1.4.2.4 自定义结构元素
  • 二、膨胀与腐蚀
    • 2.1 膨胀操作
      • 2.1.1 膨胀操作的原理
      • 2.1.2 膨胀操作的应用
      • 2.1.3 膨胀操作的代码示例
    • 2.2 腐蚀操作
      • 2.2.1腐蚀操作的原理
      • 2.2.2腐蚀操作的应用
      • 2.2.3腐蚀操作的代码示例
  • 三、开运算与闭运算
    • 3.1 开运算
      • 3.1.1 开运算的应用
      • 3.1.2 开运算的代码示例
    • 3.2 闭运算
      • 3.2.1 闭运算的应用
      • 3.2.2 闭运算的代码示例
  • 四、黑帽运算与礼帽运算
    • 4.1 黑帽运算
      • 4.1.1 黑帽运算的应用
      • 4.1.2 黑帽运算的代码示例
    • 4.2 礼帽运算
      • 4.2.1 礼帽运算的应用
      • 4.2.2 礼帽运算的代码示例
  • 五、击中与击不中
    • 5.1 击中运算
    • 5.2 击不中运算
    • 5.3 击中与击不中运算的应用
    • 5.4 击中与击不中的代码示例
  • 六、细化与粗化
    • 6.1 细化操作
    • 6.2 粗化操作
    • 6.3 细化与粗化操作的应用
    • 6.4 细化与粗化的代码示例
  • 总结


前言

图像形态学是一门强大而有趣的技术,它通过对图像进行形态学操作,使图像更适合后续处理步骤。在本文中,我们将深入探讨OpenCV中的图像形态学操作,快速入门这一关键领域。

Logo

一、图像形态学基础

1.1 背景介绍

图像形态学作为数字图像处理的一个分支,致力于通过形态学操作实现对图像特征的提取、噪音的去除以及目标的分割。这一领域的研究为计算机视觉、图像识别和医学图像处理等领域提供了强大的工具和方法。

1.2 像素距离

在图像处理中,像素距离是一项关键的概念,它涉及到图像中像素点之间的空间关系。理解像素距离对于各种图像分析任务非常重要。

1.2.1 什么是像素距离?

像素距离是指图像中两个像素点之间的距离或度量。这一概念在许多图像处理任务中都有广泛的应用,例如目标的距离测量、轮廓分析等。

1.2.2 常见的像素距离度量方法

请参考机器学习中常见的距离公式和相似度计算方法简介中的常见的距离公式相关内容

1.2.3 计算像素距离的代码实现

在OpenCV中,计算像素距离通常使用 cv2.distanceTransform 函数。这个函数可以计算图像中每个像素点到最近的零值像素的距离。

import cv2
import numpy as np# 生成简单的二值化图像
image = np.zeros((300, 300), dtype=np.uint8)+150
cv2.rectangle(image, (50, 50), (250, 250), 0, -1)
cv2.circle(image, (200, 200), 50, 255, -1)margin = np.zeros((300, 10), dtype=np.uint8)
# 计算像素距离
distance_transform = cv2.distanceTransform(image, cv2.DIST_L2, 3)
distance_transform = cv2.normalize(distance_transform, None, 255,0, cv2.NORM_MINMAX, cv2.CV_8UC1)# 显示像素距离图像
cv2.imshow('Distance Transform', cv2.hconcat([image, margin, distance_transform]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Distance Transform

通过这样的计算,我们可以获得图像中每个像素点到最近的零值像素的距离,并在图像上进行可视化展示。

在图像处理中,像素距离是一项重要的概念,它为我们提供了衡量图像空间关系的有效工具。OpenCV中的 cv2.distanceTransform 函数使得计算像素距离变得简单而高效。在实际应用中,了解并熟练使用像素距离的概念,将有助于更好地理解和处理图像,为后续的图像形态学操作打下基础。

1.3 图像连通性

在图像处理中,图像连通性是一个关键概念,它描述了图像中像素点之间的连接关系。理解图像的连通性有助于分析和处理图像中的目标、区域及其结构。本节将深入讨论图像连通性的概念以及在OpenCV中的应用。

1.3.1 什么是图像连通性?

图像连通性是指图像中像素点之间的连接关系或连通关系。当两个像素点通过相邻的水平、垂直或对角线位置相连时,它们被认为是连通的。连通性的概念对于分析图像中的物体、区域或对象之间的连接关系至关重要。

1.3.2 连通类型

图像连通性可以根据连接像素点的方式分为不同类型,常见的包括:

  1. 4连通: 像素点通过水平和垂直方向相邻时被视为连通。

  2. 8连通: 像素点通过水平、垂直和对角线方向相邻时被视为连通。

  3. D连通: 一种介于4连通和8连通之间的连通类型,通常指像素点通过水平、垂直和对角线方向的一部分相邻时被视为连通。

在实际应用中,选择适当的连通类型取决于图像中目标的形状和特性。

1.3.3 连通组件标记

在图像处理中,常常需要标记和识别图像中的不同连通组件,即图像中连通的区域。这个过程被称为连通组件标记。OpenCV提供了相关函数来执行这一任务,如 cv2.connectedComponents

import cv2
import numpy as np# 生成简单的二值化图像
image = np.zeros((300, 300), dtype=np.uint8)+150
cv2.rectangle(image, (50, 50), (150, 150), 255, -1)
cv2.rectangle(image, (50, 50), (250, 250), 0, -1)
cv2.circle(image, (150, 150), 50, 255, -1)# 连通组件标记
num_labels, labels = cv2.connectedComponents(image)# 共享的参数
shared_params = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 2,"color": 255,"lineType": cv2.LINE_AA,
}
shared_params2 = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 10,"color": 0,"lineType": cv2.LINE_AA,
}
# 添加文字
cv2.putText(image, "Original Image",**shared_params)connected_image = cv2.hconcat([image])
for label in range(0, num_labels):component = np.zeros_like(image)component[labels == label] = 255cv2.putText(component, f'Component {label+1}', **shared_params2)cv2.putText(component, f'Component {label+1}', **shared_params)connected_image = cv2.hconcat([connected_image,component])cv2.imshow('Connected Components', connected_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Connected Components

在这个例子中,我们生成了一个简单的二值化图像,并使用 cv2.connectedComponents 对图像进行连通组件标记。通过遍历标记结果,我们可以分别显示不同的连通组件,以便更好地理解图像中的连通性。

一些场景中需要实现图像的连通性检测并在原图中用框线标出,我们可以使用OpenCV的cv2.connectedComponentsWithStats来获取图像中的连通组件。然后,遍历每个连通组件,获取其边界框信息,并在原图中用绿色矩形标出。

import cv2
import numpy as np
import random# 创建一个空白的图像
width, height = 500, 500
image = np.zeros((height, width, 3), dtype=np.uint8)# 定义绘制椭圆的函数
def draw_random_ellipse(img):# 生成随机椭圆的参数center = (random.randint(0, width-1), random.randint(0, height-1))axes = (random.randint(10, 100), random.randint(10, 100))angle = random.randint(0, 360)color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))# 绘制椭圆cv2.ellipse(img, center, axes, angle, 0, 360, color, -1)# 定义检查椭圆是否重叠的函数
def check_overlap(new_ellipse, existing_ellipses):for existing_ellipse in existing_ellipses:# 获取椭圆的掩码new_mask = np.zeros_like(image, dtype=np.uint8)existing_mask = np.zeros_like(image, dtype=np.uint8)cv2.ellipse(new_mask, new_ellipse[0], new_ellipse[1], new_ellipse[2], 0, 360, (255, 255, 255), -1)cv2.ellipse(existing_mask, existing_ellipse[0], existing_ellipse[1], existing_ellipse[2], 0, 360, (255, 255, 255), -1)# 检查是否有重叠的部分overlap = cv2.bitwise_and(new_mask, existing_mask)if np.sum(overlap) > 0:return Truereturn False# 生成不重叠的椭圆
num_ellipses = 10
ellipses = []
for _ in range(num_ellipses):while True:new_ellipse = ((random.randint(0, width-1), random.randint(0, height-1)),(random.randint(10, 100), random.randint(10, 100)),random.randint(0, 360),(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))if not check_overlap(new_ellipse, ellipses):ellipses.append(new_ellipse)break# 绘制不重叠的椭圆
for ellipse in ellipses:cv2.ellipse(image, ellipse[0], ellipse[1], ellipse[2], 0, 360, ellipse[3], -1)# 将图像转换为灰度
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 进行连通组件标记
_, labels, stats, centroids = cv2.connectedComponentsWithStats(gray_image)# 获取连通组件的数量(排除背景)
num_labels = len(stats) - 1# 遍历每个连通组件并在原图中用矩形标出
for i in range(1, num_labels + 1):x, y, w, h, _ = stats[i]cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)# 显示图像
cv2.imshow("Connected Components", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

一些运行效果图:

1.3.4 连通性在图像处理中的应用

  • 对象计数: 通过连通性分析,可以对图像中的对象进行计数,例如图像中的颗粒或细胞。

  • 区域分割: 连通性信息有助于对图像进行区域分割,使得图像中的不同部分能够被准确地提取和分析。

  • 目标识别: 在计算机视觉领域,通过连通性可以识别和跟踪图像中的目标,如人脸、车辆等。

图像连通性是图像处理中的一个基础而重要的概念,它为我们提供了理解和分析图像结构的有效工具。在OpenCV中,相关函数的支持使得连通性的计算变得更加便捷。通过深入理解图像连通性,我们能够更好地处理图像数据,为后续的图像分析和处理工作打下坚实的基础。

1.4 结构元素

在图像形态学操作中,结构元素是一种关键的概念,它为执行膨胀、腐蚀等操作提供了模板。本节将深入探讨结构元素的概念以及不同类型的结构元素在OpenCV中的应用。

1.4.1 什么是结构元素?

结构元素是一种小的、可以在图像上滑动的模板,用于定义形态学操作的形状和大小。它是膨胀、腐蚀、开运算和闭运算等操作的基础。

1.4.2 结构元素的类型

在OpenCV中,常见的结构元素有三种类型:矩形结构元素、圆形结构元素和十字形结构元素。

1.4.2.1 矩形结构元素

矩形结构元素是一种基本的结构元素,其形状为矩形。在图像处理中,矩形结构元素通常用于执行基本的膨胀和腐蚀操作。它的定义可以通过OpenCV的 cv2.getStructuringElement 函数实现:

import cv2
# 定义矩形结构元素
rectangle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 打印矩形结构元素
print(rectangle_kernel)

运行结果

[[1 1 1 1 1][1 1 1 1 1][1 1 1 1 1][1 1 1 1 1][1 1 1 1 1]]
1.4.2.2 圆形结构元素

圆形结构元素的形状为圆形,适用于处理需要考虑像素点周围更广泛范围的情况。同样,通过 cv2.getStructuringElement 函数可以轻松地创建圆形结构元素:

import cv2
# 定义圆形结构元素
circle_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
# 打印圆形结构元
print(circle_kernel)
[[0 0 1 0 0][1 1 1 1 1][1 1 1 1 1][1 1 1 1 1][0 0 1 0 0]]
1.4.2.3 十字形结构元素

十字形结构元素是一种与十字交叉形状相似的结构元素,适用于强调对角方向的形态学操作。创建十字形结构元素的方法如下:

import cv2
# 定义十字形结构元素
cross_kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
# 打印十字形结构元素
print(cross_kernel)
[[0 0 1 0 0][0 0 1 0 0][1 1 1 1 1][0 0 1 0 0][0 0 1 0 0]]
1.4.2.4 自定义结构元素

有时,我们可能需要根据具体任务定义自己的结构元素,例如使用特定的形状或大小。可以直接创建一个NumPy数组作为自定义的结构元素,然后传递给形态学操作的函数:

import cv2
import numpy as np# 定义自定义结构元素
custom_kernel = np.array([[0, 1, 0],[1, 1, 1],[0, 1, 0]], dtype=np.uint8)# 显示自定义结构元素
cv2.imshow('Custom Kernel', custom_kernel * 255)
cv2.waitKey(0)
cv2.destroyAllWindows()

二、膨胀与腐蚀

在图像处理中,膨胀与腐蚀是两种常用的图像形态学操作,它们分别用于扩大和减小图像中物体的区域,是图像处理中不可或缺的基础操作。

2.1 膨胀操作

膨胀是一种通过增加图像中物体的像素点来扩大物体的面积的操作。膨胀操作的核心思想是使用一个结构元素(通常是矩形、圆形或十字形),在图像上滑动,将结构元素的中心与图像中的像素匹配。如果结构元素的中心与图像中的像素点匹配,那么就将结构元素覆盖的区域置为白色(255)。

2.1.1 膨胀操作的原理

膨胀操作的数学表达可以用以下形式表示:

( A ⊕ B ) ( x , y ) = ⋃ ( i , j ) ∈ B A ( x + i , y + j ) (A \oplus B)(x, y) = \bigcup_{(i, j) \in B} A(x+i, y+j) (AB)(x,y)=(i,j)BA(x+i,y+j)

其中, A A A 是输入图像, B B B 是结构元素, ( A ⊕ B ) ( x , y ) (A \oplus B)(x, y) (AB)(x,y) 表示在图像 A A A 上对结构元素 B B B 进行膨胀操作的结果。在膨胀操作中,对于结构元素 B B B 中的每一个元素 ( i , j ) (i, j) (i,j),将图像 A A A 中与之对应的像素置为白色。最终的膨胀结果即为所有置为白色的像素的并集。

2.1.2 膨胀操作的应用

膨胀操作在图像处理中有多种应用场景:

  1. 连接物体: 将相邻的物体像素连接在一起,形成更大的物体。

  2. 填充小洞: 用于填充图像中小的空洞,使物体更加完整。

  3. 增加物体面积: 通过扩展物体的边界,增加物体的面积。

2.1.3 膨胀操作的代码示例

在OpenCV中,可以使用 cv2.dilate 函数进行膨胀操作。以下是一个简单的Python代码示例:
random_ellipse1
random_ellipse1.jpg

import cv2
import numpy as np# 读取图像
image = cv2.imread('random_ellipse1.jpg')
# 定义矩形结构元素
rectangle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 膨胀操作
dilated_image = cv2.dilate(image, rectangle_kernel, iterations=1)# 图像连通性
def draw_connected_image(src_img):# 将图像转换为灰度gray_image = cv2.cvtColor(src_img, cv2.COLOR_BGR2GRAY)# 二值化threshold_value = 20_, binary_image = cv2.threshold(gray_image, threshold_value, 255, cv2.THRESH_BINARY)# 进行连通组件标记_, labels, stats, centroids = cv2.connectedComponentsWithStats(binary_image)# 获取连通组件的数量(排除背景)num_labels = len(stats) - 1# 遍历每个连通组件并在原图中用矩形标出for i in range(1, num_labels + 1):x, y, w, h, _ = stats[i]cv2.rectangle(src_img, (x, y), (x + w, y + h), (0, 255, 0), 2)return src_img# 共享的参数
shared_params = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 2,"color": (0, 255, 0),"lineType": cv2.LINE_AA,
}
# 增加黑框
shared_params2 = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 10,"color": (0, 0, 0),"lineType": cv2.LINE_AA,
}
# 添加文字
image_txt = cv2.putText(image.copy(), "Original Image", **shared_params2)
image_txt = cv2.putText(image_txt, "Original Image", **shared_params)
dilated_image_txt = cv2.putText(dilated_image.copy(), "Dilated Image", **shared_params2)
dilated_image_txt = cv2.putText(dilated_image_txt, "Dilated Image", **shared_params)# 显示原始图像和膨胀结果
cv2.imshow('Dilated Image', cv2.vconcat([cv2.hconcat([image_txt, draw_connected_image(image.copy())]),np.zeros((10, image.shape[1] * 2, 3), dtype=np.uint8) + 255,cv2.hconcat([dilated_image_txt, draw_connected_image(dilated_image.copy())])
]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Dilated Image

我们可以看到,经过膨胀操作之后,有两处原本不相连的椭圆变为相连的情况。

2.2 腐蚀操作

与膨胀相反,腐蚀是一种通过减少物体的像素点来减小物体的面积的操作。腐蚀操作同样使用一个结构元素,当结构元素的中心与图像中的像素匹配时,仅当结构元素的所有像素都与图像中的像素匹配时,才将中心像素置为白色(255),否则置为黑色(0)。

2.2.1腐蚀操作的原理

腐蚀操作的数学表达可以用以下形式表示:

( A ⊖ B ) ( x , y ) = ⋂ ( i , j ) ∈ B A ( x + i , y + j ) (A \ominus B)(x, y) = \bigcap_{(i, j) \in B} A(x+i, y+j) (AB)(x,y)=(i,j)BA(x+i,y+j)

其中, A A A 是输入图像, B B B 是结构元素, ( A ⊖ B ) ( x , y ) (A \ominus B)(x, y) (AB)(x,y) 表示在图像 A A A 上对结构元素 B B B 进行腐蚀操作的结果。在腐蚀操作中,对于结构元素 B B B 中的每一个元素 ( i , j ) (i, j) (i,j),将图像 A A A 中与之对应的像素与结构元素的对应像素进行比较。如果结构元素覆盖的区域内所有像素都为白色,那么中心像素置为白色,否则置为黑色。最终的腐蚀结果即为所有中心像素为白色的区域的交集。

2.2.2腐蚀操作的应用

腐蚀操作在图像处理中有多种应用场景:

  1. 去除小物体: 用于去除图像中较小的物体或细小的细节。

  2. 平滑物体边界: 通过减小物体的边界,使其更加平滑。

  3. 分离连接的物体: 将相连的物体分离开,使其更容易识别和分析。

2.2.3腐蚀操作的代码示例

在OpenCV中,可以使用 cv2.erode 函数进行腐蚀操作。以下是一个简单的Python代码示例:
random_ellipse2
random_ellipse2.jpg

import cv2
import numpy as np# 读取图像
image = cv2.imread('random_ellipse2.jpg')
# 定义矩形结构元素
rectangle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 腐蚀操作
eroded_image = cv2.erode(image, rectangle_kernel, iterations=1)# 图像连通性
def draw_connected_image(src_img):# 将图像转换为灰度gray_image = cv2.cvtColor(src_img, cv2.COLOR_BGR2GRAY)# 二值化threshold_value = 20_, binary_image = cv2.threshold(gray_image, threshold_value, 255, cv2.THRESH_BINARY)# 进行连通组件标记_, labels, stats, centroids = cv2.connectedComponentsWithStats(binary_image)# 获取连通组件的数量(排除背景)num_labels = len(stats) - 1# 遍历每个连通组件并在原图中用矩形标出for i in range(1, num_labels + 1):x, y, w, h, _ = stats[i]cv2.rectangle(src_img, (x, y), (x + w, y + h), (0, 255, 0), 2)return src_img# 共享的参数
shared_params = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 2,"color": (0, 255, 0),"lineType": cv2.LINE_AA,
}
# 增加黑框
shared_params2 = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 10,"color": (0, 0, 0),"lineType": cv2.LINE_AA,
}
# 添加文字
image_txt = cv2.putText(image.copy(), "Original Image", **shared_params2)
image_txt = cv2.putText(image_txt, "Original Image", **shared_params)
eroded_image_txt = cv2.putText(eroded_image.copy(), "Eroded Image", **shared_params2)
eroded_image_txt = cv2.putText(eroded_image_txt, "Eroded Image", **shared_params)# 显示原始图像和腐蚀结果
cv2.imshow('Eroded Image', cv2.vconcat([cv2.hconcat([image_txt, draw_connected_image(image.copy())]),np.zeros((10, image.shape[1] * 2, 3), dtype=np.uint8) + 255,cv2.hconcat([eroded_image_txt, draw_connected_image(eroded_image.copy())])
]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Eroded Image

我们可以看到,有一处原本相连的椭圆,经过腐蚀操作后变为了不相连的两个椭圆。

三、开运算与闭运算

3.1 开运算

开运算原理是先对图像进行腐蚀操作,然后再对腐蚀结果进行膨胀操作。开运算通常用于去除图像中的小噪点、平滑物体边界,并保留物体的整体形状。在数学表达上,开运算可以表示为:

Opening ( A ) = ( A ⊖ B ) ⊕ B \text{Opening}(A) = (A \ominus B) \oplus B Opening(A)=(AB)B

其中, A A A 是输入图像, B B B 是结构元素, ⊖ \ominus 表示腐蚀操作, ⊕ \oplus 表示膨胀操作, Opening ( A ) \text{Opening}(A) Opening(A) 表示对图像 A A A 进行开运算的结果。

3.1.1 开运算的应用

开运算主要应用于以下场景:

  1. 去除小噪点: 通过先腐蚀操作,可以去除图像中小于结构元素的噪点。

  2. 平滑物体边界: 腐蚀操作会使物体边界向内收缩,而膨胀操作会使其向外扩张,从而平滑物体的边界。

  3. 保留整体形状: 开运算可以保留物体的整体形状,有助于提取物体的主要结构。

3.1.2 开运算的代码示例

在OpenCV中,可以使用 cv2.morphologyEx 函数进行开运算。以下是一个简单的Python代码示例:

import cv2
import numpy as np# 生成一个黑色背景的图像
image_size = (300, 300)
image = np.zeros(image_size, dtype=np.uint8)# 在图像中添加一些形状
cv2.circle(image, (50, 50), 20, 255, -1)
cv2.circle(image, (150, 150), 30, 255, -1)
cv2.rectangle(image, (200, 100), (250, 200), 255, -1)
cv2.ellipse(image, (100, 200), (40, 20), 30, 0, 360, 255, -1)
# 绘制白色椭圆弧
cv2.ellipse(image, (210, 210), (100, 50), 0, 180, 270, 255, 2)# 定义矩形结构元素
rectangle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 开运算操作
opening_result = cv2.morphologyEx(image, cv2.MORPH_OPEN, rectangle_kernel)# 图像连通性
def draw_connected_image(src_img):# 二值化threshold_value = 20_, binary_image = cv2.threshold(src_img, threshold_value, 255, cv2.THRESH_BINARY)# 进行连通组件标记_, labels, stats, centroids = cv2.connectedComponentsWithStats(binary_image)# 获取连通组件的数量(排除背景)num_labels = len(stats) - 1# 遍历每个连通组件并在原图中用矩形标出for i in range(1, num_labels + 1):x, y, w, h, _ = stats[i]cv2.rectangle(src_img, (x, y), (x + w, y + h), 127, 2)return src_img# 共享的参数
shared_params = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 2,"color": 255,"lineType": cv2.LINE_AA,
}
# 增加黑框
shared_params2 = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 10,"color": 0,"lineType": cv2.LINE_AA,
}
# 添加文字
image_txt = cv2.putText(image.copy(), "Original Image", **shared_params2)
image_txt = cv2.putText(image_txt, "Original Image", **shared_params)
opening_result_txt = cv2.putText(opening_result.copy(), "Opening Result", **shared_params2)
opening_result_txt = cv2.putText(opening_result_txt, "Opening Result", **shared_params)# 显示原始图像和开运算结果
cv2.imshow('Opening Result', cv2.vconcat([cv2.hconcat([image_txt, draw_connected_image(image.copy())]),np.zeros((10, image.shape[1] * 2), dtype=np.uint8) + 255,cv2.hconcat([opening_result_txt, draw_connected_image(opening_result.copy())])
]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Opening Result
通过理解开运算的原理和应用,我们可以更好地利用这一操作来去除图像中的噪点、平滑物体边界,从而为后续的图像分析和处理提供更清晰、更准确的数据。在实际应用中,可以根据具体情况选择不同的结构元素和迭代次数,以达到最佳的开运算效果。

3.2 闭运算

闭运算原理是先对图像进行膨胀操作,然后再对膨胀结果进行腐蚀操作。闭运算通常用于连接物体间的小孔、填充小的间隙,并保持物体的整体形状。在数学表达上,闭运算可以表示为:

Closing ( A ) = ( A ⊕ B ) ⊖ B \text{Closing}(A) = (A \oplus B) \ominus B Closing(A)=(AB)B

其中, A A A 是输入图像, B B B 是结构元素, ⊕ \oplus 表示膨胀操作, ⊖ \ominus 表示腐蚀操作, Closing ( A ) \text{Closing}(A) Closing(A) 表示对图像 A A A 进行闭运算的结果。

3.2.1 闭运算的应用

闭运算主要应用于以下场景:

  1. 连接物体间的小孔: 通过先膨胀操作,可以连接物体之间的小孔,使其更加连续。

  2. 填充小的间隙: 膨胀操作会使物体边界向外扩张,腐蚀操作会使其向内收缩,从而填充物体间的小间隙。

  3. 保持整体形状: 闭运算可以保持物体的整体形状,有助于提取物体的主要结构。

3.2.2 闭运算的代码示例

在OpenCV中,可以使用 cv2.morphologyEx 函数进行闭运算。以下是一个简单的Python代码示例:

import cv2
import numpy as np# 生成一个黑色背景的图像
image_size = (300, 300)
image = np.zeros(image_size, dtype=np.uint8)# 在图像中添加一些形状
cv2.circle(image, (50, 50), 20, 255, -1)
cv2.circle(image, (150, 150), 30, 255, -1)
cv2.rectangle(image, (200, 100), (250, 200), 255, -1)
cv2.ellipse(image, (100, 200), (40, 20), 30, 0, 360, 255, -1)
# 绘制白色椭圆弧
cv2.ellipse(image, (223, 223), (100, 50), 0, 210, 253, 255, 2)# 定义矩形结构元素
rectangle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 闭运算操作
closing_result = cv2.morphologyEx(image, cv2.MORPH_CLOSE, rectangle_kernel)# 图像连通性
def draw_connected_image(src_img):# 二值化threshold_value = 20_, binary_image = cv2.threshold(src_img, threshold_value, 255, cv2.THRESH_BINARY)# 进行连通组件标记_, labels, stats, centroids = cv2.connectedComponentsWithStats(binary_image)# 获取连通组件的数量(排除背景)num_labels = len(stats) - 1# 遍历每个连通组件并在原图中用矩形标出for i in range(1, num_labels + 1):x, y, w, h, _ = stats[i]cv2.rectangle(src_img, (x, y), (x + w, y + h), 127, 2)return src_img# 共享的参数
shared_params = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 2,"color": 255,"lineType": cv2.LINE_AA,
}
# 增加黑框
shared_params2 = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 10,"color": 0,"lineType": cv2.LINE_AA,
}
# 添加文字
image_txt = cv2.putText(image.copy(), "Original Image", **shared_params2)
image_txt = cv2.putText(image_txt, "Original Image", **shared_params)
closing_result_txt = cv2.putText(closing_result.copy(), "Closing Result", **shared_params2)
closing_result_txt = cv2.putText(closing_result_txt, "Closing Result", **shared_params)# 显示原始图像和闭运算结果
cv2.imshow('Closing Result', cv2.vconcat([cv2.hconcat([image_txt, draw_connected_image(image.copy())]),np.zeros((10, image.shape[1] * 2), dtype=np.uint8) + 255,cv2.hconcat([closing_result_txt, draw_connected_image(closing_result.copy())])
]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Closing Result
通过理解闭运算的原理和应用,我们可以更好地利用这一操作来连接物体间的小孔、填充小的间隙,从而使图像更加连续、完整。在实际应用中,可以根据具体情况选择不同的结构元素和迭代次数,以达到最佳的闭运算效果。

四、黑帽运算与礼帽运算

4.1 黑帽运算

黑帽运算原理是先对图像进行闭运算,然后将闭运算的结果与原始图像相减。黑帽运算主要用于强调图像中的小细节、小物体或者图像中的局部区域。在数学表达上,黑帽运算可以表示为:

BlackHat ( A ) = A − ( A ⊕ B ) \text{BlackHat}(A) = A - (A \oplus B) BlackHat(A)=A(AB)

其中, A A A 是输入图像, B B B 是结构元素, ⊕ \oplus 表示膨胀操作。黑帽运算的结果即为原始图像减去闭运算的结果。

4.1.1 黑帽运算的应用

黑帽运算主要应用于以下场景:

  1. 强调小细节: 通过突出图像中的小细节,使其更加突出。

  2. 增强小物体: 用于增强图像中的小物体,使其更容易被检测和识别。

  3. 局部区域处理: 对图像中的局部区域进行强调,有助于分析局部特征。

4.1.2 黑帽运算的代码示例

以下是一个简单的Python代码示例:

import cv2
import numpy as np# 生成一个黑色背景的图像
image_size = (300, 300)
image = np.zeros(image_size, dtype=np.uint8)# 在图像中添加一些形状
cv2.circle(image, (50, 50), 20, 255, -1)
cv2.circle(image, (150, 150), 30, 255, -1)
cv2.rectangle(image, (200, 100), (250, 200), 255, -1)
cv2.ellipse(image, (100, 200), (40, 20), 30, 0, 360, 255, -1)
# 绘制白色椭圆弧
cv2.ellipse(image, (223, 223), (100, 50), 0, 210, 253, 255, 2)# 定义矩形结构元素
rectangle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 黑帽运算
blackhat_result = cv2.morphologyEx(image, cv2.MORPH_BLACKHAT, rectangle_kernel)# 共享的参数
shared_params = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 2,"color": 255,"lineType": cv2.LINE_AA,
}
# 增加黑框
shared_params2 = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 10,"color": 0,"lineType": cv2.LINE_AA,
}
# 添加文字
image_txt = cv2.putText(image.copy(), "Original Image", **shared_params2)
image_txt = cv2.putText(image_txt, "Original Image", **shared_params)
blackhat_result_txt = cv2.putText(blackhat_result.copy(), "BlackHat Result", **shared_params2)
blackhat_result_txt = cv2.putText(blackhat_result_txt, "BlackHat Result", **shared_params)# 显示原始图像和黑帽运算结果
cv2.imshow('BlackHat Result', cv2.hconcat([image_txt,np.zeros((image.shape[0], 10), dtype=np.uint8) + 255,blackhat_result_txt]))
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

4.2 礼帽运算

礼帽运算原理是先对图像进行开运算,然后将开运算的结果与原始图像相减。礼帽运算主要用于强调图像中的大细节、大物体或者图像中的全局区域。在数学表达上,礼帽运算可以表示为:

TopHat ( A ) = ( A ⊕ B ) − A \text{TopHat}(A) = (A \oplus B) - A TopHat(A)=(AB)A

其中, A A A 是输入图像, B B B 是结构元素, ⊕ \oplus 表示膨胀操作。礼帽运算的结果即为开运算的结果减去原始图像。

4.2.1 礼帽运算的应用

礼帽运算主要应用于以下场景:

  1. 强调大细节: 通过突出图像中的大细节,使其更加显著。

  2. 增强大物体: 用于增强图像中的大物体,使其更容易被检测和识别。

  3. 全局区域处理: 对图像中的全局区域进行强调,有助于分析整体特征。

4.2.2 礼帽运算的代码示例

以下是一个简单的Python代码示例:

import cv2
import numpy as np# 生成一个黑色背景的图像
image_size = (300, 300)
image = np.zeros(image_size, dtype=np.uint8)# 在图像中添加一些形状
cv2.circle(image, (50, 50), 20, 255, -1)
cv2.circle(image, (150, 150), 30, 255, -1)
cv2.rectangle(image, (200, 100), (250, 200), 255, -1)
cv2.ellipse(image, (100, 200), (40, 20), 30, 0, 360, 255, -1)
# 绘制白色椭圆弧
cv2.ellipse(image, (223, 223), (100, 50), 0, 210, 253, 255, 2)# 定义矩形结构元素
rectangle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 礼帽运算
tophat_result = cv2.morphologyEx(image, cv2.MORPH_TOPHAT, rectangle_kernel)# 共享的参数
shared_params = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 2,"color": 255,"lineType": cv2.LINE_AA,
}
# 增加黑框
shared_params2 = {"org": (10, 30),"fontFace": cv2.FONT_HERSHEY_SIMPLEX,"fontScale": 1,"thickness": 10,"color": 0,"lineType": cv2.LINE_AA,
}
# 添加文字
image_txt = cv2.putText(image.copy(), "Original Image", **shared_params2)
image_txt = cv2.putText(image_txt, "Original Image", **shared_params)
tophat_result_txt = cv2.putText(tophat_result.copy(), "TopHat Result", **shared_params2)
tophat_result_txt = cv2.putText(tophat_result_txt, "TopHat Result", **shared_params)# 显示原始图像和礼帽运算结果
cv2.imshow('TopHat Result', cv2.hconcat([image_txt,np.zeros((image.shape[0], 10), dtype=np.uint8) + 255,tophat_result_txt]))
cv2.waitKey(0)
cv2.destroyAllWindows()

TopHat Result

通过理解黑帽运算和礼帽运算的原理和应用,我们可以更好地运用这两种操作来强调图像中的细节,实现更有针对性的图像处理效果。在实际应用中,可以根据具体情况选择不同的结构元素和运算类型,以达到最佳的效果。

五、击中与击不中

5.1 击中运算

击中运算用于检测图像中与给定模板相匹配的区域。在击中运算中,模板(结构元素)被应用于输入图像,只有当模板的所有像素与图像中对应位置的像素匹配时,才将中心像素置为白色(255),否则置为黑色(0)。数学表达上,击中运算可以表示为:

( A ⊙ B ) ( x , y ) = { 255 if  A ( x + i , y + j ) = B ( i , j ) for all  ( i , j ) ∈ B 0 otherwise (A \odot B)(x, y) = \begin{cases} 255 & \text{if } A(x+i, y+j) = B(i, j) \text{ for all } (i, j) \in B \\ 0 & \text{otherwise} \end{cases} (AB)(x,y)={2550if A(x+i,y+j)=B(i,j) for all (i,j)Botherwise

其中, A A A 是输入图像, B B B 是结构元素, ( A ⊙ B ) ( x , y ) (A \odot B)(x, y) (AB)(x,y) 表示在图像 A A A 上对结构元素 B B B 进行击中运算的结果。

5.2 击不中运算

击不中运算是击中运算的补操作,用于检测图像中与给定模板不匹配的区域。在击不中运算中,模板(结构元素)被应用于输入图像,只有当模板的所有像素与图像中对应位置的像素不匹配时,才将中心像素置为白色(255),否则置为黑色(0)。数学表达上,击不中运算可以表示为:

( A ⊘ B ) ( x , y ) = { 255 if  A ( x + i , y + j ) ≠ B ( i , j ) for all  ( i , j ) ∈ B 0 otherwise (A \oslash B)(x, y) = \begin{cases} 255 & \text{if } A(x+i, y+j) \neq B(i, j) \text{ for all } (i, j) \in B \\ 0 & \text{otherwise} \end{cases} (AB)(x,y)={2550if A(x+i,y+j)=B(i,j) for all (i,j)Botherwise

其中, A A A 是输入图像, B B B 是结构元素, ( A ⊘ B ) ( x , y ) (A \oslash B)(x, y) (AB)(x,y) 表示在图像 A A A 上对结构元素 B B B 进行击不中运算的结果。

5.3 击中与击不中运算的应用

  1. 目标检测: 击中运算可用于检测图像中是否存在特定形状的目标。

  2. 形态学骨架提取: 击中运算与击不中运算在形态学骨架提取中有广泛应用。

  3. 图像分割: 运算可用于分割图像中的不同区域。

5.4 击中与击不中的代码示例

在OpenCV中,可以使用 cv2.morphologyEx 函数进行击中与击不中运算。以下是一个简单的Python代码示例:

import cv2
import numpy as np# 生成一个黑色背景的图像
image_size = (300, 300)
image = np.zeros(image_size, dtype=np.uint8)# 在图像中添加一些形状
cv2.circle(image, (50, 50), 20, 255, -1)
cv2.circle(image, (150, 150), 30, 255, -1)
cv2.rectangle(image, (200, 100), (250, 200), 255, -1)
cv2.ellipse(image, (100, 200), (40, 20), 30, 0, 360, 255, -1)
# 绘制白色椭圆弧
cv2.ellipse(image, (223, 223), (100, 50), 0, 210, 253, 255, 2)
# 盐噪声
pepper_noise = np.random.rand(*image.shape) < 0.5
image[pepper_noise] = 0# 定义结构元素(内核)
kernel = np.array([[1, 0, 1],[0, -1, 0],[1, 0, 1]], dtype=np.int8)# 击中运算
hitmiss_hit_result = cv2.morphologyEx(image.copy(), cv2.MORPH_HITMISS, kernel)# 击不中运算
hitmiss_miss_result = cv2.morphologyEx(image, cv2.MORPH_HITMISS, cv2.bitwise_not(kernel))# 显示原始图像、击中运算结果和击不中运算结果
cv2.imshow('Hit and Miss Result', cv2.hconcat([image, hitmiss_hit_result, hitmiss_miss_result]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Hit and Miss在形态学操作中,结构元素是一个小的二进制矩阵(或核),它定义了要在图像上应用的操作的形状。结构元素中的元素值通常是0和1,其中1表示结构元素的一部分,0表示不是结构元素的一部分。负数通常用于表示不考虑的区域。

在形态学击中和击不中操作中,结构元素是由1、0和-1组成的。具体含义如下:

  • 1:表示目标的一部分(白色区域)。
  • 0:表示不考虑的区域。
  • -1:表示背景的一部分(黑色区域)。

在先前的代码示例中,kernel_hitkernel_miss中的1、0和-1的分布被设计为符合形态学击中和击不中的操作。这是为了确保在目标被击中时(kernel_hit),结构元素的白色部分与目标的白色部分重合,而在目标未被击中时(kernel_miss),结构元素的白色部分与目标的黑色背景部分重合。

这种表示方式可以根据具体的问题和需求进行调整,以确保形态学操作能够正确地捕捉目标的特定形状。

六、细化与粗化

6.1 细化操作

细化是一种形态学操作,用于减小二值图像中物体的宽度,使其更接近于图像中的中轴线。细化操作通过迭代地击中运算和击不中运算,逐渐减小物体的宽度。细化的数学表达可以表示为:

( A ⊗ B ) = A − ( A ⊙ B ) (A \otimes B) = A - (A \odot B) (AB)=A(AB)

其中, A A A 是输入图像, B B B 是结构元素, ⊗ \otimes 表示细化操作, ⊙ \odot 表示击中运算。细化操作的结果即为原始图像减去击中运算的结果。

6.2 粗化操作

粗化是细化操作的补操作,用于增加二值图像中物体的宽度,使其更接近于图像中的中轴线。粗化操作通过迭代地击中运算和击不中运算,逐渐增加物体的宽度。粗化的数学表达可以表示为:

( A ⊙ B ) ∪ A (A \odot B) \cup A (AB)A

其中, A A A 是输入图像, B B B 是结构元素, ⊙ \odot 表示击中运算。粗化操作的结果即为击中运算的结果与原始图像的并集。

6.3 细化与粗化操作的应用

  1. 骨架提取: 细化操作可用于提取图像中物体的骨架。

  2. 字符识别: 在字符识别中,细化可以帮助识别字符的主要形状。

  3. 图像分析: 细化和粗化操作可用于图像分析中的特征提取。

6.4 细化与粗化的代码示例

在OpenCV中,可以使用 cv2.morphologyEx 函数进行细化和粗化操作。以下是一个简单的Python代码示例:

import cv2
import numpy as np# 生成一个黑色背景的图像
image_size = (300, 300)
image = np.zeros(image_size, dtype=np.uint8)# 在图像中添加一些形状
cv2.circle(image, (50, 50), 20, 255, -1)
cv2.circle(image, (150, 150), 30, 255, -1)
cv2.rectangle(image, (200, 100), (250, 200), 255, -1)
cv2.ellipse(image, (100, 200), (40, 20), 30, 0, 360, 255, -1)
# 绘制白色椭圆弧
cv2.ellipse(image, (223, 223), (100, 50), 0, 210, 253, 255, 2)# 执行细化操作
thin = cv2.ximgproc.thinning(image, thinningType=cv2.ximgproc.THINNING_GUOHALL)# 执行粗化操作
# 创建形态学操作的结构元素
kernel = np.ones((3, 3), np.uint8)# 使用形态学操作执行粗化
thick = cv2.dilate(image, kernel, iterations=1)# 显示原始图像、细化操作结果和粗化操作结果
cv2.imshow('Thin and Thick Result', cv2.hconcat([image, thin, thick]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Thin and Thick Result

通过理解细化与粗化操作的原理和应用,我们可以更好地运用这两种操作来实现骨架提取、字符识别等图像处理任务。在实际应用中,可以根据具体情况选择不同的结构元素和迭代次数,以达到最佳的细化或粗化效果。


总结

在本文中,我们介绍了图像形态学的基础知识和操作。首先,通过背景介绍,我们了解到图像形态学在图像处理中的重要性。接着,讨论了像素距离的概念及其度量方法,并提供了计算像素距离的代码实现。图像连通性作为关键概念,我们详细介绍了其定义、不同的连通类型以及在图像处理中的应用。

结构元素作为形态学操作的基础,我们介绍了不同类型的结构元素,并展示了如何自定义结构元素。膨胀、腐蚀、开运算、闭运算、黑帽运算和礼帽运算等操作被详细解释,并提供了相应的代码示例。最后,我们了解了击中与击不中、细化与粗化操作及其在图像处理中的应用,并展示了相应的代码示例。

通过本文的学习,我们对图像形态学的原理和实际应用有基本的理解,能够灵活运用这些操作解决实际图像处理问题。形态学操作在计算机视觉、图像识别等领域有着广泛的应用,为图像处理提供了强大的工具和技术。

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

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

相关文章

在 el-table 中嵌入 el-checkbox el-input el-upload 多组件,实现复杂业务场景

由于业务场景的复杂性&#xff0c;需实现&#xff1a;在 el-table 表格中 嵌入 el-checkbox 多选框 及 el-input 输入框 及 el-upload 上传组件 &#xff0c;先附上实现效果图。 从图片可以看出其实就是一个规格可以带有多个属性的规格表&#xff0c;实现此效果需涉及到的知识点…

【机器学习基础】对数几率回归(logistic回归)

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习 欢迎订阅&#xff01;后面的内容会越来越有意思~ &#x1f4a1;往期推荐&#xff1a; 【机器学习基础】机器学习入门&#xff08;1&#xff09; 【机器学习基…

ADS村田电感.mod(spice netlist文件)和.s2p模型导入与区别

ADS村田电感.mod&#xff08;spice netlist文件&#xff09;和.s2p模型导入与区别 简介环境过程s2pspice netlist&#xff08;.mod文件&#xff09;导入和结果对比 简介 记录了ADS村田电感.mod&#xff08;spice netlist文件&#xff09;和.s2p模型导入与区别 环境 ADS2020 …

什么是UV贴图?

UV 是与几何图形的顶点信息相对应的二维纹理坐标。UV 至关重要&#xff0c;因为它们提供了表面网格与图像纹理如何应用于该表面之间的联系。它们基本上是控制纹理上哪些像素对应于 3D 网格上的哪个顶点的标记点。它们在雕刻中也很重要。 为什么UV映射很重要&#xff1f; 默认情…

opencv(2): 视频采集和录制

视频采集 相关API VideoCapture()cap.read()&#xff1a; 返回两个值&#xff0c;第一个参数&#xff0c;如果读到frame&#xff0c;返回 True. 第二个参数为相应的图像帧。cap.release() VideoCapture cv2.VideoCapture(0) 0 表示自动检测&#xff0c;如果在笔记本上运行&…

助力水泥基建裂痕自动化巡检,基于yolov5融合ASPP开发构建多尺度融合目标检测识别系统

道路场景下的自动化智能巡检、洞体场景下的壁体类建筑缺陷自动检测识别等等已经在现实生活中不断地落地应用了&#xff0c;在我们之前的很多博文中也已经有过很多相关的实践项目经历了&#xff0c;本文的核心目的是想要融合多尺度感受野技术到yolov5模型中以期在较低参数量的情…

计算属性与watch的区别,fetch与axios在vue中的异步请求,单文本组件使用,使用vite创建vue项目,组件的使用方法

7.计算属性 7-1计算属性-有缓存 模板中的表达式虽然很方便,但是只能做简单的逻辑操作,如果在模版中写太多的js逻辑,会使得模板过于臃肿,不利于维护,因此我们推荐使用计算属性来解决复杂的逻辑 <!DOCTYPE html> <html lang"en"> <head><meta …

Go vs Rust:文件上传性能比较

在本文中&#xff0c;主要测试并比较了Go—Gin和Rust—Actix之间的多部分文件上传性能。 设置 所有测试都在配备16G内存的 MacBook Pro M1 上执行。 软件版本为&#xff1a; Go v1.20.5Rust v1.70.0 测试工具是一个基于 libcurl 并使用标准线程的自定义工具&#xff0c;能…

【性能】如何计算 Web 页面的 FP 指标

什么是 FP 指标 FP (First Paint) 为首次渲染的时间点&#xff0c;在性能统计指标中&#xff0c;从用户开始访问 Web 页面的时间点到 FP 的时间点这段时间可以被视为 白屏时间&#xff0c;也就是说在用户访问 Web 网页的过程中&#xff0c;FP 时间点之前&#xff0c;用户看到的…

KeyarchOS的CentOS迁移实践:使用操作系统迁移工具X2Keyarch V2.0

KeyarchOS的CentOS迁移实践&#xff1a;使用操作系统迁移工具X2Keyarch V2.0 作者&#xff1a; 猫头虎博主 文章目录 KeyarchOS的CentOS迁移实践&#xff1a;使用操作系统迁移工具X2Keyarch V2.0&#x1f405;摘要引言1. 迁移前的精心准备1.1 系统环境介绍1.2 深度数据验证1.2.…

Maven编译报错:javacTask: 源发行版 1.8 需要目标发行版 1.8

报错截图&#xff1a; IDEA中的jdk检查都正常设置的1.8一点毛病没有。参考其他帖子链接如下&#xff1a; https://blog.csdn.net/zhishidi/article/details/131480199https://blog.51cto.com/u_16213460/7197764https://blog.csdn.net/lck_csdn/article/details/125387878 逐…

Vue指令修饰符、v-bind、v-model、computed计算属性、watch侦听器

前言 持续学习总结输出中&#xff0c;Vue指令修饰符、v-bind、v-model、computed计算属性、watch侦听器 一、指令修饰符 1.什么是指令修饰符&#xff1f; 所谓指令修饰符就是通过“.”指明一些指令后缀 &#xff0c;不同的后缀封装了不同的处理操作 —> 简化代码 2.按键…

LeetCode(29)三数之和【双指针】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 三数之和 1.题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复…

Android 13.0 Launcher3仿ios长按app图标实现抖动动画开始拖拽停止动画

1.概述 在13.0的系统rom定制化开发中,在对系统原生Launcher3的定制需求中,也有好多功能定制的,在ios等电子产品中 的一些好用的功能,也是可以被拿来借用的,所以在最近的产品开发需求中,需求要求模仿ios的 功能实现长按app图标实现抖动动画,接下来看如何分析该功能的实现…

电子学会2023年6月青少年软件编程(图形化)等级考试试卷(二级)真题,含答案解析

青少年软件编程(图形化)等级考试试卷(二级) 一、单选题(共25题,共50分) 1. 运行下列哪段程序,可以让狗狗走到木屋门口?( ) A.

微信第三方平台开发重点概念流程梳理

标题 微信开发的亿点点概念第三方平台代开发流程亿些概念开发流程 代公众号使用JS SDK一些概念具体流程引用 微信开发的亿点点概念 AppID&#xff1a;AppID是不同类型的产品的账号ID,是账号的唯一标识符。例如公众号的AppID、小程序的AppID、开放平台的AppID、第三方平台的App…

OceanBase:Zone管理

OceanBase 集群由若干个 Zone 组成。从物理层面来讲&#xff0c;一个 Zone 通常是一个独立的物理部署单元&#xff0c;可以是一个数据中心&#xff08;IDC&#xff09;或者云上的一个 Zone&#xff08;可用区&#xff09;&#xff0c;也可以是一个单独的机架&#xff08;Rack&a…

2023.11.15 hive sql之函数标准,字符串,日期,数学函数

目录 一.函数分类标准 二.查看官方函数,与简单演示 三.3种类型函数演示 四.字符串函数 1.常见字符串函数 2.索引函数 解析函数 五.日期函数 1.获取当前时间 2.获取日期相关 3.周,季度等计算 4.时间戳 六.数学函数 一.函数分类标准 目前hive三大标准 UDF:&#xff08…

Apache Hive源码阅读环境搭建

前置软件&#xff1a; JDK 1.8 Maven 3.3.9 1 下载源码 # 下载源码 git clone https://github.com/apache/hive.gitcd hive# 查看标签 git tag# 切换到要阅读的指定版本的tag git checkout rel/release-2.1.02 编译源码 mvn clean install -DskipTests执行报错 日志如下 E…

VisualBox7.0.12 主机和宿舍互PING设置

设置成桥接模式 主机设置 虚拟机设置