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

计算机视觉Open-CV

一·边界填充

通过在图像边缘添加按特定规则生成的像素,解决边缘处理问题,适配算法需求与场景要求

结合代码来看,这个核心体现为:

  1. cv2.copyMakeBorder()实现填充,通过top/bottom/left/right控制填充范围;
  2. borderType定义填充规则(如常数、反射、复制等),直接对应 “特定规则” 的核心设计;
  3. 最终生成不同填充效果的图像,满足不同场景下对边缘扩展的需求(如算法计算、显示美化等)。
import cv2
ys = cv2.imread('yueshan.png')
# ys=cv2.resize(ys,dsize=None,fx=0.5,fy=0.5)  #  图片缩放
# ys=cv2.resize(ys,(640,480))
top,bottom,left,right = 50,50,50,50constant = cv2.copyMakeBorder(ys,top,bottom,left,right,borderType=cv2.BORDER_CONSTANT,value=(229,25,80))
reflect = cv2.copyMakeBorder(ys,top,bottom,left,right,borderType=cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(ys,top,bottom,left,right,borderType=cv2.BORDER_REFLECT101)
replicate = cv2.copyMakeBorder(ys,top,bottom,left,right,borderType=cv2.BORDER_REPLICATE)
wrap = cv2.copyMakeBorder(ys,top,bottom,left,right,borderType=cv2.BORDER_WRAP)cv2.imshow('yuantu', ys)
cv2.waitKey(0)
cv2.imshow('CONSTANT', constant)
cv2.waitKey(0)
cv2.imshow('REFLECT', reflect)
cv2.waitKey(0)
cv2.imshow('REFLECT_101', reflect101)
cv2.waitKey(0)
cv2.imshow('REPLICATE', replicate)
cv2.waitKey(0)
cv2.imshow('WRAP', wrap)
cv2.waitKey(0)

一、什么是边界填充?

边界填充是图像处理中常见的操作,指在原始图像的四周(上、下、左、右)添加额外的像素区域(边框)。它的用途包括:

  • 为卷积操作、特征提取等算法提供边界处理(避免边缘信息丢失);
  • 调整图像尺寸以满足特定需求;
  • 美化图像显示(如添加边框装饰)。

二、cv2.copyMakeBorder()函数详解

这个函数是 OpenCV 专门用于添加边界的工具,代码中已经给出了参数说明,这里结合实例进一步解释:

1. 核心参数
  • src:原始图像(如代码中的ys,即读取的 “yueshan.png”);
  • top, bottom, left, right:上、下、左、右四个方向添加的边框宽度(代码中均设为 50,即各加 50 像素的边框);
  • borderType:边界填充类型(决定边框像素如何生成);
  • value:仅当borderType=cv2.BORDER_CONSTANT时需要,指定边框的常数颜色(代码中是(229,25,80),对应 RGB 颜色的红色系)。
2. 五种边界填充类型及效果

代码中演示了 5 种常用类型,用通俗的方式理解:

  • cv2.BORDER_CONSTANT:边框是固定颜色(由value指定)。例如给图像加一个红色边框。
  • cv2.BORDER_REFLECT:边框是原始边缘的 “镜面反射”,且包含边缘像素本身。
    举例:原始边缘是abcdefgh,则边框为gfedcba|abcdefgh|hgfedcba(左右对称,包含边缘的第一个和最后一个像素)。
  • cv2.BORDER_REFLECT_101(或BORDER_DEFAULT:与REFLECT类似,但边框不包含原始边缘的最后一个像素。
    举例:原始边缘abcdefgh,边框为gfedcb|abcdefgh|gfedcb(左右对称,去掉了边缘的最后一个像素)。
  • cv2.BORDER_REPLICATE:边框像素完全复制原始图像的最边缘像素。
    举例:原始边缘abcdefgh,边框为aaaaaa|abcdefgh|hhhhhhh(左边全是第一个像素a,右边全是最后一个像素h)。
  • cv2.BORDER_WRAP:边框是原始图像的 “循环延续”,类似将图像首尾相接。
    举例:原始边缘abcdefgh,边框为cdefgh|abcdefgh|abcdefg(左边用图像后半部分填充,右边用图像前半部分填充)。

二·图像运算

效果

代码


import cv2# 读取图片
# 将 tim.jpg 替换你实际的图片名,若扩展名是 JPG 就写 tim.JPG,保持和实际文件一致
img_a = cv2.imread('tim.jpg')
# 将 yuant.png 替换你实际的图片名,保持和实际文件一致
img_b = cv2.imread('yuant.png')# 统一图片大小,这里以 img_a 的尺寸为准,也可以自己指定固定尺寸(比如 (640, 480) )
target_height, target_width = img_a.shape[:2]
# 把 img_b 调整成和 img_a 一样的宽高
img_b = cv2.resize(img_b, (target_width, target_height))# 1. 图像加法运算(Python 里直接 + 号,按 OpenCV 像素相加规则:超过 255 会取模,即 (a + b) % 256 )
add_result = img_a + img_b
cv2.imshow('Add Result (+)', add_result)
cv2.waitKey(0)# 2. 使用 cv2.add 函数加法(像素和超过 255 会截断为 255 )
add_cv_result = cv2.add(img_a, img_b)
cv2.imshow('Add Result (cv2.add)', add_cv_result)
cv2.waitKey(0)# 3. 图像加权运算(这里给了示例权重,你可以自己调整 alpha、beta、gamma 的值玩效果)
alpha = 0.5  # img_a 的权重
beta = 0.5   # img_b 的权重
gamma = 0    # 亮度调节值
weighted_result = cv2.addWeighted(img_a, alpha, img_b, beta, gamma)
cv2.imshow('Weighted Add Result', weighted_result)
cv2.waitKey(0)# 关闭所有窗口
cv2.destroyAllWindows()

这段代码主要演示了 OpenCV 中图像加法运算的三种实现方式,核心是展示不同的图像融合效果。具体解析如下:

1. 核心功能

通过三种不同的方法将两张图像进行融合,对比不同运算规则下的视觉效果差异。

2. 代码步骤解析

(1)准备工作

python

运行

# 读取两张图片
img_a = cv2.imread('tim.jpg')
img_b = cv2.imread('yuant.png')# 统一图片尺寸(必须步骤,否则无法进行像素级运算)
target_height, target_width = img_a.shape[:2]  # 获取img_a的高和宽
img_b = cv2.resize(img_b, (target_width, target_height))  # 调整img_b尺寸与img_a一致

  • 图像运算要求两张图尺寸完全相同,因此先将img_b调整为img_a的尺寸。
(2)三种加法运算对比
① 直接用+号运算

python

运行

add_result = img_a + img_b

  • 规则:像素值相加后若超过 255(像素最大值),结果取模((a + b) % 256)。
  • 例:像素值 (200 + 100) = 300 → 300 % 256 = 44,结果会偏暗或出现异常色。
② cv2.add()函数运算

python

运行

add_cv_result = cv2.add(img_a, img_b)

  • 规则:像素值相加后若超过 255,直接截断为 255(保持白色 / 高光)。
  • 例:(200 + 100) = 300 → 255,结果更亮,适合保留高光区域。
③ 加权加法cv2.addWeighted()

python

运行

weighted_result = cv2.addWeighted(img_a, alpha, img_b, beta, gamma)

  • 规则:按权重融合两张图,公式为result = img_a×alpha + img_b×beta + gamma
  • 参数意义:
    • alpha/beta:两张图的权重(通常alpha + beta = 1,如各 0.5 表示均等融合);
    • gamma:额外亮度调节值(可正负,如 + 10 增加亮度)。
  • 效果:平滑过渡的融合效果,常用于图像叠加(如加水印、合成场景)。

3. 运行效果

代码会依次弹出 3 个窗口,分别显示三种加法的结果,按任意键切换,最后关闭所有窗口。通过对比可以直观看到:

  • +号运算可能产生色彩失真;
  • cv2.add()容易出现过亮区域;
  • cv2.addWeighted()融合最自然,是实际应用中最常用的图像叠加方法。

三·阈值处理

效果


代码


import cv2image = cv2.imread('yuant.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. 导入库

    python

    运行

    import cv2
    

    导入 OpenCV 库,用于图像处理。

  2. 读取图像

    python

    运行

    image = cv2.imread('yuant.png', 0)  # 灰度图
    

    读取名为 'yuant.png' 的图像,并以灰度模式 (参数 0) 加载。灰度图每个像素只有一个通道,值在 0-255 之间 (0 为黑色,255 为白色)。

  3. 阈值化处理
    代码使用了 5 种不同的阈值化方法,都以 175 作为阈值,255 作为最大值:

    • cv2.THRESH_BINARY:二值化处理,像素值大于 175 的变为 255 (白色),小于等于 175 的变为 0 (黑色)
    • cv2.THRESH_BINARY_INV:反二值化处理,像素值大于 175 的变为 0 (黑色),小于等于 175 的变为 255 (白色)
    • cv2.THRESH_TRUNC:截断处理,像素值大于 175 的设为 175,小于等于 175 的保持不变
    • cv2.THRESH_TOZERO:像素值大于 175 的保持不变,小于等于 175 的变为 0 (黑色)
    • cv2.THRESH_TOZERO_INV:像素值大于 175 的变为 0 (黑色),小于等于 175 的保持不变
  4. 显示图像

    • cv2.imshow()用于创建显示窗口并显示图像
    • cv2.waitKey(0)用于暂停程序,等待用户按下任意键后再继续执行,这样可以看清每张图像
  5. 代码依次显示原始灰度图和 5 种阈值化处理后的图像:

运行这段代码时,会依次弹出 6 个窗口,分别显示原始灰度图和 5 种不同阈值化处理的结果,每次按任意键会关闭当前窗口并显示下一张图像。

这种阈值化处理在图像分割、目标检测、图像预处理等场景中非常常用,可以帮助突出感兴趣的区域或简化图像信息。

四·平滑处理

效果


import cv2
import numpy as npdef add_peppersalt_noise(image, n=10000):result = image.copy()h, w = image.shape[:2]for i in range(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] = 0else:result[x, y] = 255return result# 读取图像并显示原始图像
image = cv2.imread('yuant.png')
cv2.imshow('yutu', image)  # 修正:使用位置参数,不使用关键字参数
cv2.waitKey(0)# 添加椒盐噪声并显示
noise = add_peppersalt_noise(image)
cv2.imshow('noise', noise)  # 修正:使用位置参数
cv2.waitKey(0)# 应用均值模糊
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)# 应用方框滤波
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)GaussianB = cv2.GaussianBlur(noise,(3, 3), 1)
cv2.imshow('GaussianBlur', GaussianB)
cv2.waitKey(0)medianB = cv2.medianBlur(noise,3)
cv2.imshow('medianBlur', medianB)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 关闭所有窗口
cv2.destroyAllWindows()

代码整体说明

  1. 导入库

    • cv2:OpenCV 库,用于图像处理
    • numpy:用于生成随机数,辅助添加噪声
  2. 自定义函数:添加椒盐噪声

    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(low=1, high=h)y = np.random.randint(low=1, high=w)# 50%概率生成黑色噪声(椒噪声),50%生成白色噪声(盐噪声)if np.random.randint(low=0, high=2) == 0:result[x, y] = 0  # 黑色噪声else:result[x, y] = 255  # 白色噪声return result
    

    椒盐噪声是一种常见的图像噪声,表现为图像中随机出现的黑白点,就像撒了盐和胡椒一样。

  3. 主程序流程

    • 读取原始图像并显示
    • 给图像添加椒盐噪声并显示
    • 分别用四种平滑方法处理含噪声图像并显示结果

四种平滑处理方法详解

  1. 均值模糊 (cv2.blur)

    python

    运行

    blur_1 = cv2.blur(noise, (3,3))  # 3x3卷积核
    blur_2 = cv2.blur(noise, (63,63))  # 63x63卷积核
    
    • 原理:使用一个滑动窗口(卷积核),将窗口内所有像素的平均值作为中心像素的值
    • 特点
      • 卷积核越大,模糊效果越强
      • 简单高效,但会使图像边缘变得模糊
      • 对椒盐噪声的抑制效果一般
  2. 方框滤波 (cv2.boxFilter)

    python

    运行

    # 归一化方框滤波(效果等同于均值模糊)
    boxFilter_1 = cv2.boxFilter(noise,-1, (3,3), normalize = True)
    # 非归一化方框滤波
    boxFilter_2 = cv2.boxFilter(noise,-1, (3,3), normalize = False)
    
    • 原理
      • normalize=True时,与均值模糊完全相同,计算窗口内像素平均值
      • normalize=False时,直接计算窗口内像素值之和(可能超过 255 导致像素值溢出,图像会偏白)
    • 特点:比均值模糊更灵活,可以选择是否归一化
  3. 高斯模糊 (cv2.GaussianBlur)

    python

    运行

    GaussianB = cv2.GaussianBlur(noise,(3, 3), 1)
    
    • 原理:使用高斯函数生成的卷积核进行模糊处理,窗口中心的像素权重更高,边缘像素权重更低
    • 参数(3,3)是卷积核大小,1是高斯函数的标准差
    • 特点
      • 模糊效果更自然,对图像细节保留更好
      • 对高斯噪声抑制效果好,但对椒盐噪声效果一般
      • 边缘模糊程度比均值模糊轻
  4. 中值模糊 (cv2.medianBlur)

    python

    运行

    medianB = cv2.medianBlur(noise,3)
    

    • 原理:用窗口内所有像素值的中值替换中心像素的值,而不是平均值
    • 特点
      • 非常适合去除椒盐噪声(因为噪声是极端值,中值计算会忽略它们)
      • 能较好地保留图像边缘信息
      • 处理速度相对较慢

效果对比总结

  • 从去除椒盐噪声的效果来看:中值模糊 > 高斯模糊 > 均值模糊 / 方框滤波
  • 从保留图像细节来看:中值模糊 > 高斯模糊 > 均值模糊 / 方框滤波
  • 从计算速度来看:均值模糊 / 方框滤波 > 高斯模糊 > 中值模糊

最后视频的平滑处理应该是怎么样的呢

五·视频的平滑处理

# 导入视频处理所需库
import cv2  # OpenCV库,用于视频读写和图像处理
import numpy as np  # 用于数值运算
import random  # 用于生成随机噪声# 打开视频文件(替换为实际视频路径)
cap = cv2.VideoCapture('test.avi')# 检查视频文件是否成功打开
if not cap.isOpened():print("无法打开视频文件")exit()# 获取视频基本属性
fps = cap.get(cv2.CAP_PROP_FPS)  # 视频帧率(每秒帧数)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # 视频帧宽度
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 视频帧高度# 创建视频写入器,用于保存处理后的视频
# 编码格式为XVID,输出文件为noise.avi和smooth.avi,保持原视频帧率和尺寸
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out_noise = cv2.VideoWriter('noise.avi', fourcc, fps, (width, height))
out_smooth = cv2.VideoWriter('smooth.avi', fourcc, fps, (width, height))# 设置窗口缩放比例(缩小视频显示尺寸)
scale = 0.5
new_width = int(width * scale)  # 缩放后的宽度
new_height = int(height * scale)  # 缩放后的高度# 循环读取视频帧并处理
while True:ret, frame = cap.read()  # 读取一帧视频(ret为读取成功标志,frame为帧数据)if not ret:  # 若读取失败(如到达视频末尾),退出循环break# 调整原视频帧尺寸并显示resized_original = cv2.resize(frame, (new_width, new_height))  # 缩放帧cv2.imshow('Original Video', resized_original)  # 显示原视频窗口# 为当前帧添加椒盐噪声noisy_frame = frame.copy()  # 复制原帧,避免修改原图# 生成10000个噪声点(椒盐噪声:随机黑白点)for _ in range(10000):x = random.randint(0, width - 1)  # 随机x坐标y = random.randint(0, height - 1)  # 随机y坐标if random.random() < 0.5:noisy_frame[y, x] = 0  # 黑色噪声点else:noisy_frame[y, x] = 255  # 白色噪声点# 显示含噪声的视频帧resized_noisy = cv2.resize(noisy_frame, (new_width, new_height))cv2.imshow('Noisy Video', resized_noisy)out_noise.write(noisy_frame)  # 将含噪声帧写入视频文件# 对含噪声帧进行平滑处理(中值滤波)# 中值滤波对椒盐噪声去除效果较好,参数5为滤波核大小(5x5)smooth_frame = cv2.medianBlur(noisy_frame, 5)# 显示平滑处理后的视频帧resized_smooth = cv2.resize(smooth_frame, (new_width, new_height))cv2.imshow('Smooth Video', resized_smooth)out_smooth.write(smooth_frame)  # 将平滑后的帧写入视频文件# 按空格键(ASCII码32)退出程序if cv2.waitKey(int(1000 / fps)) & 0xFF == 32:break# 释放资源(关闭视频文件和窗口)
cap.release()  # 释放视频读取器
out_noise.release()  # 释放噪声视频写入器
out_smooth.release()  # 释放平滑视频写入器
cv2.destroyAllWindows()  # 关闭所有显示窗口

这段代码首先打开指定的视频文件,然后逐帧读取。对于每一帧,先展示原视频帧,接着生成带有椒盐噪声的帧并展示,再使用中值滤波对含噪声帧进行平滑处理并展示,同时将含噪声和处理后的帧分别写入新的视频文件。最后,按 q 键可退出程序并释放相关资源。

http://www.dtcms.com/a/330899.html

相关文章:

  • Swift 实战:用链表和哈希表写出高性能的贪吃蛇引擎(LeetCode 353)
  • 力扣-1143.最长公共子序列
  • 【LeetCode 热题 100】295. 数据流的中位数——最大堆和最小堆
  • 前端开发如何优化 SEO:常见问题及解决方案全解析​
  • JMeter性能测试详细版(适合0基础小白学习--非常详细)
  • 简单好用的桌面时钟—— Digital Clock 4
  • 飞算JavaAI开发全流程解析:从自然语言到可运行工程的智能进化
  • [Android] 二十四节气日历v1.0.3 - 弘扬传统文化,精致设计,无广告纯净体验!
  • 考研408《计算机组成原理》复习笔记,第五章(3)——CPU的【数据通路】
  • 双机热备实验
  • Linux编程1:进程和线程
  • DTW算法判断两条曲线的相似度,Python代码
  • [激光原理与应用-272]:理论 - 波动光学 - 单纯的白色其实并不单纯
  • 迅为RK3562开发板获取Android13源码
  • 3D商品展示:技术狂欢下的普及困局
  • 【新启航】起落架大型结构件深孔检测探究 - 激光频率梳 3D 轮廓检测
  • Uniapp 自定义头部导航栏
  • 表达式树实战:Unity动态逻辑编程
  • 考研408《计算机组成原理》复习笔记,第三章(6)——Cache(超级重点!!!)
  • 【科研绘图系列】R语言绘制蝶形条形图蝶形柱状堆积图
  • 考研408《计算机组成原理》复习笔记,第四章(3)——指令集、汇编语言
  • 一致性哈希Consistent Hashing
  • Rust Web框架Axum学习指南之入门初体验
  • Java面试宝典:JVM性能优化
  • 【代码随想录day 20】 力扣 669. 修剪二叉搜索树
  • MySQL 性能优化实战指南:释放数据库潜能的艺术
  • 【visual studio】visual studio配置环境opencv和onnxruntime
  • 零知开源——基于STM32F4的HC-12无线通信系统及ST7789显示应用
  • 【Linux】库制作与原理
  • mysql卸载了 服务内还显示如何解决