1、图像翻转(图像镜像旋转)
在OpenCV中,图片的镜像旋转是以图像的中心为原点进行镜像翻转的
1.1 函数功能概述
cv2.flip 函数的作用是对输入图像进行翻转(翻转方式包括水平翻转、垂直翻转以及同时进行水平和垂直翻转)
1.2 函数
cv2.flip(src, flipCode[, dst]) -> dst
该函数接受三个参数,其中前两个参数 src 和 flipCode 是必选的,dst 是可选参数。函数返回值为翻转后的图像 dst
1.3 参数说明
- src:这是要进行翻转操作的输入图像,它可以是各种类型和深度的多通道图像(比如常见的彩色图像(通常是三通道,即 RGB 或 BGR 格式,OpenCV 默认使用 BGR 格式)、灰度图像(单通道)等)
- flipCode:用于指定具体的翻转类型的一个整数标志:
- 为
0
时(flipcode=0 ),表示沿 X 轴翻转(即垂直翻转)- 为
1
时(flipcode>0 ),表示沿 Y 轴翻转(即水平翻转)- 为
-1
时(flipcode<0 ),表示同时沿 X 轴和 Y 轴翻转
- dst:这是一个可选参数,代表输出图像。如果在调用函数时不提供这个参数,那么函数会自动创建一个与输入图像
src
具有相同尺寸和类型的输出图像,并在其中存储翻转后的结果。如果提供了这个参数,那么翻转后的图像将存储在这个指定的dst
中1.4 例子
import cv2 # 读取图片 image = cv2.imread("../images/car2.png") # 翻转:0-垂直翻转 1-水平翻转 -1:水平和垂直 new_image = cv2.flip(image, 0) # 显示原始图像和翻转后的图像 cv2.imshow("img01", image) cv2.imshow("ima02", new_image) cv2.waitKey(0) cv2.destroyAllWindows()
import cv2 as cv # 读取图像 img=cv.imread("images/cat1.png") img_r=cv.resize(img,(520,520)) # 图像翻转:cv2.flip(img,翻转类型标志0、-1、1),原点在图像中心位置 # 垂直翻转:flipcode=0,沿x轴翻转,上下翻转 flip0=cv.flip(img_r,0) # 水平翻转:flipcode=1,沿y轴翻转,左右翻转 flip1=cv.flip(img_r,1) # 水平+垂直翻转:flipcode=-1,沿x、y都翻转 flip2=cv.flip(img_r,-1) cv.imshow("img",img_r) cv.imshow("flip0",flip0) cv.imshow("flip1",flip1) cv.imshow("flip2",flip2) cv.waitKey(0) cv.destroyAllWindows()
2、图像仿射变换
仿射变换(Affine Transformation)是一种线性变换,它保持了点之间的相对距离不变,即平行线在变换后仍然保持平行。在图像处理中,仿射变换常用于旋转、缩放、平移和剪切(使物体发生倾斜变形 )等操作
2.1 cv2.getRotationMatrix2D 函数
2.1.1 功能
用于图像的旋转变换,旋转矩阵是一个 2x3 的矩阵,可以用来将图像围绕指定的中心点旋转指定的角度,并且可以选择是否进行缩放
2.1.2 函数名
cv2.getRotationMatrix2D(center, angle, scale) -> M
2.1.3 参数说明
- center:旋转中心点的坐标,格式为 (x, y)
- angle:旋转角度,单位为度。正角度表示逆时针旋转,负角度表示顺时针旋转
- scale:缩放比例。若设置为 1,则不进行缩放;若大于 1 则放大,小于 1 则缩小
2.1.4 返回值
2x3 的旋转矩阵
M
,用于后续的仿射变换
2.2 cv2.warpAffine 函数
2.2.1 功能
进行仿射变换,将输入图像根据给定的变换矩阵
M
进行变换2.2.2 函数名
cv2.warpAffine(src, M, dsize, dst) → dst
2.2.3 参数说明
- src:输入图像
- M:2x3 的变换矩阵(这里就是 cv2.getRotationMatrix2D 计算得到的旋转矩阵),类型为 np.float32
- dsize:输出图像的尺寸,形式为 (width, height)
- dst(可选):输出图像。如果未提供,则会自动创建一个新的图像。
2.3 图像旋转
旋转操作能够让图像绕着某个指定点旋转特定的角度
import cv2 img1 = cv2.imread("../images/fangshe.jpg") # 获取图像的尺寸 (h, w) = img1.shape[:2] print((h, w)) # 计算旋转坐标,中心点坐标 center = (w // 2, h // 2) print(center) # 旋转角度 angle = 45 # 获取旋转矩阵,1-表示不缩放,原始大小 m = cv2.getRotationMatrix2D(center, angle, 1) # 进行仿射变换 img2 = cv2.warpAffine(img1, m, (w, h)) cv2.imshow("img1", img1) cv2.imshow("img2", img2) # 保存旋转后的图片 save = cv2.imwrite("../save_image/xuanzhuan.jpg", img2) if save: print("ok") else: print("failed") cv2.waitKey(0) cv2.destroyAllWindows()
2.4 图像平移
平移操作可以将图像中的每个点沿着x 轴和 y 轴方向移动指定的距离,实现图像位置的改变
import cv2 import numpy as np img1 = cv2.imread("../images/fangshe.jpg") # 使用 img.shape 获取图像的形状信息时,它返回的是一个元组 # 对于彩色图像而言,这个元组的形式通常是 (高度, 宽度, 通道数) # 对于灰度图像,元组形式为 (高度, 宽度)。 # 获取图片像素。img.shape[:2] 表示取这个元组的前两个元素,也就是图像的高度和宽度 (h, w) = img1.shape[:2] # 定义平移参数,向左移动100px,向下平移50px tx = 200 ty = 200 # *****构建平移矩阵 # [[a b c][d e f]]中,a和e分别控制x轴和y轴方向的缩放和旋转 # 当a=1且b=0时,意味着在x轴方向上既没有缩放(缩放因子为1)也没有旋转 # 当e=1且d=0时,意味着在y轴方向上既没有缩放也没有旋转 # 所以这里的两个保证了平移操作不会改变图像的大小和角度 m = np.float32([[1, 0, tx], [0, 1, ty]]) # 进行仿射变换 # 宽度在前,高度在后,这与 img.shape 返回的元组顺序是相反的 img2 = cv2.warpAffine(img1, m, (w, h)) cv2.imshow("img1", img1) cv2.imshow("img2", img2) # 保存旋转后的图片 save = cv2.imwrite("../save_image/pingyi.jpg", img2) if save: print("ok") else: print("failed") cv2.waitKey(0) cv2.destroyAllWindows()
2.5 图像缩放
缩放操作可以改变图像的大小,通过调整缩放因子可以实现图像的放大或缩小
import cv2 import numpy as np img1 = cv2.imread("../images/fangshe.jpg") # 获取图片像素 (h, w) = img1.shape[:2] # 定义缩放的大小,大于1的值就是放大 tx = 0.5 ty = 0.5 # 构建矩阵 # 位于(0,1)和(1,0)位置的 0 表示在缩放过程中不会引入旋转或剪切等其他变换 # 位于(0,2)和(1,2)位置的 0 表示在缩放过程中不会进行平移操作 m = np.float32([[tx, 0, 0], [0, ty, 0]]) # 进行仿射变换 img2 = cv2.warpAffine(img1, m, (int(w * tx), int(h * ty))) cv2.imshow("img1", img1) cv2.imshow("img2", img2) # 保存旋转后的图片 save = cv2.imwrite("../save_image/suofang.jpg", img2) if save: print("ok") else: print("failed") cv2.waitKey(0) cv2.destroyAllWindows()
2.6 图像剪切
剪切操作可以改变图像的形状,使其在某个方向上倾斜
import cv2 import numpy as np img1 = cv2.imread("../images/fangshe.jpg") # 获取图片像素 (h, w) = img1.shape[:2] # 定义剪切的x轴和y轴的比例,小于1 tx = 0 ty = -1 # 构建矩阵 # tx:位于矩阵的 (0, 1) 位置,它是水平方向的剪切因子。当 tx 不为 0 时,图像会在水平方向上发生错切 # 如果 tx 为正数,图像会沿着 x 轴正方向倾斜;如果 tx 为负数,图像会沿着 x 轴负方向倾斜 # ty:位于矩阵的 (1, 0) 位置,它是垂直方向的剪切因子。当 ty 不为 0 时,图像会在垂直方向上发生错切 # 如果 ty 为正数,图像会沿着 y 轴正方向倾斜;如果 ty 为负数,图像会沿着 y 轴负方向倾斜。 m = np.float32([[1, tx, 0], [ty, 1, 0]]) # 进行仿射变换 img2 = cv2.warpAffine(img1, m, (w, h)) cv2.imshow("img1", img1) cv2.imshow("img2", img2) # 保存旋转后的图片 save = cv2.imwrite("../save_image/jianqie.jpg", img2) if save: print("ok") else: print("failed") cv2.waitKey(0) cv2.destroyAllWindows()
3、图像色彩空间转换
3.1 色彩空间转换的作用
- 方便图像处理:不同色彩空间的通道代表不同属性(例如 RGB 空间通过红、绿、蓝通道强度表示颜色;HSV 空间中,H(色相)决定颜色种类,S(饱和度)体现颜色深浅,V(亮度)表示明暗。针对不同处理需求,选择合适色彩空间能简化操作)
- 提高图像处理效果:在特定色彩空间下,可提升处理效果(如 HSV 空间中,通过调整 S 和 V,能增强图像对比度并去除噪点)
- 节省计算资源:某些情况下,特定色彩空间可减少计算量(例如 RGB 空间每个像素需 3 个通道,而灰度空间仅需 1 个通道。若仅处理亮度信息,转换为灰度空间可节省资源)
3.2 cv2.cvtColor()函数
3.2.1 功能
用于图像颜色空间的转换,可将图像从一种颜色空间转换为另一种
3.2.2 语法
cv2.cvtColor(src,code)
3.2.3 参数说明
src:输入图像(可为 NumPy 数组或 OpenCV 的 Mat 对象)
code指定转换类型,使用预定义的转换代码(如cv2.COLOR_BGR2GRAY表示从 BGR 到灰度图像的转换)注意,OpenCV 默认读取图像的格式是 BGR,而非 RGB
3.3 RGB 转 Gray(灰度)
可以减少数据量并简化算法
import cv2 image = cv2.imread("../images/car2.png") # 转换成灰度图像 gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 效果 cv2.imshow("image", gray_image) cv2.waitKey(0) cv2.destroyAllWindows()
3.4 RGB 转 HSV
HSV色彩空间在颜色分割和颜色识别中非常有用
import cv2 # 在某些情况下,使用某些特定的颜色空间可以提高图像处理的效果。 # 例如,在HSV空间中,可以通过调整S(饱和度)和V(亮度)来提高图像的对比度并去除噪 image = cv2.imread("../images/car2.png") # 将图像从BGR到HSV图像的转换 image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 转换后的图像 cv2.imshow('new Image', image) cv2.waitKey(0) cv2.destroyAllWindows()
4、图像二值化处理
4.1 图像二值化处理的作用
- 简化数据:二值化后的图像仅包含两种像素值(通常为 0 和 255),相比原始图像丰富的像素值信息,数据量大幅减少。这使得后续对图像进行分析、特征提取等操作时,计算机处理的数据量降低,从而提升处理速度和效率
- 突出特征:通过设定合适的阈值,二值化能够将图像中的前景对象与背景清晰地分离,二值化可以更容易地识别和提取感兴趣的对象或特征
- 提高准确性:在图像中,噪声通常表现为像素值的随机波动。二值化过程可以将低于或高于一定阈值的噪声像素去除,只保留符合条件的主要特征像素(例如在对含有噪声的指纹图像进行二值化处理时,能够去除噪声干扰,使指纹的纹路特征更加清晰,进而提高指纹识别的准确性)
- 便于测量和识别:在物体检测和形状分析领域,二值化后的图像中物体轮廓以清晰的黑白边界呈现。这方便了对物体轮廓的提取和分析
- 适用于阈值处理:当图像中前景和背景在灰度值上存在明显差异时,二值化是一种简单有效的阈值处理方法。通过设定合适的阈值,能够准确区分前景和背景
- 图像分割:图像分割是将图像划分为不同的有意义区域的过程。二值化是一种基础且常用的图像分割方法,它将图像分为前景和背景两个部分,为后续更复杂的图像分割和分析奠定基础
4.2 cv2.threshold函数详解
4.2.1 功能
将灰度图像转换为二值图像,根据指定的阈值将像素值分为两类:高于阈值的像素设为一个值(通常是255),低于阈值的像素设为另一个值(通常是0)
4.2.2 语法
retval, dst = cv2.threshold(src, thresh, maxval, type)
4.2.3 参数
- src:输入的灰度图像
- thresh:设定的阈值,作为像素值分类的界限
- maxval:当像素值超过阈值(根据不同的阈值类型判断)时,赋予该像素的最大值(在大多数情况下,这个值设为 255,代表白色)
- type:阈值类型,决定了如何根据阈值对像素值进行处理
type常见类型
- cv2.THRESH_BINARY :超过阈值的像素设为最大值,其余设为0
- cv2.THRESH_BINARY_INV :超过阈值的像素设为0,其余设为最大值
- cv2.THRESH_TRUNC :超过阈值的像素设为阈值,其余不变
- cv2.THRESH_TOZERO :超过阈值的像素不变,其余设为0
- cv2.THRESH_TOZERO_INV :超过阈值的像素设为0,其余不变
4.2.4 返回值
retval:实际使用的阈值(在一些简单阈值处理情况下,它与输入的
thresh
值相同。但在自适应阈值处理等情况下,函数会根据图像内容自动计算并返回一个合适的阈值)dst:输出的二值化图像(与输入图像 src 大小相同,数据类型也通常为 8 位无符号整数,像素值根据所选阈值类型和设定参数变为 0 或 maxval 等)
4.3 例子
import cv2 # 读取图像并转换为灰度图 image = cv2.imread("../images/car2.png", cv2.IMREAD_GRAYSCALE) # 应用阈值 thresh_value = 127 # 使用 cv2.threshold 函数对灰度图像进行二值化处理 # 函数返回两个值,retval 是实际使用的阈值(在某些自适应阈值情况下可能与输入的 thresh_value 不同,这里一般相同) # binary_image 是输出的二值化图像 # 在这个例子中,采用 cv2.THRESH_BINARY 阈值类型 # 意味着图像中像素值大于 127 的将被设为 255(白色),小于等于 127 的将被设为 0(黑色) retval, binary_image = cv2.threshold(image, thresh_value, 255, cv2.THRESH_BINARY) # 显示结果 cv2.imshow('原图', image) cv2.imshow('二值图像', binary_image) cv2.waitKey(0) cv2.destroyAllWindows()
5、图像掩模
5.1 概述
图像掩模是一种图像处理技术,其核心作用是创建一个掩模(mask),这个掩模可以理解为与原图像大小相同的图像,只不过它的像素值通常只有两种状态(二值图像),用于屏蔽或突出原图像中的特定区域。主要目的是通过掩模提取图像中特定颜色的区域
5.2 cv2.inRange函数
5.2.1 功能
用于创建颜色掩模的函数,它会遍历输入图像的每个像素,判断其是否在指定的颜色范围内
5.2.2 函数原型
cv2.inRange(src, lowerb, upperb)
5.2.3 参数
- src:表示输入的图像(可以是彩色图像(如常见的 BGR 格式)或灰度图像)
- lowerb:颜色范围的下界(以数组或元组形式表示)(指定了要提取颜色的最小值,每个元素对应颜色空间中相应通道的下限值)
- upperb:颜色范围的上界(以数组或元组形式表示)(指定了要提取颜色的最大值,每个元素对应颜色空间中相应通道的上限值)
5.2.4 返回值
函数返回一个二值图像,其中白色部分(通常值为 255)表示在指定颜色范围内的区域,黑色部分(通常值为 0)表示不在该范围内的区域。这个二值图像就是我们所需的掩模,可用于后续对原图像特定区域的提取、过滤等操作
5.3 例子
import cv2 import numpy as np image = cv2.imread('../images/car.png') # 将图像从 BGR 转换到 HSV 颜色空间 image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 定义一个HSV颜色空间(蓝色区域) lower = np.array([100, 100, 100]) height = np.array([140, 255, 255]) # 掩码处理 mask = cv2.inRange(image, lower, height) cv2.imshow('mask', mask) cv2.waitKey(0) cv2.destroyAllWindows()
6、图像位与操作
6.1 概述
cv2.bitwise_and() 函数用于对两个图像进行按位与操作 ,这个操作会逐个像素地对两个输入图像进行比较,只有在两个像素均为 255(白色)时,输出的像素才会为 255(白色),否则输出为 0(黑色) 。这种特性使得它在掩膜和图像分割等任务中发挥着重要作用
6.2 cv2.bitwise_and() 函数
6.2.1 功能
该函数用于对两个图像执行按位与操作,并返回结果图像
6.2.2 函数原型
dst = cv2.bitwise_and(src1, src2, mask=None)
6.2.3 参数
- src1 :第一个输入图像
- src2 :第二个输入图像,要求与
src1
具有相同的尺寸(宽和高)以及数据类型- mask :可选参数,用于指定掩膜(当提供掩膜时,只有在掩膜中对应位置像素值为非零的地方,才会对
src1
和src2
对应位置的像素进行按位与操作,并将结果存入输出图像。如果掩膜对应位置像素值为 0,则输出图像对应位置像素值直接设为 0,不进行src1
和src2
的按位与计算)6.2.4 返回值
函数返回经过按位与操作后的图像 dst,其尺寸和数据类型与输入图像
src1
(或src2
)一致6.3 例子
import cv2 import numpy as np # 读取图像 image = cv2.imread("../images/car2.png") # 将图像从 BGR 转换到 HSV 颜色空间 hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 定义颜色范围,(蓝色区域) lower = np.array([100, 100, 100]) upper = np.array([140, 255, 255]) # 使用 inRange 函数创建掩模 mask = cv2.inRange(hsv_image, lower, upper) # 位与操作 # 由于是对图像自身操作,src1和src2都为image image = cv2.bitwise_and(image, image, mask=mask) cv2.imshow('01', image) cv2.waitKey(0) cv2.destroyAllWindows()
7、图像检测轮廓
7.1 cv2.findContours 函数
7.1.1 功能概述
用于在二值图像中查找轮廓(轮廓是指图像中具有相同颜色或强度的连续点组成的曲线),它能够表示物体的边界,常用于物体检测、分割和形状分析
7.1.2 函数原型
contours, hierarchy = cv2.findContours(image, mode, method)
7.1.3 参数
- image:输入的二值图像。通常在调用该函数之前需要将图像转换为灰度图像并进行二值化处理 (诸如 cv2.threshold 进行阈值处理或 cv2.Canny 进行边缘检测等方法将灰度图像转换为二值图像,以便查找轮廓)
- mode:轮廓检索模式,决定了函数如何查找和组织轮廓
- cv2.RETR_EXTERNAL:只检索最外层的轮廓,内部的轮廓将被忽略(适用于只关注物体外部边界的情况,例如统计图像中离散物体的数量)
- cv2.RETR_LIST:检索所有的轮廓,并将它们以列表的形式存储,不建立轮廓之间的层级关系(适用于对轮廓层级关系不关心,只需要获取所有轮廓点集的场景)
- cv2.RETR_TREE:检索所有轮廓,并建立轮廓之间的树形层级关系(常用于复杂形状分析或需要对轮廓进行层次化处理的任务)
- method:轮廓逼近方法,决定了如何对轮廓点进行近似
- cv2.CHAIN_APPROX_SIMPLE:该方法会压缩轮廓点,仅保留轮廓的端点(例如,对于一条直线段,只保留其两个端点,而不存储中间的所有点,这样可以大大减少数据量,同时又能保持轮廓的基本形状,适用于大多数实际应用场景)
- cv2.CHAIN_APPROX_NONE:保留轮廓上的所有点,不进行任何压缩(适用于对轮廓细节要求极高,不能丢失任何点的情况,但会占用较多的内存)
7.1.4 返回值
- contours:一个 Python 列表,列表中的每个元素是一个轮廓(即一组点),每个轮廓以 NumPy 数组的形式存储,数组中的每个元素代表轮廓上的一个点
- hierarchy:轮廓的层级信息,是一个包含轮廓之间关系的数组数组中的每个元素包含四个值,分别表示当前轮廓的下一个轮廓、上一个轮廓、子轮廓和父轮廓的索引。如果某个关系不存在,则对应的值为 -1。层级信息在需要分析轮廓之间的嵌套关系时非常有用
7.2 cv2.boundingRect 函数
7.2.1 功能概述
用于计算轮廓的最小外接矩形,这个函数可以返回一个包含轮廓的最小矩形的边界框。该矩形完全包围轮廓,且其边与图像的坐标轴平行。这个函数在对象检测、图像分割等任务中很有用
7.2.2 函数原型
x, y, w, h = cv2.boundingRect(contour)
其中 contour 是由 cv2.findContours 函数获取的单个轮廓
7.2.3 返回值
- x:矩形左上角点的 x 坐标
- y:矩形左上角点的 y 坐标
- w:矩形的宽度
- h:矩形的高度
7.3 cv2.drawContours 函数
7.3.1 功能概述
用于在图像上绘制轮廓的函数
7.3.2 函数原型
cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
7.3.3 参数
- image:这是目标图像,即要在其上绘制轮廓的图像(它可以是灰度图像或彩色图像,数据类型通常为 numpy.ndarray。如果是彩色图像,轮廓颜色将以 BGR(蓝、绿、红)格式指定;如果是灰度图像,轮廓颜色将以单一灰度值指定)
- contours:这是一个包含所有要绘制的轮廓的 Python 列表(每个轮廓是一个 numpy.ndarray 类型的数组,数组中的每个元素代表轮廓上的一个点,通常表示为 (x, y) 坐标对。这些轮廓一般是通过 cv2.findContours() 函数从二值图像中提取得到的)
- contourIdx:该参数用于指定要绘制的轮廓的索引(如果设置为
-1
,则表示绘制列表中所有的轮廓;如果设置为一个非负整数n
,则只绘制索引为n
的轮廓)- color:用于指定轮廓的颜色(如果
image
是彩色图像,color
应该是一个包含三个元素的元组,分别代表 BGR 通道的值;如果image
是灰度图像,color
应该是一个单一的整数,表示灰度值)- thickness(可选):表示轮廓线的宽度(默认值为
1,
如果设置为-1
,则表示填充轮廓内部,而不是绘制轮廓线)- lineType,hierarchy,maxLevel,offset(不必理会)
7.3.4 返回值
cv2.drawContours() 函数会直接在输入的 image上进行绘制操作,并返回绘制了轮廓的图像。需要注意的是,该函数会修改原始的 image 数组
7.4 例子
cv2.findContours 函数,cv2.drawContours 函数和cv2.boundingRect 函数
import cv2 # 读取图像并转换为灰度图像 image = cv2.imread("../images/chepai.png") gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 二值化处理 retval, binary_image = cv2.threshold(gray_image, 100, 255, cv2.THRESH_BINARY) # 查找轮廓 contours, hierarchy = cv2.findContours(binary_image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) print(len(contours)) # 把灰度图像转换彩色图像 output_image = cv2.cvtColor(binary_image, cv2.COLOR_GRAY2BGR) # 绘制轮廓 -1表示绘制所有轮廓 cv2.drawContours(output_image, contours, -1, (0, 255, 0), 2) # 获取所有轮廓的坐标,宽度,高度 for contour in contours: x, y, w, h = cv2.boundingRect(contour) print(x, y, w, h) if w > 140 and w < 160: cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2) cv2.imshow('Contours', image) # 显示结果 # cv2.imshow('Contours', output_image) cv2.waitKey(0) cv2.destroyAllWindows()
8、滤波器(卷积核)
8.1 基本概念
在深度学习中,滤波器又称为卷积核,图像滤波就是通过滤波器得到另一个图像的过程
8.2 卷积核大小
一般为奇数(3×3、5×5、7×7)这是为了保证锚点在中间,防止位置发生偏移。锚点是卷积核中的一个关键位置,通常位于卷积核中心
8.3 卷积核大小的影响
卷积核越大,能看到的信息越多,提取的特征越好,但同时计算量也越大
9、图像平滑处理
9.1 图像噪声定义和性质
9.1.1 图像噪声定义
图像噪声是图像中不必要的干扰信息,妨碍人们通过视觉对图像信息的理解。噪声在理论上可以定义为“不可预测,只能用概率统计方法来认识的随机误差” ,因此可看作多维随机过程,用概率分布函数和概率密度分布函数描述
9.1.2 图像噪声分类
- 外部噪声(由外部环境因素如光线变化、电磁干扰引起)
- 内部噪声(由设备本身因素如传感器噪声、电路噪声引起)
9.1.3 图像噪声产生原因
- 传感器和电路产生噪声(扫描仪或数码相机的传感器和电路可能会产生电子噪声,导致图像中出现噪点 )
- 长时间曝光(在拍摄夜景时,由于CCD无法处理较慢的快门速度所带来的巨大工作量,导致一些特定的像素失去控制,产生噪点 )
- 格式压缩(使用JPEG格式对图像进行压缩时,由于图像数据的处理方式,可能会在边缘位置产生不自然的结合,形成噪点 )
- 感光元件特性(感光元件的热稳定性等特性也可能导致噪点的产生 )
9.1.4 图像噪声影响和解决方法
噪声影响图像质量,使其信息模糊,可通过图像降噪技术减少噪声,图像平滑处理是减少噪声的一种方式
9.2 高斯滤波
9.2.1 主要作用
去除图像中的噪声,并减少图像细节,以实现图像的平滑处理
9.2.2 原理
利用高斯函数对图像进行加权平均,每个像素值被周围像素加权平均值取代,权重由高斯分布函数计算,能有效去除噪声并保留图像整体特征
9.2.3 适用场景
- 去除高斯噪声:对周围像素加权平均,抑制噪声影响。
- 模糊处理:平均周围像素值实现图像模糊。
- 提取大致轮廓:平滑图像细节,有助于提取大致轮廓和结构特征
9.2.4 cv2.GaussianBlur()函数
该函数可以对图像进行高斯模糊处理,即在每个像素周围使用高斯核来加权平均计算像素值,从而达到模糊效果
cv2.GaussianBlur(src, ksize, sigmaX)
参数
src:输入图像
ksize:高斯核大小,元组形式(width, height)
sigmaX:高斯核在 x 方向上的标准差
9.2.5 例子
import cv2 img = cv2.imread("../images/renwu02.png") # 定义高斯核大小和标准差 ksize = (7, 7) sigma = 4 # 对图像进行高斯模糊处理 new_image = cv2.GaussianBlur(img, ksize, sigma) # 显示原始图像和滤波后的图像 cv2.imshow('old Image', img) cv2.imshow('new Image', new_image) cv2.waitKey(0) cv2.destroyAllWindows()
9.3 双边滤波
9.3.1 主要作用
双边滤波通过考虑像素点的空间距离和灰度差异,实现了对图像进行平滑的同时,尽量保留图像的边缘细节
9.3.2 原理
在滤波时既考虑像素点与周围像素点的空间距离权重,又考虑灰度差异权重,使像素点最终值由邻域像素根据这两个权重组合计算得出,从而在平滑图像时保留边缘信息
9.3.3 适用场景
适用于各种图像,尤其在人脸识别、图像增强和图像去噪等需平滑且保留边缘细节的领域
9.3.4 cv2.bilateralFilter() 函数
对图像进行双边滤波处理,即在保持边缘清晰的同时,对图像进行平滑处理
cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace)
参数
src:输入图像
d:滤波器直径,用于指定在每个像素周围考虑的像素邻域大小 ,正奇数
sigmaColor:颜色空间的标准差,用于控制滤波过程中颜色相似性的权重。较大的值意味着更宽松的颜色相似性条件
- 大 sigmaColor 值:当 sigmaColor 较大时,颜色差异较大的像素也会被赋予较大的权重,这意味着滤波器会在更大范围内进行平滑处理,导致图像细节的丢失较多
- 小 sigmaColor 值:当sigmaColor 较小时,只有颜色差异较小的像素会被赋予较大的权重,滤波器主要在颜色相似的区域内进行平滑处理,这样可以更好地保留边缘和细节
sigmaSpace :坐标空间的标准差,用于控制滤波过程中空间相似性的权重。较大的值意味着更宽松的空间相似性条件
- 大 sigmaSpace 值:当 sigmaSpace 较大时,空间上距离较远的像素也会被赋予较大的权重,这意味着滤波器会在更大的空间范围内进行平滑处理,导致图像的局部细节被进一步平滑
- 小 sigmaSpace 值:当 sigmaSpace 较小时,只有空间上距离较近的像素会被赋予较大的权重,滤波器主要在局部范围内进行平滑处理,这样可以更好地保留局部细节和边缘信息
9.3.5 例子
import cv2 image = cv2.imread("../images/renwu02.png") # 设置双边滤波参数 # 滤波直径 d = 19 color = 100 space = 150 # 双边滤波 b_image = cv2.bilateralFilter(image, d, color, space) cv2.imshow("image", image) cv2.imshow("b_image", b_image) cv2.waitKey(0) cv2.destroyAllWindows()
9.4 中值滤波
9.4.1 主要作用
去除图像中的胡椒噪声或其他类型的脉冲噪声
9.4.2 原理
将每个像素点周围邻域像素按灰度值大小排序,取中间值作为该像素点输出值,能有效去除椒盐噪声或脉冲噪声,使图像平滑
9.4.3 适用场景
适合处理受椒盐噪声干扰的图像(如传感器捕获的图像或传输中受干扰的图像)
9.4.4 cv2.medianBlur()函数
用于对图像进行中值滤波处理,可用于去除图像中的椒盐噪声或斑点噪声
cv2.medianBlur(src, ksize)
参数
src:输入图像
ksize:孔径大小,大于1的奇数
9.4.5 例子
import cv2 image1 = cv2.imread("../images/hujiao.png") # 定义卷积大小 d = 5 # 中值滤波 m_image = cv2.medianBlur(image1, d) cv2.imshow("image1", image1) cv2.imshow("m_image", m_image) cv2.waitKey(0) cv2.destroyAllWindows()
10、图像边缘检测
10.1 使用 OpenCV 进行图像边缘检测的原因
- 对图像分割和特征提取至关重要:图像边缘代表了物体与背景、物体与物体之间的边界(例如,在识别图像中的汽车时,汽车的边缘可以帮助我们将汽车从背景中分离出来,并提取出汽车的形状特征)
- 蕴含丰富信息:图像边缘包含了诸如形状、方向、纹理等丰富的信息,通过分析这些信息可以推断出物体的类型和姿态(例如,圆形物体的边缘是平滑的曲线,而矩形物体的边缘则是直线。同时,边缘的纹理信息也可以反映物体表面的粗糙程度)
- 减少数据量并保留重要信息:边缘检测可以将图像中的大部分非边缘区域去除,只保留边缘部分
- 标识数字图像中亮度变化明显的点:这些点通常对应着物体的边界或区域,通过检测这些边缘点可以确定图片中物体的位置和形状
10.2 Canny 边缘检测
10.2.1 概述
是一种广泛应用于图像处理、计算机视觉和机器学习中的边缘检测算法,常用于物体识别、图像分割等任务。该算法具有低错误率、高定位精度和单边缘响应等优点,能够有效地提取图像中的边缘信息
10.2.2 cv2.Canny函数
10.2.2.1 功能概述
该函数实现了 Canny 边缘检测算法,用于提取输入图像中的边缘信息
10.2.2.2 函数语法
edges = cv2.Canny(image, threshold1, threshold2)
10.2.2.3 参数
image:输入的灰度图像
- threshold1:第一个阈值,用于边缘检测的低阈值 (低阈值用于识别可能的边缘像素。当一个像素的梯度值大于低阈值时,该像素可能是边缘的一部分,但由于噪声等因素的影响,单独依靠低阈值会识别出很多虚假边缘)
- hreshold2: 第二个阈值,用于边缘检测的高阈值(高阈值用于识别强烈的边缘像素。如果一个像素的梯度值大于高阈值,那么这个像素几乎可以肯定是边缘的一部分。高阈值的存在可以有效地减少由于噪声引起的虚假边缘)
10.2.2.4 返回值
edges :返回检测到的边缘图像,是一个二值图像(边缘部分为白色(像素值为 255),其他部分为黑色(像素值为 0))
10.2.2.5 例子
import cv2 # 读取并转换为灰度图 image = cv2.imread("../images/car2.png") image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 应用 Canny 边缘检测 img = cv2.Canny(image, 100, 800) # 显示结果 cv2.imshow('bianyuan', img) cv2.waitKey(0) cv2.destroyAllWindows()
11、图像形态学操作
11.0 概念
形态学操作是基于形状的图像处理技术,其核心在于利用预先定义的结构元素(一个小的矩阵)对图像进行处理,以此提取图像中的有用特征,广泛应用于边界检测、噪声去除等任务
形态学变换是一种基于形状的简单变换,它的处理对象通常是二值化图像(形态学变换有两个输入,一个输出:输入为原图像、核(结构化元素),输出为形态学变换后的图像)
11.1 腐蚀
11.1.1 原理
腐蚀操作的核心思想是,若一个结构元素完全包含在前景物体内部,那么该结构元素对应的输出图像位置的值为 1(白色),否则为 0(黑色)。简单来说,就是减少图像中白色区域的大小,常用于消除小的白色噪声点
腐蚀操作就是使用核在原图(二值化图)上进行从左到右、从上到下的滑动(也就是从图像的左上角开始,滑动到图像的右下角)。在滑动过程中,令核值为1的区域与被核覆盖的对应区域进行相乘,得到其最小值,该最小值就是卷积核覆盖区域的中心像素点的新像素值,接着继续滑动。由于操作图像为二值图,所以不是黑就是白,这就意味着,在被核值为1覆盖的区域内,只要有黑色(像素值为0),那么该区域的中心像素点必定为黑色(0)。这样做的结果就是会将二值化图像中的白色部分尽可能的压缩
11.1.2 函数原型
eroded = cv2.erode(src, kernel, dst,iterations=1)
11.1.3 参数
- src:输入图像
- kernel:结构元素,是一个矩阵结构数据,用于定义腐蚀操作的方式
- dst(可选):输出图像。若未提供,会自动创建一个新的图像
- iterations(可选):腐蚀操作的迭代次数,默认为 1。增加迭代次数会使腐蚀效果更明显,但也会让前景物体变得更小
11.1.4 例子
import cv2 import numpy as np # 读取图像 img = cv2.imread("../images/ceshi02.jpg") # 定义结构元素 kernel = np.ones((3, 3), np.uint8) # 执行腐蚀操作 eroded = cv2.erode(img, kernel, iterations=3) # 显示结果 cv2.imshow('Original Image', img) cv2.imshow('Eroded Image', eroded) cv2.waitKey(0) cv2.destroyAllWindows()
11.2 膨胀
11.2.1 原理
膨胀操作与腐蚀相反,它会增加图像中白色区域的大小,常用于填补前景物体中的小洞或扩大前景物体的边界
11.2.2 函数原型
dilated = cv2.dilate(src, kernel, iterations=1)
11.2.3 例子
import cv2 import numpy as np # 读取图像 img = cv2.imread("../images/ceshi02.jpg") # 定义结构元素 kernel = np.ones((5, 5), np.uint8) # 执行腐蚀操作 eroded = cv2.dilate(img, kernel, iterations=3) # 显示结果 cv2.imshow('Original Image', img) cv2.imshow('Eroded Image', eroded) cv2.waitKey(0) cv2.destroyAllWindows()
11.3 开运算
11.3.1 原理
开运算是先进行腐蚀操作,再进行膨胀操作的过程。它常用于消除噪点, 去除小的物体、平滑较大的物体边界以及填充细长的突出部分
11.3.2 函数原型
opened = cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel)
11.3.3 参数
- src:输入图像
- cv2.MORPH_OPEN:指定进行开运算
- kernel:结构元素,用于定义形态学操作的方式 ,可通过 cv2.getStructuringElement 函数获得
11.3.4 op: 形态学操作的类型
- cv2.MORPH_OPEN :开运算
- cv2.MORPH_CLOSE :闭运算
- cv2.MORPH_GRADIENT :形态学梯度
- cv2.MORPH_TOPHAT :顶帽
- cv2.MORPH_BLACKHAT :黑帽
11.3.5 例子
import cv2 import numpy as np # 读取图像 img = cv2.imread("../images/kai.jpg") # 定义结构元素 kernel = np.ones((7, 7), np.uint8) # 执行腐蚀操作 eroded = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # 显示结果 cv2.imshow('Original Image', img) cv2.imshow('Eroded Image', eroded) cv2.waitKey(0) cv2.destroyAllWindows()
11.4 闭运算
11.4.1 原理
闭运算是先膨胀后腐蚀的过程,常用于填充前景物体中的小洞,平滑较大物体的边界以及连接邻近的物体
11.4.2 例子
import cv2 import numpy as np # 读取图像 img = cv2.imread("../images/bi01.jpeg") # 定义结构元素 kernel = np.ones((17, 17), np.uint8) # 执行腐蚀操作 eroded = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) # 显示结果 cv2.imshow('Original Image', img) cv2.imshow('Eroded Image', eroded) cv2.waitKey(0) cv2.destroyAllWindows()
11.5 形态学梯度
11.5.1 原理
形态学梯度是通过计算膨胀后的图像与腐蚀后的图像之间的差值得到的,其作用是强化图像的边缘信息,并且对噪声有一定的抑制作用
计算公式为:形态学梯度 = 膨胀的图 - 腐蚀的图
11.5.2 例子
import cv2 import numpy as np # 读取图像 img = cv2.imread("../images/xtx.gif") # 定义结构元素 kernel = np.ones((9, 9), np.uint8) # 执行腐蚀操作 eroded = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) # 显示结果 cv2.imshow('Original Image', img) cv2.imshow('Eroded Image', eroded) cv2.waitKey(0) cv2.destroyAllWindows()
11.6 顶帽(礼帽 )
11.6.1 原理
顶帽变换是原图像与开运算结果的差值(结果是放大了裂缝或者局部低亮度的区域 ),用于获取图像中的亮细节(得到的效果图突出了比原图轮廓周围的区域更明亮的区域 )
顶帽 = 原图 - 开运算结果(得到大图形外的小图形 )
礼帽运算用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用礼帽运算进行背景提取
11.6.2 例子
import cv2 import numpy as np # 读取图像 img = cv2.imread("../images/kai.jpg") # 定义结构元素 kernel = np.ones((7, 7), np.uint8) # 执行腐蚀操作 eroded = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) # 显示结果 cv2.imshow('Original Image', img) cv2.imshow('Eroded Image', eroded) cv2.waitKey(0) cv2.destroyAllWindows()
11.7 黑帽
11.7.1 原理
黑帽变换是闭运算结果与原图像的差值,用于获取图像中的暗细节(黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关 )
黑帽 = 闭运算结果 - 原图(得到大图形内的小图形 )
黑帽运算用来分离比邻近点暗一些的斑块
11.7.2 例子
import cv2 import numpy as np # 读取图像 img = cv2.imread("../images/bi01.jpeg") # 定义结构元素 kernel = np.ones((7, 7), np.uint8) # 执行黑帽操作 eroded = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel) # 显示结果 cv2.imshow('Original Image', img) cv2.imshow('Eroded Image', eroded) cv2.waitKey(0) cv2.destroyAllWindows()
11.8 总结
腐蚀:黑色变多,白色(有颜色)变少
膨胀:黑色变少,白色(有颜色)变多
开运算:先腐蚀后膨胀,白色先变少再变多:去除白色的毛刺
闭运算:先膨胀后腐蚀,黑色先变少在变多:去除黑色的毛刺
顶帽(礼帽):原图和开运算的差,留下白色毛刺,提取出有颜色的"毛刺"的特征
黑帽::原图和闭运算的差,留下黑色毛刺,提取出暗颜色的"毛刺"的特征
形态学梯度:开运算和闭运算的差,提取图像的边缘信息