文章目录
一、OpenCV常用函数
以下是一些常用的 OpenCV 图像处理函数的详细信息,包括参数、返回值及示例:
1. cv2.imread()
- 功能:读取图像文件。
- 参数:
filename
:图像文件的路径(字符串)。flags
:读取标志,默认值为cv2.IMREAD_COLOR
,可选值包括:cv2.IMREAD_GRAYSCALE
:以灰度模式读取。cv2.IMREAD_UNCHANGED
:包含 alpha 通道的读取。
- 返回值:图像数组(如果读取失败,则返回
None
)。
示例:
import cv2
img = cv2.imread('image.png', cv2.IMREAD_COLOR)
if img is None:
print("图像加载失败")
2. cv2.imshow()
- 功能:显示图像。
- 参数:
winname
:窗口名称(字符串)。mat
:要显示的图像(numpy 数组)。
- 返回值:无。
示例:
cv2.imshow('Display Image', img)
3. cv2.imwrite()
- 功能:保存图像到文件。
- 参数:
filename
:保存的文件名(字符串)。img
:要保存的图像(numpy 数组)。
- 返回值:布尔值,表示保存是否成功。
示例:
success = cv2.imwrite('output.png', img)
if success:
print("图像保存成功")
4. cv2.resize()
- 功能:调整图像大小。
- 参数:
src
:输入图像(numpy 数组)。dsize
:目标尺寸(元组(width, height)
),设置为(0, 0)
时可用fx
和fy
缩放因子。fx
:水平方向的缩放因子(浮点数)。但imgae格式为(height, width, channels)fy
:垂直方向的缩放因子(浮点数)。
- 返回值:调整后的图像(numpy 数组)。
示例:
resized_img = cv2.resize(img, (200, 300)) # 直接指定尺寸
resized_img = cv2.resize(img, (0, 0), fx=2, fy=2) # 使用缩放因子
5. cv2.add()
- 功能:像素级别相加两张图像。
- 参数:
src1
:第一张输入图像(numpy 数组)。src2
:第二张输入图像(numpy 数组)。
- 返回值:相加后的图像(numpy 数组)。
示例:
result_img = cv2.add(img1, img2)
cv2.addWeighted
res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0) # 0.4*img_cat+img_dog*0.6+0
6. cv2.waitKey()
- 功能:等待键盘输入。
- 参数:
delay
:等待时间(毫秒),如果为0
,则无限等待。
- 返回值:按下键的 ASCII 码(整数)。
示例:
cv2.waitKey(0) # 等待任意键
7. cv2.destroyAllWindows()
- 功能:关闭所有创建的窗口。
- 参数:无。
- 返回值:无。
示例:
cv2.destroyAllWindows()
8. cv2.cvtColor()
- 功能:转换图像颜色空间。
- 参数:
src
:输入图像(numpy 数组)。code
:颜色转换代码,例如:cv2.COLOR_BGR2GRAY
:从 BGR 转换为灰度。cv2.COLOR_GRAY2BGR
:从灰度转换为 BGR。
- 返回值:转换后的图像(numpy 数组)。
示例:
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
这些函数构成了 OpenCV 的基础,适用于各种图像处理任务。
二、阈值与平滑处理
1、图像阈值
二值化操作(cv2.threshold
)
cv2.threshold
是 OpenCV 中用于图像阈值处理的函数,常用于图像二值化。以下是详细信息:
函数概述
-
功能:将图像转换为二值图像,通常用于图像分割。
-
参数:
src
:输入图像(灰度图像,numpy 数组)。thresh
:阈值,低于此值的像素将被设为maxval
,高于此值的像素将被设为0
或255
(根据类型)。maxval
:用于设置高于阈值的像素的值,通常为255
。type
:阈值类型,可以是以下值之一:cv2.THRESH_BINARY
:二值化。cv2.THRESH_BINARY_INV
:反向二值化。cv2.THRESH_TRUNC
:截断。cv2.THRESH_TOZERO
:大于阈值的值保持不变,其他设置为0
。cv2.THRESH_TOZERO_INV
:小于阈值的值设置为0
。
-
返回值:一个元组,包含两个元素:
retval
:使用的阈值。dst
:输出的阈值图像(numpy 数组)。
示例代码
import cv2
# 读取图像并转换为灰度图
img = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
# 应用阈值处理
thresh_value = 128
max_value = 255
retval, binary_img = cv2.threshold(img, thresh_value, max_value, cv2.THRESH_BINARY)
# 显示结果
cv2.imshow('Binary Image', binary_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
使用场景
阈值处理广泛应用于图像分割、边缘检测和特征提取等任务,可以帮助突出目标物体并减少背景干扰。
2、平滑处理
平滑操作(滤波
)
# 均值滤波
# 简单的平均卷积操作
blur = cv2.blur(img, (3, 3)) # 是将每个像素的值替换为该像素邻域内像素值的平均值
# 方框滤波
# 基本和均值一样,可以选择归一化
box = cv2.boxFilter(img,-1,(3,3), normalize=True) # 越界就取255
# normalize=True: 如果设置为 True,表示对核的输出结果进行归一化处理,即计算区域内的像素平均值。如果设置为 False,将计算区域内像素的总和。
# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)
# 中值滤波
# 相当于用中值代替
median = cv2.medianBlur(img, 5) # 中值滤波
res = np.hstack((blur,aussian,median))
三、形态学操作
1、腐蚀操作
腐蚀操作 (cv2.erode
)
- 功能:缩小图像中的白色区域,去除小的噪声。
- 参数:
src
:输入图像(通常是二值图像)。kernel
:结构元素,用于腐蚀操作(numpy 数组)。iterations
:迭代次数,默认值为 1。
- 返回值:腐蚀后的图像(numpy 数组)。
- 原始图像:在整个腐蚀过程中,所有像素点的判断都是基于输入的原始图像数据。更新每个像素点时使用的是原始未更新的像素点数据。
示例:
# 用于对二值化图像或者灰度图像的形态学处理。腐蚀操作可以去除小的白噪点或在二值图像中缩小前景物体,通常用于形态学操作如物体检测和图像预处理。
kernel = np.ones((3,3),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)# 在每个像素位置,将卷积核覆盖在图像上,如果卷积核下方的所有像素值都为1,则保留该像素的值,否则将该像素值设为0。
# 这会使得前景区域(亮色部分)变小,或去掉小的噪声点。
2、膨胀操作
膨胀操作 (cv2.dilate
)
- 功能:放大图像中的白色区域,填补小的空洞。
- 参数:
src
:输入图像(通常是二值图像)。kernel
:结构元素(numpy 数组)。iterations
:迭代次数,默认值为 1。
- 返回值:膨胀后的图像(numpy 数组)。
示例:
kernel = np.ones((3,3),np.uint8)
dige_dilate = cv2.dilate(dige_erosion,kernel,iterations = 1)
3、开运算&闭运算
开运算 (cv2.morphologyEx
)
- 功能:先腐蚀后膨胀,去除小的物体和噪声。
- 参数:
src
:输入图像(通常是二值图像)。op
:操作类型,设置为cv2.MORPH_OPEN
。kernel
:结构元素(numpy 数组)。
- 返回值:开运算后的图像(numpy 数组)。
示例:
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
闭运算 (cv2.morphologyEx
)
- 功能:先膨胀后腐蚀,填补小的空洞。
- 参数:
src
:输入图像(通常是二值图像)。op
:操作类型,设置为cv2.MORPH_CLOSE
。kernel
:结构元素(numpy 数组)。
- 返回值:闭运算后的图像(numpy 数组)。
示例:
kernel = np.ones((5,5),np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
4、梯度运算
# 梯度=膨胀-腐蚀
pie = cv2.imread('pie.png')
kernel = np.ones((7,7),np.uint8)
dilate = cv2.dilate(pie,kernel,iterations = 5)
erosion = cv2.erode(pie,kernel,iterations = 5)
gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)
5、礼帽与黑帽
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)
6、常用操作用途
在图像处理中,开运算、闭运算、礼帽操作 和 黑帽操作 都是基于 形态学操作 的方法,常用于图像的预处理,尤其是在去噪、增强图像特征、分割等任务中。
1. 开运算(Opening Operation)
开运算由先腐蚀后膨胀组成,主要用于去除图像中的小噪点。
- 效果:去除图像中的小亮点(噪声),保持较大物体的形状和边界完整。
- 应用场景:适用于消除小的白色噪点,但不影响整体的形态。
公式:开运算 = 腐蚀 + 膨胀
- 腐蚀:先将图像的前景区域缩小,去除小的噪声点。
- 膨胀:在腐蚀之后,再恢复物体的形状。
实际效果:
- 如果图像中有一些孤立的小亮点噪声,开运算会去掉它们,而不会对较大的物体产生明显影响。
2. 闭运算(Closing Operation)
闭运算是先膨胀后腐蚀,用于填补物体上的小孔洞或缝隙。
- 效果:填补图像中的小黑洞,闭合前景物体内的小裂缝或孔洞,同时保留物体的整体形状。
- 应用场景:用于去除前景物体内部的小黑洞,或者连接断开的物体。
公式:闭运算 = 膨胀 + 腐蚀
- 膨胀:先扩展图像的前景,填补小黑点或缝隙。
- 腐蚀:然后恢复图像物体的边界,避免过度扩展。
实际效果:
- 如果图像中有一些小的黑色缝隙或空洞,闭运算可以填补这些区域,同时保持物体的边缘完整。
3. 礼帽操作(Top-hat Operation)
礼帽操作是原图像与开运算结果之间的差值,主要用于提取比周围亮的区域。
- 效果:突出图像中比周围亮的小区域,可以用于提取局部亮的细节。
- 应用场景:在图像中寻找比背景亮的物体,适合提取局部亮的特征,如字符识别、车牌识别等。
公式:礼帽 = 原图像 - 开运算
实际效果:
- 提取出那些比周围背景亮的小物体,能够增强图像中高亮部分的对比度。
4. 黑帽操作(Black-hat Operation)
黑帽操作是闭运算结果与原图像之间的差值,主要用于提取比周围暗的区域。
- 效果:突出图像中比周围暗的小区域,用于提取局部暗的细节。
- 应用场景:在图像中寻找比背景暗的物体,适合提取局部暗的特征。
公式:黑帽 = 闭运算 - 原图像
实际效果:
- 提取图像中比背景暗的区域,增强局部阴影或黑暗区域的细节。
总结表格:
操作名称 | 操作流程 | 效果 | 应用场景 |
---|---|---|---|
开运算 | 先腐蚀后膨胀 | 去除小亮点噪声,保留整体物体形状 | 消除图像中的小亮点噪声 |
闭运算 | 先膨胀后腐蚀 | 填补小黑洞或缝隙,保持物体边界 | 去除小黑洞或连接断开的物体 |
礼帽操作 | 原图像 - 开运算 | 提取比背景亮的小区域 | 提取局部亮的特征,如字符、车牌等 |
黑帽操作 | 闭运算 - 原图像 | 提取比背景暗的小区域 | 提取局部暗的特征,增强阴影部分 |
应用实例:
- 开运算:用于去除图片中的小白色噪点,如在车牌识别前处理照片。
- 闭运算:用于填补图像中的小黑色空洞,如在医学图像中填补细胞内部的小缺口。
- 礼帽操作:可以用于增强图像中的亮斑点特征,如识别图片中的小亮点。
- 黑帽操作:适合用于提取图片中的暗区域特征,如在摄影后期处理中突出阴影部分。
这些操作可以结合图像处理任务的不同需求来灵活使用,优化图像质量或提取特定区域特征。
四、图像梯度计算
1、sobel算子
cv2.Sobel
-
功能:计算图像的梯度,用于边缘检测。
-
参数:
src
:输入图像(灰度图像)。ddepth
:输出图像的深度,通常使用cv2.CV_64F
。
cv2.CV_64F:表示输出图像的深度类型为64位浮点型,这是==为了防止梯度结果出现负值后截断。==cv2.CV_64F 确保在计算图像梯度时,像素值能够存储负值和超过 255 的大数。
dx
:x方向的导数阶数(0表示不计算x方向的导数)。dy
:y方向的导数阶数(0表示不计算y方向的导数)。ksize
:Sobel算子的大小,通常为1、3、5、7。scale
:缩放因子(可选)。delta
:加到结果上的值(可选)。
-
返回值:计算后的梯度图像(numpy 数组)。
import cv2
img = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) # x方向的梯度
sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) # y方向的梯度
cv2.convertScaleAbs
梯度取绝对值
sobelx = cv2.convertScaleAbs(sobelx)
# 这个函数将 sobelx 中的 64 位浮点数转换为 8 位无符号整数(uint8),方便后续的图像显示。
# 它通过取绝对值 (abs),确保负值被转换为正值。
# 并将结果缩放到 0-255 的范围,适合显示和处理。
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
# 将 sobelx 和 sobely 按 1:1 的比例加权合并,生成一个新的图像 sobelxy,包含了水平和垂直边缘的信息。
sobel_combined = cv2.magnitude(sobel_x, sobel_y) # 结合 x 和 y 方向的梯度
2、Scharr算子和laplacian算子
cv2.Scharr
- 功能:与 Sobel 类似,但使用更高阶的核,通常能提供更好的边缘检测效果。
- 参数:
- 与
cv2.Sobel
相同。 ksize
默认值为 -1,表示使用 Scharr 算子。
- 与
- 返回值:计算后的梯度图像(numpy 数组)。
scharr_x = cv2.Scharr(img, cv2.CV_64F, 1, 0) # x方向的梯度
scharr_y = cv2.Scharr(img, cv2.CV_64F, 0, 1) # y方向的梯度
scharr_combined = cv2.magnitude(scharr_x, scharr_y)
cv2.Laplacian
- 功能:计算图像的拉普拉斯变换,用于边缘检测。
- 参数:
src
:输入图像(灰度图像)。ddepth
:输出图像的深度,通常使用cv2.CV_64F
。ksize
:拉普拉斯算子的大小,通常为1、3、5、7。scale
:缩放因子(可选)。delta
:加到结果上的值(可选)。
- 返回值:计算后的拉普拉斯图像(numpy 数组)。
laplacian = cv2.Laplacian(img, cv2.CV_64F, ksize=3)
#不同算子的差异
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
laplacian = cv2.Laplacian(img,cv2.CV_64F) # 对噪音点敏感
laplacian = cv2.convertScaleAbs(laplacian)
res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show(res,'res')
五、边缘检测
canny边缘检测
1) 使用高斯滤波器,以平滑图像,滤除噪声。
2) 计算图像中每个像素点的梯度强度和方向。
3) 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
4) 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
5) 通过抑制孤立的弱边缘最终完成边缘检测。
Canny边缘检测是一种经典且高效的边缘检测算法,整个流程可以分为五个主要步骤,每个步骤都承担着不同的任务,确保检测到准确且连续的边缘。以下是对整个流程的总结:
1. 高斯滤波器去噪
==使用高斯滤波器对输入图像进行平滑处理,目的是减小噪声的影响。==噪声对边缘检测有很大的干扰,所以通过高斯滤波器可以去除图像中的大部分噪声,同时保留主要的图像结构。
2. 计算梯度强度和方向
==通过Sobel算子或者类似的方法,计算图像中每个像素点的梯度强度和方向。==梯度强度代表像素点亮度变化的幅度,梯度方向指向亮度变化最快的方向。在这一步中,你将得到每个像素点的梯度大小和梯度方向,这是判断边缘的重要依据。
3. 非极大值抑制
为了使边缘更精确,需要在局部范围内筛选出最强的边缘像素点。非极大值抑制是这一过程的关键:
- 对每个像素点,沿着其梯度方向(通常取0°, 45°, 90°, 135°)检查该方向上的相邻像素点。
- 如果当前像素的梯度强度大于其梯度方向上两个相邻像素的强度,则保留这个像素,认为它可能是边缘的一部分。
- 否则,抑制该像素,将其梯度强度设为0,消除杂散响应(非边缘像素)。
是的,对梯度幅值图像中的每一个像素都执行非极大值抑制。即使图像中的某些像素不在边缘上,也会进行检测,但如果不是局部极大值,它们的值会被抑制为 0。
这一过程通过去除多余的边缘点,使得保留下来的边缘变得更细、更精确。
4. 双阈值检测
在非极大值抑制之后的图像中,边缘像素被细化,但还需要进一步确认哪些像素是真正的边缘,哪些是噪声或者弱边缘。双阈值检测通过设置两个阈值(高阈值和低阈值)来进行分类:
- 强边缘:梯度强度高于高阈值的像素点直接保留。
- 弱边缘:梯度强度介于低阈值和高阈值之间的像素,需要进一步判断。
- 非边缘:梯度强度低于低阈值的像素点被直接舍弃。
5. 抑制孤立弱边缘,完成边缘检测
==为了确保最终的边缘是连续的,弱边缘像素点需要进一步通过连接性判断。如果弱边缘像素与强边缘相连,则保留该弱边缘,认为它是边缘的一部分;否则,舍弃该弱边缘,认为它不是边缘。==这样可以有效减少孤立的、无意义的弱边缘,使得边缘检测结果更加可靠。
整体总结:
- 高斯滤波器平滑图像,减少噪声干扰。
- 计算梯度强度和方向,标记出可能的边缘位置。
- 非极大值抑制通过保留局部最大梯度强度的像素,确保边缘清晰且细化。
- 双阈值检测进一步筛选强边缘和弱边缘,并通过阈值分割图像中的边缘像素。
- 抑制孤立弱边缘,通过连接性检查,保留真正的边缘,丢弃不连贯的噪声边缘。
这个五步流程使得Canny边缘检测能够在噪声环境下仍然检测出精确、连续的边缘,并广泛应用于各种图像处理任务中。
六、图像金字塔与轮廓检测
1、上下采样都会损失信息吗
是的,上下采样都会不同程度地损失信息,但损失的类型和程度有所不同。
1. 下采样(Downsampling)
信息损失类型:细节丢失
- 下采样是通过减少图像中的像素数量来缩小图像尺寸的一种操作。常见的下采样方法包括跳过某些像素、平均池化、最大池化等。
- 在高斯金字塔中,通常通过对图像进行高斯平滑(消除高频细节)后,再进行下采样。这样虽然可以尽量保留重要的结构信息,但仍然会丢失一些细节,尤其是图像的高频部分(如边缘、纹理等)。
- 下采样的目的是减少图像的分辨率以适应特定任务(如多尺度分析),但不可避免地会丢失部分信息。
示例:
- 降采样步长较大的话,图像会失去更多的细节。比如,将 100x100 的图像直接缩小到 50x50 像素,原本相邻的像素点会被合并或舍弃,导致细节消失。
2. 上采样(Upsampling)
信息损失类型:引入插值误差,虚假信息
-
上采样是将低分辨率图像扩大到高分辨率的过程。这种操作本质上是推测或补全高分辨率的像素值,常用的方法有双线性插值、双三次插值等。
-
上采样不会增加图像的真实信息,相反,它会基于现有的低分辨率信息进行插值,因而可能引入一些不准确的推测,造成失真或模糊。
-
尽管上采样扩大了图像尺寸,但由于缺少新的原始信息,这种操作也无法恢复因下采样而丢失的细节。
-
将 50x50 的图像放大到 100x100 时,新增的像素点会基于现有像素进行插值,但这些新像素点的值并不代表图像的真实细节,可能会造成图像模糊或不准确。
3. 减少损失的方式
在上下采样过程中,尽管信息损失不可避免,但有一些方法可以减少损失的影响:
- 平滑处理:在下采样之前对图像进行平滑处理(如高斯滤波)可以去除一些噪声,保留较为重要的低频信息。
- 超分辨率技术:上采样时引入如深度学习的超分辨率算法,可以在放大图像时生成较为自然和清晰的高分辨率图像,减少虚假信息。
- 多尺度金字塔:使用图像金字塔技术,能够在不同尺度下保留部分细节,便于多尺度图像分析。
总结:
- 下采样时,图像的细节会丢失,特别是高频信息。
- 上采样时,无法恢复丢失的细节,可能引入插值误差或伪影。
- 无论是上下采样,信息损失是不可避免的,但可以通过一些方法尽量减少损失或降低其对图像质量的影响。
2、实际流程
在制作高斯金字塔的过程中,图像的缩放和卷积核的操作并不完全一样。主要区别在于:
- 图像的下采样和上采样涉及的是对图像大小的调整,而卷积核的操作是为了平滑图像,使其适合进行下采样或上采样。
- 卷积核在下采样或上采样过程中通常保持不变,并不会像图像一样直接缩放或扩展。
高斯金字塔中的两个主要步骤:
- 高斯模糊:在下采样之前,通常会对图像进行高斯模糊,以减少采样后高频噪声的影响。高斯模糊使用固定大小的高斯核进行卷积。
- 下采样(PyrDown):对模糊后的图像进行降采样,通常是通过将图像每隔一个像素进行采样,从而将图像的宽度和高度缩小为原来的1/2。
- 上采样(PyrUp):对图像进行上采样,将图像的尺寸放大到原来的两倍。放大后可能会出现像素值的空洞,因此通常在上采样后再次使用卷积核对图像进行平滑处理。
下采样时:
- 图像操作:下采样是指通过去除图像中的像素,使图像的分辨率降低,通常每隔一个像素进行采样。
- 卷积核操作:在进行下采样之前,通常使用一个固定的高斯卷积核来对图像进行平滑处理,以消除采样引入的混叠效应。这个卷积核的大小通常不变,例如常见的 5×5 或 3×3 高斯核。这个过程是为了在采样前减少高频分量,防止高频分量混叠。
下采样后,图像尺寸缩小,但卷积核保持不变。卷积核并不会因为图像缩小而缩小。
上采样时:
- 图像操作:上采样是将图像插值放大到原来的两倍。常见的插值方法是线性插值或最近邻插值,这会导致图像出现一些空洞或模糊。
- 卷积核操作:在上采样后,通常使用高斯卷积核对放大的图像进行平滑,以去除由于上采样造成的细节不连贯或噪声。这个卷积核的大小也保持不变。
- 进行上采样后,虽然图像的分辨率变高了,但图像可能会变得模糊
上采样后,图像尺寸变大,但卷积核同样保持不变,并不会因为图像放大而扩大。
总结:
- 在高斯金字塔的下采样过程中,图像缩小,但是卷积核保持不变,使用固定大小的高斯核对图像进行平滑处理。
- 在上采样过程中,图像放大,卷积核也同样保持不变,用来平滑处理插值产生的噪声和细节不连贯。
因此,图像的缩放与卷积核的缩放是两个独立的过程,卷积核的大小和操作并不会随图像的缩放而变化。
cv2.pyrUp
&cv2.pyrDown
down=cv2.pyrDown(img)
up2=cv2.pyrUp(up)
3、轮廓检测
cv2.findContours
cv2.findContours(img, mode, method)
是 OpenCV 中用于检测图像轮廓的函数。轮廓是图像中具有相同强度或颜色的所有连续点的边界,通常用于对象检测、形状分析等任务。函数定义:
contours, hierarchy = cv2.findContours(img, mode, method)
参数说明:
img(输入图像):
- 输入的图像应该是二值图像(即每个像素值是0或255),通常是在图像进行阈值化或边缘检测(如 Canny 边缘检测)后得到的。如果输入图像是灰度图像或彩色图像,必须先对其进行预处理(例如二值化)。
注意:该函数会修改输入图像,因此在调用该函数时最好传入图像的副本,避免直接修改原始图像。
mode(轮廓检索模式):
- 控制轮廓检索的方法,有以下选项:
cv2.RETR_EXTERNAL
:只检索最外层的轮廓。cv2.RETR_LIST
:检索所有轮廓,但不建立轮廓间的层级关系。cv2.RETR_CCOMP
:检索所有轮廓,并将它们组织为两级层次结构,外层边界为一级,内部对象的边界为另一层。cv2.RETR_TREE
:检索所有轮廓,并构建完整的嵌套轮廓层次结构。method(轮廓近似方法):
- 控制如何处理轮廓上的点集:
cv2.CHAIN_APPROX_NONE
:存储所有轮廓点,轮廓上的每个像素点都会被存储,可能产生大量数据。cv2.CHAIN_APPROX_SIMPLE
:压缩轮廓,垂直、水平、斜对角线方向上的冗余点会被压缩,只保留端点。例如,一个矩形只需存储四个顶点。cv2.CHAIN_APPROX_TC89_L1
和cv2.CHAIN_APPROX_TC89_KCOS
:使用 Teh-Chin 链式逼近算法。返回值:
contours:
- 这是一个 Python 列表,包含图像中所有轮廓。每个轮廓本身也是一个
numpy
数组,表示轮廓上的点集。- 每个轮廓可以理解为一个边界线(对象的边界),由该对象上的一系列点组成。
hierarchy:
- 这是一个
numpy
数组,用于描述轮廓之间的层次结构,格式为[next, previous, first_child, parent]
。具体来说:
next
:下一个轮廓的索引。previous
:前一个轮廓的索引。first_child
:第一个子轮廓的索引。parent
:父轮廓的索引。使用场景:
- 对象检测:通过提取图像中的对象轮廓,可以检测物体的边界,进行物体识别和跟踪。
- 形状分析:可以通过轮廓的形状计算物体的周长、面积等几何特征,进行形状匹配。
- 图像分割:轮廓可以用来分割图像中的不同区域。
总结:
cv2.findContours
是一个强大的轮廓提取工具,在图像分析、对象检测等应用中具有广泛用途。通过适当的预处理(如二值化或边缘检测)和合理的参数设置,可以高效地从图像中提取有用的轮廓信息。
cv2.drawContours
cv2.drawContours(image, contours, contourIdx, color, thickness)
是 OpenCV 中用于绘制轮廓的函数。它可以将通过cv2.findContours
提取的轮廓在图像上绘制出来,以便可视化。函数定义:
cv2.drawContours(image, contours, contourIdx, color, thickness)
参数说明:
image(输入图像):
- 要在其上绘制轮廓的图像。图像可以是彩色图像(BGR格式)或灰度图像。绘制后,原图像会被修改。
contours(轮廓):
- 通过
cv2.findContours
得到的轮廓列表。每个轮廓都是一个由点组成的数组。contourIdx(轮廓索引):
- 指定要绘制的轮廓的索引。可以设置为以下值:
-1
:绘制所有轮廓。0
、1
、2
等:绘制特定的轮廓,索引对应于contours
列表中的位置。color(颜色):
- 绘制轮廓的颜色,通常以 BGR 格式指定。例如,绿色可以表示为
(0, 255, 0)
。thickness(线宽):
- 绘制轮廓的线宽,单位为像素。可以设置为
cv2.FILLED
来填充轮廓区域。返回值:
- 该函数没有返回值,但会直接在输入图像上绘制轮廓。
示例代码:
import cv2 # 读取图像并转换为灰度图像 img = cv2.imread('image.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化图像 ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 查找轮廓 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 绘制所有轮廓 cv2.drawContours(img, contours, -1, (0, 255, 0), 2) # 显示结果 cv2.imshow('Contours', img) cv2.waitKey(0) cv2.destroyAllWindows()
使用场景:
- 可视化轮廓:在图像上绘制轮廓,以便更直观地理解图像中物体的边界。
- 调试:在进行图像处理时,可以通过绘制轮廓检查算法的正确性和效果。
- 分析结果:绘制后,可以进一步分析轮廓的特征,如面积、周长等。
总结:
cv2.drawContours
是一个简单而有效的工具,用于在图像上绘制和可视化轮廓信息。通过合理设置参数,可以自定义绘制的效果,帮助进行图像分析和处理。
轮廓检测与边缘检测区别🛫
边缘检测和轮廓检测虽然都是图像处理中的重要步骤,但它们在目的和处理方式上有显著的区别。
区别点 | 边缘检测 | 轮廓检测 |
---|---|---|
目的 | 检测图像中像素值变化最明显的地方(通常是物体边缘)。 | 找出图像中连通的边界或闭合的形状。 |
输出 | 输出的是一条条离散的边缘线段或像素点。 | 输出的是轮廓的几何形状,通常是多边形或连续的边界。 |
算法 | 主要使用Sobel、Canny等边缘检测算法。 | 使用 cv2.findContours 函数,根据二值图提取轮廓。 |
输入 | 通常是灰度图或经过滤波的图像。 | 通常是经过边缘检测或二值化处理后的图像。 |
处理方式 | 通过计算像素间的梯度变化来确定边缘。 | 通过分析二值图中的连通区域或物体的外边界来确定轮廓。 |
应用场景 | 通常用于检测细节,找出图像中的所有边缘。 | 用于识别物体的形状或边界,特别是在形状分析、物体识别中。 |
复杂度 | 比轮廓检测更快,但信息较为零散。 | 轮廓检测更慢,但可以重构物体的完整形状,信息更全面。 |
简单来说,边缘检测可以用于找出图像中的所有边缘,而轮廓检测则通过这些边缘来识别和重构图像中的形状和物体。
边缘检测示例
- 原始图像:想象一张白色背景上有一个黑色的圆形。
- 边缘检测结果:经过 Canny 边缘检测后,你会得到一个二值图像,只显示圆的边缘(黑色线条)。
轮廓检测示例
- 原始图像:同样是那张白色背景上有黑色圆形的图像。
- 轮廓检测结果:使用
cv2.findContours
后,你得到的是一个包含圆的边界点的轮廓,可以用于后续处理,如计算面积或绘制轮廓。关键区别
- 边缘检测强调的是边缘的存在,仅显示边缘线。
- 轮廓检测提供了对象的完整形状描述,可以识别和处理更复杂的图像结构。
如果你能在图像处理软件中实际尝试这两个步骤,你会更加清楚它们的差异!
4、轮廓特征与预测
轮廓近似
cnt = contours[0]
# 计算轮廓的周长,并计算多边形逼近的精度
epsilon = 0.10 * cv2.arcLength(cnt, True) #epsilon 是一个浮点数,表示多边形逼近的精度。值越小,逼近的曲线越接近原始轮廓;值越大,逼近的曲线越简单。
# 使用多边形逼近算法简化轮廓
approx = cv2.approxPolyDP(cnt, epsilon, True)
# 复制原图像,防止对原图进行修改
draw_img = img.copy()
# 在图像上绘制简化后的轮廓
res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
# 显示结果
cv_show(res, 'res')
外接矩形
# 获取外接矩形坐标和尺寸
# cv2.boundingRect(cnt) 计算轮廓 cnt 的最小外接矩形,返回 (x, y, w, h),其中 (x, y) 是矩形左上角的坐# 标,w 是宽度,h 是高度。
x, y, w, h = cv2.boundingRect(cnt)
# 在图像上绘制外接矩形
# 在原图 img 上绘制外接矩形,使用绿色 (0, 255, 0),线条宽度为 2。
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 显示结果
cv_show(img, 'img')
外接圆
(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2)
cv_show(img,'img')
5、模版匹配
模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度.这个差别程度的计算方法在opencv里有6种, 然后将每次计算的结果放入一个矩阵里,作为结果输出。假如原图形是AxB大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b+1)
cv2.matchTemplate
res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
res
中的值代表模板匹配的得分。
参数cv2.TM_SQDIFF
:
- TM_SQDIFF:计算平方不同,计算出来的值越小,越相关
- TM_CCORR:计算相关性,计算出来的值越大,越相关
- TM_CCOEFF:计算相关系数,计算出来的值越大,越相关
- TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关
- TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关
- TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关
- 归一化的更可靠
- https://docs.opencv.org/3.3.1/df/dfb/group__imgproc__object.html#ga3a7850640f1fe1f58fe91a2d7583695d
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
print(min_val,' ', max_val, min_loc, max_loc) # 39168.0 74403584.0 (107, 89) (159, 62)
cv2.rectangle
cv2.rectangle(image, pt1, pt2, color, thickness)
是 OpenCV 中用于在图像上绘制矩形的函数。这个函数常用于标记图像中的特定区域,或在图像处理和计算机视觉任务中可视化结果。
函数定义:
cv2.rectangle(image, pt1, pt2, color, thickness)
参数说明:
- image(输入图像):
- 要在其上绘制矩形的图像。可以是彩色图像(BGR格式)或灰度图像。
- pt1(矩形的一个顶点):
- 一个元组,表示矩形左上角的坐标,如
(x1, y1)
。
- 一个元组,表示矩形左上角的坐标,如
- pt2(矩形的另一个顶点):
- 一个元组,表示矩形右下角的坐标,如
(x2, y2)
。
- 一个元组,表示矩形右下角的坐标,如
- color(颜色):
- 矩形的颜色,通常以 BGR 格式指定,例如,红色可以表示为
(0, 0, 255)
。
- 矩形的颜色,通常以 BGR 格式指定,例如,红色可以表示为
- thickness(线宽):
- 矩形边框的线宽,单位为像素。如果设置为
cv2.FILLED
,则矩形将被填充。
- 矩形边框的线宽,单位为像素。如果设置为
for meth in methods:
img2 = img.copy()
# 匹配方法的真值
method = eval(meth) # methods 是一个包含匹配方法名的列表(如 cv2.TM_CCOEFF, cv2.TM_SQDIFF 等)。通过 eval(meth) 将字符串转换为实际的 OpenCV 方法。
print (method)
# 使用 cv2.matchTemplate() 进行模板匹配,res 是匹配结果图像。模板匹配的结果是一个灰度图,越亮的地方表示匹配度越高(对于大多数方法)。
res = cv2.matchTemplate(img, template, method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小值
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
# 画矩形
# 根据匹配区域的左上角 top_left 位置以及模板的宽高 (w, h) 计算矩形的右下角 bottom_right,然后使用 cv2.rectangle() 在图像 img2 上绘制匹配区域。
cv2.rectangle(img2, top_left, bottom_right, 255, 2)
plt.subplot(121), plt.imshow(res, cmap='gray')
plt.xticks([]), plt.yticks([]) # 隐藏坐标轴
plt.subplot(122), plt.imshow(img2, cmap='gray')
plt.xticks([]), plt.yticks([])
plt.suptitle(meth)
plt.show()
匹配多个对象
img_rgb = cv2.imread('mario.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.jpg', 0)
h, w = template.shape[:2]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
# 取匹配程度大于%80的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]): # *号表示可选参数
bottom_right = (pt[0] + w, pt[1] + h)
cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.imshow('img_rgb', img_rgb)
cv2.waitKey(0)
loc[::-1]
:
- 这个操作将
loc
中的数组顺序反转,使得 y 坐标在前,x 坐标在后。这是因为在绘制矩形时,我们需要先给出左上角的点(x,y)。
七、直方图与傅里叶变换
1、直方图
cv2.calcHist
cv2.calcHist
是 OpenCV 中==用于计算图像直方图的函数。==直方图是表示图像中像素值分布的图形,可以用于图像分析、增强和比较。
函数定义:
cv2.calcHist(images, channels, mask, histSize, ranges)
参数说明:
- images(输入图像):
- 输入图像的列表。通常传入一张图像或多张图像的列表。用中括号 [] 括来例如[img],通常是灰度图形式
- channels(通道):
- 指定计算直方图的通道索引。例如,对于彩色图像,通常可以使用
0
(蓝色通道)、1
(绿色通道)、2
(红色通道)来计算各个通道的直方图。
- 指定计算直方图的通道索引。例如,对于彩色图像,通常可以使用
- mask(掩膜):
- 可选参数,用于指定计算直方图的区域。如果为
None
,则计算整个图像的直方图。
- 可选参数,用于指定计算直方图的区域。如果为
- histSize(直方图大小):
- 指定直方图的 bin 数(即区间的数量),通常是一个整数。例如,常用的值为
256
,表示像素值范围 [0, 255] 的直方图。
- 指定直方图的 bin 数(即区间的数量),通常是一个整数。例如,常用的值为
- ranges(范围):
- 指定像素值的范围。对于灰度图像,通常是
[0, 256]
;对于彩色图像,可以分别为每个通道设置范围。
- 指定像素值的范围。对于灰度图像,通常是
返回值:
- 返回计算得到的直方图,通常是一个 Numpy 数组,表示各个 bin 的像素计数。
img = cv2.imread('cat.jpg',0) #0表示灰度图
hist = cv2.calcHist([img],[0],None,[256],[0,256])
hist.shape # (256, 1)
2、均衡化
cv2.equalizeHist
cv2.equalizeHist
是 OpenCV 中用于图像直方图均衡化的函数。直方图均衡化是一种常用的图像增强技术,旨在改善图像的对比度,使得图像的亮度分布更加均匀。函数定义:
cv2.equalizeHist(src)
参数说明:
- src(输入图像):
- 输入的灰度图像,通常是单通道(如
cv2.IMREAD_GRAYSCALE
读取的图像)。返回值:
- 返回经过均衡化处理后的图像,图像的直方图被调整为更均匀的分布。
使用步骤:
- 读取一张灰度图像。
- 调用
cv2.equalizeHist
进行直方图均衡化。- 显示原图与均衡化后的图像以进行比较。
img.ravel()
img.ravel()
将图像展平成一维数组。通常图像是二维(灰度图)或三维(彩色图)的矩阵,ravel()
会将这些像素值压缩成一维的形式,便于进行直方图统计。
img = cv2.imread('clahe.jpg',0) #0表示灰度图 #clahe
plt.hist(img.ravel(),256)
equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)
res = np.hstack((img,equ))
cv_show(res,'res')
cv2.createCLAHE
(自适应均衡化)
cv2.createCLAHE
是 OpenCV 中用于创建自适应直方图均衡化(CLAHE,Contrast Limited Adaptive Histogram Equalization)对象的函数。CLAHE 是传统直方图均衡化的改进版本,能够有效避免均衡化过程中出现的过度对比增强问题,特别适合处理局部对比度不足的图像。
函数定义:
cv2.createCLAHE(clipLimit=40.0, tileGridSize=(8, 8))
参数说明:
clipLimit
(对比度限制):- CLAHE 的核心参数之一,用于限制对比度增强的程度。如果某个局部区域的像素值超过
clipLimit
,则会进行剪裁。较高的clipLimit
会产生更强的对比度增强,默认值为 40.0。
- CLAHE 的核心参数之一,用于限制对比度增强的程度。如果某个局部区域的像素值超过
tileGridSize
(网格大小):- 图像被划分为多个小块,每个小块都进行独立的直方图均衡化。
tileGridSize
参数定义了这些小块的大小,通常是一个 2D 的元组(x, y)
,默认为(8, 8)
。值越大,小块区域越大,均衡化效果更接近全局均衡化。
- 图像被划分为多个小块,每个小块都进行独立的直方图均衡化。
返回值:
- 返回一个 CLAHE 对象,该对象可以用来对图像执行自适应直方图均衡化。
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
res_clahe = clahe.apply(img)
# res_clahe = clahe.apply(img) 是使用创建的 CLAHE 对象对输入图像进行自适应直方图均衡化的操作。这个函数# # 将对图像的对比度进行增强,以改善其可视效果,特别是在局部对比度不足的区域。
res = np.hstack((img,equ,res_clahe))
cv_show(res,'res')
3、傅里叶变换(了解即可)
1、图像中的高低频❤️
“高频”和“低频”是图像处理中的两个概念,它们主要描述的是图像中灰度或颜色值随空间位置的变化速率。
1. 高频:变化剧烈的灰度分量
- 定义:==高频分量指的是图像中灰度值或颜色变化非常迅速、剧烈的区域。==通常这些区域包括图像中的边缘、细节部分或纹理丰富的区域。
- 原因:在边缘区域,像素的灰度值从一个物体到另一个物体的过渡非常快,导致相邻像素间的灰度变化非常大。也就是说,灰度值在空间上迅速波动,形成了高频信息。
- 例子:物体边界、文字、细小纹理等地方。比如一幅图像中的物体轮廓、文字的边缘、叶子的细小脉络等。
数学解释:在图像的频域表示中,灰度值变化快意味着空间中的高频成分占据较大比例。这类似于在一段音乐中,频繁的音调变化会产生高频音符。
2. 低频:变化缓慢的灰度分量
- 定义:低频分量指的是图像中灰度值变化较为平缓、缓慢的区域。这类区域通常没有明显的边缘或剧烈的颜色变化,呈现出平滑的过渡。
- 原因:在像大海、天空等场景中,灰度值或颜色在较大的空间范围内变化非常小。由于相邻像素之间的灰度差异很小,图像中的变化很缓慢,属于低频信息。
- 例子:蓝天、大海、草地等大面积均匀或渐变的区域。
数学解释:低频信息对应的是空间中的缓慢变化。例如在一张平坦的天空图像中,灰度值在很大一块区域内非常接近,这表明图像在空间频域上主要是低频成分。
视觉化理解:
高频区域:如果你想象一张图像的边缘处,灰度或颜色变化突然且迅速(从黑到白),这些地方就被称为高频区域。
低频区域:在一片平坦的颜色区域(如天空或海面),灰度变化非常平缓或几乎没有变化,这就属于低频区域。
为什么这样区分?
人眼感知:人眼对图像的高频部分(如边缘和纹理)更加敏感。这也是为什么边缘检测算法和锐化滤波器主要用于增强图像中的高频信息,使得图像看起来更加清晰。
滤波器设计:在图像处理和压缩中,通常将图像分为高频和低频部分。高频部分通常包含图像的细节和纹理,而低频部分则包含图像的整体亮度和颜色过渡。在一些场景下,低频部分可以被压缩得更多,而保留高频部分以确保图像的视觉清晰度。
总结:
- 高频指的是图像中灰度或颜色变化剧烈的部分,例如边缘和细节。
- 低频指的是图像中变化缓慢或几乎没有变化的部分,例如大面积的均匀区域(如天空或海洋)。
这种区分源自图像的空间变化速率,高频部分代表快速变化的细节,低频部分则表示缓慢的变化或均匀区域。
傅里叶变换是一种将信号从时域/空域(即我们常见的图像、声音的物理空间表示)转换到频域的方法,它是信号处理中的重要工具。图像处理中的傅里叶变换则将图像从空间域转换为频率域,可以方便地分析图像的频率成分。
2、傅里叶变换
基本概念:
傅里叶变换是将信号或图像分解为不同频率的正弦波的和。对于图像而言,傅里叶变换可以帮助我们分析图像中不同频率成分的分布。
- 时域/空域:信号或图像的常规表示方式。对于图像来说,就是每个像素点的亮度值。
- 频域:信号或图像的频率表示方式。它反映了图像中变化快的区域(高频)和变化慢的区域(低频)。通过傅里叶变换,我们可以将图像从像素空间转换到频率空间。
在图像处理中,频率可以简单理解为图像中的细节变化。比如,图像中细小的纹理、边缘等都是高频成分,而大的平滑区域则为低频成分。
公式解释:
离散傅里叶变换(DFT)的公式如下:
$
F(u,v) = \sum_{x=0}{M-1}\sum_{y=0}{N-1}f(x,y)\cdot e^{-j2\pi\left(\frac{ux}{M} + \frac{vy}{N}\right)}
$
其中:
- ( f(x, y) ) 是输入的图像(空间域)。
- ( F(u, v) ) 是傅里叶变换后的频域表示。
- ( M ) 和 ( N ) 是图像的宽度和高度。
- ($ e^{-j2\pi\left(\frac{ux}{M} + \frac{vy}{N}\right)} $) 是复指数,用于将空间域数据映射到频域。
复数表示中的实部和虚部的意义:
-
实部 (Real Part) 和 虚部 (Imaginary Part) 是傅里叶变换的结果之一,它们分别表示频率成分的振幅和相位。
- 实部:对应频率分量的振幅。
- 虚部:对应频率分量的相位。
图像的频域表示为复数形式,其中频率信息的大小存储在实部和虚部中。为了可视化频域信息,通常会计算频率的幅度谱(Magnitude Spectrum),这是实部和虚部的组合,即:
$
\text{Magnitude} = \sqrt{\text{Re}^2 + \text{Im}^2}
$
3. **傅里叶反变换 **
傅里叶变换的逆操作叫做傅里叶反变换,它将频域信息重新转换回时域或空域。通过反变换,可以从频率信息恢复原始图像。
离散傅里叶反变换(IDFT)的公式为:
$
f(x, y) = \frac{1}{MN} \sum_{u=0}^{M-1} \sum_{v=0}^{N-1} F(u,v) \cdot e^{j2\pi\left(\frac{ux}{M} + \frac{vy}{N}\right)}
$
通过这个公式,频率域的数据 ( F(u,v) ) 可以还原成图像域数据 ( f(x,y) )。
傅里叶变换和反变换的作用:
- DFT:将图像分解为各个频率分量,便于分析和处理图像中的频率信息。比如,可以利用高频成分检测图像的边缘,或者通过低频成分分析图像的整体结构。
- IDFT:将频域中的处理结果反变换回图像空间,得到修改后的图像。
4. 低通滤波和高通滤波
傅里叶变换能够将图像信息分解为频率成分,因此可以通过对频域中不同频率成分的操作,实现不同的滤波器功能,如低通滤波和高通滤波。
低通滤波器(Low-Pass Filter, LPF):
==低通滤波器允许低频成分通过,抑制高频成分。==低频成分通常包含图像的主要轮廓、整体形状等信息,而高频成分则包含边缘、细节等信息。
-
低通滤波作用:去除图像中的高频噪声,平滑图像。常见的平滑滤波器(如高斯滤波器)就是一种低通滤波器。
应用场景:在图像降噪、去除小细节、模糊化处理时,常用低通滤波器。
高通滤波器(High-Pass Filter, HPF):
高通滤波器允许高频成分通过,抑制低频成分。高频成分通常包含图像中的边缘、纹理等细节信息。
-
高通滤波作用:突出图像中的细节和边缘。高通滤波可以增强图像的边缘,使得图像看起来更加清晰。
应用场景:图像锐化、边缘检测等操作中常使用高通滤波器。
低通和高通滤波与傅里叶变换的关系:
- 在频域中,通过低通滤波器可以抑制频谱中的高频部分,只保留频谱中的低频区域(通常位于频谱的中心)。
- 通过高通滤波器,可以抑制频谱中的低频部分,突出高频区域(通常位于频谱的边缘)。
通过傅里叶变换,图像在频域中的频率分布非常清晰,从而可以通过对不同频率区域的处理(如掩膜操作),实现高通或低通滤波器的作用。
总结:
- 傅里叶变换 (DFT) 将图像从空间域(像素值)转换到频域(频率信息),其中频域包含了图像的低频(平滑区域)和高频(边缘、纹理)成分。
- 傅里叶反变换 (IDFT) 则将频域信息重新转换回空间域,恢复图像。
- 低通滤波器允许低频信号通过,可以去除高频噪声,平滑图像。
- 高通滤波器允许高频信号通过,可以增强图像的边缘和细节。
傅里叶变换为我们提供了分析和处理图像的频率成分的手段。通过它,我们可以方便地进行滤波、去噪、增强等操作,帮助在不同的任务中处理图像。
5、傅里叶处理中的函数
这几个函数在图像处理和频域分析中非常重要,尤其是在进行傅里叶变换和频域滤波时。下面是对它们的详细解释:
1. cv2.dft
-
定义:计算离散傅里叶变换(DFT)。
-
函数签名:
cv2.dft(src, flags=cv2.DFT_COMPLEX_OUTPUT)
-
参数:
src
:输入图像,通常是浮点型的单通道或多通道图像。flags
:可选参数,指定输出格式,cv2.DFT_COMPLEX_OUTPUT
表示输出复数结果。
-
返回值:返回的结果是一个复数数组,包含频域信息。
2. np.fft.fftshift
-
定义:将傅里叶变换的结果进行频域中心化,移动零频率分量到频谱的中心。
-
函数签名:
np.fft.fftshift(x)
-
参数:
x
:输入的傅里叶变换结果。
-
返回值:返回中心化后的频谱数组,使低频和高频成分更易于可视化。
-
用途:在进行傅里叶变换后,低频成分通常位于图像的角落,使用
fftshift
可以将其移动到图像中心,以便更好地分析频域信息。
3. cv2.magnitude
-
定义:计算复数数组的幅值(模)。
-
函数签名:
cv2.magnitude(x, y)
-
参数:
x
:复数的实部。y
:复数的虚部。
-
返回值:返回的幅值图像,表示频域中每个点的强度。
-
用途:在频域分析中,使用
cv2.magnitude
可以提取频率分量的强度信息。
4. cv2.idft
-
定义:计算逆离散傅里叶变换(IDFT),将频域信息转换回空间域。
-
函数签名:
cv2.idft(dft, flags=cv2.DFT_SCALE)
-
参数:
dft
:输入的复数频域数组。flags
:可选参数,cv2.DFT_SCALE
用于缩放输出,使其与输入图像的大小相同。
-
返回值:返回的结果是恢复的图像(空间域)。
-
用途:
cv2.idft
用于从频域重建图像,通常在频域处理后进行。
6、实例
低通滤波
img = cv2.imread('lena.jpg',0)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2) # 中心位置
# 低通滤波
'''
mask:创建一个和图像同样大小的全零矩阵(相当于掩膜),用于滤波操作。
mask[crow-30:crow+30, ccol-30:ccol+30] = 1:在图像中心区域(30x30的正方形区域)设置为1,代表低通滤波器会保留该区域的频率信息,
而外部区域(高频部分)会被滤除。
'''
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
# IDFT
fshift = dft_shift*mask # 将掩膜应用到傅里叶变换后的频谱上,过滤掉高频部分,只保留中心低频成分。
f_ishift = np.fft.ifftshift(fshift) # 将频谱反转回原始位置(频谱移回左上角),为反傅里叶变换做准备。
img_back = cv2.idft(f_ishift) # 进行反傅里叶变换,将频率域信息转换回空间域。
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1]) # 计算反变换后的图像的幅度,恢复图像数据。
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])
plt.show()
高通滤波
img = cv2.imread('lena.jpg',0)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2) # 中心位置
# 高通滤波
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 0
# IDFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])
plt.show()