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

自适应二值化与形态学变换在图像颜色识别与替换中的应用解析

目录

  • 前言
  • 一、自适应二值化
  • 1.1 取均值 ADAPTIVE_THRESH_MEAN_C
  • 1.2 高斯加权求和 ADAPTIVE_THRESH_GAUSSIAN_C
  • 1.2.1 一维高斯分布
  • 1.2.2 二维高速分布
  • 1.2.3 二维高斯分布权重计算规则 
  • 1.2.3.1 用户设置了σ
  • 1.2.3.2 用户没有设置σ
  • 1.3 代码
  • 二、形态学变换
  • 2.1 核 
  • 2.2 腐蚀
  • 2.3 膨胀
  • 2.4 代码 
  • 三、图片颜色识别 
  • 3.1 RGB颜色空间
  • 3.2 HSV颜色空间
  •  3.3 色彩空间转换
  • 3.4 制作掩膜
  • 3.5 与运算
  • 3.6 代码 
  • 四、图片颜色的替换
  • 4.1 开运算
  • 4.2 颜色替换
  • 2. 代码
  • 五、练习集群
  • 5.1  练习1
  • 5.2  练习2
  • 5.3 练习3
  • 5.4 练习4
  • 5.5 练习5 
  • 5.6 练习6 
  • 总结

前言

书接上文

从像素到二值化:OpenCV图像处理实战入门指南-CSDN博客文章浏览阅读557次,点赞13次,收藏10次。本文通过OpenCV库实战解析机器视觉核心概念,从像素本质、三维矩阵存储原理切入,结合棋盘格绘制与通道拆分实验揭示计算机眼中的图像逻辑,重点探讨灰度化三大算法(加权平均/最大值/平均值)及六种二值化方法(阈值法/反阈值法/截断阈值法/零处理/OTSU算法),通过Python代码演示图像处理全流程,帮助读者快速掌握图像特征提取核心技能,提升工程实践能力。 https://blog.csdn.net/qq_58364361/article/details/146798890?fromshare=blogdetail&sharetype=blogdetail&sharerId=146798890&sharerefer=PC&sharesource=qq_58364361&sharefrom=from_link


一、自适应二值化

与上一章的二值化算法相比,自适应二值化更加适合明暗分布不均匀的图片,导致图片上每个小部分都有自己的前景和背景,此时可以使用自适应二值化,自适应二值化会对图像的所有像素点单独计算阈值,这样更好的针对每个像素点判断是前景还是背景。

自适应二值化可以更好的保留图片的信息。

参数

  • maxval最大值通常255
  • aadaptiveMethod:小区域阈值的计算方式
    • ADAPTIVE_THRESH_MEAN_C:小区域内取均值
    • ADAPTIVE_THRESH_GAUSSIAN_C:小区域内加权求和,权重是个高斯核
  • thresholdType:二值化方法
    • THRESH_BINARY 阈值法
    • THRESH_BINARY_INV 反阈值法
  • blockSize:小区域的面积,通常取奇数,例如7表示7*7,后期称之为核(各种滤波和卷积等都用的到),计算的方式为滑动(从左到右,从上到下)计算
  • c:最终阈值等于计算的阈值减去此值

1.1 取均值 ADAPTIVE_THRESH_MEAN_C

取blockSize=3,因此小区域面积为3*3,从原图的左上角像素点(162)开始计算其邻域的平均值,如果处于边缘区域就会进行边缘填充,填充值就是边界的像素点,如下所示。

计算九个点的平均值后减去c,就是最终当前像素点的阈值。

可以手动调节C值和BlockSize等值观察二值化结果:

  • C值越大前景色越多
  • blockSize分别为7和3的二值化效果


1.2 高斯加权求和 ADAPTIVE_THRESH_GAUSSIAN_C


1.2.1 一维高斯分布

高斯分布,通过概率密度函数进行定义,一维的高斯概率分布函数为

通过改变函数中和的值,我们可以得到如下图像,其中均值为μ,标准差为σ。


1.2.2 二维高速分布

根据一维高斯分布,拓展到二维高斯分布的表达式为:

高斯概率函数相对二维坐标产生,其中(x,y)为点坐标,以3*3的核为例,其点坐标分布如下:


1.2.3 二维高斯分布权重计算规则 

把1.2.2节的九个点坐标分别计算权重并不是简单的套用公式,而是要分为以下几种情况:

1.2.3.1 用户设置了σ

此时把σ和x,y分别带入高斯函数计算权重

1.2.3.2 用户没有设置σ

此时要看blockSize的大小,即核的边长。

  • 如果blockSize小于等于7

    此时直接套用固定系数

    例如核的blockSize=3时,使用转置矩阵进行乘法,得到九个点的权重值:

  • blockSize大于等于7

直接套用下面的公式:

size表示kernel(核)的尺寸,即blockSize,可以计算出σ的值,再结合(x,y)的坐标值带入到高斯密度函数中计算出权重。


1.3 代码

# 导入必要的库
import cv2               # OpenCV库,提供图像处理功能(版本需>3.0)
import numpy as np       # 数值计算库,用于处理矩阵运算
import matplotlib.pyplot as plt  # 绘图库,用于图像可视化(建议使用%matplotlib inline在Notebook中显示)# 定义图像显示函数
def show_image(image, name):"""图像显示工具函数(存在潜在问题需注意)参数:image: 输入图像(需为BGR或Grayscale格式)name : 显示图像的标题"""# 设置中文字体显示(仅在安装了中文字体的系统中有效)plt.rcParams['font.sans-serif'] = ['SimHei']       # 设置中文字体(Windows系统有效)plt.rcParams['axes.unicode_minus'] = False         # 解决负号显示为方块的问题# 注意:当传入单通道图像时,此转换会报错!# 解决方法:在显示灰度/二值图像前添加条件判断if len(image.shape) == 3:  # 仅当为三通道图像时进行转换image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)else:image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)  # 灰度图转RGB用于显示# 创建图像窗口plt.imshow(image)plt.title(name)     # 设置标题(依赖中文字体设置)plt.axis('off')     # 隐藏坐标轴# 主程序入口
if __name__ == '__main__':# 文件路径设置(建议使用os.path处理路径,增强跨平台兼容性)path = "image.jpg"  # 输入图像路径(需确保文件存在)# 读取原始图像(返回值检查建议:if image_np is None: 处理错误)image_np = cv2.imread(path)  # 默认读取为BGR格式的uint8数组# 创建1行2列的子图布局(121表示1行2列第1个位置)plt.figure(figsize=(10,5))  # 建议设置画布大小plt.subplot(121)show_image(image_np, "原始图像")  # 显示原始图像# 转换为灰度图像(可选方法:cv2.COLOR_BGR2GRAY)image_np_h = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)  # 输出为单通道矩阵# 自适应阈值处理(高斯加权法)"""参数详解:src:输入灰度图像(必须单通道)maxValue:满足阈值时设置的最大值(通常设为255)adaptiveMethod:ADAPTIVE_THRESH_MEAN_C:邻域均值法ADAPTIVE_THRESH_GAUSSIAN_C:高斯加权法(效果更好但更耗时)thresholdType:THRESH_BINARY: 二值化(白字黑底)THRESH_BINARY_INV:反二值化(黑底白字)blockSize:邻域大小(必须奇数,值越大背景噪点越少但细节丢失越多)C:从均值/加权均值中减去的常数(用于微调阈值)"""image_np_adaptive = cv2.adaptiveThreshold(image_np_h,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,77,  # 建议根据图像尺寸调整(典型值11-101)4    # 根据图像对比度调整(典型值2-10))# 保存处理结果(建议检查保存是否成功)cv2.imwrite("demo_adaptive.jpg", image_np_adaptive)  # 默认保存为单通道图像# 显示处理结果(需要处理单通道图像的显示问题)plt.subplot(122)show_image(image_np_adaptive, "自适应阈值")  # 当前版本已修复显示问题# 显示所有图像(在脚本中需要调用,Notebook中可能自动显示)plt.tight_layout()  # 添加自动调整布局plt.show()


二、形态学变换

形态学变换(Morphological Transformations)是一种基于形状的简单变换,它的处理对象通常是二值化后(白色前景,黑色背景)的图像。

形态学变换需要两个输入

  • 源图像(二值化)
  • 核(结构化元素)

输出为形态学变换后的图像:

  • 腐蚀
  • 膨胀

上面两种形态学变换的处理结果是相反的,腐蚀会让较亮的元素变少,膨胀会让较亮的元素变多。

节点参数如下:

  • morph_op_type 形态学操作类型
    • erode 腐蚀
    • dilate 膨胀
  • shape 核的形状
    • MORPH_RECT 矩形
    • MORPH_ELLIPSE 椭圆
    • MORPH_CROSS 十字形
  • ksize 核尺寸

以腐蚀、矩形核、3*3尺寸的参数为例,说明计算过程:

实际图像是11111111或00000000,下面用一个1或0代替。

最终计算结果:

需要注意的是,上面的边缘填充都是补零,使用的Border Constant规则,这种填充的规则是一圈都填充一个设定value值,例如0。

卷积核中的0区域不考虑,例如十字形和椭圆形。


2.1 核 

在上一章自适应二值化中已经接触过核的概念,实际上就是一个小区域,通常为3*3、5*5、7*7等,本章中的核会增加结构:

  • 矩形结构
  • 椭圆结构
  • 十字形结构

通过不同的结构可以对不同特征的图像进行形态学操作的处理。


2.2 腐蚀

后续的图像处理,通常都会把前景设置为白色,下面就是一个腐蚀的操作效果:

腐蚀操作的具体步骤如下:

1. 选择一个核kernel(模板template)的结构元素,它是一个定义好的小型矩阵,用于在图像上滑动(从左上到右下)。核的大小和形状会决定腐蚀操作的强度。

2. 滑动核:将核在原始图像中从左到右,从上到下滑动,每次滑动,核覆盖图像的一个区域。

3. 计算:与之前的自适应二值化不同,此处不再进行平均值计算,计算的是位与操作,例如二值化之后的图像只会有纯白和纯黑,纯白的二进制是11111111,纯黑的而执行是00000000。

4. 重复步骤:继续滑动核并重复上述过程,直到图像的所有部分都被处理。

5. 结果:腐蚀操作的结构是一个“更瘦”或“更小”的前景图像,因为白色区域的边缘被削减了,只要白色边缘的像素点有黑色像素,这些边缘就会被消除。


2.3 膨胀

膨胀操作的具体步骤如下:

1. 选择一个核kernel(模板template)的结构元素,它是一个定义好的小型矩阵,用于在图像上滑动(从左上到右下)。核的大小和形状会决定膨胀操作的强度。

2. 滑动核:将核在原始图像中从左到右,从上到下滑动,每次滑动,核覆盖图像的一个区域。

3. 计算:与之前的自适应二值化不同,此处不再进行平均值计算,计算的是位或操作,例如二值化之后的图像只会有纯白和纯黑,纯白的二进制是11111111,纯黑的而执行是00000000。

4. 重复步骤:继续滑动核并重复上述过程,直到图像的所有部分都被处理。

5. 结果:膨胀操作的结构是一个“更胖”或“更大”的前景图像,因为白色区域的边缘被扩大了,同时填充了前景之间的空隙,把黑色间隙通过膨胀填充为白色。


2.4 代码 

# 导入OpenCV计算机视觉库、numpy数学计算库和matplotlib绘图库
import cv2
import numpy as np
import matplotlib.pyplot as plt# 自定义图像显示函数(假设在别处已定义)
def show_image(img, title):"""将BGR格式图像转换为RGB格式并显示"""img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) if len(img.shape)==3 else imgplt.imshow(img_rgb, cmap='gray')plt.title(title)plt.axis('off')if __name__ == '__main__':# 图像路径(注意:实际使用时需要确保文件存在)path = "image_2.jpg"# 使用OpenCV读取图像,默认BGR格式image = cv2.imread(path)# 创建1x3的子图画布布局,激活第一个位置plt.subplot(131)# 显示原始BGR图像(show_image会做BGR到RGB的转换)show_image(image, "原始图像")# 将彩色图像转换为灰度图像image_h = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 使用Otsu自动阈值算法进行图像二值化# 参数说明:# 127:初始阈值(Otsu会自动覆盖这个值)# 255:最大值(超过阈值的像素设为白色)# THRESH_BINARY + THRESH_OTSU:组合使用二进制阈值和Otsu算法ret, image2 = cv2.threshold(image_h, 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 在第二个位置显示二值化结果plt.subplot(132)show_image(image2, "二值化图像")# 创建5x5矩形结构元素(用于形态学操作)kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))# 执行腐蚀操作(消除细小噪声,分离相邻物体)# 腐蚀原理:用结构元素扫描图像,取邻域内最小值image_fs = cv2.erode(image2, kernel)# 在第三个位置显示腐蚀后的图像plt.subplot(133)show_image(image_fs, "腐蚀图像")# 显示所有子图plt.show()


三、图片颜色识别 

在本章中,主要通过掩膜对原图像进行与运算来找到要识别的颜色。


3.1 RGB颜色空间

在图像处理中,最常见的就是RGB颜色空间。RGB颜色空间是我们接触最多的颜色空间,是一种用于表示和显示彩色图像的一种颜色模型。RGB代表红色(Red)、绿色(Green)和蓝色(Blue),这三种颜色通过不同强度的光的组合来创建其他颜色,广泛应用于我们的生活中,比如电视、电脑显示屏以及上面实验中所介绍的RGB彩色图。

RGB颜色模型基于笛卡尔坐标系,如下图所示,RGB原色值位于3个角上,二次色青色、红色和黄色位于另外三个角上,黑色位于原点处,白色位于离原点最远的角上。因为黑色在RGB三通道中表现为(0,0,0),所以映射到这里就是原点;而白色是(255,255,255),所以映射到这里就是三个坐标为最大值的点。

RGB颜色空间可以产生大约1600万种颜色,几乎包括了世界上的所有颜色,也就是说可以使用RGB颜色空间来生成任意一种颜色


3.2 HSV颜色空间

HSV颜色空间(HSV颜色模型,也成为HSL)是一种与RGB颜色模型并列的颜色空间表示法。

HSV颜色空间使用色调或色相(Hue)饱和度(Saturation)亮度或明度(Value)三个参数来表示颜色,色调H表示颜色的种类,如红色、绿色、蓝色等;饱和度表示颜色的纯度或强度,如红色越纯,饱和度就越高;亮度表示颜色的明暗程度,如黑色比白色亮度低。HSV颜色模型是一种六角锥体模型,如下图所示:

由于HSV颜色连续RGB更适合进行颜色范围划分常见颜色经过试验得到范围如下

由于颜色8所以最多表示256数字无法完全表示360°OpenCV重新换算色调角度范围0180°。

HSV三个属性是相互共同作用的,例如橙色必须是H范围11-25且S范围是43-255且V范围46-255。

HSV具有的优势如下:


 3.3 色彩空间转换


3.4 制作掩膜

掩膜(Mask)是一种在图像处理中常见的操作(类似于PS中的蒙版),它可以选择性地遮挡图像的某个部分,从而实现特定任务的目标。

 掩膜通常是一个二值化图像,并且与原图相同大小,其中目标区域被设置为1(白色),而其他区域设置为0(黑色),目标区域可以根据HSV的参数修改,上左图中就是制作红色掩膜的过程。

通过掩膜可以使用白色区域操作原图中的同位置像素。


3.5 运算


3.6 代码 

import cv2
import numpy as np
import matplotlib.pyplot as pltdef show_image(image, name):"""显示图像Args:image: 输入图像,可以是灰度图或彩色图name: 图像显示的标题"""plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题if len(image.shape) == 3:  # 如果是彩色图像image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # BGR转RGBelse:  # 如果是灰度图像image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)  # 灰度转RGBplt.imshow(image)  # 显示图像plt.title(name)    # 设置标题plt.axis('off')    # 关闭坐标轴if __name__ == '__main__':path = "sansequan.jpg"  # 图像路径image = cv2.imread(path)  # 读取图像hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)  # 将图像从BGR颜色空间转换到HSV颜色空间# 制作掩膜(同时识别黄色和青色)# 定义黄色的HSV范围yellow_low = np.array([26, 43, 46])    # 黄色下限yellow_high = np.array([34, 255, 255]) # 黄色上限# 制作黄色掩膜mask1 = cv2.inRange(hsv_image, yellow_low, yellow_high)  # 根据阈值创建黄色掩膜# 定义青色的HSV范围cyan_low = np.array([78, 43, 46])     # 青色下限cyan_high = np.array([99, 255, 255])   # 青色上限mask2 = cv2.inRange(hsv_image, cyan_low, cyan_high)  # 根据阈值创建青色掩膜# 合并黄色和青色掩膜mask = cv2.bitwise_or(mask1, mask2)  # 对两个掩膜进行或运算# 通过掩膜提取原图中的目标颜色区域res = cv2.bitwise_and(image, image, mask=mask)  # 按位与运算# 显示图像plt.figure(figsize=(8, 8), dpi=300)  # 创建画布plt.subplot(131)  # 1行3列第1个子图show_image(image, "原图")  # 显示原图plt.subplot(132)  # 1行3列第2个子图show_image(mask, "掩膜")   # 显示掩膜plt.subplot(133)  # 1行3列第3个子图show_image(res, "结果")    # 显示结果


四、图片颜色的替换

在上一个实验中,可以在图像中识别某一种(多种)颜色,那么就可以对这些颜色进行单独操作,比如替换成其他的颜色,原理就是在得到掩膜后,对掩膜中白色区域的原图进行一个像素值的修改。


4.1 运算

在形态学变换章节中学习了腐蚀和膨胀的工作原理,开运算就是先对图像进行腐蚀操作,再进行膨胀操作,开运算的效果是可以去除二值化图中的小噪点,并分离相连的物体。

运算节点参数如下

kernel表示尺寸

开运算的参数比较简洁,如果需要细节的操作,可以手动编程使用腐蚀和膨胀函数细节控制。

经过开运算,上图图像的连接部分和边缘毛刺都被消除。


4.2 颜色替换

由于掩膜与原图的大小相同,并且像素的一一对应的,可以得到掩膜中的白色区域坐标,把掩膜中所有白色区域的坐标带入到原图中,就可以得到原图中所有红色区域的坐标。拿到原图红色的坐标后,可以进行任何红色像素值的操作,例如修改颜色。


2. 代码

import cv2
import numpy as np
import matplotlib.pyplot as pltpath = "sigequan.jpg"
image = cv2.imread(path)
plt.figure(figsize=(8, 8), dpi=300)
plt.subplot(141)
show_image(image, "原图")
#hsv
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 制作红色掩膜
red_low = np.array([0, 43, 46])    # 红色下限
red_high = np.array([10, 255, 255]) # 红色上限
mask1 = cv2.inRange(hsv_image, red_low, red_high)  # 根据阈值创建红色掩膜
red_low = np.array([156, 43, 46])    # 红色下限
red_high = np.array([180, 255, 255]) # 红色上限
mask2 = cv2.inRange(hsv_image, red_low, red_high)  # 根据阈值创建红色掩膜
mask = cv2.bitwise_or(mask1, mask2)  # 对两个掩膜进行或运算
#展示一下掩膜
plt.subplot(142)
show_image(mask, "红色掩膜")
#开运算
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))  # 创建矩形结构元素
mask_opened = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)  # 开运算
plt.subplot(143)
show_image(mask_opened, "红色掩膜开运算")
plt.show()
#颜色替换
#遍历掩膜像素
for i in range(mask_opened.shape[0]):for j in range(mask_opened.shape[1]):if mask_opened[i,j] == 255:#修改原图颜色image[i,j] = (255,0,0)
#展示图片
show_image(image, "原图")
plt.show()


五、练习集群

5.1  练习1

墙上的贴纸用白色显示,墙用黑色显示,要求效果尽量好。

import cv2
import matplotlib.pyplot as pltdef show_image(image, name):"""显示图像Args:image: 输入图像(numpy数组)name: 图像标题(str)"""plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题if len(image.shape) == 3:  # 彩色图像image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # BGR转RGBelse:  # 灰度图像image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)  # 灰度转RGBplt.imshow(image)  # 显示图像plt.title(name)  # 设置标题plt.axis('off')  # 关闭坐标轴if __name__ == '__main__':path = "image.jpg"  # 图像路径image_np = cv2.imread(path)  # 读取图像plt.figure(figsize=(10,10),dpi=300)  # 创建画布plt.subplot(121)  # 子图1show_image(image_np, "原始图像")  # 显示原始图像# 图像处理部分image_np_h = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)  # 转为灰度图image_np_adaptive = cv2.adaptiveThreshold(image_np_h,  # 输入灰度图像255,  # 输出最大值cv2.ADAPTIVE_THRESH_GAUSSIAN_C,  # 自适应方法(高斯加权)cv2.THRESH_BINARY_INV,  # 二值化类型(反二值化)77,  # 邻域大小4  # 常数C)cv2.imwrite("demo_adaptive.jpg", image_np_adaptive)  # 保存结果plt.subplot(122)  # 子图2show_image(image_np_adaptive, "自适应阈值")  # 显示处理结果plt.tight_layout()  # 调整子图间距plt.show()  # 显示图像


5.2  练习2

处理整个图片,尽量只显示

,其他部分都是白色。

import cv2
import matplotlib.pyplot as pltdef show_image(image, name):"""显示图像Args:image: 输入图像(numpy数组)name: 图像标题(str)"""plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题if len(image.shape) == 3:  # 彩色图像image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # BGR转RGBelse:  # 灰度图像image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)  # 灰度转RGBplt.imshow(image)  # 显示图像plt.title(name)  # 设置标题plt.axis('off')  # 关闭坐标轴if __name__ == '__main__':path = "yaohe.jpg"  # 图像路径image_np = cv2.imread(path)  # 读取图像plt.figure(figsize=(10,10),dpi=300)  # 创建画布plt.subplot(121)  # 子图1show_image(image_np, "原始图像")  # 显示原始图像# 图像处理部分image_np_h = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)  # 转为灰度图image_np_adaptive = cv2.adaptiveThreshold(image_np_h,  # 输入灰度图像255,  # 输出最大值cv2.ADAPTIVE_THRESH_GAUSSIAN_C,  # 自适应方法(高斯加权)cv2.THRESH_BINARY,  # 二值化类型(反二值化)999,  # 邻域大小120  # 常数C)kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))  # 创建椭圆结构元素#膨胀image_np_dilate = cv2.dilate(image_np_adaptive, kernel)  # 膨胀操作kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))  # 创建更小的椭圆结构元素#腐蚀image_np_erode = cv2.erode(image_np_dilate, kernel)  # 第一次腐蚀image_np_erode = cv2.erode(image_np_erode, kernel)  # 第二次腐蚀image_np_erode = cv2.erode(image_np_erode, kernel)  # 第三次腐蚀plt.subplot(122)  # 子图2show_image(image_np_erode, "腐蚀")  # 显示腐蚀后的图像plt.show()  # 显示图像


5.3 练习3

识别下图中的蓝色(不包括云的边框)和橙色

#%%
import cv2
import numpy as np
import matplotlib.pyplot as pltdef show_image(image, name):"""显示图像Args:image: 输入图像(numpy数组)name: 图像标题(str)"""plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题if len(image.shape) == 3:  # 彩色图像image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # BGR转RGBelse:  # 灰度图像image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)  # 灰度转RGBplt.imshow(image)  # 显示图像plt.title(name)  # 设置标题plt.axis('off')  # 关闭坐标轴if __name__ == '__main__':path = "caihong.jpg"  # 图像路径image_np = cv2.imread(path)  # 读取图像plt.figure(dpi=300)  # 创建画布plt.subplot(241)  # 子图1show_image(image_np, "原始图像")#转换色彩空间image_np_hsv = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)  # 转为HSV图#制作掩膜#橙色掩膜o_low = np.array([11, 43, 46])  # 橙色下限o_high = np.array([25, 255, 255])  # 橙色上限mask = cv2.inRange(image_np_hsv, o_low, o_high)  # 掩膜1plt.subplot(242)show_image(mask, "橙色掩膜")#制作蓝色掩膜blue_low = np.array([110, 43, 46])  # 蓝色下限blue_high = np.array([124, 255, 255])  # 蓝色上限mask_blue = cv2.inRange(image_np_hsv, blue_low, blue_high)  # 掩膜1#开运算kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))  # 创建椭圆结构元素mask_blue = cv2.morphologyEx(mask_blue, cv2.MORPH_OPEN, kernel)  # 开运算plt.subplot(243)show_image(mask_blue, "蓝色掩膜")mask = mask + mask_blue  # 掩膜相加plt.subplot(244)show_image(mask, "掩膜")ret = cv2.bitwise_and(image_np, image_np, mask=mask)  # 掩膜与原图相乘plt.subplot(245)show_image(ret, "最终图像")plt.show()  # 显示图像


5.4 练习4

 把百事可乐的配色改为可口可乐风格

import cv2
import numpy as np
import matplotlib.pyplot as pltdef show_image(image, name):"""显示图像Args:image: 输入图像(numpy数组)name: 图像标题(str)"""plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题if len(image.shape) == 3:  # 彩色图像image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # BGR转RGBelse:  # 灰度图像image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)  # 灰度转RGBplt.imshow(image)  # 显示图像plt.title(name)  # 设置标题plt.axis('off')  # 关闭坐标轴if __name__ == '__main__':path = "kele.jpg"image = cv2.imread(path)plt.figure(dpi=300)plt.subplot(131)show_image(image, "原始图像")#图像处理部分image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)  # 转为HSV图#制作蓝色掩膜blue_low = np.array([90, 110, 110])  # 蓝色下限blue_high = np.array([120, 255, 255])  # 蓝色上限mask_blue = cv2.inRange(image_hsv, blue_low, blue_high)  # 掩膜1plt.subplot(132)show_image(mask_blue, "蓝色掩膜")for i in range(mask_blue.shape[0]):for j in range(mask_blue.shape[1]):if mask_blue[i][j] == 255:image[i][j] = [32, 45, 159]  # 将蓝色区域变为红色plt.subplot(133)show_image(image, "红色图像")plt.show()  # 显示图像


5.5 练习5 

 把越和幸运都换成蓝色,让墙变得更白

import cv2
import numpy as np
import matplotlib.pyplot as pltdef show_image(image, name):"""显示图像Args:image: 输入图像(numpy数组)name: 图像标题(str)"""plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题if len(image.shape) == 3:  # 彩色图像image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # BGR转RGBelse:  # 灰度图像image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)  # 灰度转RGBplt.imshow(image)  # 显示图像plt.title(name)  # 设置标题plt.axis('off')  # 关闭坐标轴path = "image.jpg"
image = cv2.imread(path)  # 读取图像
plt.figure(dpi=300)  # 创建画布,设置DPI
plt.subplot(331)  # 创建3x3子图,位置1
show_image(image, "原始图像")  # 显示原始图像# 图像处理部分
image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)  # 转为HSV色彩空间# 制作黑色掩膜
black_low = np.array([0, 0, 0])  # 黑色HSV下限
black_high = np.array([180, 255, 80])  # 黑色HSV上限
mask_black = cv2.inRange(image_hsv, black_low, black_high)  # 生成黑色区域掩膜# 制作蓝色掩膜
blue_low = np.array([90, 110, 110])  # 蓝色HSV下限
blue_high = np.array([120, 255, 255])  # 蓝色HSV上限
mask_blue = cv2.inRange(image_hsv, blue_low, blue_high)  # 生成蓝色区域掩膜# 制作黄色掩膜
yellow_low = np.array([15, 80, 0])  # 黄色HSV下限
yellow_high = np.array([40, 255, 255])  # 黄色HSV上限
mask_yellow = cv2.inRange(image_hsv, yellow_low, yellow_high)  # 生成黄色区域掩膜
plt.subplot(332)  # 子图位置2
show_image(mask_yellow, "黄色掩膜")  # 显示黄色掩膜# 制作红色掩膜
red_low = np.array([0, 50, 0])  # 红色HSV下限(低色调范围)
red_high = np.array([15, 255, 255])  # 红色HSV上限
red_mask = cv2.inRange(image_hsv, red_low, red_high)  # 生成红色区域掩膜(低色调)
red_low = np.array([150, 50, 0])  # 红色HSV下限(高色调范围)
red_high = np.array([200, 255, 255])  # 红色HSV上限
red_mask = red_mask + cv2.inRange(image_hsv, red_low, red_high)  # 合并高低色调红色掩膜
plt.subplot(333)  # 子图位置3
show_image(red_mask, "红色掩膜")  # 显示红色掩膜mask = mask_yellow + red_mask  # 合并黄色和红色掩膜
plt.subplot(334)  # 子图位置4
show_image(mask, "黄红组合掩膜")  # 显示组合掩膜# 把区域改成蓝色
for i in range(mask.shape[0]):  # 遍历图像高度for j in range(mask.shape[1]):  # 遍历图像宽度if mask[i][j] == 255:  # 如果是掩膜区域image[i][j] = (149,86,24)  # 修改为蓝色(BGR格式)
plt.subplot(335)  # 子图位置5
show_image(image, "转变字体颜色")  # 显示颜色修改后的图像mask = mask_blue + mask_yellow + red_mask + mask_black  # 合并所有颜色掩膜
plt.subplot(336)  # 子图位置6
show_image(mask, "完整掩膜")  # 显示完整掩膜# 掩膜取反
mask = 255 - mask  # 对掩膜取反
plt.subplot(337)  # 子图位置7
show_image(mask, "掩膜取反")  # 显示取反后的掩膜for i in range(mask.shape[0]):  # 遍历图像高度for j in range(mask.shape[1]):  # 遍历图像宽度if mask[i][j] == 255:  # 如果是掩膜区域image[i][j] = (255,255,255)  # 修改为白色(BGR格式)
plt.subplot(338)  # 子图位置8
show_image(image, "最终图像")  # 显示最终处理结果
plt.show()  # 显示图像


5.6 练习6 

把原图的噪点去掉。

import cv2
import numpy as np
import matplotlib.pyplot as pltdef show_image(image, name):"""显示图像Args:image: 输入图像(numpy数组)name: 图像标题(str)"""plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题if len(image.shape) == 3:  # 彩色图像image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # BGR转RGBelse:  # 灰度图像image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)  # 灰度转RGBplt.imshow(image)  # 显示图像plt.title(name)  # 设置标题plt.axis('off')  # 关闭坐标轴path = "quzao.jpg"
image = cv2.imread(path)  # 读取图像
image_fuben = image
plt.figure(dpi=300)  # 创建画布,设置DPI
plt.subplot(231)  # 创建2x3子图,位置1
show_image(image, "原始图像")  # 显示原始图像
# 图像处理部分
image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)  # 转为HSV色彩空间
image_hsv_fuben = cv2.cvtColor(image_fuben, cv2.COLOR_BGR2HSV)  # 转为HSV色彩空间
# 制作黄色掩膜
yellow_low = np.array([15, 80, 0])  # 黄色HSV下限
yellow_high = np.array([40, 255, 255])  # 黄色HSV上限
mask_yellow = cv2.inRange(image_hsv, yellow_low, yellow_high)  # 生成黄色区域掩膜
#制作红色掩膜
red_low = np.array([0, 50, 0])  # 红色HSV下限(低色调范围)
red_high = np.array([15, 255, 255])  # 红色HSV上限
red_mask = cv2.inRange(image_hsv, red_low, red_high)  # 生成红色区域掩膜(低色调)
red_low = np.array([150, 50, 0])  # 红色HSV下限(高色调范围)
red_high = np.array([200, 255, 255])  # 红色HSV上限
red_mask = red_mask + cv2.inRange(image_hsv, red_low, red_high)  # 合并高低色调红色掩膜
#制作绿色掩膜
green_low = np.array([35, 43, 46])  # 绿色HSV下限
green_high = np.array([77, 255, 255])  # 绿色HSV上限
mask_green = cv2.inRange(image_hsv, green_low, green_high)  # 生成绿色区域掩膜
#制作蓝色掩膜
blue_low = np.array([90, 110, 110])  # 蓝色HSV下限
blue_high = np.array([120, 255, 255])  # 蓝色HSV上限
mask_blue = cv2.inRange(image_hsv, blue_low, blue_high)  # 生成蓝色区域掩膜
#制作总掩膜
mask = mask_yellow + red_mask + mask_green + mask_blue  # 合并所有颜色掩膜
plt.subplot(232)  # 子图位置2
show_image(mask, "颜色掩膜")  # 显示颜色掩膜
#开运算
kernel = np.ones((5, 5), np.uint8)  # 定义卷积核
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)  # 开运算
# 掩膜取反
mask = 255 - mask  # 对掩膜取反
for i in range(mask.shape[0]):  # 遍历图像高度for j in range(mask.shape[1]):  # 遍历图像宽度if mask[i][j] == 255:  # 如果是掩膜区域image[i][j] = (255,255,255)  # 修改为白色(BGR格式)
#制作黑色掩膜
black_low = np.array([0, 0, 0])  # 黑色HSV下限
black_high = np.array([180, 254, 254])  # 黑色HSV上限
mask_black = cv2.inRange(image_fuben, black_low, black_high)  # 生成黑色区域掩膜
#膨胀
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2,2))
mask_black = cv2.dilate(mask_black, kernel)  # 膨胀
for i in range(mask_black.shape[0]):  # 遍历图像高度for j in range(mask_black.shape[1]):  # 遍历图像宽度if mask_black[i][j] == 255:  # 如果是黑色区域image[i][j] = (187,157,137)  # 修改为黑色(BGR格式)
plt.subplot(233)  # 子图位置3
show_image(image, "最终图像")  # 显示最终处理结果
plt.show()  # 显示图像


总结

        本文深入探讨图像处理中自适应二值化、形态学变换及颜色操作的核心技术。自适应二值化通过动态计算像素阈值,有效解决明暗不均图像的前景分离问题,其均值与高斯加权方法可灵活调整细节保留与噪声控制。形态学变换通过腐蚀、膨胀及开运算优化二值图像结构,消除噪声并增强目标特征。基于HSV颜色空间的掩膜技术结合位运算实现精准颜色识别,通过颜色范围定义与开运算优化掩膜后,完成特定颜色区域的像素替换。文中结合代码实例,展示了从二值化处理到颜色替换的全流程,为复杂场景下的图像分析提供实用解决方案。

相关文章:

自适应二值化与形态学变换在图像颜色识别与替换中的应用解析

目录 前言一、自适应二值化1.1 取均值 ADAPTIVE_THRESH_MEAN_C1.2 高斯加权求和 ADAPTIVE_THRESH_GAUSSIAN_C1.2.1 一维高斯分布1.2.2 二维高速分布1.2.3 二维高斯分布权重计算规则 1.2.3.1 用户设置了σ1.2.3.2 用户没有设置σ1.3 代码二、形态学变换2.1 核 2.2 腐蚀2.3 膨胀…...

JsonCpp 处理 JSON(现代 C++ 方案)(三)

第三部分:JsonCpp 处理 JSON(现代 C++ 方案) 📢 快速掌握 JSON!文章 + 视频双管齐下 🚀 如果你觉得阅读文章太慢,或者更喜欢 边看边学 的方式,不妨直接观看我录制的 JsonCpp 课程视频!🎬 视频里会用更直观的方式讲解 JsonCpp 的核心概念、实战技巧,并配有动手演…...

flutter 曲线学习 使用第三方插件实现左右滑动

flutter 曲线的使用 实现左右滑动 TemperatureChartPage() TemperatureChartPage2() – 不太完善 方法 ChartDrawPage import package:doluyo/dly_package/widget/dly_widget.dart; import package:fl_chart/fl_chart.dart; import package:flutter/material.dart; impor…...

【WRF工具】GIS4WRF详细介绍:配置 WPS/WRF

【WRF工具】GIS4WRF详细介绍 QGIS-GIS4WRF安装(Installation)安装 QGIS安装 GIS4WRF GIS4WRF 配置(Configuration)一、如何进入配置界面二、可配置内容1️⃣ 设置工作目录2️⃣ 与 WPS/WRF 集成3️⃣ 与 NCAR 数据档案集成 参考 GIS4WRF 是一个在 QGIS 中…...

【自用记录】本地关联GitHub以及遇到的问题

最近终于又想起GitHub,想上传代码和项目到仓库里。 由于很早之前有在本地连接过GitHub(但没怎么用),现在需要重新搞起(操作忘得差不多)。 在看教程实操的过程中遇到了一些小问题,遂记录一下。 前…...

小程序中跨页面组件共享数据的实现方法与对比

小程序中跨页面/组件共享数据的实现方法与对比 在小程序开发中,实现不同页面或组件之间的数据共享是常见需求。以下是几种主要实现方式的详细总结与对比分析: 一、常用数据共享方法 全局变量(getApp())、本地缓存(w…...

ngx_http_core_merge_srv_conf

定义在 src\http\ngx_http_core_module.c static char * ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) {ngx_http_core_srv_conf_t *prev parent;ngx_http_core_srv_conf_t *conf child;ngx_str_t name;ngx_http_server_name_t…...

如何在中科方德llinux系统上离线安装salt-minion

1,我的系统是什么 国产操作系统 中科方德 NFSChina Server release 4.0.240701 (RTM4-G320) 2,首先准备好两个安装包 salt-minion-2015.8.8-2.el7.noarch.rpm和salt-2015.8.8-2.el7.noarch.rpm 后者这个是前者的依赖项。 所以先安装salt-2015.8.8-2.e…...

RAG系统实战:当检索为空时,如何实现生成模块的优雅降级(Fallback)?

目录 RAG系统实战:当检索为空时,如何实现生成模块的优雅降级(Fallback)? 一、为什么需要优雅降级(Fallback)? 二、常用的优雅降级策略 策略一:预设后备提示&#xff0…...

输电线路航空标志球:低空飞行的安全路标 / 恒峰智慧科技

在现代社会,随着航空业的快速发展,低空飞行活动日益频繁。为了确保飞行安全,避免飞机与高压电线等障碍物发生碰撞,输电线路航空标志球应运而生。这种装置被广泛应用于高压输电线路上,尤其是超高压和跨江输电线&#xf…...

【SPP】蓝牙 SDP 协议在SPP中的互操作性解析

在蓝牙通信体系中,服务发现协议(SDP, Service Discovery Protocol)扮演着 "服务目录" 的核心角色。对于串口通信协议(SPP, Serial Port Profile)而言,SDP 服务记录是设备间建立串口连接的基础&am…...

本地部署vanna ai+通过http请求调用vanna

本地部署vanna ai ① 准备python环境,推荐最新的python12、13版本 ② 安装vanna库 我这里安装的python环境是python312 进入目录python312/Scripts,在该目录下的命令行窗口中输入以下命令:pip jinstall vanna pip install vanna③ 配置向…...

seq2seq

理解 transformer 中的 encoder decoder 详细的 transformer 教程见:【极速版 – 大模型入门到进阶】Transformer 文章目录 🌊 Encoder: 给一排向量输出另外一排向量🌊 Encoder vs. Decoder: multi-head attention vs. masked multi-head at…...

C++ ---- 虚继承

一、什么是虚继承 虚继承就是子类中只有一份间接父类的数据。用于解决多继承中的父类为非虚继承时出现的二义性问题,即菱形继承问题。继承方式需要加上virtual关键字。 二、虚继承的特性 以菱形继承为例: 1.不使用虚继承 根据输出的大小和关系图&…...

COMSOL多层圆片随机堆积三维模型

构建多层圆片随机堆积三维模型可用于材料、化工、土木、生物医学等多领域的研究,如复合材料设计、催化剂载体、颗粒物堆积研究等。本案例介绍在COMSOL内建立三维圆片堆积模型。 三维圆片堆积模型可采用CAD纤维密堆积3D插件建立,参数设置如图所示&#…...

PHP 开发API接口签名验证

就安全来说,所有客户端和服务器端的通信内容应该都要通过加密通道(HTTPS)传输,明文的HTTP通道将会是man-in-the- middle及其各种变种攻击的温床。所谓man-in-the-middle攻击简单讲就是指恶意的黑客可以在客户端和服务器端的明文通信通道上做手 脚&#x…...

Web开发-JavaEE应用ORM框架SQL预编译JDBCMyBatisHibernateMaven

知识点: 0、安全开发-JavaEE-构建工具-Maven 1、安全开发-JavaEE-ORM框架-JDBC 2、安全开发-JavaEE-ORM框架-Mybatis 3、安全开发-JavaEE-ORM框架-Hibernate 4、安全开发-JavaEE-ORM框架-SQL注入&预编译 一、演示案例-WEB开发-JavaEE-构建工具-Maven IDEA配置m…...

软考-数据库系统工程师第四版pdf

软考-数据库系统工程师第四版pdf git中的文件相对没有那么清楚,网盘的有高清版 github下载 这里我给出仓库地址 链接: https://github.com/yaodada123/ruankao-pdf https://github.com/yaodada123/ruankao-pdf gitee下载 https://gitee.com/yao-hengchao/ruank…...

扫描仪+文档pdf编辑器+pdf格式转换器

小扫描仪是一款集“扫描仪文档pdf编辑器pdf格式转换器”于一体的多功能扫描软件,软件功能丰富,而且目前是免费,功能包括扫描、编辑、转换三部分。 扫描:扫描的功能包括文档扫描、身份证扫描、护照扫描、书籍扫描、OCR和二维码。 扫…...

【stm32--HAL库DMA+USART+空闲中断不定长收发数据】

串口通信-Hal库实现不定长度收发,DMAUSART DMA串口STM32CUBEMX配置(工程创建)基础配置时钟配置工程配置 代码编写现象 DMA 在正式配置之前,我们先来一起简单了解一下DMA。DMA(Direct Memory Access,直接内…...

5G-A技术

最近的iOS 18.4 推送了 新功能,最引人注目的便是这个5G-A的这个功能,那什么是5G-A呢 ? 目前北京 四环内 还是有能显示出5G-A标志的。 5G-A 🌐 一句话概括: 5G-A 更快的速度 更低的延迟 更强的AI能力 更智能的网…...

Vue 组件 - 动态组件

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue 组件 - 动态组件 目录 动态组件 选项卡页面示例 更简单写法 增加输入框 弥补措施 总结 动态组件 选项卡页面示例 功能:选项卡功能,设置导航点击哪个显示相应页面。 设置三个全局组件&#…...

ffmpeg滤镜使用

ffmpeg实现画中画效果 FFmpeg中,可以通过overlay将多个视频流、多个多媒体采集设备、多个视频文件合并到一个界面中,生成画中画的效果 FFmpeg 滤镜 overlay 基本参数 x和y x坐标和Y坐标 eof action 遇到 eof表示时的处理方式,默认为重复。…...

【MVC简介-产生原因、演变历史、核心思想、组成部分、使用场景】

MVC简介 产生原因: MVC(Model-View-Controller)模式诞生于20世纪70年代,由Trygve Reenskaug在施乐帕克研究中心(Xerox PARC)为Smalltalk语言设计,目的是解决图形用户界面(GUI&…...

基于大模型的房间隔缺损手术全流程预测与方案优化研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与目标 1.3 研究方法与创新点 二、房间隔缺损概述 2.1 房间隔缺损定义与分类 2.2 发病机制与病理生理 2.3 流行病学特征 三、大模型在房间隔缺损预测中的应用原理 3.1 大模型技术简介 3.2 数据收集与预处理 3.3 模型…...

什么是 CSSD?

文章目录 一、什么是 CSSD?CSSD 的职责 二、CSSD 是如何工作的?三、CSSD 为什么会重启节点?情况一:网络和存储都断联(失联)情况二:收到其他节点对自己的踢出通知(外部 fencing&#…...

uniapp APP端在线升级(简版)

设计思路: 1.版本比较:应用程序检查其当前版本与远程服务器上可用的最新版本 2. 更新状态指示:如果应用程序是不是最新的版本,则页面提示下载最新版本。 3.下载启动:通过plus.downloader.createDownload()启动新应用…...

2024年蓝桥杯Java B组省赛真题超详解析-分布式队列

问题:你需要回答在某个时刻,队列中有多少个元素具有可见性 方案:跟踪每个副节点已经同步到主节点队列的元素数量,并找出所有副节点中同步到的最少元素数量,这个数量即为所有副节点都已经同步的元素数量。 解析&#…...

Vue3入门

环境准备: node.js vscode or webstorm 哪个熟悉用哪个 这两个都是傻瓜式安装 浏览器直接搜索 下载即可 安装: 安装完node.js之后 按住快捷键 winR 打开命令提示符输入node 将显示版本信息 接着我们通过 vite 构建vue3工程 优点: 轻量快速的热重载(HMR&#xf…...

向量库(Vector Database)概述

向量库(Vector Database)概述 1. 核心概念 ​向量 高维空间中的数值数组,通常由模型(如BERT、ResNet)将非结构化数据(文本、图像等)转换为嵌入向量。 ​向量相似性 衡量方法:余弦相…...

Oracle迁移达梦遇中断?试试SQLark的断点续迁功能!

在企业级数据迁移项目中,如果迁移单表数据量超过亿行、占用空间超过100GB时,一旦遇到网络中断或迁移报错,往往需要整表重新迁移,导致效率低下,严重影响项目进度。针对这一痛点,SQLark 支持对 Oracle→DM 的…...

上海某海外视频平台Android高级工程师视频一面

问的问题比较细,有很多小细节在里面,平时真不一定会注意到,做一个备忘: 1.Object类里面有哪些方法? Object 类是 Java 中所有类的根类,它定义了一些基本方法,供所有类继承和重写1. 常用方法 1…...

基于yolov11的汽车损伤检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv11的汽车损伤检测系统是一种先进的计算机视觉技术,旨在快速准确地识别汽车的各种损伤类型。该系统利用YOLOv11模型的强大性能,实现了对车辆损伤的精确检测与分类。 该系统能够识别的损伤类型包括裂纹(crack&#xff…...

华为IP(3)

DHCP Relay报文格式 DHCP Relay主要负责转发DHCP客户端与DHCP服务器之间的DHCP报文,所以DHCP Relay的报文格式只是把DHCP的报文部分字段做了相应的修改,报文格式没有发生变化 hops:表示当前DHCP报文经过DHCP中继的数目,该字段由…...

面试问题总结:qt工程师/c++工程师

C 语言相关问题答案 面试问题总结:qt工程师/c工程师 C 语言相关问题答案 目录基础语法与特性内存管理预处理与编译 C 相关问题答案面向对象编程模板与泛型编程STL 标准模板库 Qt 相关问题答案Qt 基础与信号槽机制Qt 界面设计与布局管理Qt 多线程与并发编程 目录 基础…...

【TS学习】(15)分布式条件特性

在 TypeScript 中,分布式条件类型(Distributive Conditional Types) 是一种特殊的行为,发生在条件类型作用于裸类型参数(Naked Type Parameter) 时。这种特性使得条件类型可以“分布”到联合类型的每个成员…...

四款高效数据报表工具 让数据分析更简单

概述 在数字化时代,企业和组织越来越依赖数据驱动决策,报表软件成为提高数据可视化能力、优化业务管理的关键工具。本文将为大家介绍四款功能强大的报表软件,帮助不同需求的企业找到合适的解决方案。 一、山海鲸报表 山海鲸报表是一款零代…...

QT 非空指针 软件奔溃

在用QT的实际项目中,出现如下现象: 运行软件再关闭软件,然后再运行软件会崩溃。等待5~10分钟,再运行软件,又正常,百思不得其解,后面找到原因是在头文件里定义指针变量时没有赋初nullptr&#x…...

图漾相机——C#语言属性设置

文章目录 前言1.示例程序说明2.SDK API功能介绍2.1 ListDevice2.2 Open2.3 OpenDeviceByIP2.4 Close2.5 DeviceStreamEnable2.6 DeviceStreamFormatDump2.7 DeviceStreamFormatConfig2.8 DeviceReadCurrentEnumData2.9 DeviceReadCalibData2.10 DeviceStreamOn2.11 DeviceStrea…...

WPF中viewmodel单例模式

1、单例模式介绍 单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。它常用于需要全局唯一访问点的场景,如配置管理、日志记录、数据库连接等。 2、WPF 中 ViewModel 的单例实现 在 WPF 中&#…...

AI比人脑更强,因为被植入思维模型【36】时光机理论思维

giszz的理解:据说是软银孙正义提出的一种思维模型,他利用同一时间内的地区差,通过引入技术、思维,在同一地区,形成了时间差。所谓商业模式,有时就是打空间差、时间差,信息差。 一、定义 时光机…...

SQL Server:用户权限

创建 & 删除 1. 创建用户命令整理 创建 admin2 用户 -- 在 master 数据库创建登录名 USE master; BEGINCREATE LOGIN [admin2] WITH PASSWORDNCljslrl0620!, DEFAULT_DATABASE[master], CHECK_EXPIRATIONOFF, CHECK_POLICYON; END;-- 在 db03 数据库创建用户并添加到相应…...

Qt之QTextEdit控制文本滚动, 停止滚动, 开始滚动, 鼠标控制滚动

对工作台文本框进行控制。含以下内容。详细说明在源码中可查看 至最底部停止滚动开始滚动 源码分两部分. .h文件和.cpp文件 MyTextEdit.h #ifndef MYTEXTEDIT_H #define MYTEXTEDIT_H#include <QObject> #include <QTextEdit> #include <QScrollBar> #includ…...

策略模式与元数据映射模式融合 JSR 380 验证规范实现枚举范围校验

类文件 Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER,ElementType.TYPE_USE }) Retention(RetentionPolicy.RUNTIME) Documented Constraint(validatedBy {InEnumValidator.class, InEnumColle…...

9对象树(3)

目录 创建自定义的类&#xff0c;最主要的目的,是自定义一个析构函数,在析构函数中,完成打印.方便咱们看到最终的自动销毁对象的效果!!! 写完一个函数的声名之后, 按下 altenter, 在按下enter就可以自动的在对应的 cpp 文件中添加函数的定义了 内置类型&#xff0c;析构不会明…...

深入 OpenPDF:高级 PDF 生成与操作技巧

1 引言 1.1 项目背景 在许多企业级应用中,生成和操作 PDF 文档是一个常见的需求。PDF(Portable Document Format)因其格式统一、易于打印和分发而被广泛使用。本文将介绍如何使用 OpenPDF 库在 Java 项目中生成和操作 PDF 文档。 1.2 技术选型理由 OpenPDF:OpenPDF 是一…...

电脑屏幕亮度随心控,在Windows上自由调整屏幕亮度的方法

调整电脑屏幕的亮度对于保护视力和适应不同环境光线条件非常重要。无论是在白天强光下还是夜晚昏暗环境中&#xff0c;合适的屏幕亮度都能让您的眼睛更加舒适。本文中简鹿办公小编将向您介绍几种在 Windows 系统中调整屏幕亮度的方法。 方法一&#xff1a;使用快捷键 大多数笔…...

Navicat导出mysql数据库表结构说明到excel、word,单表导出方式记录

目前只找到一张一张表导出的方式 使用information_schema传入表名查询 字段名根据需要自行删减&#xff0c;一般保留序号、字段名、类型、说明就行 SELECT COLUMNS.ORDINAL_POSITION AS 序号, COLUMNS.COLUMN_NAME AS 字段名, COLUMNS.COLUMN_TYPE AS 类型(长度), COLUMNS.N…...

【C++笔记】C++常见二叉树OJ和拓扑排序

【C笔记】C常见二叉树OJ和拓扑排序 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C笔记 文章目录 【C笔记】C常见二叉树OJ和拓扑排序前言一.二叉树OJ1.1 根据二叉树创建字符串1.2 二叉树的层序遍历1.3 二叉树的最近公共祖先1.4 将二叉搜索…...

ARM-----数据处理、异常处理、模式切换

实列一&#xff1a; 1. 异常向量表 area reset, code, readonly code32 entry area reset, code, readonly&#xff1a;定义一个名为reset的代码区域&#xff0c;只读。 code32&#xff1a;指示编译器生成32位ARM指令。 entry&#xff1a;标记程序的入口点。 2. 程序入口…...