> 技术文档 > OpenCV 图像处理核心技术:边界填充、算术运算与滤波处理实战

OpenCV 图像处理核心技术:边界填充、算术运算与滤波处理实战

目录

一、边界填充:cv2.copyMakeBorder () 函数详解

1. 函数参数说明

2. 常见边界填充类型及效果

3. 代码示例

二、图像算术运算:加法与加权加法

1. 普通加法(+ 运算符)

2. cv2.add () 函数

3. 加权加法:cv2.addWeighted () 函数

三、阈值处理:图像二值化与分割

1. 函数参数说明

2. 代码示例

四、图像平滑处理(模糊处理)

1. 常见滤波算法及函数

2. 代码示例(含噪声添加)

3. 滤波效果对比


在计算机视觉领域,OpenCV 库提供了丰富的图像处理函数,助力开发者实现各类图像编辑与分析任务。本文将围绕边界填充、图像算术运算、阈值处理以及平滑滤波等核心技术,通过具体代码示例详细讲解其实现方法与应用场景。

一、边界填充:cv2.copyMakeBorder () 函数详解

边界填充(Padding)是图像处理中常用的技术,可用于图像增强、卷积运算前的预处理等场景。OpenCV 的 cv2.copyMakeBorder() 函数提供了多种边界填充方式,能满足不同的需求。

1. 函数参数说明

cv2.copyMakeBorder(src: UMat, top: int, bottom: int, left: int, right: int, borderType: int, dst: UMat | None = ..., value: cv2.typing.Scalar = ...)
  • src:要扩充边界的原始图像。
  • top, bottom, left, right:相应方向上的边框宽度。
  • borderType:边界填充类型,决定了填充像素的计算方式。
  • value:当 borderType 为 cv2.BORDER_CONSTANT 时,指定填充的常数数值。

2. 常见边界填充类型及效果

  • cv2.BORDER_CONSTANT:添加常数边界,填充像素值为指定的 value
  • cv2.BORDER_REFLECT:镜面反射填充,类似 gfedcba|abcdefgh|hgfedcba(交界处像素被复制)。
  • cv2.BORDER_REFLECT_101(或 cv2.BORDER_DEFAULT):改进型镜面反射,类似 gfedcb|abcdefgh|gfedcba(交界处像素不重复)。
  • cv2.BORDER_REPLICATE:边界像素复制填充,类似 aaaaaa|abcdefgh|hhhhhhh
  • cv2.BORDER_WRAP:循环填充,类似 cdefgh|abcdefgh|abcdefg

3. 代码示例

import cv2# 读取图像a = cv2.imread(\'img_1.jpg\')# 设置各方向填充宽度top, bottom, left, right = 50, 50, 50, 50# 不同类型的边界填充constant = cv2.copyMakeBorder(a, top, bottom, left, right, cv2.BORDER_CONSTANT, value=0) # 常数填充(黑色)reflect = cv2.copyMakeBorder(a, top, bottom, left, right, cv2.BORDER_REFLECT) # 镜面反射填充reflect101 = cv2.copyMakeBorder(a, top, bottom, left, right, cv2.BORDER_REFLECT101) # 改进型镜面反射replicate = cv2.copyMakeBorder(a, top, bottom, left, right, cv2.BORDER_REPLICATE) # 边界复制填充wrap = cv2.copyMakeBorder(a, top, bottom, left, right, cv2.BORDER_WRAP) # 循环填充# 显示结果cv2.imshow(\'原始图像\', a)cv2.waitKey(0)cv2.imshow(\'CONSTANT 填充\', constant)cv2.waitKey(0)cv2.imshow(\'REFLECT 填充\', reflect)cv2.waitKey(0)cv2.imshow(\'REFLECT101 填充\', reflect101)cv2.waitKey(0)cv2.imshow(\'REPLICATE 填充\', replicate)cv2.waitKey(0)cv2.imshow(\'WRAP 填充\', wrap)cv2.waitKey(0)cv2.destroyAllWindows()

二、图像算术运算:加法与加权加法

图像算术运算包括像素值的加减乘除等操作,常用于图像融合、亮度调整等场景。OpenCV 提供了两种主要的加法运算方式:普通加法(+ 运算符)和 cv2.add() 函数,以及用于图像融合的加权加法 cv2.addWeighted() 函数。

1. 普通加法(+ 运算符)

普通加法遵循 “截断规则”:当像素值相加结果小于 255 时,直接取和;当结果大于 255 时,用结果减去 256 进行截断(例如 260 - 256 = 4)。

import cv2a = cv2.imread(\'img_1.jpg\')b = cv2.imread(\'img_2.jpg\')# 单个图像像素值整体加常数(调整亮度)c = a + 10 cv2.imshow(\'原始图像\', a)cv2.imshow(\'像素值+10\', c)cv2.waitKey(0)# 图像局部区域相加c = a[50:250, 50:200] + b[50:250, 50:200]cv2.imshow(\'局部区域相加\', c)cv2.waitKey(0)cv2.destroyAllWindows()

2. cv2.add () 函数

cv2.add() 函数遵循 “饱和规则”:当像素值相加结果小于 255 时,直接取和;当结果大于 255 时,取最大值 255。

import cv2a = cv2.imread(\'img_1.jpg\')b = cv2.imread(\'img_2.jpg\')# 调整图像大小至相同尺寸b = cv2.resize(b, dsize=(400, 400))a = cv2.resize(a, dsize=(400, 400))# 图像整体相加c = cv2.add(a, b) cv2.imshow(\'cv2.add() 结果\', c)cv2.waitKey(0)cv2.destroyAllWindows()

3. 加权加法:cv2.addWeighted () 函数

加权加法可实现图像的平滑融合,公式为 dst = src1×α + src2×β + γ,其中 α 和 β 是权重,γ 是亮度调整常数。

import cv2a = cv2.imread(\'img_1.jpg\')b = cv2.imread(\'img_2.jpg\')# 调整图像大小至相同尺寸b = cv2.resize(b, dsize=(400, 400))a = cv2.resize(a, dsize=(400, 400))# 加权融合:a 占比 0.2,b 占比 0.8,亮度补偿 10c = cv2.addWeighted(a, 0.2, b, 0.8, gamma=10) cv2.imshow(\'加权融合结果\', c)cv2.waitKey(0)cv2.destroyAllWindows()

三、阈值处理:图像二值化与分割

阈值处理通过设定像素值阈值,将图像分割为目标区域和背景区域,是图像分割的基础技术。OpenCV 的 cv2.threshold() 函数支持多种阈值分割类型。

1. 函数参数说明

retval, dst = cv2.threshold(src, thresh, maxval, type)
  • retval:返回的阈值。
  • dst:阈值分割结果图像。
  • src:输入图像(可多通道,8 位或 32 位浮点型)。
  • thresh:设定的阈值。
  • maxvaltype 为 THRESH_BINARY 或 THRESH_BINARY_INV 时的最大值。
  • type:阈值分割类型,具体规则如下表:
类型 像素值 > thresh 时 其他情况 cv2.THRESH_BINARY maxval 0 cv2.THRESH_BINARY_INV 0 maxval cv2.THRESH_TRUNC thresh 当前灰度值 cv2.THRESH_TOZERO 当前灰度值 0 cv2.THRESH_TOZERO_INV 0 当前灰度值

2. 代码示例

import cv2# 读取灰度图像image = cv2.imread(\'img_1.jpg\', 0) # 不同类型的阈值处理ret, binary = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY) # 二值化ret1, binaryinv = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY_INV) # 反二值化ret2, trunc = cv2.threshold(image, 150, 255, cv2.THRESH_TRUNC) # 截断处理ret3, tozero = cv2.threshold(image, 150, 255, cv2.THRESH_TOZERO) # 低于阈值置0ret4, tozeroinv = cv2.threshold(image, 150, 255, cv2.THRESH_TOZERO_INV) # 高于阈值置0# 显示结果cv2.imshow(\'原始灰度图\', image)cv2.waitKey(0)cv2.imshow(\'THRESH_BINARY\', binary)cv2.waitKey(0)cv2.imshow(\'THRESH_BINARY_INV\', binaryinv)cv2.waitKey(0)cv2.imshow(\'THRESH_TRUNC\', trunc)cv2.waitKey(0)cv2.imshow(\'THRESH_TOZERO\', tozero)cv2.waitKey(0)cv2.imshow(\'THRESH_TOZERO_INV\', tozeroinv)cv2.waitKey(0)cv2.destroyAllWindows()

四、图像平滑处理(模糊处理)

平滑处理通过消除图像中的噪声和细节,使图像变得模糊,常用于噪声抑制、边缘软化等场景。OpenCV 提供了多种平滑滤波算法,适用于不同类型的噪声和应用需求。

1. 常见滤波算法及函数

  • 均值滤波cv2.blur(),通过邻域像素平均值计算结果像素,适用于高斯噪声。
  • 方框滤波cv2.boxFilter(),可选择是否归一化,归一化时与均值滤波效果相同。
  • 高斯滤波cv2.GaussianBlur(),基于高斯函数计算权重,对高斯噪声抑制效果好。
  • 中值滤波cv2.medianBlur(),用邻域像素中位数替换中心像素,对椒盐噪声抑制效果显著。

2. 代码示例(含噪声添加)

首先定义一个添加椒盐噪声的函数,再对比不同滤波算法的效果:

import cv2import numpy as np# 添加椒盐噪声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(low=1, high=h) y = np.random.randint(low=1, high=w) # 随机生成黑色或白色噪声点 if np.random.randint(low=0, high=2) == 0: result[x, y] = 0 # 黑色噪声 else: result[x, y] = 255 # 白色噪声 return result# 读取图像并添加噪声image = cv2.imread(\'img_1.jpg\')cv2.imshow(\'原始图像\', image)cv2.waitKey(0)noise_image = add_peppersalt_noise(image)cv2.imshow(\'含椒盐噪声图像\', noise_image)cv2.waitKey(0)# 1. 均值滤波blur_3x3 = cv2.blur(noise_image, ksize=(3, 3)) # 3x3卷积核blur_63x63 = cv2.blur(noise_image, ksize=(63, 63)) # 63x63卷积核(模糊更严重)cv2.imshow(\'均值滤波(3x3)\', blur_3x3)cv2.waitKey(0)cv2.imshow(\'均值滤波(63x63)\', blur_63x63)cv2.waitKey(0)# 2. 方框滤波box_norm = cv2.boxFilter(noise_image, -1, ksize=(3, 3), normalize=True) # 归一化(同均值滤波)box_nonorm = cv2.boxFilter(noise_image, -1, ksize=(3, 3), normalize=False) # 不归一化cv2.imshow(\'方框滤波(归一化)\', box_norm)cv2.waitKey(0)cv2.imshow(\'方框滤波(不归一化)\', box_nonorm)cv2.waitKey(0)# 3. 高斯滤波gaussian = cv2.GaussianBlur(noise_image, ksize=(3, 3), sigmaX=1) # 标准差为1cv2.imshow(\'高斯滤波(3x3)\', gaussian)cv2.waitKey(0)# 4. 中值滤波median = cv2.medianBlur(noise_image, ksize=3) # 3x3卷积核cv2.imshow(\'中值滤波(3x3)\', median)cv2.waitKey(0)cv2.destroyAllWindows()

3. 滤波效果对比

  • 均值滤波和方框滤波(归一化)对高斯噪声有效,但会使图像边缘模糊。
  • 高斯滤波保留边缘信息更好,适合需要保留细节的场景。
  • 中值滤波是椒盐噪声的 “克星”,能有效去除噪声同时减少边缘模糊。