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,亮度补偿 10
c = 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
:设定的阈值。maxval
:type
为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) # 低于阈值置0
ret4, 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 cv2
import 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) # 标准差为1
cv2.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. 滤波效果对比
- 均值滤波和方框滤波(归一化)对高斯噪声有效,但会使图像边缘模糊。
- 高斯滤波保留边缘信息更好,适合需要保留细节的场景。
- 中值滤波是椒盐噪声的 “克星”,能有效去除噪声同时减少边缘模糊。