【Open CV图像处理】修改运算与平滑处理

目录

图像修改

图片打码

图片组合

图片缩放

图像运算

图片加法

cv2.add()运算

图片加权运算

阈值处理

图像平滑处理

椒盐噪声生成

滤波处理

均值滤波

方框滤波

高斯滤波

中值滤波

视频平滑处理作业


一、图像修改

图片打码
python 复制代码
import cv2
import numpy as np
# 图片打码
a = cv2.imread(r'./xin.jpg')
xxx = np.random.randint(0, 256, (3, 3))
print(xxx)
a[100:200, 200:300] = np.random.randint(0, 256, (100, 100, 3))
cv2.imshow('masaike', a)
cv2.waitKey(0)
cv2.destroyAllWindows()
  1. 图片本质是三维numpy数组:(高度, 宽度, 3个RGB通道),可通过数组切片直接修改像素。

  2. 切片语法:a高度起始:高度结束, 宽度起始:宽度结束,对应图片的矩形区域。

  3. np.random.randint(0,256,(h,w,3)):生成0~255的随机像素值,模拟马赛克效果。

注意:

赋值的数组大小必须完全匹配切片区域的大小

切片:100:200 高度共 100行,200:300 宽度共 100列

随机数组必须是 (100,100,3),行列数量不一致会直接报错。

运行效果

图片组合
python 复制代码
# 图片组合
a = cv2.imread('xin.jpg')
b = cv2.imread('o.png')
b[200:350, 200:350] = a[50:200, 100:250]
cv2.imshow('b', b)
cv2.imshow('a', a)
cv2.waitKey(0)
cv2.destroyAllWindows()
  1. 图片像素可以跨图片复制粘贴:将一张图的像素区域,直接赋值给另一张图的区域。

  2. 原理:OpenCV图片均为numpy数组,数组之间支持直接赋值操作。

注意:

两张图片的切片区域,尺寸必须严格一致,行列数量不匹配,会直接报错。

运行效果

图片缩放
python 复制代码
# 图片缩放
a = cv2.imread('xin.jpg')
# 写法1:直接指定宽高缩放
a_new = cv2.resize(a, dsize=(600,200))
# 写法2:按比例缩放(fx宽比例、fy高比例)
# a_new = cv2.resize(a, None, fx=1.5, fy=0.5)
cv2.imshow('a',a)
cv2.imshow('a_new',a_new)
cv2.waitKey(0)
cv2.destroyAllWindows()

两个核心使用方式:

方式1:dsize=(宽度, 高度),直接指定输出图片的宽高

方式2:fx、fy 缩放系数,fx=1.5代表宽度放大1.5倍,fy=0.5代表高度缩小一半

注意:

  1. dsize 格式为 (宽, 高),与图片数组(高,宽)顺序相反,容易写反。

  2. 两种缩放方式二选一:指定dsize后,fx/fy会自动失效。

  3. 缩小图片会丢失细节,放大图片会产生模糊,无法还原原始清晰度。

运行效果

二、图像运算

图片加法
python 复制代码
import cv2
# 图像加法运算:当某位置像素相加得到的数值大于255时,将该位置数值相加结果阶段减去256(例如:相加后得到260,实际是260-256=4)
a = cv2.imread('mimi.jpg')
b = cv2.imread('xin_new.jpg')
c = a+100
cv2.imshow('yuan', a)
cv2.imshow('a+10', c)
cv2.waitKey(0)
c = a[50:450, 50:450]+b[50:450, 50:450]
cv2.imshow('a+b', c)
cv2.waitKey(0)
  1. 像素和 <255:结果 = 两像素直接相加

  2. 像素和 >255:执行取模运算(循环截断),公式:结果 = 总和 - 256

例:260 → 260-256 = 4

注意:

他的本质是 numpy 数组运算,遵循 uint8 类型的循环溢出规则

两张图片相加时,参与运算的区域尺寸必须完全一致,否则直接报错

运行效果

cv2.add()运算
python 复制代码
# cv2.add()运算规则:当某位置像素相加得到的数字大于255时,该位置数值为255
a = cv2.imread('mimi.jpg')
b = cv2.imread('xin_new.jpg')
b = cv2.resize(b, (400, 400))
a = cv2.resize(a, (400, 400))
c = cv2.add(a, b)
cv2.imshow('a add b', c)
cv2.waitKey(0)
cv2.destroyAllWindows()
  1. 像素和 <255:结果 = 两像素直接相加

  2. 像素和 >255:执行饱和截断,直接固定最大值为255

注意:

  1. 他与 + 运算最大区别是,溢出后不会归零,直接保持纯白255

  2. 两张图片宽高必须完全一致,否则运算直接报错

  3. 专门用于图像融合,是OpenCV官方推荐的加法方式

运行效果

图片加权运算
python 复制代码
# 图像加权运算:计算两张图片的像素值之和,将每张图的权重都考虑进来(公式c像素=a像素×α权重+b像素×β权重+γ偏移量/变亮变暗)
a = cv2.imread('mimi.jpg')
b = cv2.imread('xin_new.jpg')
b = cv2.resize(b, (400, 400))
a = cv2.resize(a, (400, 400))
c = cv2.addWeighted(a, 0.5, b, 0.4, 10)
cv2.imshow('addWeighed', c)
cv2.waitKey(0)
cv2.destroyAllWindows()

公式:dst = src1 × α + src2 × β + γ

alpha(α):第一张图的权重系数(透明度,0~1之间)

beta(β):第二张图的权重系数(透明度,0~1之间)

gamma(γ):全局亮度偏移值,给整张融合图片统一提亮/压暗

注意:

  1. 同样要求两张图片尺寸完全一致

  2. 权重之和 alpha+beta 通常设为1,保证亮度均衡;大于1画面会整体变亮

  3. gamma为最终提亮值,正数提亮、负数压暗,是调整画面明暗的常用参数

运行效果

阈值处理

剔除图像内像素值高于/低于设定阈值的像素点,实现图像二值分割(黑白区分)。

标准函数格式:

retval, dst = cv2.threshold(src, thresh, maxval, type)

  1. src:需要做阈值分割的图像,必须先转为灰度图(代码中 flags=0 就是读取灰度图)

  2. thresh:手动设定的分割阈值

  3. maxval:像素超过阈值时填充的最大值

  4. type:阈值分割的5种类型

返回值

retval:最终生效的阈值(手动设置时和thresh一致,自动阈值算法才会变化)

dst:阈值处理后的结果图像

阈值类型 像素值 > 175 其他情况(≤175) 含义
cv2.THRESH_BINARY 设为maxval(255)(纯白) 设为0(纯黑) 标准二值化:亮部变白,暗部变黑
cv2.THRESH_BINARY_INV 设为0(纯黑) 设为maxval(255)(纯白) 反二值化:亮部变黑,暗部变白
cv2.THRESH_TRUNC 固定为阈值175 保持原灰度值 高光截断:超过阈值的像素统一变暗,画面呈现灰调
cv2.THRESH_TOZERO 保持原灰度值 设为0(纯黑) 暗部抑制:低于阈值的像素变黑,亮部保持不变
cv2.THRESH_TOZERO_INV 设为0(纯黑) 保持原灰度值 亮部抑制:高于阈值的像素变黑,暗部保持不变
python 复制代码
import cv2
image = cv2.imread('zl.png', 0)
ret, binary = cv2.threshold(image, 175, 255, cv2.THRESH_BINARY)
ret1, binaryinv = cv2.threshold(image, 175, 255, cv2.THRESH_BINARY_INV)
ret2, trunc = cv2.threshold(image, 175, 255, cv2.THRESH_TRUNC)
ret3, tozero = cv2.threshold(image, 175, 255, cv2.THRESH_TOZERO)
ret4, tozeroinv = cv2.threshold(image, 175, 255, cv2.THRESH_TOZERO_INV)
cv2.imshow('gray', image)
cv2.waitKey(0)
cv2.imshow('binary', binary)
cv2.waitKey(0)
cv2.imshow('binaryinv', binaryinv)
cv2.waitKey(0)
cv2.imshow('trunc', trunc)
cv2.waitKey(0)
cv2.imshow('tozero', tozero)
cv2.waitKey(0)
cv2.imshow('tozeroinv', tozeroinv)
cv2.waitKey(0)
  1. 强制灰度图:threshold 函数只能接收单通道灰度图,彩色图必须先转灰度,否则直接报错

  2. maxval仅2种模式生效:只有 BINARY / BINARY_INV 会用到maxval,另外3种类型该参数无效

  3. 像素取值范围:所有阈值处理基于 0~255 的uint8像素值,超出范围会直接截断

运行效果

三、图像平滑处理

椒盐噪声生成

给图片添加椒盐噪声(黑白随机噪点)

  1. 定义生成椒盐噪点的函数

  2. 读取原图并显示

  3. 调用函数生成带噪点的图片

  4. 显示带噪点的图片

python 复制代码
import cv2
import numpy as np
# 导入OpenCV图像处理库与数值计算库,是所有OpenCV项目的基础依赖。
# 定义【椒盐噪声生成函数】
def add_peppersalt_noise(image, n=10000):
    # 复制原图,避免直接修改原始图片
    result = image.copy()
    # 获取图片的高度、宽度(shape[:2]只取前两个维度,排除RGB通道)
    h, w = image.shape[:2]
    
    # 循环n次,生成n个随机噪点
    for i in range(n):
        # 随机生成x坐标(纵向:0 ~ 图片高度h之间)
        x = np.random.randint(0, h)
        # 随机生成y坐标(横向:0 ~ 图片宽度w之间)
        y = np.random.randint(0, w)
        
        # 50%概率生成黑点,50%概率生成白点
        if np.random.randint(0, 2) == 0:
            result[x, y] = 0      # 0 = 纯黑色(胡椒噪点)
        else:
            result[x, y] = 255     # 255 = 纯白色(盐粒噪点)
    
    # 返回添加完噪点的图片
    return result

函数核心知识点1. 椒盐噪声定义:0 → 黑色胡椒噪点,255 → 白色盐粒噪点

  1. 参数n=10000:噪点的总数量,数值越大噪点越密集,画面越模糊。

  2. image.copy():复制原图操作,核心原则:绝对不能直接修改原始图片。

  3. np.random.randint(0,2):随机生成0或1,保证黑白噪点的生成概率各占一半。

python 复制代码
# 读取原始图片
image = cv2.imread('xin_new.png')
# 显示原图
cv2.imshow('yntu', image)
cv2.waitKey(0)  # 等待按键,不按则窗口一直停留
# 调用函数,给图片添加椒盐噪点
noise = add_peppersalt_noise(image)
# 显示添加噪点后的图片
cv2.imshow('noise', noise)
cv2.waitKey(0)

注意:

  1. 彩色图兼容:该函数可直接用于彩色图片,代码会自动给3个RGB通道同时添加黑白噪点,无需额外修改。

  2. 噪点数量调整:

n=5000:轻微噪点

n=10000:常规密度噪点(当前代码默认值)

n=50000:重度噪点,画面会严重受损

滤波处理
均值滤波
python 复制代码
blur_1 = cv2.blur(noise, (3, 3))
cv2.imshow('blur_1', blur_1)
cv2.waitKey(0)
blur_2 = cv2.blur(noise, (63, 63))
cv2.imshow('blur_2', blur_2)
cv2.waitKey(0)
  1. 参数 (3,3):卷积核大小,代表取周围3×3=9个像素,求平均值替换中心像素

  2. 原理:邻域所有像素取平均值,让整体画面模糊平滑

  3. 两组对比效果:

(3,3):小卷积核,轻微模糊,能去除部分噪点

(63,63):大卷积核,画面极度模糊,丢失大量细节

去除噪声效果差,只能弱化噪点,无法彻底清除,画面会整体发糊。

效果展示

方框滤波
python 复制代码
boxFilter_1 = cv2.boxFilter(noise, -1, (3,3), normalize = True)
cv2.imshow('boxFilter_1',boxFilter_1)
cv2.waitKey(0)

boxFilter_2 = cv2.boxFilter(noise, -1, (3,3), normalize = False)
cv2.imshow('boxFilter_2',boxFilter_2)
cv2.waitKey(0)
  1. -1:输出图像深度,固定写 -1 即可,代表和原图格式保持一致

  2. (3,3):卷积核大小,和均值滤波完全一致

  3. normalize

True 归一化:求和后÷像素数量,结果和 cv2.blur 均值滤波一模一样

False 不归一化:直接累加所有像素值,数值极易超过255,画面会变成几乎纯白色

方框滤波本质是均值滤波的通用版,仅归一化模式有实际使用价值。

高斯滤波
python 复制代码
GaussianB = cv2.GaussianBlur(noise, (3,3), sigmaX=1)
cv2.imshow('GaussianBlur',GaussianB)
cv2.waitKey(0)
  1. 原理:距离中心越近的像素权重越高,模拟人眼观察效果,模糊效果更自然

  2. 参数 sigmaX=1:X方向高斯标准差,数值越大,模糊程度越强

去噪效果优于均值滤波,画面不会出现生硬的方块模糊,但对椒盐噪声的去除效果依旧一般,仅能弱化噪点,无法彻底清除

中值滤波
python 复制代码
medianB = cv2.medianBlur(noise, 3)
cv2.imshow('medianBlur',medianB)
cv2.waitKey(0)
cv2.destroyAllWindows()
  1. 参数 3:卷积核尺寸,必须是奇数(3、5、7......)

  2. 原理:取3×3邻域内所有像素的中间值,直接剔除0和255的极值噪点

去除椒盐噪声效果最好,能直接清除黑白噪点,画面保留细节,不会像均值滤波一样整体严重发糊

效果展示

视频平滑处理作业

给定一个视频文件:'test.avi',要求完成以下操作:

1、使其每一帧画面都随机生成10000个黑白点(椒盐噪声)添加噪声效果,

2、然后选择合适的图像平滑处理方法,处理每一帧画面,消除噪声的同时尽可能使原画面清晰,

3、同时弹出三个窗口,分别展示原视频、含有噪声的视频、平滑处理后的视频。

代码实现

python 复制代码
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):
        x = np.random.randint(0, h)
        y = np.random.randint(0, w)
        if np.random.randint(0, 2) == 0:
            result[x, y] = 0
        else:
            result[x, y] = 255
    return result

video_capture = cv2.VideoCapture('test.avi')
if not video_capture.isOpened():
    print("无法打开视频文件")
    exit()

while True:
    ret, frame = video_capture.read()
    if not ret:
        break
    noise_frame = add_peppersalt_noise(frame, n=10000)
    medianB_frame = cv2.medianBlur(noise_frame, 3)
    cv2.imshow('yuan Video', frame)
    cv2.imshow('Noise Video', noise_frame)
    cv2.imshow('medianB Video', medianB_frame)
    if cv2.waitKey(100) == 27:
        break
video_capture.release()
cv2.destroyAllWindows()

代码解读

整体逻辑流程

  1. 定义函数:给单张图片添加椒盐黑白噪点

  2. 打开视频文件,循环读取每一帧画面

  3. 给每一帧视频画面添加噪点

  4. 使用中值滤波去除椒盐噪点

  5. 同时显示「原图、带噪视频、去噪后视频」三个窗口,对比效果

  6. 按下ESC键结束程序

第一部分:椒盐噪声生成函数

python 复制代码
import cv2
import numpy as np
# 定义椒盐噪声生成函数
def add_peppersalt_noise(image, n=10000):
    # 复制原图,绝对不修改原始图片
    result = image.copy()
    # 获取图片高度、宽度(只取前两个维度,排除RGB通道)
    h, w = image.shape[:2]
    # 循环n次,生成n个随机噪点
    for i in range(n):
        # 随机生成纵向坐标x(0 ~ 图片高度之间)
        x = np.random.randint(0, h)
        # 随机生成横向坐标y(0 ~ 图片宽度之间)
        y = np.random.randint(0, w)
        # 50%概率生成黑点,50%概率生成白点
        if np.random.randint(0, 2) == 0:
            result[x, y] = 0      # 0 = 纯黑色(胡椒噪点)
        else:
            result[x, y] = 255     # 255 = 纯白色(盐粒噪点)
    return result

第二部分:视频读取 + 逐帧处理逻辑

python 复制代码
# 打开视频文件test.avi
video_capture = cv2.VideoCapture('test.avi')
# 判断视频是否成功打开
if not video_capture.isOpened():
    print("无法打开视频文件")
    exit()
# 无限循环读取视频每一帧
while True:
    # 读取一帧画面:ret=是否读取成功,frame=当前帧图片
    ret, frame = video_capture.read()
    # 视频播放完毕,跳出循环结束
    if not ret:
        break
    
    # 1. 给当前帧添加椒盐噪点
    noise_frame = add_peppersalt_noise(frame, n=10000)
    # 2. 中值滤波去除椒盐噪点(3×3卷积核,去噪最优方案)
    medianB_frame = cv2.medianBlur(noise_frame, 3)
    
    # 三个窗口同步显示,实时对比效果
    cv2.imshow('yuan Video', frame)        # 原始干净视频
    cv2.imshow('Noise Video', noise_frame) # 布满黑白噪点的视频
    cv2.imshow('medianB Video', medianB_frame) # 中值滤波去噪后的视频
    
    # 按下ESC键(按键码27)退出循环
    if cv2.waitKey(100) == 27:
        break

# 释放视频资源,关闭所有窗口
video_capture.release()
cv2.destroyAllWindows()

cv2.VideoCapture('test.avi'):打开视频,视频本质就是连续播放的图片帧

while True 循环:一帧一帧读取视频画面,逐帧处理

关键执行顺序:原图帧 → 添加椒盐噪点 → 中值滤波去噪,处理顺序不能颠倒

中值滤波去除椒盐噪点的效果最好,必须先生成噪点,再去噪

卷积核尺寸必须是奇数(3、5、7......),偶数会直接报错

waitKey(100):控制视频播放速度,数值越大播放越慢

视频读取完毕后会自动结束循环,不会卡死程序

运行展示

相关推荐
lqqjuly11 小时前
状态空间模型:从经典控制论到现代序列建模——S4、Mamba 及其理论体系的完整论述(三)
人工智能
财经资讯数据_灵砚智能11 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(日间)2026年5月28日
大数据·人工智能·python·信息可视化·自然语言处理·ai编程·灵砚智能
weixin_4684668511 小时前
基于OpenCV的工业相机标定技术实战
图像处理·人工智能·opencv·计算机视觉·相机标定·机器视觉·工业相机
徐安安ye11 小时前
FlashAttention输出全是NaN?数值问题排查指南
人工智能·深度学习·机器学习
架构源启11 小时前
Spring AI 进阶篇(12)-边缘计算与离线部署:模型量化、本地推理与隐私保护实战
人工智能·spring·边缘计算
Ricky055311 小时前
YOLO-FCE:一种基于特征与聚类增强的物种分类目标检测模型(澳大利亚2026年研究)
图像处理·人工智能·yolo·目标检测·分类
学习中.........11 小时前
大语言模型的推理机制与工程应用
人工智能·语言模型·自然语言处理
一切皆是因缘际会11 小时前
从模型竞赛到全域智能的时代跃迁
人工智能·深度学习·ai·分布式系统
2601_9578885611 小时前
流量终局与信源争夺:GEO(生成式引擎优化)时代的爬虫分析与数据管道构建
人工智能·爬虫