OpenCV库 详细常见操作

时间:2024-10-03 08:00:21

在PyCharm中使用OpenCV时,可以访问OpenCV库提供的丰富函数来进行图像处理和计算机视觉任务。以下是一些常用的OpenCV库函数及其简要说明:

一、图像读取与显示

  1. cv2.imread():读取图像文件。
  2. cv2.imshow():在一个窗口中显示图像。
  3. cv2.imwrite():将图像保存到文件。

二、图像属性与像素处理

  1. 获取图像属性:通过访问图像的.shape.size.dtype属性,可以获取图像的高、宽、通道数,像素数目以及图像数据类型。
  2. 像素访问与修改:可以直接通过图像的坐标值访问和修改像素值。
  3. 颜色通道获取:
    1. 颜色通道提取
      • 使用cv2.split(img)函数,您可以将图像img的B(蓝色)、G(绿色)和R(红色)通道分离为三个独立的数组。
    2. 查看蓝色通道
      • 通过b变量,您可以访问蓝色通道的数据,并使用b.shape查看其形状(高度和宽度)。注意,这里显示的形状是(414, 500),表明图像的高度为414像素,宽度为500像素。由于这是一个灰度通道,所以没有深度(或颜色通道)维度。
    3. 合并颜色通道
      • 使用cv2.merge((b, g, r))函数,您可以将B、G、R三个通道重新合并为一个三通道图像。合并后的图像形状为(414, 500, 3),其中3表示颜色通道数。
    4. 只保留特定颜色通道
      • 您通过复制原始图像img来创建新图像cur_img,然后设置不需要的通道为0(黑色)。例如,为了只保留红色通道,您将蓝色和绿色通道设置为0。
    5. 显示图像
      •  
              
        import cv2
        import numpy as np
        img = cv2.imread('your_image.jpg')
        # 颜色通道提取
        b, g, r = cv2.split(img)
        # 查看蓝色通道
        print(b)
        print(b.shape)
        # 合并颜色通道
        img_merged = cv2.merge((b, g, r))
        print(img_merged.shape)
        # 只保留R通道
        cur_img = img.copy()
        cur_img[:, :, 0] = 0 # B通道
        cur_img[:, :, 1] = 0 # G通道
        cv2.imshow('R', cur_img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        # 只保留G通道
        cur_img = img.copy()
        cur_img[:, :, 0] = 0 # B通道
        cur_img[:, :, 2] = 0 # R通道
        cv2.imshow('G', cur_img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        # 只保留B通道
        cur_img = img.copy()
        cur_img[:, :, 1] = 0 # G通道
        cur_img[:, :, 2] = 0 # R通道
        cv2.imshow('B', cur_img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

三、图像色彩空间转换

  1. cv2.cvtColor():转换图像的色彩空间,如BGR到灰度、BGR到HSV等。

四、图像几何变换

  1. cv2.resize():调整图像的大小。
  2. cv2.flip():翻转图像,可以沿x轴、y轴或同时沿x轴和y轴翻转。
  3. cv2.warpAffine():应用仿射变换,如平移、旋转等。
  4. cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE):边界填充
  5. cv2.addWeighted():图像融合,例如:res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0),0为gamma值,Gamma值的取值范围通常为0.1至2.2之间。不同的Gamma值会对图像产生不同的影响。一般来说,较小的Gamma值会使图像变亮,而较大的Gamma值则会使图像变暗。
  6. 拉普拉斯金字塔与高斯金字塔是两种在图像处理中广泛使用的金字塔结构
    1. 一、定义与构建方式
      1. 高斯金字塔

        • 定义:高斯金字塔是通过图像的重复降采样和高斯平滑构建的。每一级高斯金字塔包含了原始图像的一个平滑版本,分辨率逐渐降低。

        • 构建方式:从原始图像开始,首先进行高斯平滑操作,然后删除所有偶数行和偶数列(或其他降采样方法),得到下一级图像。重复此过程,直到达到所需的金字塔层级数。

        • 图像压缩:由于高斯金字塔中的图像分辨率逐渐降低,因此可以用于图像压缩。通过丢弃一些高层级的图像,可以在一定程度上减少数据量。

        • 尺度不变特征检测:高斯金字塔可以用于尺度不变特征检测,如SIFT(尺度不变特征变换)算法中,就使用了高斯金字塔来构建不同尺度的图像表示。

        • 图像融合:在图像融合任务中,高斯金字塔可以用于将不同分辨率的图像进行融合,得到更高质量的图像。

      2. 拉普拉斯金字塔

        • 定义:拉普拉斯金字塔是通过高斯金字塔中每一级的图像与其上一级的图像之间的差分构建的。每一级拉普拉斯金字塔包含了原始图像中的细节信息,分辨率也逐渐降低。

        • 构建方式:首先构建高斯金字塔,然后从高斯金字塔的顶层开始,使用上采样操作将每一级图像放大到与下一级图像相同的尺寸,并与下一级图像进行差分运算,得到拉普拉斯金字塔的对应层级。重复此过程,直到得到拉普拉斯金字塔的所有层级。

        • 图像重建:拉普拉斯金字塔可以用于图像重建任务。通过从顶层开始逐层上采样和叠加拉普拉斯图像,可以重建出原始图像或更高分辨率的图像。

        • 图像压缩:与高斯金字塔不同,拉普拉斯金字塔可以实现无损压缩。通过对原始图像进行多次下采样和上采样操作,再与原始图像进行差分,可以得到一系列高频细节图像。这些高频细节图像可以通过编码和解码过程进行压缩和恢复。

        • 边缘检测和纹理分析:由于拉普拉斯金字塔提取了图像的高频细节信息,因此可以用于边缘检测和纹理分析任务。通过对不同尺度的拉普拉斯图像进行加权叠加,可以得到边缘强度图像或纹理强度图像。

五、图像滤波与边缘检测

  1. 滤波函数

    • cv2.blur():均值滤波。
    • cv2.boxFilter():方框滤波。
    • cv2.GaussianBlur():高斯滤波。
    • cv2.medianBlur():中值滤波。
  2. 边缘检测

    • cv2.Canny():Canny算子边缘检测。

六、形态学操作

  1. 腐蚀cv2.erode()
  2. 膨胀cv2.dilate()
  3. 开运算:使用cv2.morphologyEx()函数,参数为cv2.MORPH_OPEN
  4. 闭运算:使用cv2.morphologyEx()函数,参数为cv2.MORPH_CLOSE
  5. 梯度运算:使用cv2.morphologyEx()函数,参数为cv2.MORPH_GRADIENT
  6. 顶帽操作:使用cv2.morphologyEx()函数,参数为cv2.MORPH_TOPHAT
  7. 黑帽操作:使用cv2.morphologyEx()函数,参数为cv2.MORPH_BLACKHAT。

七、图像阈值化

  1. cv2.threshold():应用固定阈值进行二值化。

八、图像轮廓

  1. cv2.findContours():查找图像中的轮廓。
  2. cv2.drawContours():绘制轮廓。

九、图像直方图

  1. 绘制直方图:使用NumPy和OpenCV的函数来绘制图像的直方图。

十、图像加法与混合

  1. cv2.add():图像加法,对应像素值相加(饱和操作)。
  2. cv2.addWeighted():图像混合,按权重混合两幅图像。

十一、其他常用函数

  1. cv2.waitKey():等待键盘输入事件,常与cv2.imshow()一起使用来控制图像显示时间。
  2. cv2.destroyAllWindows():关闭所有由cv2.imshow()产生的窗口。
  3. cv2.namedWindow():创建一个窗口。
  4. cv2.destroyWindow():关闭指定的窗口。
  5. cv2.matchTemplat():匹配模板

十二、视频获取

import cv2 # 确保导入了cv2库
# 打开视频文件
vc = cv2.VideoCapture('test.mp4')
# 检查是否成功打开视频文件
if vc.isOpened():
ret, frame = vc.read() # 读取第一帧来检查视频是否可读
else:
ret = False # 如果视频未打开,设置ret为False
# 使用while循环读取视频帧
while ret:
# 读取每一帧
ret, frame = vc.read()
# 如果读取帧失败(例如视频结束),则退出循环
if frame is None:
break
# 将帧从BGR颜色空间转换为灰度
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 显示灰度帧
cv2.imshow('result', gray)
# 如果按下ESC键(ASCII码27),则退出循环
if cv2.waitKey(10) & 0xFF == 27:
break
# 释放视频捕获对象
vc.release()
# 关闭所有OpenCV窗口
cv2.destroyAllWindows()

 十三、傅里叶变换

  1. 图像格式转换:在进行傅里叶变换之前,需要将图像的数据类型转换为float32,这是因为傅里叶变换涉及复数运算,而float32类型可以支持这种运算。
  2. 执行傅里叶变换:使用傅里叶变换函数(如OpenCV中的cv2.dft()numpy.fft.fft2())对图像进行变换。这一步将图像从空间域转换到频率域。
  3. 频谱中心化:由于傅里叶变换的结果通常将低频分量分布在四个角落,为了更方便地观察和分析频谱,需要将低频分量移动到图像的中心。这通常通过numpy.fft.fftshift()函数来实现。
  4. 滤波:在频率域中,可以使用滤波器对图像进行滤波处理。常见的滤波器包括低通滤波器和高通滤波器。低通滤波器可以保留低频成分而去除高频成分,用于图像平滑;高通滤波器则保留高频成分而去除低频成分,用于边缘检测或增强细节。
  5. 去中心化和逆变换:在滤波之后,需要将频谱再次去中心化(使用numpy.fft.ifftshift()函数),然后执行逆傅里叶变换(如OpenCV中的cv2.idft()numpy.fft.ifft2()),将图像从频率域转换回空间域。
  6. 显示结果:最后,将逆变换后的图像转换为可显示的格式(如灰度图像),并使用图像显示函数(如matplotlib.pyplot.imshow())进行显示。
  7. 图像滤波:傅里叶变换可以用于图像的滤波处理。通过设计不同的滤波器,可以在频率域中对图像进行滤波,从而实现图像平滑、去噪、边缘检测等效果。
  8. 图像压缩:傅里叶变换还可以用于图像的压缩和编码。通过将图像从空间域转换到频率域,可以分析和量化图像中的频域信息,从而保留图像的主要频率成分,减少图像的数据量,提高图像的传输和存储效率。
  9. 图像增强和修复:在图像增强中,傅里叶变换可以用于增强图像中的某些频率成分,从而使得图像看起来更加清晰。而在图像修复中,傅里叶变换可以用于恢复损坏的图像数据,特别是在噪声处理和去模糊方面有着广泛的应用。
  10. 图像特征提取:傅里叶变换提供了一种从频率角度观察和分析图像的方法,可以用于提取图像的形状、纹理等特征。这些特征可以用于图像识别、分类等应用。

上述的详细解释:

1. cv2.imread()

  • 功能:读取图像文件。
  • 格式cv2.imread(filepath, flags)
    • filepath:图像文件的路径。
    • flags:指定读取图像的方式。常用的有:
      • cv2.IMREAD_COLOR:加载彩色图片,默认参数,可以直接写1。
      • cv2.IMREAD_GRAYSCALE:以灰度模式加载图片,可以直接写0。

2. cv2.imshow()

  • 功能:在窗口中显示图像。
  • 格式cv2.imshow(winname, mat)
    • winname:用于显示图像的窗口名称,用户自己根据需要设定,但避免使用中文名称。
    • mat:需要被显示的图像。

3. cv2.waitKey()

  • 功能:等待键盘输入事件。
  • 格式cv2.waitKey(delay)
    • delay:等待键盘输入事件的时间(以毫秒为单位)。当值为负数、0或空时,表示无限期等待。

4. cv2.destroyAllWindows()

  • 功能:销毁所有OpenCV创建的窗口。
  • 格式cv2.destroyAllWindows()

5. cv2.imwrite()

  • 功能:将图像数据保存到文件中。
  • 格式cv2.imwrite(filename, img[, params])
    • filename:要保存的文件名,包括路径和文件扩展名(如.jpg、.png等)。
    • img:要保存的图像数据,可以是ndarray格式的图像数据。
    • params:可选参数,用于指定保存图像的参数(如图像格式),但通常可以省略,直接通过文件扩展名来确定格式。

6. cv2.cvtColor()

  • 功能:转换图像的颜色空间。
  • 格式cv2.cvtColor(src, code[, dst[, dstCn]])
    • src:要转换颜色空间的图像。
    • code:颜色空间转换代码,如
      • cv2.COLOR_BGR2GRAY:从BGR色彩空间转换到灰度色彩空间。
      • cv2.COLOR_BGR2HSV:从BGR色彩空间转换到HSV色彩空间。
      • cv2.COLOR_HSV2BGR:从HSV色彩空间转换回BGR色彩空间。
    • dst:输出图像,与src图像大小和深度相同。可选参数。
    • dstCn:目标图像中的通道数。如果参数为0,则通道数自动从srccode得出。可选参数。

7. cv2.resize()

  • 功能:调整图像大小。
  • 格式cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
    • src:要调整大小的输入图像。
    • dsize:目标图像的大小,可以是元组(width, height)或仅宽度值(此时高度会按比例调整)。
    • dst:输出图像,用于存储调整大小后的图像。如果未提供,则函数会创建一个新的输出图像。可选参数。
    • fx:水平方向的缩放比例。可选参数。
    • fy:垂直方向的缩放比例。可选参数。res = cv2.resize(img, (0, 0), fx=1, fy=3)
    • interpolation:插值方法,用于确定调整图像尺寸时如何处理像素值。常用的有cv2.INTER_NEAREST(最近邻插值)、cv2.INTER_LINEAR(双线性插值,默认)、cv2.INTER_AREA(使用像素区域关系进行重采样)、cv2.INTER_CUBIC(4x4像素领域的双三次插值)等。

8. cv2.flip()

  • 功能:翻转图像。
  • 格式cv2.flip(src, flipCode)
    • src:原始图像。
    • flipCode:翻转类型。常用的有0(沿x轴翻转)、1(沿y轴翻转)、-1(同时沿x轴和y轴翻转)。

9. cv2.warpAffine()

  • 功能:对图像进行仿射变换。
  • 格式cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])
    • src:输入图像。
    • M:2x3的仿射变换矩阵。
    • dsize:输出图像的大小,格式为(width, height)
    • dst:输出图像,用于存储仿射变换后的图像。如果未提供,则函数会创建一个新的输出图像。可选参数。
    • flags:插值方法的组合。默认为cv2.INTER_LINEAR(线性插值)。其他选项包括cv2.INTER_NEAREST(最近邻插值)、cv2.INTER_AREA(区域插值)、cv2.INTER_CUBIC(三次样条插值)等。
    • borderMode:边界像素模式。可选参数。
    • borderValue:边界填充值。默认为0(黑色)。可以设置为其他颜色值。

10.边界填充 cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)


top_size,bottom_size,left_size,right_size = (50,50,50,50)

replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)

import matplotlib.pyplot as plt
plt.subplot(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')

plt.show()

BORDER_REPLICATE:复制法,也就是复制最边缘像素。
BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba
BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg
BORDER_CONSTANT:常量法,常数值填充。

 

高斯金字塔和拉普拉斯金字塔的过程

import cv2
import numpy as np # 导入必要的库
# 读取图像
img = cv2.imread("AM.png")
# 显示原始图像
cv2.imshow('img', img)
# 打印原始图像的尺寸
print(img.shape) # 输出: (442, 340, 3)
# 对原始图像进行升采样(图像尺寸加倍)
up = cv2.pyrUp(img)
# 显示升采样后的图像
cv2.imshow('up', up)
# 打印升采样后图像的尺寸
print(up.shape) # 输出: (884, 680, 3)
# 对原始图像进行降采样(图像尺寸减半)
down = cv2.pyrDown(img)
# 显示降采样后的图像
cv2.imshow('down', down)
# 打印降采样后图像的尺寸
print(down.shape) # 输出: (221, 170, 3)
# 对已经升采样过的图像再次进行升采样(尺寸再次加倍)
up2 = cv2.pyrUp(up)
# 显示再次升采样后的图像
cv2.imshow('up2', up2)
# 打印再次升采样后图像的尺寸
print(up2.shape) # 输出: (1768, 1360, 3)
# 对原始图像进行升采样,然后对升采样后的图像进行降采样
# 这通常用于观察升采样后降采样对图像的影响
up = cv2.pyrUp(img)
up_down = cv2.pyrDown(up)
# 显示升采样后降采样的图像
cv2.imshow('up_down', up_down)
# 水平拼接原始图像和升采样后降采样的图像以便比较
# 注意:这里缺少cv2.imshow的调用,应该添加cv2.imshow('comparison', np.hstack((img, up_down)))
# 但由于您的注释中提到了这一点,我将在注释中指出
# 打印拼接图像的指令(虽然实际未执行,但基于您的意图)
cv_show(np.hstack((img,up_down)),'up_down') # 应替换为 cv2.imshow
# 计算原始图像与升采样后降采样图像之间的差异
# 构建拉普拉斯金字塔,但尝试捕捉高频细节的损失
down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv_show(l_1,'l_1')
  1. shape属性
    • .shape属性返回一个元组,表示数组在每个维度上的大小。
    • 对于二维图像(灰度图),.shape返回(高度, 宽度)
    • 对于三维图像(彩色图,通常是BGR格式),.shape返回(高度, 宽度, 通道数)
    • 例如,如果有一个640x480的灰度图像,其.shape属性将是(480, 640)。如果是一个640x480的BGR彩色图像,其.shape属性将是(480, 640, 3)
  2. size属性
    • 在NumPy数组中,.size属性返回数组中所有元素的总数。
    • 对于图像来说,这相当于图像的高度乘以宽度再乘以通道数(对于彩色图像)。
    • 例如,对于640x480的BGR彩色图像,.size将是480 * 640 * 3 = 921600
    • 需要注意的是,在OpenCV中处理的图像对象(通常是cv2.imread()函数返回的)并没有直接的.size属性。但可以通过计算.shape属性的乘积来得到图像的大小,即image.shape[0] * image.shape[1] * (image.shape[2] if len(image.shape) == 3 else 1)
  3. dtype属性
    • .dtype属性返回数组中元素的数据类型。
    • 对于图像来说,这通常是uint8(无符号8位整型),表示每个像素值都是一个0到255之间的整数。
    • 其他可能的数据类型包括float32int32等,但它们在图像处理中不常见。

滤波函数

  1. cv2.blur():均值滤波
    • 参数格式cv2.blur(src, ksize[, dst[, anchor[, borderType]]])
      • src:输入图像。
      • ksize:滤波核的大小,例如(5, 5)
      • dst:输出图像(可选)。
      • anchor:锚点位置(可选,通常默认为核的中心)。
      • borderType:像素外推方法(可选,通常默认为cv2.BORDER_DEFAULT)。
    • 用处:对图像进行平滑处理,减少噪声,但可能导致边缘模糊。
  2. cv2.boxFilter():方框滤波
    • 参数格式:与cv2.blur()相似,但boxFilter允许更精确地控制归一化(即是否将核系数之和除以核的大小)。
    • 用处:与均值滤波类似,但提供了额外的归一化选项。当normalize=True时,它等同于均值滤波;当normalize=False时,它计算的是每个像素邻域内的像素值之和。
  3. cv2.GaussianBlur():高斯滤波
    • 参数格式cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])
      • sigmaX:X方向上的高斯核标准差。
      • sigmaY:Y方向上的高斯核标准差(可选,如果为0,则根据sigmaX计算)。
    • 用处:对图像进行平滑处理,同时更好地保留边缘细节。高斯滤波是一种加权平均,权重由二维高斯函数给出。
  4. cv2.medianBlur():中值滤波
    • 参数格式cv2.medianBlur(src, ksize[, dst])
      • ksize:必须是正奇数,例如3、5、7等。
    • 用处:去除图像中的椒盐噪声(即随机出现的黑色或白色像素点)。中值滤波用像素邻域内的中值替换该像素值。

边缘检测

  1. cv2.Canny():Canny算子边缘检测
    • 参数格式cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])
      • threshold1:第一个阈值,用于边缘检测的初步筛选。
      • threshold2:第二个阈值,用于边缘检测的进一步筛选,通常比threshold1大。
      • apertureSize:Sobel算子的大小(可选,通常默认为3)。
      • L2gradient:一个布尔值,指示是否使用更精确的L2范数进行梯度计算(可选,通常默认为False)。
    • 用处:检测图像中的边缘。Canny算子是一种多阶段算法,它首先使用高斯滤波器平滑图像,然后计算图像梯度,接着应用非极大值抑制,最后使用双阈值检测边缘。

1. 腐蚀(cv2.erode())

参数格式

cv2.erode(src, kernel, anchor=None, iterations=1, borderType=cv2.BORDER_CONSTANT, borderValue=None)
  • src:输入图像,必须是二值图像或灰度图像。
  • kernel:用于腐蚀操作的结构元素(也称核)。它定义了邻域的形状和大小。
  • anchor:锚点位置,决定了核的哪个像素点与输入图像的像素点对齐。默认是核的中心。
  • iterations:腐蚀操作的迭代次数。默认是1。
  • borderType:像素外推方法。默认是cv2.BORDER_CONSTANT,表示用常数值填充边界。
  • borderValue:当borderType=cv2.BORDER_CONSTANT时,这个参数指定了边界填充的常数值。

用处
腐蚀操作主要用于消除图像中的小白噪声(即小的亮区域),以及断开连接的对象等。它可以使图像中的亮区域变得更小,或者使物体之间的间隙变得更宽。

2. 膨胀(cv2.dilate())

参数格式

cv2.dilate(src, kernel, anchor=None, iterations=1, borderType=cv2.BORDER_CONSTANT, borderValue=None)

参数与腐蚀操作类似,只是函数名和操作效果不同。

用处
膨胀操作主要用于填充图像中的小黑洞(即小的暗区域),以及连接邻近的对象等。它可以使图像中的暗区域变得更小,或者使物体之间的连接变得更紧密。

3. 开运算(cv2.morphologyEx())

参数格式

cv2.morphologyEx(src, op, kernel, anchor=None, iterations=1, borderType=cv2.BORDER_CONSTANT, borderValue=None)
  • op:形态学操作类型,对于开运算,应设置为cv2.MORPH_OPEN
  • 其他参数与腐蚀和膨胀操作类似。

用处
开运算实际上是先进行腐蚀操作再进行膨胀操作。它主要用于去除小的亮区域(噪声)而保持较大的亮区域不变,同时能够平滑图像的边界。

4. 闭运算(cv2.morphologyEx())

参数格式
与开运算相同,只是op参数应设置为cv2.MORPH_CLOSE

用处
闭运算实际上是先进行膨胀操作再进行腐蚀操作。它主要用于填充小的暗区域(黑洞)而保持较大的暗区域不变,同时能够平滑图像的边界。

5. 梯度运算(cv2.morphologyEx())

参数格式
与开运算和闭运算相同,只是op参数应设置为cv2.MORPH_GRADIENT

用处
梯度运算用于获取图像的轮廓或边缘。它实际上是膨胀图像与腐蚀图像之间的差异,能够突出显示图像中的边缘特征。

6. 顶帽操作(cv2.morphologyEx())

参数格式
与前面的操作相同,只是op参数应设置为cv2.MORPH_TOPHAT

用处
顶帽操作是原图像与开运算结果之间的差异。它主要用于提取比背景亮的区域,同时去除小的亮区域(噪声)。

7. 黑帽操作(cv2.morphologyEx())

参数格式
与前面的操作相同,只是op参数应设置为cv2.MORPH_BLACKHAT

用处
黑帽操作是闭运算结果与原图像之间的差异。它主要用于提取比背景暗的区域,同时去除小的暗区域(黑洞)。

根据您引用的历史对话片段信息,以下是对OpenCV中相关函数参数格式及其作用的详细解释:

七、图像阈值化

  1. cv2.threshold()

    参数格式

    ret, dst = cv2.threshold(src, thresh, maxval, type)
    • src:输入图像,必须是灰度图像。
    • thresh:用于分类的阈值。
    • maxval:当像素值超过(对于THRESH_BINARYTHRESH_BINARY_INV)或低于(对于THRESH_TRUNCTHRESH_TOZERO)阈值时赋予的值。
    • type:阈值化操作的类型,例如
      • cv2.THRESH_BINARY

        这是最基本的二值化操作。如果像素值高于(有时是等于,这取决于具体实现)阈值,则将该像素设置为最大值(通常为255,白色),否则设置为0(黑色)。

      • cv2.THRESH_BINARY_INV

        这是THRESH_BINARY的反向操作。如果像素值低于阈值,则将其设置为最大值,否则设置为0。

      • cv2.THRESH_TRUNC

        如果像素值高于阈值,则将其截断为阈值。否则,像素值保持不变。

      • cv2.THRESH_TOZERO

        如果像素值低于阈值,则将其设置为0。否则,像素值保持不变。

      • cv2.THRESH_TOZERO_INV

        这是THRESH_TOZERO的反向操作。如果像素值高于阈值,则将其设置为0。否则,像素值保持不变。

      • cv2.THRESH_OTSU

        这种方法会自动计算一个合适的阈值,称为Otsu阈值。它基于图像的直方图,试图找到一个阈值,该阈值能够最小化类内方差或等价地最大化类间方差。要使用这种方法,你需要将cv2.threshold()函数的type参数设置为cv2.THRESH_BINARY | cv2.THRESH_OTSU。注意,在这种情况下,你提供的thresh参数将被忽略,因为Otsu方法会自动计算阈值。

      • cv2.THRESH_TRIANGLE

        这种方法基于图像的直方图,使用一种不同的算法来计算阈值。它试图找到一个阈值,该阈值能够最大化图像前景和背景之间的类间方差,但与Otsu方法不同,它使用的是直方图的累积分布函数的三角形近似。要使用这种方法,你需要将cv2.threshold()函数的type参数设置为cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE。同样,在这种情况下,你提供的thresh参数将被忽略。

    作用
    应用固定阈值或自适应阈值将灰度图像转换为二值图像。

八、图像轮廓

  1. cv2.findContours()

    参数格式

    contours, hierarchy = cv2.findContours(image, mode, method)
    • image:输入图像,通常是二值图像。
    • 轮廓检索模式(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

        使用一种基于L1范数的近似算法(由Teh和Chin在1989年提出)来减少轮廓点的数量。这种方法试图通过最小化原始轮廓和近似轮廓之间的L1距离来找到最佳的轮廓逼近。

      • cv2.CHAIN_APPROX_TC89_KCOS

        这是另一种基于Teh和Chin算法的近似方法,但它使用K-cosine距离作为度量标准。这种方法在某些情况下可能比L1方法更有效,特别是当轮廓的形状比较复杂时。

    注意:在OpenCV 4.x中,cv2.findContours()返回三个值,但在OpenCV 3.x中,它只返回两个值(contours和hierarchy),并且图像需要先被转换为灰度并应用阈值化。

    作用
    在二值图像中查找轮廓。

  2. cv2.drawContours()

    参数格式

    cv2.drawContours(image, contours, contourIdx, color, thickness)
    • image:绘制轮廓的目标图像。
    • contours:在cv2.findContours()中找到的轮廓列表。
    • contourIdx:指定要绘制的轮廓的索引。如果为负数,则绘制所有轮廓。
    • color:轮廓的颜色。
    • thickness:轮廓的厚度。如果为负值(例如cv2.FILLED),则轮廓内部将被填充。

    作用
    在图像上绘制轮廓。

使用OpenCV进行图像轮廓检测和处理的基本步骤。

轮廓检测

  1. 读取图像

    img = cv2.imread('contours.png')
  2. 转换为灰度图像

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  3. 应用二值化

    ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

    这一步将灰度图像转换为二值图像,其中所有像素值大于或等于127的设置为255(白色),小于127的设置为0(黑色)。

  4. 查找轮廓

    binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

    注意:在OpenCV的不同版本中,findContours函数的返回值可能有所不同。在某些版本中,它只返回contourshierarchy,而不返回binary(因为binary就是传入的阈值化图像)。

绘制轮廓

  • 绘制所有轮廓

    draw_img = img.copy()
    res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)

    这里-1表示绘制所有轮廓。

  • 绘制特定轮廓(例如第一个轮廓):

    draw_img = img.copy()
    res = cv2.drawContours(draw_img, [contours[0]], -1, (0, 0, 255), 2)

    或者更明确地指定索引:

    res = cv2.drawContours(draw_img, contours, 0, (0, 0, 255), 2)

轮廓特征

  • 面积

    area = cv2.contourArea(contours[0])
  • 周长

    perimeter = cv2.arcLength(contours[0], True)

轮廓近似

  • 使用approxPolyDP进行轮廓近似
    epsilon = 0.15 * cv2.arcLength(contours[0], True)
    approx = cv2.approxPolyDP(contours[0], epsilon, True)
    然后绘制近似轮廓。

边界矩形

  • 计算并绘制边界矩形

    x, y, w, h = cv2.boundingRect(contours[0])
    img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
  • 计算轮廓面积与边界矩形面积的比率

    rect_area = w * h
    extent = float(area) / rect_area

外接圆

  • 计算并绘制外接圆
    (x, y), radius = cv2.minEnclosingCircle(contours[0])
    center = (int(x), int(y))
    radius = int(radius)
    img = cv2.circle(img, center, radius, (0, 255, 0), 2)

九、图像直方图

绘制直方图通常不是由单个OpenCV函数完成的,而是结合NumPy和OpenCV的函数来实现。例如,使用cv2.calcHist()计算直方图,然后使用Matplotlib等库绘制直方图。

十、图像加法与混合

  1. cv2.add()

    参数格式

    dst = cv2.add(src1, src2)
    • src1src2:输入图像,它们的大小和类型必须相同。

    作用
    对两幅图像的对应像素值进行饱和加法操作。

  2. cv2.addWeighted()

    参数格式

    dst = cv2.addWeighted(src1, alpha, src2, beta, gamma)
    • src1src2:输入图像,它们的大小和类型必须相同。
    • alpha:第一幅图像的权重。
    • beta:第二幅图像的权重。
    • gamma:一个加到加权和上的标量值。

    作用
    按指定的权重混合两幅图像,并可以添加一个标量值来调整结果。

十一、其他常用函数

  1. cv2.waitKey()

    参数格式

    key = cv2.waitKey(delay)
    • delay:等待键盘输入事件的毫秒数。如果为0,则无限期等待。

    作用
    等待指定的毫秒数,直到键盘输入事件发生。常与cv2.imshow()一起使用来控制图像显示时间。

  2. cv2.destroyAllWindows()

    无参数

    作用
    关闭所有由cv2.imshow()产生的窗口。

  3. cv2.namedWindow()

    参数格式

    cv2.namedWindow(winname, flags=cv2.WINDOW_AUTOSIZE)
    • winname:窗口的名称。
    • flags:窗口的属性标志,例如cv2.WINDOW_AUTOSIZEcv2.WINDOW_NORMAL

    作用
    创建一个具有指定名称和属性的窗口。

  4. cv2.destroyWindow()

    参数格式

    cv2.destroyWindow(winname)
    • winname:要关闭的窗口的名称。

    作用
    关闭指定的窗口。

cv2.matchTemplate()

是OpenCV库中用于执行模板匹配的函数。

cv2.matchTemplate(image, templ, method, result=None, mask=None)

  • image:待检测的图像,通常是一个灰度图像,以减少计算量。图像的数据类型应为uint8float32
  • templ:模板图像,用于在待检测图像中查找匹配的区域。模板图像也通常是一个灰度图像,并且其大小和比例应与待检测图像中的目标对象相匹配。
  • method:指定匹配方法的标志。OpenCV提供了多种匹配方法,包括平方差匹配(cv2.TM_SQDIFF)、归一化平方差匹配(cv2.TM_SQDIFF_NORMED)、相关匹配(cv2.TM_CCORR)、归一化相关匹配(cv2.TM_CCORR_NORMED)、相关系数匹配(cv2.TM_CCOEFF)和归一化相关系数匹配(cv2.TM_CCOEFF_NORMED)。不同的匹配方法会产生不同的匹配结果,因此需要根据具体需求选择合适的方法。
  • result:可选参数,用于存储匹配结果的矩阵。如果未提供,则OpenCV会自动分配一个矩阵来存储结果。
  • mask:可选参数,用于指定模板图像中的有效区域。如果提供了掩模图像,则只有掩模图像中非零区域对应的模板像素才会参与匹配计算。这可以用于忽略模板图像中的某些部分,例如背景或噪声。

傅里叶变化例子

pip install opencv-python numpy matplotlib
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像并转换为灰度图
image = cv2.imread('path_to_your_image.jpg', cv2.IMREAD_GRAYSCALE)
# 将图像数据类型转换为float32
image_float = np.float32(image)
# 执行二维离散傅里叶变换
dft = np.fft.fft2(image_float)
# 将零频率分量移动到频谱中心
dft_shift = np.fft.fftshift(dft)
# 计算频谱的幅值
magnitude_spectrum = 20 * np.log(np.abs(dft_shift) + 1)
# 显示原始图像和频谱图
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.title('Original Image')
plt.imshow(image, cmap='gray')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.title('Magnitude Spectrum')
plt.imshow(magnitude_spectrum, cmap='gray')
plt.axis('off')
plt.show()

在上面的代码中:

  1. 我们首先使用cv2.imread函数读取图像,并将其转换为灰度图。
  2. 然后,将图像的数据类型转换为float32,因为傅里叶变换涉及复数运算。
  3. 使用np.fft.fft2函数对图像执行二维离散傅里叶变换。
  4. 使用np.fft.fftshift函数将零频率分量移动到频谱的中心。
  5. 计算频谱的幅值,并将其转换为对数尺度以便于可视化。这里使用了20 * np.log(np.abs(dft_shift) + 1)来计算对数幅值,这是图像处理中常用的技巧,可以使得频谱图更加易于观察。
  6. 最后,使用matplotlib.pyplot库显示原始图像和频谱图