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

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

摘要:本文系统梳理了 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), dtype=np.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, fx=0.5, fy=0.5)

img = cv2.imread('qi_e.png') resized1 = cv2.resize(img, (200, 200)) # 指定大小 resized2 = cv2.resize(img, None, fx=0.5, fy=0.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, value=None)
  • src: 待扩充边界的原始图像。
  • top, bottom, left, right: 分别代表在图像上、下、左、右四个方向要扩充的像素宽度。
  • borderType: 定义边界填充的算法类型(核心参数)。
  • value: 当borderTypecv2.BORDER_CONSTANT时,用于指定填充的固定颜色值(BGR格式)。
五种常用填充模式

假设原图像素序列为abcdefgh,以下为五种常用填充模式的原理与效果:

填充模式OpenCV 常量原理描述效果示例 (原序列: abcdefgh)
常数填充cv2.BORDER_CONSTANT使用指定的固定颜色(value参数)填充边界。iiiii | abcdefgh | iiiii(i 代表自定义的常数值)
镜像反射 (含边界)cv2.BORDER_REFLECT以边缘像素为对称轴进行镜像翻转,交界处像素会被重复复制。fedcba | abcdefgh | hgfedcb
镜像反射 (不含边界)cv2.BORDER_REFLECT_101cv2.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_101

3. 镜像反射 (含边界):如图根据定义的边界长度,以边缘像素为轴进行镜像翻转,交界处的像素被重复复制。

4. 边缘复制:直接复制图像最边缘的像素值,向外无限延伸。

cv2.BORDER_REPLICATE

5. 循环包裹:将图像另一侧的像素“搬”过来填充当前边界,类似于首尾相连的环绕效果。如图:将图片下边部分的内容填充到上边界,上边部分的内容填充到下边界,右边部分的内容填充到左边界,左边部分的内容填充到右边部分

小结:在实际卷积操作中,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_BINARYcv2.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_BINARYmaxval0
cv2.THRESH_BINARY_INV0maxval
cv2.THRESH_TRUNCthresh当前灰度值
cv2.THRESH_TOZERO当前灰度值0
cv2.THRESH_TOZERO_INV0当前灰度值
image=cv2.imread('Tom.jpg',0) ret,binary=cv2.threshold(image,175,255,cv2.THRESH_BINARY) #标准二值化 ret1,binaryinv=cv2.threshold(image,175,255,cv2.THRESH_BINARY_INV) #反二值化 ret2,trunc=cv2.threshold(image,175,255,cv2.THRESH_TRUNC) #截断处理 ret3,tozero=cv2.threshold(image,175,255,cv2.THRESH_TOZERO) #置零处理 ret4,tozeroinv=cv2.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, n=10000): 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,n=10000): result = image.copy() h,w=image.shape[:2]#获取图片的高和宽 for i in range(n):#生成n个椒盐噪声 x=np.random.randint(0,h) y=np.random.randint(0,w) if np.random.randint(0,2)==0: result[x,y]=0 else: result[x,y]=255 return result image=cv2.imread('qi_e.png') noise=add_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_1=cv2.blur(noise,(3,3)) #卷积核为3*3 cv2.imshow('blur_1',blur_1) cv2.waitKey(0) blur_2=cv2.blur(noise,(9,9)) #卷积核为9*9 cv2.imshow('blur_2',blur_2) cv2.waitKey(0) bul_3=cv2.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_1=cv2.boxFilter(noise,-1,(3,3),normalize=True) #进行归一化 cv2.imshow('boxFilter_1',boxFilter_1) cv2.waitKey(0) boxFilter_2=cv2.boxFilter(noise,-1,(3,3),normalize=False) #不进行归一化 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
    • sigmaXsigmaY均为 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_8UCV_16UCV_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:滤波过程中每个像素邻域的直径。如果该值为非正数(如 -1),OpenCV 会根据 sigmaSpace 自动计算得出。该值越大,考虑的空间范围越广,但计算量也会显著增加。
sigmaColor:颜色空间的标准差。该参数控制像素值相似性的权重,值越大,表示颜色容忍度越高,会有更宽广的颜色被混合在一起,产生更大的平滑区域。
sigmaSpace:坐标空间的标准差。该参数控制空间距离的权重,值越大,意味着越远的像素也会相互影响,从而使更大区域内足够相似的颜色获取相同的值。
dst:输出图像。如果未指定,会自动创建一个新的数组来存储结果,其大小和类型与输入图像相同。
borderType:边界填充方式,默认为 BORDER_DEFAULT,一般无需更改。
适用场景
它是实现“保边去噪”的首选算法。在有效平滑图像、去除噪声的同时,能够极好地保留甚至锐化图像中的边缘和纹理细节,非常适合用于图像增强、医学图像处理以及制作卡通风格特效。
常用写法

邻域直径设为9,颜色和空间标准差均设为75
dst = cv2.bilateralFilter(src, 9, 75, 75)

或者让 d 自动计算(传入 -1)

dst = cv2.bilateralFilter(src, -1, 75, 75)

bilateralFilter_1=cv2.bilateralFilter(noise,15,100,100) cv2.imshow('bilateralFilter_1',bilateralFilter_1) cv2.waitKey(0) cv2.destroyAllWindows()

运行结果说明:

图像经过双边滤波之后,边缘轮廓、纹理细节完整保留;但算法对于椒盐类型的冲击噪声去除能力有限,处理后仍然残留细小噪点。 双边滤波依靠空间距离、像素灰度相似度双重权重加权运算;它主打保边平滑,适合高斯噪声降噪、人像美颜、医学影像处理、图片卡通特效。

总结建议:

  • 如果是椒盐噪声(图像上有明显的黑白噪点),直接用中值滤波。
  • 如果是高斯噪声(图像整体有颗粒感),选高斯滤波。
  • 如果既要去噪又要保留清晰的边缘,选双边滤波(但计算速度最慢)。
  • 均值滤波和方框滤波计算速度最快,通常用于对速度要求高、对画质要求不苛刻的预处理阶段。

📌 总结

本文梳理了 OpenCV 从基础读写到高级滤波的核心知识点。在实际的计算机视觉项目中,图像预处理(如灰度化、降噪、阈值化)往往决定了后续特征提取和模型识别的上限。建议大家多动手调整滤波器的参数(如ksizesigma),直观感受不同算法对图像细节的影响。