当前位置: 首页 > news >正文

【OpenCV 核心基础操作全解析:从边界填充到图像平滑】

OpenCV 作为 Python 计算机视觉领域的核心库,其基础操作是入门计算机视觉的必经之路。本文将围绕边界填充、图像运算、阈值处理、图像平滑四大核心模块,结合实战代码拆解原理与应用,帮助新手快速掌握 OpenCV 图像预处理的核心逻辑。

一、环境准备

1. 依赖安装

确保已安装 OpenCV 和 NumPy 库,执行以下命令完成安装:

pip install opencv-python numpy

2. 素材准备

准备 1-2 张测试图片(如zx_min.jpglp.png),放置在代码同级目录下,建议选择彩色、分辨率适中的图片,便于观察处理效果。

二、核心操作详解

(一)边界填充:给图像添加自定义边框

边界填充(Padding)是图像预处理的基础操作,常用于卷积运算中边缘信息补全、图像可视化时的边框美化等场景,OpenCV 中通过cv2.copyMakeBorder()实现。

1. 函数核心参数

cv2.copyMakeBorder(src, top, bottom, left, right, borderType, value)
参数说明
src待填充的原始图像
top/bottom/left/right上 / 下 / 左 / 右四个方向的边框宽度(单位:像素)
borderType边框类型(核心:5 种预设类型)
valueBORDER_CONSTANT类型需要,指定边框颜色(BGR 格式,如 (299,25,80))

2. 5 种边框类型对比

边框类型填充规则效果示例(以序列 abcdefgh 为例)
BORDER_CONSTANT固定颜色填充` 自定义颜色abcdefgh自定义颜色 `
BORDER_REFLECT镜面反射(包含边界像素重复)`gfedcbaabcdefghhgfedcba`
BORDER_REFLECT101镜面反射(无边界重复,推荐)`gfedcbabcdefghgfedcb`
BORDER_REPLICATE重复边界像素`aaaaaaabcdefghhhhhhhh`
BORDER_WRAP循环填充(上下左右边界互替)`cdefghabcdefghabcdefg`

3. 实战代码

'''----------------边界填充-------------------------''' # cv2.copyMakeBorder()是OpenCV库中的一个函数,用于给图像添加额外的边界(padding)。 # 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:定义要添加边框的类型,它可以是以下的一种: # cv2.BORDER_CONSTANT:添加的边界框像素值为常数(需要额外再给定一个参数)。 # 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 import cv2 zm=cv2.imread('zx_min.jpg') # zm=cv2.resize(zm,dsize=None,fx=0.5,fy=0.5) # zm=cv2.resize(zm,(640,480)) top,bottom,left,right=50,50,50,50 consant=cv2.copyMakeBorder(zm,top,bottom,left,right,borderType=cv2.BORDER_CONSTANT,value=(299,25,80)) reflect=cv2.copyMakeBorder(zm,top,bottom,left,right,borderType=cv2.BORDER_REFLECT) reflect101=cv2.copyMakeBorder(zm,top,bottom,left,right,borderType=cv2.BORDER_REFLECT101) replicate=cv2.copyMakeBorder(zm,top,bottom,left,right,borderType=cv2.BORDER_REPLICATE) wrap=cv2.copyMakeBorder(zm,top,bottom,left,right,borderType=cv2.BORDER_WRAP) cv2.imshow('zx_min',zm) # cv2.waitKey(0) cv2.imshow('CONSTANT',consant) # 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()

(二)图像运算:像素级加法与加权融合

图像运算的本质是对像素值的逐点计算,核心分为普通加法加权加法,适用于图像融合、亮度调节等场景。

1. 普通加法:两种规则的差异
运算方式核心规则代码示例
原生+超过 255 取余((a+b)%256),易导致颜色失真c = a[区域] + b[区域]
cv2.add()超过 255 取 255(饱和加法),符合人眼视觉习惯c = cv2.add(a, b)

注意:加法运算要求两张图像尺寸、通道数完全一致,需先用 cv2.resize() 统一尺寸。

2. 加权加法:图像融合的核心


加权加法通过 cv2.addWeighted() 实现,支持调节图像透明度,公式为:


• alpha/beta:两张图像的权重(通常和为 1,如 0.5+0.5);
• gamma:亮度调节常量(可正可负,如 10 表示整体亮度 +10)。
实战代码:

'''-----------------图像运算-----------------------''' # 图像加法运算 # 对于+号运算,当对图像a,图像b进行加法求和时,遵循以下规则: # 当某位置像素相加得到的数值小于255时,该位置数值为两图像该位置像素相加之和 # 当某位置像素相加得到的数值大于255时,该位置数值将截断结果并将其减去 256 例如:相加后是260,实际是260-256= 4 a = cv2.imread('lp.png') b = cv2.imread('zx_min.jpg') # 3. 对图片a的所有像素值加10(像素级加法,遵循模256规则) # 原理:每个像素的B/G/R三个通道值都+10,比如像素(100,150,200)→(110,160,210);若加完超255则取余,如(250,250,250)+10→(4,4,4) c = a + 10 cv2.imshow('yuan', a) cv2.imshow('a+10', c) cv2.waitKey(0) # 7. 截取图片a和b的指定区域并逐像素相加 # a[50:450,50:400]:截取a的行50到449、列50到399的矩形区域(高400像素,宽350像素) # b[50:450,50:400]:截取b的相同位置区域(要求b的尺寸≥450行×400列,否则报错) # 加法规则:对应位置的像素值相加,超255则取余(如250+10=260→260-256=4) c = a[50:450,50:400] + b[50:450,50:400] cv2.imshow('a+b', c) cv2.waitKey(0) # 对于cv2.add()运算,当对图像a,图像b进行加法求和时,遵循以下规则: # 当某位置像素相加得到的数值小于255时,该位置数值为两图像该位置像素相加之和 #当某位置像素相加得到的数值大于255时,该位置数值为255 # # 图像加权运算 #就是在计算两幅图像的像素值之和时,将每幅图像的权重考虑进来,可以用公式表示dst=src1xa+src2xB+V import cv2 a = cv2.imread('lp.png') b = cv2.imread('zx_min.jpg') # 3. 将图片b缩放为 400x400 像素(宽400,高400) # cv2.resize(待缩放图像, (目标宽度, 目标高度)):统一尺寸是像素运算的前提 b = cv2.resize(b, (400, 400)) # 4. 将图片a也缩放为 400x400 像素,保证和b尺寸完全一致 # (cv2.addWeighted要求两张图像尺寸、通道数必须相同,否则报错) a = cv2.resize(a, (400, 400)) # 5. 图像加权融合(核心函数:cv2.addWeighted) # 公式:c = a*0.5 + b*0.5 + 10 # 参数说明: # a:第一张输入图像 # 0.5:a的权重(表示a占融合结果的50%透明度) # b:第二张输入图像 # 0.5:b的权重(表示b占融合结果的50%透明度) # 10:亮度调节常量(给所有像素值加10,整体提亮,可正可负) c = cv2.addWeighted(a, 0.5, b, 0.5, 10) cv2.imshow('addWeighted', c) cv2.waitKey(0) cv2.destroyAllWindows()

(三)阈值处理:图像二值化的核心


阈值处理是将灰度图像转为黑白二值图的关键操作,通过设定 “像素分界线”(阈值)区分前景与背景,核心函数为 cv2.threshold()。

1. 函数核心参数
ret, dst = cv2.threshold(src, thresh, maxval, type)
  • thresh:阈值(0-255,如 150);
  • maxval:最大值(通常为 255,代表纯白);
  • type:阈值处理类型(5 种核心类型)。
2. 5 种阈值类型规则(以阈值 150 为例)
类型处理规则视觉效果
THRESH_BINARY≥150 → 255(白),<150 → 0(黑)亮区变白,暗区变黑
THRESH_BINARY_INV≥150 → 0(黑),<150 → 255(白)亮区变黑,暗区变白
THRESH_TRUNC≥150 → 150(截断),<150 → 原值亮区 “封顶”,暗区不变
THRESH_TOZERO≥150 → 原值,<150 → 0(黑)亮区保留,暗区变黑
THRESH_TOZERO_INV≥150 → 0(黑),<150 → 原值亮区变黑,暗区保留
3. 实战代码
import cv2 import cv2 # 读取图片并转为灰度图(参数0指定灰度模式,像素值范围0-255) image = cv2.imread('lpp.png', 0) # 阈值处理核心参数:阈值150,最大值255(纯白) # 1. 二值化:≥150→255(白),<150→0(黑) | ret返回实际使用的阈值(此处为150) ret, binary = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY) # 2. 反向二值化:≥150→0(黑),<150→255(白) ret1, binaryinv = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY_INV) # 3. 截断处理:≥150→150(封顶),<150→保留原值 ret2, trunc = cv2.threshold(image, 150, 255, cv2.THRESH_TRUNC) # 4. 低于阈值置0:≥150→保留原值,<150→0(黑) ret3, tozero = cv2.threshold(image, 150, 255, cv2.THRESH_TOZERO) # 5. 高于阈值置0:≥150→0(黑),<150→保留原值 ret4, tozeroinv = cv2.threshold(image, 150, 255, cv2.THRESH_TOZERO_INV) # 显示所有处理结果(一次性展示,按任意键关闭所有窗口) cv2.imshow('gray', image) # 灰度原图 cv2.imshow('binary', binary) # 二值化结果 cv2.imshow('binaryinv', binaryinv) # 反向二值化 cv2.imshow('trunc', trunc) # 截断效果 cv2.imshow('tozero', tozero) # 低于阈值置0 cv2.imshow('tozeroinv', tozeroinv) # 高于阈值置0 cv2.waitKey(0) # 阻塞窗口,按任意键退出

(四)图像平滑:噪声去除的核心手段

图像平滑(模糊处理)通过消除噪声、弱化细节实现图像模糊,常用滤波器包括均值滤波、方框滤波、高斯滤波、中值滤波,以下先实现 “添加椒盐噪声” 模拟真实场景,再演示滤波效果。

1. 生成椒盐噪声(模拟图像噪声)
import cv2 import numpy as np # 定义添加椒盐噪声的函数 def add_peppersalt_noise(image, n=10000): result = image.copy() # 避免修改原图 h, w = image.shape[:2] # 对于彩色图像(默认 BGR 格式):image.shape 返回 (高度, 宽度, 通道数),例如 (720, 1080, 3);对于灰度图像(单通道):image.shape 返回 (高度, 宽度),例如 (720, 1080);获取图像高、宽 for i in range(n): # 随机生成噪声点坐标 x = np.random.randint(0, h) y = np.random.randint(0, w) # 随机生成黑色(0)或白色(255)噪声 result[x, y] = 0 if np.random.randint(0,2)==0 else 255 return result # 读取图像并添加噪声 image = cv2.imread('zx_min.jpg') noise_image = add_peppersalt_noise(image) # 显示原图与噪声图 cv2.imshow('原图', image) cv2.imshow('椒盐噪声图', noise_image)
2. 常用滤波器实战
# 1. 均值滤波(邻域平均,核越大越模糊) blur_3 = cv2.blur(noise_image, (3,3)) # 3x3 核(轻度模糊) blur_63 = cv2.blur(noise_image, (63,63)) # 63x63 核(重度模糊) cv2.imshow('均值滤波 3x3', blur_3) cv2.imshow('均值滤波 63x63', blur_63) # 2. 方框滤波(可归一化/非归一化) # normalize=True:等价于均值滤波;False:像素值求和(易过曝) 一、核心结论 cv2.boxFilter() 中 normalize=True/False 决定了是否对滤波后的像素值进行归一化(均值化),是方框滤波的核心参数,直接影响滤波效果: normalize=True:归一化(默认)→ 等价于均值滤波,滤波后图像亮度正常; normalize=False:不归一化 → 像素值直接求和,大概率溢出(255),图像整体偏白 / 过曝。 二、原理拆解(3×3 核为例) 1. 方框滤波的本质 方框滤波是对图像中每个像素的「邻域(核大小)内所有像素值求和」,再根据 normalize 参数决定是否除以邻域像素总数: 邻域像素总数 = 核的宽 × 核的高(3×3 核 = 9 个像素) normalize=True(归一化) 计算公式:目标像素值=邻域像素总数/邻域内所有像素值之和 例:3×3 邻域像素和为 1000 → 目标值 = 1000/9 ≈ 111(正常范围 0-255); • 效果:和 cv2.blur(noise, (3,3)) 完全一致,是常规的 “均值模糊”,图像亮度自然。 normalize=False(不归一化) 计算公式:目标像素值= 例:3×3 邻域像素和为 1000 → 目标值 = 1000(远超 255); 关键:OpenCV 中图像像素值默认是 uint8 类型(0-255),超过 255 的部分会被截断为 255(饱和处理); 效果:大部分像素值直接溢出为 255,图像呈现大面积白色(过曝),仅极少数暗区域可能保留细节。 box_norm = cv2.boxFilter(noise_image, -1, (3,3), normalize=True) box_unnorm = cv2.boxFilter(noise_image, -1, (3,3), normalize=False) cv2.imshow('方框滤波(归一化)', box_norm) cv2.imshow('方框滤波(非归一化)', box_unnorm) # 3. 高斯滤波(高斯权重,模糊更自然) gaussian = cv2.GaussianBlur(noise_image, (3,3), 1) cv2.imshow('高斯滤波 3x3', gaussian) # 4. 中值滤波(专治椒盐噪声) median = cv2.medianBlur(noise_image, 3) # 核大小为奇数 cv2.imshow('中值滤波 3x3', median) cv2.waitKey(0) cv2.destroyAllWindows()

3. 滤波器效果对比

滤波器核心特点最佳适用场景
均值滤波简单平均,模糊均匀轻度降噪、整体模糊
方框滤波可选择是否归一化自定义权重求和、特殊效果
高斯滤波高斯权重,边缘更柔和自然模糊、保留边缘的降噪
中值滤波取邻域中值,无像素求和椒盐噪声去除(效果最佳)

三、核心总结

  1. 边界填充BORDER_REFLECT101是卷积操作补边的首选,BORDER_CONSTANT适合自定义颜色边框;
  2. 图像运算cv2.add()优于原生+号,addWeighted()是图像融合的核心函数;
  3. 阈值处理:二值化是图像分割基础,阈值需根据图像亮度灵活调整(建议 120-180 之间调试);
  4. 图像平滑:中值滤波对椒盐噪声效果最佳,高斯滤波模糊更自然,滤波核越大效果越明显(需为奇数)。

四、注意事项

  1. 所有操作前需校验图像读取是否成功(if image is None),避免路径错误导致报错;
  2. 像素运算、滤波等操作需保证图像尺寸 / 通道数一致,必要时用cv2.resize()统一;
  3. 阈值处理建议先转为灰度图,彩色图需分通道处理;
  4. 显示图像后需调用cv2.waitKey(0)阻塞窗口,最后用cv2.destroyAllWindows()释放资源。
http://www.jsqmd.com/news/767917/

相关文章:

  • Windows 10/11系统下,Grounded Segment Anything环境配置避坑全记录(附常见错误解决方案)
  • Yum下载不了问题
  • ElectronOpenHarmony 跨平台实战开发:Electron-forge 打包时 ECONNRESET 错误解决方案 PC适配
  • Docker 27 医疗容器认证避坑指南:为什么83%的HIS系统容器化项目因OCI运行时配置失败被驳回?
  • Agent设计模式全景图:2026年工程实践关键,避开10万开源项目踩过的坑!
  • Nez精灵图集打包器:自动化管理游戏资源的终极指南
  • 2026甄选:新疆靠谱的PE管厂家/管道/管材生产厂家榜单推荐观察 - 栗子测评
  • IAPWS Python库:工业级热力学计算与工程分析的终极解决方案
  • 通过OpenClaw Agent工具接入Taotoken的配置要点详解
  • 3步快速上手OBS浏览器插件:让你的直播画面动起来
  • 2026 三款入门便携电钢琴实测:学生党预算内选购参考
  • 速成蓝桥杯之DP(三)
  • 终极Karakeep图片处理指南:Sharp优化与格式转换实用技巧
  • PYTHON为什么内置的有错不让执行,只要不崩那完全无所谓呀
  • Godot像素风渲染器:从原理到实战,打造复古游戏画面
  • 【Linux环境下MySQL 5.7的完整安装与配置指南】
  • java基础总结笔记(2026.05.06)
  • 使用bluesky队列服务器
  • 自建智能语音音乐库:开源music-skill项目部署与集成指南
  • TDR阻抗测试仪Bamtone H系列深度评测
  • HALCON深度学习模型部署新选择:一份详细的OpenVINO 2021.4 LTS集成与配置避坑指南
  • 对Java继承中的访问权限与强转问题的小理解
  • 唯众AI教学与实训平台:从教学到科研全流程,附实操代码与技术拆解
  • 二进制分析框架pasta:连接Ghidra与angr的中间表示与自动化工具链
  • 从零构建智能网页向量索引系统:原理、实现与优化
  • 紧急预警:Docker 27.1将废弃--link参数,所有依赖可视化编排的低代码平台(如简道云、明道云)容器化方案需立即重构——附向后兼容迁移路径图
  • 基于Transformer与零样本分类的文本氛围分析工具VibeCheck实践指南
  • 1Panel开源服务器面板:Go+React架构与容器化运维实践
  • 构建Python量化交易回测平台:5步实现专业级可视化分析工具
  • PCB切片分析工具:Bamtone MS90集成AI的智能测量解决方案