资讯动态

Opencv基础:图像基础操作和图像平滑与降噪

发布时间:2026/8/5 8:27:19 来源:尧图企业网站定制
摘要本文系统梳理了 OpenCV 图像处理的核心基础操作涵盖图像读写、通道分离、算术运算、边界填充、阈值处理以及多种平滑降噪滤波算法并提供了完整的 Python 代码示例。 前言在计算机视觉的世界里图像本质上就是一个由数字组成的 NumPy 数组。OpenCV 作为该领域的事实标准库为我们提供了极其丰富的像素级操作接口。本文将结合实战代码带你系统梳理 OpenCV 的核心基础操作涵盖图像读写、通道分离、算术运算、边界填充、阈值处理以及多种平滑降噪滤波算法。一、 图像的读取、显示与保存1. 基础属性获取读取图像后我们可以通过 NumPy 的属性来了解图像的基本信息。需要注意的是OpenCV 默认读取的是BGR格式而非 RGB。import cv2 import numpy as np img cv2.imread(qi_e.png) # 读取图像 if img is None: print(图片读取失败请检查路径) else: print(图片形状(shape):, img.shape) # (高, 宽, 通道数) print(图像数据类型(dtype):, img.dtype) # 通常为 uint8 print(图像大小(size):, img.size) # 总像素数 高 × 宽 × 通道数 cv2.imshow(Image, img) cv2.waitKey(0) # 0 表示永久等待按键 cv2.destroyAllWindows()2. 灰度图读取与保存在后续的边缘检测或阈值处理中我们通常需要将图像转为单通道的灰度图这能大幅减少计算量。读取图片灰度图有以下方法方式一读取时直接指定灰度模式gray_img cv2.imread(qi_e.png, cv2.IMREAD_GRAYSCALE)方式二读取彩色图后转换gray_img cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)读取灰度图 gray_img cv2.imread(qi_e.png, cv2.IMREAD_GRAYSCALE) # 方法一 print(图片形状(shape):, gray_img.shape) print(图像数据类型(dtype):, gray_img.dtype) print(图像大小(size):, gray_img.size) cv2.imshow(Gray Image, gray_img) cv2.waitKey(0) cv2.destroyAllWindows() 图片保存 cv2.imwrite(qi_e_GRAY.png, gray_img)二、 图像基础操作ROI、通道与缩放1. ROI感兴趣区域提取ROI 是指图像中我们需要重点分析的区域。利用 NumPy 的数组切片我们可以轻松截取或修改图像的特定部分例如实现局部打码。# 提取 ROI (y1:y2, x1:x2)roi img[30:230, 40:200] # 提取 30 行到 230 行40 列到 200 列所包含的矩形区域# 截取图片部分内容 img cv2.imread(qi_e.png) roi img[30:230, :] cv2.imshow(Original, img) cv2.imshow(ROI, roi) cv2.waitKey(0) cv2.destroyAllWindows()输出展示实现局部打码img cv2.imread(qi_e.png) img[10:300, 200:400] np.random.randint(0, 256, (290, 200, 3), dtypenp.uint8) # 矩阵赋值必须是同等大小 img[10:300, 200:400]: 定位图像 img 中需要被修改的区域ROI np.random.randint(0, 256, (290, 200, 3)) 这个函数用于生成一个指定形状的随机整数矩阵作为马赛克的填充物。 0, 256生成随机整数的范围是 [0, 256)即 0 到 255。这刚好对应图像像素值的有效范围8位无符号整数。 (290, 200, 3)生成矩阵的形状。 290高度必须与左侧切片的行高一致。 200宽度必须与左侧切片的列宽一致。 3通道数代表 BGR 三个颜色通道必须与左侧图像的通道数一致。 cv2.imshow(Mosaic, img) cv2.waitKey(0) cv2.destroyAllWindows()输出展示2. 颜色通道分离与合并颜色通道分离是将一张包含颜色信息的彩色图像拆解成三张独立的、只反映单一颜色亮度分布的“灰度图”。有两种方法进行提取 BGR 颜色通道。# 方式一切片提取b img[:, :, 0]g img[:, :, 1]r img[:, :, 2]# 方式二使用 split 函数b, g, r cv2.split(img)# 1、读取图像 img cv2.imread(qi_e.png) # 2、提取颜色通道 b img[:, :, 0] # 蓝色通道 (B) g img[:, :, 1] # 绿色通道 (G) r img[:, :, 2] # 红色通道 (R) 或者使用 cv2.split(img) b, g, r cv2.split(img) b 包含蓝色通道 g 包含绿色通道 r 包含红色通道 cv2.imshow(Blue Channel, b) cv2.imshow(Green Channel, g) cv2.imshow(Red Channel, r) cv2.waitKey(0) cv2.destroyAllWindows()输出展示3. 图像缩放使用cv2.resize可以按比例放大或缩小图像。# 指定绝对大小 (宽, 高)resized cv2.resize(img, (200, 200))# 按比例缩放 (缩小一半)resized cv2.resize(img, None, fx0.5, fy0.5)img cv2.imread(qi_e.png) resized1 cv2.resize(img, (200, 200)) # 指定大小 resized2 cv2.resize(img, None, fx0.5, fy0.5) # 按比例 cv2.imshow(Original, img) cv2.imshow(Resized1, resized1) cv2.imshow(Resized2, resized2) cv2.waitKey(0) cv2.destroyAllWindows()输出展示三、 图像算术运算与边界填充1. 图像加法运算的区别运算符对于号运算当对图像 a、图像 b 进行加法求和时遵循以下规则当某位置像素相加得到的数值小于 255该位置数值为两图像该位置像素相加之和。当某位置像素相加得到的数值大于 255该位置数值将截断结果并将其减去 256。例如相加后是 260实际是 260 - 256 4。cv2.add()对于cv2.add()运算当对图像 a、图像 b 进行加法求和时遵循以下规则当某位置像素相加得到的数值小于 255该位置数值为两图像该位置像素相加之和。当某位置像素相加得到的数值大于 255该位置数值为 255饱和运算。cv2.addWeighted()图像加权运算。在计算两幅图像的像素值之和时将每幅图的权重考虑进来公式为dst src1 * α src2 * β γ。img1 cv2.imread(qi_e.png) img2 cv2.imread(风景.jpg) img1_resized cv2.resize(img1, (500, 500)) # 运算符 result1 img1_resized 10 cv2.imshow(img1 10, result1) # cv2.add() img1 cv2.resize(img1, (400, 400)) # 将图片缩放为相同大小 img2 cv2.resize(img2, (400, 400)) result2 cv2.add(img1, img2) cv2.imshow(img1 add img2, result2) # cv2.addWeighted()图像加权运算 result3 cv2.addWeighted(img1, 0.5, img2, 0.5, 10) cv2.imshow(addWeighted, result3) cv2.waitKey(0) cv2.destroyAllWindows()输出展示2. 边界填充 (Padding)在卷积运算前通常需要给图像加边框。cv2.copyMakeBorder提供了多种填充策略。函数签名与参数dst cv2.copyMakeBorder(src, top, bottom, left, right, borderType, valueNone)src: 待扩充边界的原始图像。top, bottom, left, right: 分别代表在图像上、下、左、右四个方向要扩充的像素宽度。borderType: 定义边界填充的算法类型核心参数。value: 当borderType为cv2.BORDER_CONSTANT时用于指定填充的固定颜色值BGR格式。五种常用填充模式假设原图像素序列为abcdefgh以下为五种常用填充模式的原理与效果填充模式OpenCV 常量原理描述效果示例 (原序列: abcdefgh)常数填充cv2.BORDER_CONSTANT使用指定的固定颜色value参数填充边界。iiiii | abcdefgh | iiiii(i 代表自定义的常数值)镜像反射 (含边界)cv2.BORDER_REFLECT以边缘像素为对称轴进行镜像翻转交界处像素会被重复复制。fedcba | abcdefgh | hgfedcb镜像反射 (不含边界)cv2.BORDER_REFLECT_101或cv2.BORDER_DEFAULT与 REFLECT 类似但对称轴在边缘像素外侧交界处不重复复制边界像素最推荐也是默认值。gfedcb | abcdefgh | gfedcba边缘复制cv2.BORDER_REPLICATE直接复制图像最边缘的像素值向外无限延伸。aaaaaa | abcdefgh | hhhhhh循环包裹cv2.BORDER_WRAP将图像另一侧的像素“搬”过来填充当前边界类似于首尾相连的环绕效果。cdefgh | abcdefgh | abcdefg代码示例import cv2 import numpy as np # 读取示例图像 img cv2.imread(qi_e.png) if img is None: print(图片读取失败请检查路径) exit() # 定义边界宽度 top bottom left right 50 # 1. 常数填充 (BGR: (22, 33, 44)) constant cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value(22, 33, 44)) # 2. 镜像反射 (不含边界默认推荐) reflect_101 cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REFLECT_101) # 3. 镜像反射 (含边界) reflect cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REFLECT) # 4. 边缘复制 replicate cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REPLICATE) # 5. 循环包裹 wrap cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_WRAP) # 显示结果 cv2.imshow(Original, img) cv2.imshow(BORDER_CONSTANT, constant) cv2.imshow(BORDER_REFLECT_101, reflect_101) cv2.imshow(BORDER_REFLECT, reflect) cv2.imshow(BORDER_REPLICATE, replicate) cv2.imshow(BORDER_WRAP, wrap) cv2.waitKey(0) cv2.destroyAllWindows()输出展示1. 常数填充 (BGR: (22, 33, 44)) 使用指定颜色填充边界由图可看出我们所定义的边界被指定的棕色色块填充。cv2.BORDER_CONSTANT, value(22, 33, 44)2. 镜像反射 (不含边界默认推荐)如图根据定义的边界长度以边缘像素为轴进行镜像翻转交界处的像素不会被重复复制。cv2.BORDER_REFLECT_1013. 镜像反射 (含边界)如图根据定义的边界长度以边缘像素为轴进行镜像翻转交界处的像素会被重复复制。4. 边缘复制直接复制图像最边缘的像素值向外无限延伸。cv2.BORDER_REPLICATE5. 循环包裹将图像另一侧的像素“搬”过来填充当前边界类似于首尾相连的环绕效果。如图将图片下边部分的内容填充到上边界上边部分的内容填充到下边界右边部分的内容填充到左边界左边部分的内容填充到右边部分小结在实际卷积操作中cv2.BORDER_REFLECT_101默认是最常用的填充方式因为它能较好地避免边界伪影。常数填充cv2.BORDER_CONSTANT则适用于需要特定颜色背景的场景。四、 阈值处理阈值处理是图像二值化的核心常用于将灰度图转化为黑白分明的掩码。cv2.threshold()函数用于对图像进行阈值分割其函数签名如下retval, dst cv2.threshold(src, thresh, maxval, type)src待处理的输入图像可以是多通道图像8 位或 32 位浮点型。thresh设定的阈值。maxval当type参数为cv2.THRESH_BINARY或cv2.THRESH_BINARY_INV时需要设定的最大值。retval返回的阈值。dst阈值分割结果图像与原始图像具有相同的大小和类型。type阈值分割的类型具体取值如下表所示cv2.THRESH_BINARY标准二值化。像素值大于阈值时设为最大值如255否则设为0。 cv2.THRESH_BINARY_INV反二值化。与上者相反像素值大于阈值时设为0否则设为最大值。 cv2.THRESH_TRUNC截断处理。像素值大于阈值时被截断为阈值本身小于等于阈值的保持不变。 cv2.THRESH_TOZERO置零处理。像素值大于阈值时保持原值小于等于阈值的设为0。 cv2.THRESH_TOZERO_INV反置零处理。与上者相反像素值大于阈值时设为0小于等于阈值的保持原值。阈值类型像素值 thresh其他情况cv2.THRESH_BINARYmaxval0cv2.THRESH_BINARY_INV0maxvalcv2.THRESH_TRUNCthresh当前灰度值cv2.THRESH_TOZERO当前灰度值0cv2.THRESH_TOZERO_INV0当前灰度值imagecv2.imread(Tom.jpg,0) ret,binarycv2.threshold(image,175,255,cv2.THRESH_BINARY) #标准二值化 ret1,binaryinvcv2.threshold(image,175,255,cv2.THRESH_BINARY_INV) #反二值化 ret2,trunccv2.threshold(image,175,255,cv2.THRESH_TRUNC) #截断处理 ret3,tozerocv2.threshold(image,175,255,cv2.THRESH_TOZERO) #置零处理 ret4,tozeroinvcv2.threshold(image,175,255,cv2.THRESH_TOZERO_INV) #反置零处理 cv2.imshow(image,image) cv2.waitKey(0) cv2.imshow(binary,binary) cv2.waitKey(0) cv2.imshow(binaryinv,binaryinv) cv2.waitKey(0) cv2.imshow(trunc,trunc) cv2.waitKey(0) cv2.imshow(tozero,tozero) cv2.waitKey(0) cv2.imshow(tozeroinv,tozeroinv) cv2.waitKey(0) cv2.destroyAllWindows()运行结果展示五、 图像平滑与降噪为了去除图像中的噪声如椒盐噪声我们需要使用各种滤波器。以下是自定义椒盐噪声生成函数及五种主流滤波算法的对比1. 添加椒盐噪声def add_peppersalt_noise(image, n10000): result image.copy() h, w image.shape[:2] for _ in range(n): x np.random.randint(0, h) y np.random.randint(0, w) result[x, y] 0 if np.random.randint(0, 2) 0 else 255 return result noisy_img add_peppersalt_noise(img)2. 五大滤波算法对比滤波类型核心原理适用场景边缘保留效果常用参数设置均值滤波取邻域内所有像素的平均值线性平滑去除轻微的高斯噪声轻度平滑较差边缘容易模糊cv2.blur(src, (5,5))方框滤波取邻域像素的和可选是否归一化归一化时同均值滤波不归一化用于计算积分图较差边缘容易模糊cv2.boxFilter(src, -1, (5,5))高斯滤波根据高斯分布进行加权平均线性平滑去除高斯噪声保留更多图像整体结构一般边缘仍会有一定程度模糊cv2.GaussianBlur(src, (5,5), 0)中值滤波取邻域内像素的中位数非线性去除椒盐噪声黑白噪点的首选极好能完美保护边缘不被模糊cv2.medianBlur(src, 5)双边滤波结合空间距离与像素值相似度加权非线性保边去噪图像增强卡通风格最好不仅去噪还能锐化边缘cv2.bilateralFilter(src, 9, 75, 75)对五大滤波算法的具体含义和作用以下代码示例来说明数据预处理给图片添加噪声def add_peppersalt_noise(image,n10000): result image.copy() h,wimage.shape[:2]#获取图片的高和宽 for i in range(n):#生成n个椒盐噪声 xnp.random.randint(0,h) ynp.random.randint(0,w) if np.random.randint(0,2)0: result[x,y]0 else: result[x,y]255 return result imagecv2.imread(qi_e.png) noiseadd_peppersalt_noise(image)1. 均值滤波均值滤波是指以当前点为中心用其周围N*N个点像素值的平均值来替代当前点的像素值。函数说明dst cv2.blur(src, ksize, anchor, borderType)参数详解src需要处理的输入图像。ksize滤波核卷积核的大小通常表示为 Size(宽, 高)。anchor锚点位置默认值为 (-1, -1)表示锚点位于卷积核的中心。一般情况下无需更改。borderType边界像素的外推模式默认值为 BORDER_DEFAULT。一般情况下无需更改。返回值说明该函数会返回处理后的图像其尺寸、通道数和数据类型与输入图像 src 完全相同。常用写法在绝大多数情况下只需指定输入图像和卷积核大小即可直接使用以下代码dst cv2.blur(src, ksize)#1、均值滤波 blur_1cv2.blur(noise,(3,3)) #卷积核为3*3 cv2.imshow(blur_1,blur_1) cv2.waitKey(0) blur_2cv2.blur(noise,(9,9)) #卷积核为9*9 cv2.imshow(blur_2,blur_2) cv2.waitKey(0) bul_3cv2.blur(noise,(33,33)) #卷积核为33*33 cv2.imshow(bul_3,bul_3) cv2.waitKey(0) cv2.destroyAllWindows()运行结果展示当卷积核为3*3时图像噪点被轻微平滑企鹅轮廓与背景细节基本保留适合轻度去噪。当卷积核为9*9时噪点明显减少但边缘开始模糊羽毛纹理有所损失适用于中等强度去噪。当卷积核为33*33时图像严重模糊几乎无法辨认企鹅形态仅保留大致轮廓说明过大的卷积核会导致结构信息丢失。由此可见均值滤波的卷积核越大去噪效果越强但图像细节损失也越严重实际应用中应根据噪声程度选择合适核尺寸以平衡去噪与保真。2. 方框滤波方框滤波以均值滤波为基础可选择是否对滤波结果进行归一化如果选择镜像归一化则滤波结果为领域内点的像素值之和的平均值否则滤波结果为像素值之和。dst cv2.boxFilter(src, ddepth, ksize, anchor, normalize, borderType)参数详解dst函数的返回值表示经过方框滤波处理后得到的结果图像。src需要处理的输入图像原始图像。ddepth输出图像的深度数据类型。通常设置为-1表示输出图像与原始图像保持相同的深度。ksize滤波核卷积核的大小以(宽, 高)的形式表示决定了滤波时选取的邻域范围。anchor锚点位置默认值为(-1, -1)表示锚点位于滤波核的中心即当前正在计算的目标像素点。normalize布尔值表示是否对滤波结果进行归一化处理。当值为True时进行归一化即将邻域内像素值的总和除以核的面积求平均值。此时方框滤波的效果与均值滤波完全相同。当值为False时不进行归一化直接取邻域内像素值的总和。此时极易发生数据溢出若像素总和超过 255结果将被强制截断为 255显示为纯白色。常用写法在大多数常规应用场景下直接使用以下默认参数形式即可dst cv2.boxFilter(src, -1, ksize)boxFilter_1cv2.boxFilter(noise,-1,(3,3),normalizeTrue) #进行归一化 cv2.imshow(boxFilter_1,boxFilter_1) cv2.waitKey(0) boxFilter_2cv2.boxFilter(noise,-1,(3,3),normalizeFalse) #不进行归一化 cv2.imshow(boxFilter_2,boxFilter_2) cv2.waitKey(0)运行结果展示当进行归一化时图像噪点被轻微平滑企鹅轮廓与背景细节基本保留效果等同于均值滤波。当不进行归一化时图像因像素值直接求和导致严重溢出大部分区域变为纯白仅边缘残留少量彩色噪点。由此可见归一化是方框滤波中控制输出范围的关键参数不归一化极易引发数据溢出使图像失真实际应用中应始终启用归一化以保证结果合理。3. 高斯滤波高斯滤波与均值滤波略有不同它按像素点与中心点的不同距离赋予像素点不同的权重值越靠近中心点权重值越大越远离中心点的权重值最小然后根据权重值计算领域内所有像素点的和将和作为中心点的像素值。函数原型dst cv2.GaussianBlur(src, ksize, sigmaX[, sigmaY[, borderType]])参数详解src输入图像通常为 NumPy 数组支持任意通道数但深度需为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F。ksize高斯核的大小格式为(宽, 高)。注意宽度和高度必须是正奇数如 3, 5, 7...。如果设为 0则会根据sigma值自动计算核大小。sigmaX高斯核在 X 方向水平方向的标准差。它是控制模糊程度的关键参数值越大模糊效果越强。sigmaY高斯核在 Y 方向垂直方向的标准差。若sigmaY为 0则默认等于sigmaX。若sigmaX和sigmaY均为 0则根据ksize的大小自动计算标准差通常计算公式为 σ0.3×((ksize-1)×0.5-1)0.8。borderType边界填充模式默认为cv2.BORDER_DEFAULT一般无需更改。运行结果展示当进行高斯滤波时图像噪点被有效抑制同时保留了较多边缘与纹理细节适合中等强度去噪且需保持清晰度的场景。由此可见高斯滤波通过加权平均实现平滑标准差设为1、核大小为5×5时在去噪与保真之间取得了良好平衡是图像处理中常用的默认参数组合。4. 中值滤波中值滤波将领域内的所有像素进行排序取中间值作为领域中心点的像素值。函数用法cv2.medianBlur(src, ksize[, dst])参数详解src输入图像。支持单通道、三通道或四通道图像但数据类型必须是CV_8U、CV_16U或CV_32F。对于较大尺寸的核仅支持CV_8U类型。ksize滤波器孔径的线性尺寸。它必须是一个大于1的奇数如 3, 5, 7...。与高斯滤波不同这里只需要传入一个整数代表正方形滤波器的边长。dst输出图像。如果未指定为 None则会自动创建一个新的数组来存储结果其大小和类型与输入图像相同。适用场景它是处理椒盐噪声的首选算法因为椒盐噪声通常表现为极亮或极暗的孤立像素点这些点在排序过程中会被作为最大值或最小值剔除而不会像均值滤波那样污染周围像素。常用写法# 使用 5x5 的中值滤波器dst cv2.medianBlur(src, 5)medianB cv2.medianBlur(noise,3) cv2.imshow(medianB,medianB) cv2.waitKey(0)运行结果展示图像中的孤立噪点如椒盐噪声被高效清除同时边缘和纹理信息几乎无损特别适合处理脉冲型噪声。由此可见中值滤波通过取邻域像素的中位数替代中心像素能有效抑制极端值干扰在保持图像结构完整性的同时实现去噪是处理椒盐噪声的最优选择之一。5. 双边滤波双边滤波在计算像素值的同时会考虑距离和色差信息从而可在消除噪声的同时保护边缘信息。在执行双边滤波时如果像素点与当前点色差较小则赋予其较大的权重值否则赋予其较小的权重值。cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]]) 双边滤波参数详解src输入图像。支持 8 位CV_8U或浮点型CV_32F的单通道或多通道图像。d滤波过程中每个像素邻域的直径。如果该值为非正数如 -1OpenCV 会根据 sigmaSpace 自动计算得出。该值越大考虑的空间范围越广但计算量也会显著增加。sigmaColor颜色空间的标准差。该参数控制像素值相似性的权重值越大表示颜色容忍度越高会有更宽广的颜色被混合在一起产生更大的平滑区域。sigmaSpace坐标空间的标准差。该参数控制空间距离的权重值越大意味着越远的像素也会相互影响从而使更大区域内足够相似的颜色获取相同的值。dst输出图像。如果未指定会自动创建一个新的数组来存储结果其大小和类型与输入图像相同。borderType边界填充方式默认为 BORDER_DEFAULT一般无需更改。适用场景它是实现“保边去噪”的首选算法。在有效平滑图像、去除噪声的同时能够极好地保留甚至锐化图像中的边缘和纹理细节非常适合用于图像增强、医学图像处理以及制作卡通风格特效。常用写法邻域直径设为9颜色和空间标准差均设为75dst cv2.bilateralFilter(src, 9, 75, 75)或者让 d 自动计算传入 -1dst cv2.bilateralFilter(src, -1, 75, 75)bilateralFilter_1cv2.bilateralFilter(noise,15,100,100) cv2.imshow(bilateralFilter_1,bilateralFilter_1) cv2.waitKey(0) cv2.destroyAllWindows()运行结果说明图像经过双边滤波之后边缘轮廓、纹理细节完整保留但算法对于椒盐类型的冲击噪声去除能力有限处理后仍然残留细小噪点。 双边滤波依靠空间距离、像素灰度相似度双重权重加权运算它主打保边平滑适合高斯噪声降噪、人像美颜、医学影像处理、图片卡通特效。总结建议如果是椒盐噪声图像上有明显的黑白噪点直接用中值滤波。如果是高斯噪声图像整体有颗粒感选高斯滤波。如果既要去噪又要保留清晰的边缘选双边滤波但计算速度最慢。均值滤波和方框滤波计算速度最快通常用于对速度要求高、对画质要求不苛刻的预处理阶段。 总结本文梳理了 OpenCV 从基础读写到高级滤波的核心知识点。在实际的计算机视觉项目中图像预处理如灰度化、降噪、阈值化往往决定了后续特征提取和模型识别的上限。建议大家多动手调整滤波器的参数如ksize、sigma直观感受不同算法对图像细节的影响。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价