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

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

一、环境准备

1. 依赖安装

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

python 复制代码
pip install opencv-python numpy

2. 素材准备

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

二、核心操作详解

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

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

  1. 函数核心参数
python 复制代码
cv2.copyMakeBorder(src, top, bottom, left, right, borderType, value)
参数 说明
src 待填充的原始图像
top/bottom/left/right 上 / 下 / 左 / 右四个方向的边框宽度(单位:像素)
borderType 边框类型(核心:5 种预设类型)
value BORDER_CONSTANT 类型需要,指定边框颜色(BGR 格式,如 (299,25,80))
  1. 5 种边框类型对比
边框类型 填充规则 效果示例(以序列 abcdefgh 为例)
BORDER_CONSTANT 固定颜色填充 ` 自定义颜色 abcdefgh 自定义颜色 `
BORDER_REFLECT 镜面反射(包含边界像素重复) `gfedcba abcdefgh hgfedcba`
BORDER_REFLECT101 镜面反射(无边界重复,推荐) `gfedcb abcdefgh gfedcb`
BORDER_REPLICATE 重复边界像素 `aaaaaa abcdefgh hhhhhhh`
BORDER_WRAP 循环填充(上下左右边界互替) `cdefgh abcdefgh abcdefg`
  1. 实战代码
python 复制代码
'''----------------边界填充-------------------------'''
# 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)。

实战代码:

python 复制代码
'''-----------------图像运算-----------------------'''
# 图像加法运算
# 对于+号运算,当对图像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. 函数核心参数
python 复制代码
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. 实战代码
python 复制代码
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. 生成椒盐噪声(模拟图像噪声)
python 复制代码
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. 常用滤波器实战
python 复制代码
# 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()
  1. 滤波器效果对比
滤波器 核心特点 最佳适用场景
均值滤波 简单平均,模糊均匀 轻度降噪、整体模糊
方框滤波 可选择是否归一化 自定义权重求和、特殊效果
高斯滤波 高斯权重,边缘更柔和 自然模糊、保留边缘的降噪
中值滤波 取邻域中值,无像素求和 椒盐噪声去除(效果最佳)

三、核心总结

  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() 释放资源。
相关推荐
bst@微胖子2 小时前
OpenCV 案例一【人脸检测】
人工智能·opencv·计算机视觉
编码小哥3 小时前
OpenCV直方图处理技术:均衡化与CLAHE详解
人工智能·opencv·计算机视觉
Fleshy数模6 小时前
OpenCV实现图像边缘检测:Sobel、Scharr、Laplacian与Canny算子全解析
人工智能·opencv·计算机视觉
纤纡.6 小时前
玩转 OpenCV 形态学操作与边缘检测:从入门到实战
人工智能·opencv·计算机视觉
光羽隹衡7 小时前
计算机视觉——Opencv(光流估计实现目标追踪)
人工智能·opencv·计算机视觉
TEC_INO8 小时前
Linux37:利用OPENCV 的imread读取图片信息和imwrite写入数据
人工智能·opencv·webpack
格林威11 小时前
Halcon vs OpenCV 保存图像速度对比测试
人工智能·深度学习·opencv·机器学习·计算机视觉·halcon·工业相机
sali-tec13 小时前
C# 基于OpenCv的视觉工作流-章32-圆环卷收
图像处理·人工智能·opencv·算法·计算机视觉
格林威13 小时前
Halcon vs OpenCV 速度对比(表格)
人工智能·数码相机·opencv·机器学习·计算机视觉·视觉检测·halcon