文章目录

一、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:目标尺寸(),设置为 (0, 0) 时可用 fxfy 缩放因子。
    • fx:水平方向的缩放因子(浮点数)。
    • 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

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,高于此值的像素将被设为 0255(根据类型)。
    • maxval:用于设置高于阈值的像素的值,通常为 255
    • type:阈值类型,可以是以下值之一:
      • cv2.THRESH_TRUNC:截断。
      • cv2.THRESH_TOZERO:大于阈值的值保持不变,其他设置为 0
      • cv2.THRESH_TOZERO_INV:小于阈值的值设置为 0
  • 返回值:一个元组,包含两个元素:

示例代码

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、opencv图像基本处理方法-LMLPHP

三、形态学操作

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算子

1、opencv图像基本处理方法-LMLPHP

cv2.Sobel

  • 功能:计算图像的梯度,用于边缘检测。

  • 参数:

    • src:输入图像(灰度图像)。
    • ddepth:输出图像的深度,通常使用 cv2.CV_64F
    • 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,消除杂散响应(非边缘像素)。

1、opencv图像基本处理方法-LMLPHP

这一过程通过去除多余的边缘点,使得保留下来的边缘变得更细、更精确。

4. 双阈值检测

在非极大值抑制之后的图像中,边缘像素被细化,但还需要双阈值检测通过设置两个阈值(高阈值和低阈值)来进行分类:

  • 强边缘:梯度强度高于高阈值的像素点直接保留。
  • 弱边缘:梯度强度介于低阈值和高阈值之间的像素,需要进一步判断。
  • 非边缘:梯度强度低于低阈值的像素点被直接舍弃。

5. 抑制孤立弱边缘,完成边缘检测

==为了确保最终的边缘是连续的,弱边缘像素点需要进一步通过连接性判断。如果弱边缘像素与强边缘相连,则保留该弱边缘,认为它是边缘的一部分;否则,舍弃该弱边缘,认为它不是边缘。==这样可以有效减少孤立的、无意义的弱边缘,使得边缘检测结果更加可靠。

整体总结:

  1. 高斯滤波器平滑图像,减少噪声干扰。
  2. 计算梯度强度和方向,标记出可能的边缘位置。
  3. 非极大值抑制通过保留局部最大梯度强度的像素,确保边缘清晰且细化。
  4. 双阈值检测进一步筛选强边缘和弱边缘,并通过阈值分割图像中的边缘像素。
  5. 抑制孤立弱边缘,通过连接性检查,保留真正的边缘,丢弃不连贯的噪声边缘。

这个五步流程使得Canny边缘检测能够在噪声环境下仍然检测出精确、连续的边缘,并广泛应用于各种图像处理任务中。

六、图像金字塔与轮廓检测

1、上下采样都会损失信息吗

是的,上下采样都会不同程度地损失信息,但损失的类型和程度有所不同。

1. 下采样(Downsampling)

  • 下采样是通过的一种操作。常见的下采样方法包括跳过某些像素、平均池化、最大池化等。
  • 下采样的目的是减少图像的分辨率以适应特定任务(如多尺度分析),但不可避免地会丢失部分信息。

示例:

  • 降采样步长较大的话,图像会失去更多的细节。比如,将 100x100 的图像直接缩小到 50x50 像素,原本相邻的像素点会被合并或舍弃,导致细节消失。

2. 上采样(Upsampling)

  • 上采样是将低分辨率图像扩大到高分辨率的过程。这种操作,常用的方法有双线性插值、双三次插值等。

  • 上采样不会增加图像的真实信息,相反,它会基于现有的低分辨率信息进行插值,因而

  • 尽管上采样扩大了图像尺寸,但由于缺少新的原始信息,这种操作也无法恢复因下采样而丢失的细节。

  • 将 50x50 的图像放大到 100x100 时,新增的像素点会基于现有像素进行插值,但这些新像素点的值并不代表图像的真实细节,可能会造成图像模糊或不准确。

3. 减少损失的方式

在上下采样过程中,尽管信息损失不可避免,但有一些方法可以减少损失的影响:

  • 平滑处理:在下采样之前对图像进行平滑处理(如高斯滤波)可以去除一些噪声,保留较为重要的低频信息。
  • 超分辨率技术:上采样时引入如深度学习的超分辨率算法,可以在放大图像时生成较为自然和清晰的高分辨率图像,减少虚假信息。
  • 多尺度金字塔:使用图像金字塔技术,能够在不同尺度下保留部分细节,便于多尺度图像分析。

总结:

  • 下采样时,图像的细节会丢失,特别是高频信息。
  • 上采样时,无法恢复丢失的细节,可能引入插值误差或伪影。
  • 无论是上下采样,信息损失是不可避免的,但可以通过一些方法尽量减少损失或降低其对图像质量的影响。

1、opencv图像基本处理方法-LMLPHP

2、实际流程

cv2.pyrUp&cv2.pyrDown

down=cv2.pyrDown(img)
up2=cv2.pyrUp(up)

3、轮廓检测

cv2.findContours

cv2.drawContours

轮廓检测与边缘检测区别🛫

边缘检测轮廓检测虽然都是图像处理中的重要步骤,但它们在目的和处理方式上有显著的区别。

简单来说,边缘检测可以用于找出图像中的所有边缘,而轮廓检测则通过这些边缘来识别和重构图像中的形状和物体。

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种, 然后将每次计算的结果放入一个矩阵里,作为结果输出。

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)

参数说明:

  1. image(输入图像):
    • 要在其上绘制矩形的图像。可以是彩色图像(BGR格式)或灰度图像。
  2. pt1(矩形的一个顶点):
    • 一个元组,表示矩形左上角的坐标,如 (x1, y1)
  3. pt2(矩形的另一个顶点):
    • 一个元组,表示矩形右下角的坐标,如 (x2, y2)
  4. color(颜色):
    • 矩形的颜色,通常以 BGR 格式指定,例如,红色可以表示为 (0, 0, 255)
  5. 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)

参数说明:

  1. images(输入图像):
    • 输入图像的列表。通常传入一张图像或多张图像的列表。
  2. channels(通道):
    • 指定计算直方图的通道索引。例如,对于彩色图像,通常可以使用 0(蓝色通道)、1(绿色通道)、2(红色通道)来计算各个通道的直方图。
  3. mask(掩膜):
    • 可选参数,用于指定计算直方图的区域。如果为 None,则计算整个图像的直方图。
  4. histSize(直方图大小):
    • 指定直方图的 bin 数(即区间的数量),通常是一个整数。例如,常用的值为 256,表示像素值范围 [0, 255] 的直方图。
  5. 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

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))

参数说明

  1. clipLimit(对比度限制):
    • CLAHE 的核心参数之一,用于限制对比度增强的程度。如果某个局部区域的像素值超过 clipLimit,则会进行剪裁。较高的 clipLimit 会产生更强的对比度增强,默认值为 40.0。
  2. 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')

1、opencv图像基本处理方法-LMLPHP

3、傅里叶变换(了解即可)

1、图像中的高低频❤️

,它是信号处理中的重要工具。

2、傅里叶变换

基本概念

傅里叶变换是将信号或图像分解为不同频率的正弦波的和。对于图像而言,傅里叶变换可以帮助我们分析图像中不同频率成分的分布。

  • 时域/空域:信号或图像的常规表示方式。对于图像来说,就是每个像素点的亮度值。
  • 频域:信号或图像的频率表示方式。它反映了图像中变化快的区域(高频)和变化慢的区域(低频)。通过傅里叶变换,我们可以将图像从像素空间转换到频率空间。

。比如,图像中细小的纹理、边缘等都是高频成分,而大的平滑区域则为低频成分。

公式解释

离散傅里叶变换(DFT)的公式如下:

$
F(u,v) = \sum_{x=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) )。

傅里叶变换和反变换的作用:

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()
10-23 14:35