学习日记 8.1

📅 2026/8/3 4:37:05
学习日记 8.1
前言前一篇文章讲了图片读取与显示今天继续看图像运算、阈值处理和噪声去除。主要涉及图像运算图像的加法运算与加权融合阈值处理二值化、截断等阈值操作以及图像边框的填充噪声去除椒盐噪声的生成与多种滤波器的去噪效果对比一、图像运算1.1 使用 NumPy 的加法 运算符直接用运算符做图像加法但 NumPy 的加法是取模运算import cv2 a1 cv2.imread(3.png) b1 cv2.imread(4.jpg) a1 cv2.resize(a1, (500, 400)) b1 cv2.resize(b1, (500, 400)) NumPy 加法像素值相加后对 256 取模 c1 a1 10 # 每个像素值加 10 c2 a1[50:450, 50:400] b1[50:450, 50:400] # ROI 区域相加当像素值超过 255 时NumPy 会将其对 256 取模。例如250 10 260取模后变成260 % 256 4这会导致原本应该更亮的区域反而变暗出现“溢出回绕”的现象。1.2 使用 OpenCV 的 cv2.add() 函数OpenCV 提供了专门的加法函数cv2.add()它的处理方式是饱和运算——超过 255 的值会被截断为 255a2 cv2.imread(3.png) b2 cv2.imread(4.jpg) b2 cv2.resize(b2, (400, 400)) a2 cv2.resize(a2, (400, 400)) OpenCV 加法超过 255 的像素值会被截断为 255饱和运算 c3 cv2.add(a2, b2)运算方式函数溢出处理NumPy 加法img1 img2取模运算% 256OpenCV 加法cv2.add(img1, img2)饱和运算截断到 255小结在处理图像加法时推荐使用cv2.add()因为它避免了取模操作带来的“反色”异常视觉效果更加自然。1.3 图像加权融合 —— cv2.addWeighted()有时候我们希望将两张图像按照一定比例混合而不是简单地相加。这时候就可以使用cv2.addWeighted()# 参数img1, 权重1, img2, 权重2, 亮度偏移量 c4 cv2.addWeighted(a2, 0.7, b2, 0.3, 100)公式为dst α · img1 β · img2 γ其中 α 和 β 是两幅图像的权重γ 是亮度调节参数。在上面的代码中a2占 70% 的权重b2占 30%最后再加上 100 的亮度偏移。这个函数在图像叠加、水印添加、视频特效等场景中很常用。二、图像边框与阈值处理2.1 为图像添加边框 —— cv2.copyMakeBorder()为图像添加边框可以用cv2.copyMakeBorder()支持多种填充方式import cv2 ys cv2.imread(4.jpg) top, bottom, left, right 50, 50, 50, 50 1. 常量边框用固定颜色填充 constant cv2.copyMakeBorder(ys, top, bottom, left, right, borderTypecv2.BORDER_CONSTANT, value[229, 25, 80]) 2. 镜像边框以边缘为轴进行镜像 reflect cv2.copyMakeBorder(ys, top, bottom, left, right, borderTypecv2.BORDER_REFLECT) 3. 镜像边框不含边界与 REFLECT 类似但不包含边界像素 reflect101 cv2.copyMakeBorder(ys, top, bottom, left, right, borderTypecv2.BORDER_REFLECT101) 4. 复制边框复制边缘像素 replicate cv2.copyMakeBorder(ys, top, bottom, left, right, borderTypecv2.BORDER_REPLICATE) 5. 环绕边框用对面边界的像素填充 warp cv2.copyMakeBorder(ys, top, bottom, left, right, borderTypecv2.BORDER_WRAP)五种边框类型的效果对比边框类型OpenCV 常量说明常量边框BORDER_CONSTANT用指定颜色值填充边框区域镜像边框BORDER_REFLECT以边缘像素为镜像轴向外镜像扩展如 fedcba|abcdefgh|hgfedcb反射101BORDER_REFLECT101以边缘像素为对称中心如 gfedcb|abcdefgh|gfedcba复制边框BORDER_REPLICATE直接复制最边缘的像素值如 aaaaaa|abcdefgh|hhhhhhh环绕边框BORDER_WRAP用对面边界的像素来填充如 cdefgh|abcdefgh|abcdefg默认推荐BORDER_REFLECT101 是 OpenCV 中许多函数如滤波的默认边框处理方式它在大多数场景下表现最佳。2.2 阈值处理 —— cv2.threshold()阈值处理是图像分割中最基础的方法之一设定一个阈值将像素值与阈值比较根据比较结果对像素分类。OpenCV 提供了五种阈值处理类型image cv2.imread(4.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) # 反阈值归零阈值类型处理规则效果描述THRESH_BINARYdst maxVal 若 src thresh否则 0超过阈值为白色否则为黑色THRESH_BINARY_INVdst 0 若 src thresh否则 maxVal二值化的反转版本THRESH_TRUNCdst thresh 若 src thresh否则 src超过阈值的像素被截断为阈值THRESH_TOZEROdst src 若 src thresh否则 0低于阈值的像素归零THRESH_TOZERO_INVdst 0 若 src thresh否则 src高于阈值的像素归零返回值ret是实际使用的阈值在使用 Otsu 等自适应方法时可能与传入值不同binary等是处理后的图像。应用场景阈值处理常用于文档扫描二值化、物体轮廓提取、前景/背景分离等任务。三、图像噪声与滤波3.1 椒盐噪声的生成椒盐噪声Salt-and-Pepper Noise是图像中常见的噪声类型表现为随机出现的黑白像素点像撒了盐和胡椒一样。可以手动模拟这种噪声import numpy as np def add_peppersalt_noise(image, n10000): 向图像添加椒盐噪声 Args: image: 输入图像 n: 噪声点数量 Returns: 添加了噪声的图像 result image.copy() h, w image.shape[:2] # 获取图像的高和宽 for i in range(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这段代码会在图像的随机位置生成黑白噪声点模拟真实场景中的椒盐噪声。3.2 均值滤波 —— cv2.blur() 与 cv2.boxFilter()均值滤波是最简单的线性滤波方法它用像素邻域的平均值来替代中心像素的值# 均值滤波5x5 的卷积核 blur_1 cv2.blur(noise, (5, 5)) 方框滤波当 normalizeTrue 时与均值滤波等效 boxFilter_1 cv2.boxFilter(noise, -1, (3, 3), normalizeTrue) 方框滤波normalizeFalse 时求和但不平均容易溢出 boxFilter_2 cv2.boxFilter(noise, -1, (3, 3), normalizeFalse)参数说明-1输出图像的深度-1表示与输入图像一致(3, 3)卷积核大小normalizeTrue是否对结果进行归一化处理注意当normalizeFalse时方框滤波不再除以核面积像素值容易超过 255导致画面一片白。3.3 高斯滤波 —— cv2.GaussianBlur()高斯滤波使用高斯函数作为权重分配离中心越近的像素权重越大去噪的同时能更好地保留边缘信息# 高斯滤波核大小 (3,3)标准差为 1 Gaussian_Noise cv2.GaussianBlur(noise, (3, 3), 1)参数说明(3, 3)是高斯核的大小必须是奇数1是 X 方向的标准差如果设为 0则根据核大小自动计算。3.4 中值滤波 —— cv2.medianBlur()中值滤波是非线性滤波它用邻域像素的中值替代中心像素对椒盐噪声的去除效果尤其出色# 中值滤波核大小为 3 medianB cv2.medianBlur(noise, 3)3.5 滤波效果对比结论对于椒盐噪声中值滤波是首选方案。它能在有效去除椒盐噪声的同时最大限度地保留图像的边缘细节。四、综合实战4.1 实战一摄像头实时画面与背景图融合这是一个综合运用图像运算的实战案例实现摄像头实时画面与背景图片的融合效果import cv2 cap cv2.VideoCapture(0) background cv2.imread(4.jpg) background cv2.resize(background, (640, 480)) background_gray cv2.cvtColor(background, cv2.COLOR_BGR2GRAY) if not cap.isOpened(): print(无法打开摄像头) exit() while True: ret, frame cap.read() if not ret: break frame cv2.resize(frame, (640, 480)) frame_gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 彩色融合各占 50% 透明度 c1 cv2.addWeighted(frame, 0.5, background, 0.5, 100) 灰度融合各占 50% 透明度 c2 cv2.addWeighted(frame_gray, 0.5, background_gray, 0.5, 100) cv2.imshow(Color Fusion, c1) cv2.imshow(Gray Fusion, c2) 按下 ESC 键退出 if cv2.waitKey(60) 27: break cap.release() cv2.destroyAllWindows()4.2 实战二视频椒盐噪声处理对视频文件逐帧添加椒盐噪声并使用中值滤波进行去噪import cv2 import numpy as np def add_peppersalt_noise(image, n8000): result image.copy() h, w image.shape[:2] for i in range(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 cap cv2.VideoCapture(test.avi) if not cap.isOpened(): print(无法打开视频文件) exit() while True: ret, frame cap.read() if not ret: break # 添加椒盐噪声 noise add_peppersalt_noise(frame) 中值滤波去噪 medianB cv2.medianBlur(noise, 3) 同时显示三个窗口 cv2.imshow(Original, frame) # 原视频 cv2.imshow(Noise, noise) # 含噪声视频 cv2.imshow(Denoised, medianB) # 去噪后视频 if cv2.waitKey(60) 27: break cap.release() cv2.destroyAllWindows()五、总结今天的学习内容涵盖了 OpenCV 图像处理的三个核心模块模块核心函数要点图像运算cv2.add(),cv2.addWeighted()区分 NumPy 取模加法与 OpenCV 饱和加法掌握加权融合阈值处理cv2.threshold(),cv2.copyMakeBorder()五种阈值类型 五种边框填充方式滤波去噪cv2.blur(),cv2.boxFilter(),cv2.GaussianBlur(),cv2.medianBlur()椒盐噪声首选中值滤波这些知识都是后续学习更高级图像处理操作如边缘检测、形态学操作、轮廓提取等的基础建议动手运行每一段代码观察不同参数带来的效果变化。