计算机视觉(opencv-python)之图像预处理基本操作(待补充)
图像预处理是计算机视觉任务中的关键步骤,它通过对原始图像进行处理,以提高后续图像分析、特征提取和识别的准确性。
示例图片
目录
常见图像处理方法
灰度化处理
法一
法二
说明
切片截取部分图像数据
cv2.cvtColor() 颜色空间转换
cv2.split():颜色通道提取
cv2.resize():修改图像尺寸
cv2.addWeighted()图像融合
cv2.merge()图像合并
cv2.copyMakeBorder()边界填充
cv2.threshold()全局阈值法图像二值化
cv2.adaptiveThreshold()自适应阈值法图像二值化
图像形态学基本操作
cv2.morphologyEx()函数简介
cv2.erode()腐蚀操作
腐蚀原理
cv2.dilate() 膨胀操作
膨胀原理
cv2.morphologyEx()实现开闭运算
开运算原理
闭运算原理
代码
图像几何变化操作
图像直方图修正操作
图像空域滤波操作
常见图像处理方法
灰度化处理
法一
#灰度化处理
#法1,直接读取灰度图
import cv2
gray_image=cv2.imread('test.jpg',cv2.IMREAD_GRAYSCALE)
cv2.imshow('gray_image',gray_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果
法二
#灰度化处理
#法2,读取时不指定 flags(默认 cv2.IMREAD_COLOR),然后使用 cv2.cvtColor 转换为灰度图
import cv2
image=cv2.imread('test.jpg',cv2.IMREAD_UNCHANGED)
grayt_image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv2.imshow('gray_image',gray_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果
说明
两种方法都可对彩色图像进行灰度化处理,法一是在读取图像的同时将其转换为灰度图像。法二则是先读取彩色图像,再进行颜色空间转换。法一相对于法二更加节省内存,因为法一在图像处理的读取时就进行了灰度化处理,避免了彩色图像占用的大量内存空间。
这两种处理方法的结果是一致的:
切片截取部分图像数据
读取后的图像是(高,宽,通道数)的ndarray结构,若我们对图像的某一部分感兴趣,那我们只需要在高和宽对应的数组上进行切片即可获取到图像的部分数据。
#截取部分图像数据
import cv2
image=cv2.imread('test.jpg',cv2.IMREAD_UNCHANGED)
cv2.imshow('image',image[100:500,0:300])
cv2.waitKey(0)
cv2.destroyAllWindows()
原图像的尺寸为500x500,这里我们对其进行切片截取。截取区域为高[100:500]x宽[0:300]。
cv2.cvtColor() 颜色空间转换
cv2.cvtColor()是OpenCV库中一个非常实用的函数,它能够将图像从一个颜色空间转换到另一个颜色空间。这种转换在图像处理中非常有用,因为不同的颜色空间对于特定的图像处理任务可能具有不同的优势。例如,在边缘检测中,灰度图像往往比彩色图像更有效。
#cv2.cvtColor()颜色空间转化
import cv2
image=cv2.imread('test.jpg')
image=cv2.cvtColor(src=image,code=cv2.COLOR_BGR2HSV)
#常用的颜色转化code
#BGR->Gray cv2.COLOR_BGR2GRAY
#BGR->HSV cv2.COLOR_BGR2HSV
#BGR->RGB cv2.COLOR_BGR2RGB
#BGR->CMYK cv2.COLOR_BGR2CMYK#RGB->BGR cv2.COLOR_RGB2BGR
#RGB->HSV cv2.COLOR_RGB2HSV
#RGB->GRAY cv2.COLOR_RGB2GRAY#HSV->BGR cv2.COLOR_HSV2BGR
#HSV->RGB cv2.COLOR_HSV2RGB#GRAY->BGR cv2.COLOR_GRAY2BGR
#GRAY->RGB cv2.COLOR_GRAY2RGB
cv2.imshow('image',image)
cv2.waitKey(0)
cv2.destroyAllWindows()
我们常用的一些颜色空间有BGR,RGB,HSV,CMYK,GRAY这几种,在使用cv2.cvtColor()函数进行变换时,我们只需要按照cv2.COLOR_原颜色空间2新颜色空间的格式(2表示to)传入给code便可将图像从一种颜色空间转换到另一种。
将图像由BGR颜色空间变换到HSV空间后
cv2.split():颜色通道提取
颜色通道提取是图像处理中的一个基本且重要的步骤,它涉及到从图像中分离出红色、绿色、蓝色或其他颜色通道的信息。由于读取得到的图像结果是ndarray,因此我们既可以使用cv2内置函数split分离颜色通道,又可以使用切片的方式来获取三个颜色通道的信息。
import cv2
image=cv2.imread('test.jpg',cv2.IMREAD_UNCHANGED)
b,g,r=cv2.split(image)
直接使用cv2.split()函数对图像的3个颜色通道数据进行提取
import cv2
image=cv2.imread('test.jpg',cv2.IMREAD_UNCHANGED)
b,g,r=image[:,:,0],image[:,:,1],image[:,:,2]
通过切片的方法对图像的3个颜色通道数据进行提取
二者得到的结果是一致的。
当然,如果我们只想保留图像在某个颜色通道上的数据,只需将该通道以外的所有数据置0即可。
import cv2
image=cv2.imread('test.jpg')
#将图像数据copy一份给blue_image,
#这样不会影响到后续可能要对原图像进行的操作
blue_image=image.copy()
blue_image[:,:,1]=blue_image[:,:,2]=0
cv2.imshow('blue_image',blue_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果
cv2.resize():修改图像尺寸
cv2的内置函数resize可以方便地调整图像的大小,值得注意的是,在修改图像尺寸时,为了尽量避免对图像质量造成过多的损失,可以通过选择适当的插值算法来保持图像的清晰度和细节。对此,cv2.resize函数的默认方法为
放大时:cv2.INTER_CUBIC(双三次插值)
缩小时:cv2.INTER_AREA(区域插值)
import cv2
import matplotlib.pyplot as plt
#plt.imshow的图像格式为RGB,因此读取图像数据时我们指定flags按照RGB格式
image=cv2.imread('test.jpg',cv2.IMREAD_COLOR_RGB)#原始图像大小为500x500
#resize函数参数:
image=cv2.resize(src=image, dsize=(600, 600),fx=2, fy=2, interpolation=cv2.INTER_CUBIC)
#src:原图像ndarray
#dsize元祖形式,指定图像的高和宽
#fx:x轴上图像放大或缩小倍数
#fy:y轴上图像放大或缩小倍数
#interploation:图像插值方法
#需要注意的是当dsize为(0,0)或不存在时,fx,fy才会起作用,也就是说resize函数优先使用dsize#常用的interploation参数
#cv2.INTER_NEAREST:最近邻插值(速度快,但可能导致锯齿)
#cv2.INTER_LINEAR:双线性插值(默认,适用于大多数情况)
#cv2.INTER_CUBIC:双三次插值(高质量,计算成本较高)
#cv2.INTER_AREA:区域插值(缩小图像时效果较好)
#cv2.INTER_LANCZOS4:Lanczos插值(高质量,适用于放大)
plt.imshow(image)
cv2.resize()函数参数详解:
src | 原图像ndarray |
dsize | 元祖形式,指定调整后图像的高和宽 |
fx | x轴上图像放大或缩小倍数 |
fy | y轴上图像放大或缩小倍数 |
interploation | 图像插值方法 |
需要注意的是当dsize为(0,0)或不存在时,fx,fy才会起作用,也就是说resize函数优先使用dsize
resize后的图像,原图像尺寸500x500,dsize=(0,0),按照fx,fy取值对图像大小进行调整
cv2.addWeighted()图像融合
在某些场景下我们需要对两张图片进行融合,考虑到图像经过cv2.imread()函数读取后均为ndarray,因此我们可以直接对两张图片的读取结果进行加减乘除运算,一般而言,图像进行融合时我们都采用线性融合的方式,比如我们可以直接将二者简单相加:
#图像融合,直接相加
import cv2
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
image1=cv2.imread('test.jpg',cv2.IMREAD_COLOR_RGB)
image2=cv2.imread('test1.jpg',cv2.IMREAD_COLOR_RGB)
image1=cv2.resize(image1,(800,800))
image2=cv2.resize(image2,(800,800))
newimage=image1+image2
print(image1[:3,:,0],'\n')
print(image2[:3,:,0],'\n')
print(newimage[:3,:,0])
plt.subplot(1,3,1),plt.imshow(image1),plt.title('图像1')
plt.subplot(1,3,2),plt.imshow(image2),plt.title('图像2')
plt.subplot(1,3,3),plt.imshow(newimage),plt.title('图像1+图像2')
将两个图像直接相加
结果
当然,cv2还提供了addWeighted方法实现上述效果:
#图像融合,使用cv2.addWeighted函数
import cv2
plt.rcParams['font.sans-serif']=['SimHei']
image1=cv2.imread('test.jpg',cv2.IMREAD_COLOR_RGB)
image2=cv2.imread('test1.jpg',cv2.IMREAD_COLOR_RGB)
image1=cv2.resize(image1,(800,800))
image2=cv2.resize(image2,(800,800))
newimage=cv2.addWeighted(src1=image1,alpha=0.6,src2=image2,beta=0.8,gamma=5)
#src1:图像1
#alpha:图像1系数
#src2:图像2
#beta:图像2系数
#gamma;常数项
#newimage=0.5*image1+0.8*image2+5
plt.subplot(1,3,1),plt.imshow(image1),plt.title('图像1')
plt.subplot(1,3,2),plt.imshow(image2),plt.title('图像2')
plt.subplot(1,3,3),plt.imshow(newimage),plt.title('图像1+图像2')
cv2.addWeighted()函数参数解析:
src1 | 图像1矩阵 |
alpha | 图像1系数 |
src2 | 图像2矩阵 |
beta | 图像2系数 |
gamma | 常数项 |
结果
cv2.merge()图像合并
cv2.merge()是OpenCV库中的一个函数,主要用于将多个单通道图像合并为一个多通道图像。该函数通常接受一个包含若干图像的元组或列表作为输入,这些图像需要具有相同的尺寸。
#图像合并
import cv2
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
image=cv2.imread('test.jpg',cv2.IMREAD_COLOR_RGB)
r,g,b=cv2.split(image)#先将图片拆分为3个单通道的图像
merged_image=cv2.merge([r,g,b])#将3个单通道图像合并为原图像
#在合并单通道图像时需要将各个通道的图像数据按照元祖或列表的形式传入,且每个图像数据的尺寸需要一致
#合并后的图像shape为:(高,宽,各图像通道数之和)
plt.imshow(merged_image)
结果
当然,多通道图像之间也可以合并,只要他们的形状一致即可,比如上述代码中的merged_image我们可以使用索引切片来将图像r+g与b这两个图像(2通道+1通道)进行合并。
randg=image[:,:,0:2]
b=image[:,:,2]
merged_image=cv2.merge([rang,b])
但是,对于RGB图像而言,通道数最多不超过4(png图像多一个alpha通道),所以当你试图将两个RGB图象使用cv2.merge()函数合并后,无论是cv2.imshow()还是plt.imshow()都将无法正常显示图像,因为合并后的图像的通道数>=4.
cv2.copyMakeBorder()边界填充
边界填充是图像处理中的一种常见操作,它通过在图像的边界周围添加额外的像素来改变图像的大小。这一操作在许多图像处理任务中都是必不可少的。在卷积神经网络(CNN)中进行图像分类或目标检测时,为了保持输入图像尺寸的一致性,常常需要对原始图像进行边界填充。此外,边界填充还可以用于创建图像的镜像效果,或者在图像拼接时减少接缝处的突兀感。
cv2.copyMakeBorder函数便是opencv内置用来进行图像填充的函数,它可以在图像的四周或特定的一侧添加指定宽度和类型的边框。
#边界填充cv2.copyMakeBorder()
import cv2
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
image=cv2.imread('test.jpg',cv2.IMREAD_COLOR_RGB)
default=cv2.copyMakeBorder(src=image,top=20,bottom=20,left=20,right=20,borderType=cv2.BORDER_DEFAULT)
reflect=cv2.copyMakeBorder(src=image,top=20,bottom=20,left=20,right=20,borderType=cv2.BORDER_REFLECT)
isolated=cv2.copyMakeBorder(src=image,top=20,bottom=20,left=20,right=20,borderType=cv2.BORDER_ISOLATED)
wrap=cv2.copyMakeBorder(src=image,top=20,bottom=20,left=20,right=20,borderType=cv2.BORDER_WRAP)
replicate=cv2.copyMakeBorder(src=image,top=20,bottom=20,left=20,right=20,borderType=cv2.BORDER_REPLICATE)
reflect101=cv2.copyMakeBorder(src=image,top=20,bottom=20,left=20,right=20,borderType=cv2.BORDER_REFLECT101)
constant=cv2.copyMakeBorder(src=image,top=20,bottom=20,left=20,right=20,borderType=cv2.BORDER_CONSTANT,value=(10,250,120))#绿色边框
#cv2.copyMakeBorder()参数详解:
#src:原图像数据
#top:图像顶部要添加的边框宽度
#bottom:图像底部要添加的边框宽度
#left:图像左侧要添加的边框宽度
#right:图像右侧要添加的边框宽度
#borderType:填充方式
#value:当borderType为CONSTANT时候可用,对于灰度图像,它是一个标量值;对于彩色图像,它是一个包含三个值的元组(B, G, R)。
#所有填充方式:
#cv2.BORDER_CONSTANT: 添加一个固定颜色的边框,颜色由value参数指定
#cv2.BORDER_REPLICATE: 复制图像边缘的像素值来填充边框
#cv2.BORDER_REFLECT: 镜像反射图像边缘的像素值来填充边框
#cv2.BORDER_WRAP: 使用图像的另一侧的像素值来填充边框
#cv2.BORDER_DEFAULT: 默认的边框类型,通常与cv2.BORDER_REFLECT_101相同
#cv2.BORDER_REFLECT_101: 类似于 cv2.BORDER_REFLECT,但略有不同,通常用于避免重复的边缘像素。
#cv2.BORDER_ISOLATED:不处理边界,而是直接返回原始图像,即使传入了其他参数也被忽略。
fig,axs=plt.subplots(3,3,figsize=(10,8))
axs[0][0].imshow(image),axs[0][0].set_title('原图')
axs[0][1].imshow(default),axs[0][1].set_title('borderType=default')
axs[0][2].imshow(reflect),axs[0][2].set_title('borderType=reflect')
axs[1][0].imshow(isolated),axs[1][0].set_title('borderType=isolated')
axs[1][1].imshow(wrap),axs[1][1].set_title('borderType=wrap')
axs[1][2].imshow(replicate),axs[1][2].set_title('borderType=replicate')
axs[2][0].imshow(reflect101),axs[2][0].set_title('borderType=reflect101')
axs[2][1].imshow(constant),axs[2][1].set_title('borderType=constant')
plt.tight_layout()
cv2.copyMakeBorder()函数参数详解
src | 原图像数据 |
top | 图像顶部要添加的边框宽度 |
bottom | 图像底部要添加的边框宽度 |
left | 图像左侧要添加的边框宽度 |
right | 图像右侧要添加的边框宽度 |
broderType | 填充方式 |
value | 当borderType为CONSTANT时候可用,对于灰度图像,它是一个标量值,对于彩色图像,它是一个包含三个值的元组(B, G, R)BGR为三个颜色通道上的值。 |
boderType常用参数
cv2.BORDER_CONSTANT | 添加一个固定颜色的边框,颜色由value参数指定 |
cv2.BORDER_REPLICATE | 复制图像边缘的像素值来填充边框 |
cv2.BORDER_REFLECT | 镜像反射图像边缘的像素值来填充边框 |
cv2.BORDER_WRAP | 使用图像的另一侧的像素值来填充边框 |
cv2.BORDER_DEFAULT | 默认的边框类型,通常与cv2.BORDER_REFLECT_101相同 |
cv2.BORDER_REFLECT_101 | 类似于cv2.BORDER_REFLECT,但略有不同,通常用于避免重复的边缘像素 |
cv2.BORDER_ISOLATED | 不处理边界,而是直接返回原始图像,即使传入了其他参数也被忽略 |
结果
cv2.threshold()全局阈值法图像二值化
全局阈值法图像二值化是通过设定一个全局阈值,将图像中的像素值分为两类:高于阈值的像素被设置为最大值(通常为白色),低于阈值的像素被设置为最小值(通常为黑色)。这种二值化处理能够极大地简化图像信息,突出目标特征,为后续的图像分析、特征提取等步骤提供便利。在OpenCV中,cv2.threshold()函数是实现这一功能的核心工具,它允许用户灵活设置阈值和处理方式,以满足不同的图像处理需求。
import cv2
image=cv2.imread('test.jpg',cv2.IMREAD_GRAYSCALE)
_,binary_image=cv2.threshold(src=image,thresh=100,maxval=255,type=cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#cv2.threshold()参数:
#src:原始图像通常是单通道8为灰度图
#thresh:阈值
#maxval:最大值,超过阈值的像素点的值都将被设为这个值
#type:阈值类型,cv2.THRESH_BINARY表示二值化类型
#返回值说明,cv2.threshold()函数返回两个值,第一个值是设定的thresh,第二个值是二值化后的图像数据
#常用type:
#cv2.THRESH_BINARY:当像素值大于阈值时,将其设置为最大值;当像素值小于等于阈值时,将其设置为0
#cv2.THRESH_BINARY_INV:与cv2.THRESH_BINARY相反,当像素值小于阈值时,将其设置为最大值(通常为255);当像素值大于等于阈值时,将其设置为0
#cv2.THRESH_TOZERO:当像素值大于阈值时,保持不变;当像素值小于等于阈值时,将其设置为0。
#cv2.THRESH_TOZERO_INV:与cv2.THRESH_TOZERO相反,当像素值大于阈值时,将其设置为0,当像素值小于等于阈值时,保持不变。
#cv2.THRESH_TRUNC:像素值大于阈值时,将其设置为阈值;当像素值小于等于阈值时,保持不变。
#cv2.THRESH_TRIANGLE:自动计算阈值,基于Otsu's方法的一种变体,适用于双峰直方图(即图像有两种主要的灰度分布)
#cv2.THRESH_OTSU:自动计算阈值,通过最大化类间方差来确定最佳阈值,将图像分为前景和背景两部分。
#注意,以上几种type可以混合使用。
print(_)
cv2.imshow('binary image',binary_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果
说明
在对图像进行二值化处理时我们通常需要将其转化为灰度图像并且可能还需要对图像进行去噪、平滑等预处理操作,以提高阈值处理的效果。
cv2.threshold()函数参数详解:
src | 原始图像数据 |
thresh | 阈值 |
maxval | 最大值 |
type | 阈值类型,cv2.THRESH_BINARY表示二值化类型 |
cv2.threshold()函数常用type详解
cv2.THRESH_BINARY | 当像素值大于阈值时,将其设置为最大值;当像素值小于等于阈值时,将其设置为0 |
cv2.THRESH_BINARY_INV | 与cv2.THRESH_BINARY相反,当像素值小于阈值时,将其设置为最大值(通常为255);当像素值大于等于阈值时,将其设置为0 |
cv2.THRESH_TOZERO | 当像素值大于阈值时,保持不变;当像素值小于等于阈值时,将其设置为0。 |
cv2.THRESH_TOZERO_INV | cv2.THRESH_TOZERO相反,当像素值大于阈值时,将其设置为0,当像素值小于等于阈值时,保持不变。 |
cv2.THRESH_TRUNC | 像素值大于阈值时,将其设置为阈值;当像素值小于等于阈值时,保持不变。 |
cv2.THRESH_TRIANGLE | 自动计算阈值,基于Otsu's方法的一种变体,适用于双峰直方图(即图像有两种主要的灰度分布) |
cv2.THRESH_OTSU | 自动计算阈值,通过最大化类间方差来确定最佳阈值,将图像分为前景和背景两部分。 #注意,以上几种type可以混合使用。 |
以上几种type可以混合使用,比如示例代码中我们可以同时使用cv2.THRESH_BINARY与cv2.THRESH_OTSU方法。特别的,当你指定的type中含有cv2.THRESH_TRIANGLE,cv2.THRESH_OTSU 这两种自动计算阈值的方法时,此时我们传入的thresh将被忽略,并且cv2.threshold()函数返回值的第一个元素是自动计算出来的thresh。
cv2.adaptiveThreshold()自适应阈值法图像二值化
#cv2.adaptivethreshold()自适应阈值二值化
import cv2
image=cv2.imread(r'test.jpg',cv2.IMREAD_GRAYSCALE)
adaptive_binary_image=cv2.adaptiveThreshold(src=image,maxValue=255,blockSize=11,C=10,adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,thresholdType=cv2.THRESH_BINARY)
#src:图像数据通常是单通道8为灰度图
#maxValue:最大值,超过阈值的像素点的值都将被设为这个值
#adaptiveNethod:指定自适应阈值方法
#blockSize:整数,领域值,通常是奇数,表示计算阈值时考虑的像素领域大小
#C:整数,从计算的均值或加权均值中减去的常数
#thresholdType:与cv2.threshold()函数内的type取值一致
cv2.imshow('adaptive_binary_image',binary_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.adaptiveThreshold()参数详解:
src | 图像数据通常是单通道8为灰度图 |
maxValue | 最大值,超过阈值的像素点的值都将被设为这个值 |
adaptiveMethod | 指定自适应阈值方法 |
blockSize | 整数,领域值,通常是奇数,表示计算阈值时考虑的像素领域大小 |
C | 整数,从计算的均值或加权均值中减去的常数 |
thresholdType | 与Threshold()函数内的type一致 |
cv2.adaptiveThreshold()常用adaptiveMethod详解
当我们使用adaptiveThreshold()对图像二值化操作时,adaptiveThreshold主要有以下两个取值。
cv2.ADAPTIVE_THRESH_MEAN_C | 均值二值化,计算领域内所有像素的均值并减C作为该点处的像素值 |
cv2.ADAPTIVE_THRESH_GAUSSIAN_C | 高斯加权平均二值化,计算领域内所有像素的加权平均值并减C,权重按照高斯分布分配 |
图像形态学基本操作
cv2.morphologyEx()函数简介
cv2.morphologyEx
是 OpenCV 中用于执行各种形态学操作的函数。形态学操作是一种基于形状处理图像的方法,常用于图像预处理、特征提取、噪声去除和形状分析等任务。 cv2.morphologyEx
函数能够执行多种形态学操作,通过指定不同的操作类型,可以实现膨胀、腐蚀、开运算、闭运算等效果。
cv2.morphologyEX函数参数详解
src | 原图像数据通常是单通道8位灰度图 |
op | 指定形态学操作的类型 |
kernel | 一个指定领域大小的ndarray矩阵,和卷积核类似,只不过运算方法不同 |
anchor | 锚点,结构元素(卷积核)的锚点位置 |
iterations | 相应操作进行的次数,默认为1,次数越多,效果越明显 |
borderType | 边界填充方式,与cv2.copyMakeBorder()函数中的borderType一致 |
borderValue | 当borderType为cv2.BORDER_CONSTANT时,制定的填充边界的值,对于灰度图而言是一个值,对于彩色图而言是BGR三元组(B,G,R) |
cv2.morphologyEX()常见op形态学操作类型
cv2.MORPH_ERODE | 腐蚀操作 |
cv2.MORPH_DILATE | 膨胀操作 |
cv2.MORPH_OPEN | 开运算 |
cv2.MORPH_CLOSE | 闭运算 |
cv2.MORPH_TOPHAT | 顶帽操作 |
cv2.MORPH_BLACKHAT | 黑帽操作 |
cv2.MORPH_GRADIENT | 形态学梯度 |
cv2.erode()腐蚀操作
与膨胀相反,图像腐蚀(Erosion)是一种减少图像中白色物体大小的操作,它通过使用与膨胀相同的结构元素,但是规则不同,只有当结构元素完全覆盖在白色像素上时,结构元素中心位置的黑色像素会变为白色,这意味着物体的边界会向内收缩,导致图像中的亮区域边缘向内收缩,暗区域相应扩大。图像腐蚀常用于去除小的白色噪声点、分离粘连对象、细化图像结构等场景。
#cv2.erode()膨胀操作
import cv2
import numpy as np
image=cv2.imread('black.jpg',flags=cv2.IMREAD_GRAYSCALE)
kernel=np.ones(shape=(3,3,1))
eroded_image=cv2.erode(src=image,kernel=kernel,iterations=1,borderType=cv2.BORDER_REPLICATE)
#cv2.erode()参数详解:
#src:原图像数据通常是单通道8位灰度图
#kernel:一个指定领域大小的ndarray矩阵,和卷积核类似,只不过运算方法不同,这里我们称他为结构元素
#iterations:腐蚀操作进行的次数,默认为1,次数越多,腐蚀效果越明显
#borderType:边界填充方式,与cv2.copyMakeBorder()函数中的borderType一致
#borderValue:当borderType为cv2.BORDER_CONSTANT时,制定的填充边界的值,对于灰度图而言是一个值,对于彩色图而言是BGR三元组(B,G,R)
cv2.imshow('src_mage',image)
cv2.imshow('eroded_image',eroded_image)
cv2.waitKey(0)
结果
显然,与之前的描述一致,图像中的亮区域边缘向内收缩,暗区域相应扩大
cv2.erode()函数参数详解
src | 原图像数据通常是单通道8位灰度图 |
kernel | 一个指定领域大小的ndarray矩阵,和卷积核类似,只不过运算方法不同,这里我们称他为结构元素 |
iterations | 腐蚀操作进行的次数,默认为1,次数越多,腐蚀效果越明显 |
borderType | 边界填充方式,与cv2.copyMakeBorder()函数中的borderType一致 |
borderValue | 当borderType为cv2.BORDER_CONSTANT时,制定的填充边界的值,对于灰度图而言是一个值,对于彩色图而言是BGR三元组(B,G,R) |
腐蚀原理
对图像腐蚀的原理很简单,就是结构元素(类似卷积核)沿着图像滑动(以结构元素的中心为参照点),如果与结构元素覆盖后对应的原图像的所有像素值都是1,那么中心元素保持原来的值,否则就变为0。这对于去除白噪声很有用,也可以用于断开两个连在一起的物体。
观察示例中的图片,在左侧区域内,我们无论怎么移动3x3的kernel,能够满足卷积核覆盖后对应的原图像的所有像素值都是1的位置只有上边的黄色阶梯区域,对于黑白二值图像来说1为白色,0为黑色,所以一般来说对黑白图像进行腐蚀操作后会亮区域边缘向内收缩,暗区域相应扩大。
cv2.dilate() 膨胀操作
图像膨胀(dilate)是一种主要用于增强图像中的亮区域或前景对象的图像处理技术。通过设定一个结构元素,该算法会将图像中与结构元素相匹配的部分进行扩展,使得图像中的亮区域边缘向外扩展,暗区域相应缩小。这种操作在处理二值图像或灰度图像时非常有用,特别是在需要突出图像中的特定结构或去除小孔和缝隙时。
在cv2中,cv2.dilate()函数可以用来实现上述功能
#cv2.dilate()膨胀操作
import cv2
import numpy as np
image=cv2.imread('black.jpg',flags=cv2.IMREAD_GRAYSCALE)
kernel=np.ones(shape=(3,3,1))
cv2.imshow('src_mage',image)
dilated_image=cv2.dilate(src=image,kernel=kernel,iterations=1,borderType=cv2.BORDER_REPLICATE)
#cv2.dilate()参数详解:
#src:原图像数据通常是单通道8位灰度图
#kernel:一个指定领域大小的ndarray矩阵,和卷积核类似,只不过运算方法不同
#iterations:膨胀操作进行的次数,默认为1,次数越多,膨胀效果越明显
#borderType:边界填充方式,与cv2.copyMakeBorder()函数中的borderType一致
#borderValue:当borderType为cv2.BORDER_CONSTANT时,制定的填充边界的值,对于灰度图而言是一个值,对于彩色图而言是BGR三元组(B,G,R)
cv2.imshow('dilated_image',dilated_image)
cv2.waitKey(0)
结果
显然,与之前的描述一致,图像中的亮区域边缘向外扩展,暗区域相应缩小。
cv2.dilate()函数参数详解
src | 原图像数据通常是单通道8位灰度图 |
kernel | 一个指定领域大小的ndarray矩阵,和卷积核类似,只不过运算方法不同 |
iterations | 膨胀操作进行的次数,默认为1,次数越多,膨胀效果越明显 |
borderType | 边界填充方式,与cv2.copyMakeBorder()函数中的borderType一致 |
borderValue | 当borderType为cv2.BORDER_CONSTANT时,制定的填充边界的值,对于灰度图而言是一个值,对于彩色图而言是BGR三元组(B,G,R) |
膨胀原理
膨胀的操作与腐蚀相反,这里的相反指的是运算相反,而不是值相反。膨胀操作的结构元素(类似卷积核)沿着图像滑动(以卷积核的中心为参照点),如果与结构元素覆盖后对应的原图像的像素值只要有一个是1,中心像素值就是1,否则为0。对于灰度化二值图像来说1为白色,0为黑色,所以一般来说对黑白图像进行膨胀操作后会亮区域边缘向外扩展,暗区域相应缩小。
cv2.morphologyEx()实现开闭运算
开运算原理
图像的开运算是指对图像先腐蚀后膨胀的过程。这个过程有助于去除小的对象(即前景中的小白点),在分离物体、消除小颗粒噪声或“断开”物体之间的连接时非常有用。开运算可以使得物体的轮廓变得平滑,同时减小其面积,而不会影响物体的整体形状和位置。在处理二值图像或灰度图像时,开运算是一种非常有效的形态学处理方法。
开运算原理图
闭运算原理
图像的闭运算是指对图像先膨胀后腐蚀的过程,这个过程常用于填补图像中的小孔或狭缝,以及连接相邻的物体。闭运算能够使物体的轮廓变得更为平滑,同时增加其面积,但不会显著改变物体的整体形状和位置。在二值图像或灰度图像的处理中,闭运算也是一种非常有用的形态学处理方法,特别是在需要填补图像中的小缺陷或连接相邻的分割区域时。通过闭运算,可以使得图像中的物体更加完整和连贯,为后续的图像分析或识别工作提供便利。
闭运算原理图
代码
import cv2
import numpy as np
kernel=np.ones(shape=(3,3))
image=cv2.imread('black.jpg')
opened_image=cv2.morphologyEx(src=image,op=cv2.MORPH_OPEN,kernel=kernel,anchor=(-1,1),iterations=1,borderType=cv2.BORDER_CONSTANT,borderValue=25)
closed_image=cv2.morphologyEx(src=image,op=cv2.MORPH_CLOSE,kernel=kernel,anchor=(-1,1),iterations=1,borderType=cv2.BORDER_CONSTANT,borderValue=25)
cv2.imshow('image',image)
cv2.imshow('opened_image',opened_image)
cv2.imshow('closed_image',closed_image)
cv2.waitKey(0)
使用cv2.morphologyEx()函数分别实现开运算与闭运算
结果
图像几何变化操作
图像直方图修正操作
图像空域滤波操作
相关文章:

计算机视觉(opencv-python)之图像预处理基本操作(待补充)
图像预处理是计算机视觉任务中的关键步骤,它通过对原始图像进行处理,以提高后续图像分析、特征提取和识别的准确性。 示例图片 目录 常见图像处理方法 灰度化处理 法一 法二 说明 切片截取部分图像数据 cv2.cvtColor() 颜色空间转换 cv2.split(…...
数据结构秘籍(四) 堆 (详细包含用途、分类、存储、操作等)
1 引言 什么是堆? 堆是一种满足以下条件的树:(树这一篇可以参考我的文章数据结构秘籍(三)树 (含二叉树的分类、存储和定义)-CSDN博客) 堆中的每一个结点值都大于等于(…...

前端正则表达式完全指南:从入门到实战
文章目录 第一章:正则表达式基础概念1.1 什么是正则表达式1.2 正则表达式工作原理1.3 基础示例演示 第二章:正则表达式核心语法2.1 元字符大全表2.2 量词系统详解2.3 字符集合与排除 第三章:前端常用正则模式3.1 表单验证类3.1.1 邮箱验证3.1…...

【SRC实战】小游戏漏洞强制挑战
小游戏业务分析: 1、挑战成功加分,失败减分,存在段位机制,段位影响榜单排名 2、随机推荐挑战对象,随着等级升高不再推荐低等级玩家 3、玩家等级需要培养,培养需要道具,道具需要看广告/完成任务/付费 4、…...

细说 Java 集合之 Map
前言:本文基于JDK8 一、HashMap 1.1、hash方法 hash方法是map中的基石,后续很多操作都依赖hash方法; 下面是 jdk 7 中 hash方法,注意hashSeed 这个扰动因子,该值随机,所以同一个 key 每次调用hash方法后…...
【vue-echarts】——05.柱状图
文章目录 一、柱状图基本设置1.实现代码2.结果展示二、柱状图效果实现11.代码实现2.结果展示三、柱状图效果实现21.代码实现2.结果展示一、柱状图基本设置 柱状图:一种图表类型,因为构成是由一根一根类似柱子的数据条组合而成的坐标平面,所以命名为柱状 图。主要是用来反应对…...

【C】链式二叉树算法题1 -- 单值二叉树
leetcode链接https://leetcode.cn/problems/univalued-binary-tree/description/ 1 题目描述 如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回 true;否则返回 false。 示例 1࿱…...

C++11——智能指针和function库
目录 一、智能指针 1. std::unique_ptr(独占所有权指针) 2. std::shared_ptr(共享所有权指针) 3. std::weak_ptr(弱引用指针) 关键区别总结 最佳实践 基本用法 可封装的对象类型 核心特性 示例代码…...

[操作系统] 文件的软链接和硬链接
文章目录 引言硬链接(Hard Link)什么是硬链接?硬链接的特性硬链接的用途 软链接(Symbolic Link)什么是软链接?软链接的特性软链接的用途 软硬链接对比文件的时间戳实际应用示例使用硬链接节省备份空间用软链…...

RabbitMQ面试题及原理
RabbitMQ使用场景: 异步发送(验证码、短信、邮件…)MYSQL和Redis, ES之间的数据同步分布式事务削峰填谷 1. 消息可靠性(不丢失) 消息丢失场景: RabbitMQ-如何保证消息不丟失? 开启生产者确…...
SpringBoot中Get请求和POST请求接收参数详解
1、Get请求 1.1 方法形参接收参数 这种方式一般适用参数比较少的情况,并且前后端参数名称必须保持一致 RestController RequestMapping(“/user”) Slf4j public class DemoController { GetMapping("/query") public void getStudent(String name,Strin…...

分布式日志和责任链路
目录 日志问题 责任链问题 分布式日志 GrayLog简介 部署安装 收集日志 配置Inputs 集成微服务 日志回收策略 搜索语法 搜索语法 自定义展示字段 日志统计仪表盘 创建仪表盘 链路追踪 APM 什么是APM 原理 技术选型 Skywalking简介 部署安装 微服务探针 整合…...

h5 IOS端渐变的兼容问题 渐变实现弧形效果
IOS端使用渐变的时候有兼容问题 以下是问题效果,图中黑色部分期望的效果应该是白色的。但是ios端是下面的样子…… 安卓pc 支持: background-image: radial-gradient(circle 40rpx at 100% 0, #f3630c 40rpx, rgb(255, 255, 255) 50%);安卓pc ios支持…...

哈希算法--猜数字游戏
1.题目要求 输入两个位数相同的数,判断对应位置的数字是否相等,返回两个数。第一个数是数字和位置完全猜对的数字个数,第二个数是数字大小猜对但位置不对的数字个数 2.逐步编程 2.1 定义函数 def g(secret,guess):sec_dic{}gue_dic{}# 定义…...

idea生成自定义Maven原型(archetype)项目工程模板
一、什么是Maven原型(Maven archetype) 引自官网的介绍如下: Maven原型插件官网地址 这里采用DeepSeek助手翻译如下: Maven 原型 什么是原型? 简而言之,原型是一个 Maven 项目模板工具包。原型被定义为一…...

Redis面试常见问题——使用场景问题
目录 Redis面试常见问题 如果发生了缓存穿透、击穿、雪崩,该如何解决? 缓存穿透 什么是布隆过滤器? 缓存击穿 缓存雪崩 双写一致性(redis做为缓存,mysql的数据如何与redis进行同步呢?) …...
样式和ui(待更新)
element-plus 先在项目下执行安装语句执行按需导入的命令按照官方文档修改vitest.json sass样式定制 npm -i sass -D在项目下准备定制的样式文件 styles/element/index.scss(!注意这里是.scss文件在vitest.json 修改配置文件 Components({resolvers: [ElementPlusResolver(…...

大摩闭门会:250228 学习总结报告
如果图片分辨率不足,可右键图片在新标签打开图片或者下载末尾源文件进行查看 本文只是针对视频做相应学术记录,进行学习讨论使用...

线程(Thread)
一、概念 线程:线程是一个轻量级的进程 二、线程的创建 1、线程的空间 (1)进程的空间包括:系统数据段、数据段、文本段 (2) 线程位于进程空间内部 (3) 栈区独享、与进程共享文本段、…...
AI军备竞赛2025:GPT-4.5的“情商革命”、文心4.5的开源突围与Trae的代码革命
AI军备竞赛2025:GPT-4.5的“情商革命”、文心4.5的开源突围与Trae的代码革命 ——一场重塑人类认知边界的技术战争 一、OpenAI的“感性觉醒”:GPT-4.5的颠覆与争议 1.1 从“冷面学霸”到“温柔导师”:AI的情商跃迁 当用户输入“朋友放鸽子&…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...