玩转 OpenCV 图像处理:从边界填充到图像滤波全解析

OpenCV 作为计算机视觉领域最常用的开源库,提供了丰富的图像处理函数,能轻松实现图像边界填充、像素运算、阈值处理和图像平滑(滤波)等核心操作。本文将从实用角度出发,详解 OpenCV 中这些基础且高频的图像处理技术,重点聚焦图像滤波的原理与实战,帮助初学者快速掌握核心用法。

一、基础铺垫:图像边界填充

在图像处理中,当需要对图像边缘进行操作(如卷积、滤波)时,边界像素往往会因缺乏邻域信息导致处理不完整,此时就需要用为cv2.copyMakeBorder()图像添加边界(填充)。

核心参数与填充类型

python 复制代码
import cv2
import numpy as np

# 读取图像
img = cv2.imread('img1.jpeg')
# 定义上下左右填充宽度
top, bottom, left, right = 50, 50, 50, 50

# 1. 常数填充:边界像素为指定颜色
constant = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(229, 25, 80))
# 2. 反射填充:边界像素为原图像边缘的镜面反射
reflect = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REFLECT)
# 3. 反射填充(优化版):避免边界重复
reflect101 = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REFLECT101)
# 4. 复制填充:用最边缘像素填充整个边界
replicate = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REPLICATE)
# 5. 环绕填充:上下左右边界循环替换
wrap = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_WRAP)

不同填充类型适用于不同场景:常数填充适合需要明确边界颜色的场景,反射 / 复制填充适合滤波时保持边缘连续性,环绕填充则适用于周期性图像处理。

二、像素级操作:图像运算

图像的本质是像素矩阵,OpenCV 支持两种核心加法运算,以及更灵活的加权运算。

1. 普通加法(+):截断规则

普通加法遵循「模 256」规则,像素和超过 255 时会减去 256:

python 复制代码
a = cv2.imread('img1.jpeg')
b = cv2.imread('img2.jpeg')
# 像素值整体加10
c1 = a + 10
# 局部区域像素相加
c2 = a[50:450, 50:400] + b[50:450, 50:400]

2. cv2.add ():饱和规则

cv2.add()更符合人眼视觉,像素和超过 255 时直接取 255:

python 复制代码
# 统一图像尺寸
a = cv2.resize(a, (400, 400))
b = cv2.resize(b, (400, 400))
c = cv2.add(a, b)

3. 加权加法(cv2.addWeighted):图像融合

加权运算公式:dst = src1*α + src2*β + γ,适合图像融合(如水印、渐变):

python 复制代码
# α=0.5, β=0.5, γ=10(亮度补偿)
blend = cv2.addWeighted(a, 0.5, b, 0.5, 10)

三、像素筛选:阈值处理cv2.threshold()

阈值处理是将图像像素分为「高于阈值」和「低于阈值」两类,实现图像二值化或像素截断,核心函数cv2.threshold():

python 复制代码
# 读取灰度图像
gray = cv2.imread('img1.jpeg', 0)
# 二值化阈值:像素>175设为255(白),否则0(黑)
ret, binary = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY)
# 反二值化:像素>175设为0,否则255
ret, binary_inv = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY_INV)
# 截断:像素>175设为175,否则不变
ret, trunc = cv2.threshold(gray, 175, 255, cv2.THRESH_TRUNC)
# 归零:像素>175不变,否则0
ret, tozero = cv2.threshold(gray, 175, 255, cv2.THRESH_TOZERO)

阈值处理常用于图像分割、文字提取、轮廓检测等场景。

四、重点:图像平滑(滤波)------ 消除噪声的核心手段

图像噪声(如椒盐噪声、高斯噪声)会影响后续处理,滤波是消除噪声的关键,OpenCV 提供了 4 种常用滤波方式,我们先构造含椒盐噪声的图像,再对比不同滤波效果:

1. 生成椒盐噪声

python 复制代码
def add_peppersalt_noise(image, n=10000):
    """添加椒盐噪声:随机生成黑白噪点"""
    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)
        # 随机生成黑/白点
        result[x, y] = 0 if np.random.randint(0, 2) == 0 else 255
    return result

# 读取图像并添加噪声
img = cv2.imread('img1.jpeg')
noise_img = add_peppersalt_noise(img)

2. 均值滤波(cv2.blur):简单平均

原理:用邻域内所有像素的平均值替换中心像素,优点是简单,缺点是会模糊图像边缘,核越大模糊越明显。

python 复制代码
# 3x3核均值滤波(轻度模糊)
blur_3 = cv2.blur(noise_img, (3, 3))
# 30x30核均值滤波(重度模糊)
blur_30 = cv2.blur(noise_img, (30, 30))

3. 方框滤波(cv2.boxFilter):可归一化的均值滤波

原理:与均值滤波类似,但可通过normalize参数控制是否归一化:

  • normalize=True:等同于均值滤波(邻域和 / 面积);
  • normalize=False:直接取邻域和,超过 255 则截断为 255(易过曝)。
python 复制代码
# 归一化方框滤波(同均值滤波)
box_norm = cv2.boxFilter(noise_img, -1, (3, 3), normalize=True)
# 不归一化方框滤波(易出现白色区块)
box_unnorm = cv2.boxFilter(noise_img, -1, (3, 3), normalize=False)

4. 高斯滤波(cv2.GaussianBlur):保留边缘的模糊

原理:对邻域像素加权平均(距离中心越近权重越高),能在消除噪声的同时,更好保留图像边缘细节,是最常用的滤波方式。

python 复制代码
# 3x3核,X/Y方向标准差=1
gaussian = cv2.GaussianBlur(noise_img, (3, 3), 1)

5. 中值滤波(cv2.medianBlur):专治椒盐噪声

原理 :用邻域像素的中位数替换中心像素,能完美消除椒盐噪声(黑白噪点),且不会模糊边缘,是处理椒盐噪声的首选。

python 复制代码
# 3x3核中值滤波(核大小需为奇数)
median = cv2.medianBlur(noise_img, 3)

滤波效果对比

滤波类型 核心特点 适用场景
均值滤波 简单平均,模糊明显 轻度噪声、无边缘保护需求
方框滤波 可归一化,灵活控制 自定义加权平均场景
高斯滤波 加权平均,保留边缘 通用降噪(高斯噪声)
中值滤波 中位数替换,无模糊 椒盐噪声、颗粒噪声

五、完整实战代码

python 复制代码
import cv2
import numpy as np

# ========== 1. 边界填充 ==========
img = cv2.imread('img1.jpeg')
top, bottom, left, right = 50, 50, 50, 50
constant = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(229, 25, 80))

# ========== 2. 图像运算 ==========
a = cv2.imread('img1.jpeg')
b = cv2.imread('img2.jpeg')
a = cv2.resize(a, (400, 400))
b = cv2.resize(b, (400, 400))
blend = cv2.addWeighted(a, 0.5, b, 0.5, 10)

# ========== 3. 阈值处理 ==========
gray = cv2.imread('img1.jpeg', 0)
ret, binary = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY)

# ========== 4. 图像滤波 ==========
def add_peppersalt_noise(image, n=10000):
    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)
        result[x, y] = 0 if np.random.randint(0, 2) == 0 else 255
    return result

noise_img = add_peppersalt_noise(img)
# 均值滤波
blur = cv2.blur(noise_img, (3, 3))
# 方框滤波
box = cv2.boxFilter(noise_img, -1, (3, 3), normalize=True)
# 高斯滤波
gaussian = cv2.GaussianBlur(noise_img, (3, 3), 1)
# 中值滤波
median = cv2.medianBlur(noise_img, 3)

# 显示结果
cv2.imshow('原始图像', img)
cv2.imshow('椒盐噪声', noise_img)
cv2.imshow('均值滤波', blur)
cv2.imshow('高斯滤波', gaussian)
cv2.imshow('中值滤波', median)
cv2.waitKey(0)
cv2.destroyAllWindows()

总结

  1. OpenCV 的边界填充、图像运算、阈值处理是图像处理的基础,填充用于边缘补全,运算用于像素级操作,阈值用于像素筛选;
  2. 图像滤波是消除噪声的核心:均值滤波简单但模糊明显,高斯滤波兼顾降噪与边缘保留,中值滤波是椒盐噪声的 "克星";
  3. 实际开发中需根据噪声类型选择滤波方式:高斯噪声用高斯滤波,椒盐噪声用中值滤波,通用场景优先选高斯滤波。

掌握这些基础操作,就能应对大部分入门级的图像处理需求,后续可结合卷积、形态学操作等进阶技术,实现更复杂的计算机视觉任务。

相关推荐
芯盾时代6 小时前
部署OpenClaw的安全风险
人工智能·安全·ai
chaors6 小时前
Langchain入门到精通0x05:预制链
人工智能·langchain·ai编程
GWQ3336 小时前
2026中国南京国际电池及储能技术博览会影响力如何?商机在哪里?
大数据·人工智能
AI工程架构师6 小时前
langChain 快速入门
人工智能
gustt6 小时前
RAG 实战:彻底搞懂 LangChain 文本切割器(Splitter)
人工智能·llm
chaors6 小时前
Langchain入门到精通0x04:大模型怎么记忆?
人工智能·langchain·ai编程
慢煮AI6 小时前
果蝇大脑“住进”电脑:从生物结构到数字生命的通俗解读
人工智能·架构
AI-小柒6 小时前
巨省Token:OpenClaw安装部署并接入数眼智能特价模型全流程(包含Windows和Mac)
大数据·人工智能·windows·网络协议·tcp/ip·http·macos
软件资深者6 小时前
阿里云轻量服务器部署 OpenClaw 完整教程
数据库·人工智能·ai·open claw·龙虾·openclaw安装·clawx
Monly216 小时前
大模型:prompt提示词工程指南
人工智能·prompt