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

OpenCV图像处理2:边界填充与平滑滤波实战

前面学了一些关于opencv图像处理的内容,现在继续。

一 图像填充

        边界填充(Border Padding)​,即在图像四周添加指定宽度的像素区域。其核心函数是cv2.copyMakeBorder(),通过不同的填充方式(borderType)处理图像边缘,常用于避免卷积操作(如滤波)时边界信息丢失调整图像尺寸。有下面四种参数

  1. 黑色边框​(常数填充)BORDER_CONSTANT
  2. 镜像反射含边缘​(如照镜子) ​BORDER_REFLECT
  3. 镜像反射不含边缘​(更平滑)BORDER_REFLECT_101
  4. 拉伸边缘像素​(复制最外侧像素)BORDER_REPLICATE
  5. 循环平铺图像​(类似纹理重复)BORDER_WRAP

代码部分

1 常数填充

这里top,bottom,left,right=50,50,50,50,表示要向上下左右要填充的大小,这里填充的是黑色,RGB值为0,0,0。如果是填充其他值可以修改。

zxc=cv2.imread('img.png')
top,bottom,left,right=50,50,50,50
constant=cv2.copyMakeBorder(zxc, top, bottom, left, right,borderType=cv2.BORDER_CONSTANT,value=(0,0,0))
cv2.imshow('zxc',zxc)
cv2.imshow('constant',constant)
cv2.waitKey(0)

2 边缘折射填充

BORDER_REFLECT和BORDER_REFLECT101方法差不多,但通过图我们可以看出来,第一种边缘部分有点点突兀,而第二种就比较平滑。

import cv2zxc=cv2.imread('img.png')
top,bottom,left,right=50,50,50,50
reflact=cv2.copyMakeBorder(zxc,top,bottom,left,right,borderType=cv2.BORDER_REFLECT)
reflact101=cv2.copyMakeBorder(zxc,top,bottom,left,right,borderType=cv2.BORDER_REFLECT101)
cv2.imshow('zxc',zxc)
cv2.imshow('constant',reflact)
cv2.imshow('reflect',reflact101)
cv2.waitKey(0)

3 拉伸填充

import cv2zxc=cv2.imread('img.png')
top,bottom,left,right=50,50,50,50
replicate=cv2.copyMakeBorder(zxc,top,bottom,left,right,borderType=cv2.BORDER_REPLICATE)
cv2.imshow('zxc',zxc)
cv2.imshow('constant',replicate)
cv2.waitKey(0)

4 循环平铺填充

import cv2zxc=cv2.imread('img.png')
top,bottom,left,right=50,50,50,50
cv2.imshow('zxc',zxc)
wrap=cv2.copyMakeBorder(zxc,top,bottom,left,right,borderType=cv2.BORDER_WRAP)
cv2.imshow('reflect',wrap)
cv2.waitKey(0)

二 图像加运算

第一篇文章也说了,opencv把图片转化为了一个一个 像素值,那么就可以进行加,这里有两种方法,一个是直接加,一个是用add方法。注意这里相加,要尺寸大小一样才能相加。

1 直接加

对两张图像每个像素值直接相加(例:像素A(150) + 像素B(120) = 270 → 截断为255)

import cv2long=cv2.imread('img_3.png')
tu=cv2.imread('img_5.png')
long=cv2.resize(long,(800,600))
tu=cv2.resize(tu,(800,600))
c=long+tu
cv2.imshow('long',long)
cv2.imshow('tu',tu)
cv2.imshow('aa',c)
cv2.waitKey(0)

2 cv2.addWeighted加权相加

这种更平滑,不会有出现超过255像素值的那种情况

import cv2long=cv2.imread('img_3.png')
tu=cv2.imread('img_5.png')
long=cv2.resize(long,(800,600))
tu=cv2.resize(tu,(800,600))
d=cv2.addWeighted(long,0.5,tu,0.5,0)cv2.imshow('bb',d)
cv2.waitKey(0)

三 阈值处理

阈值处理就是对图片像素值设定一个阈值,大于这个就是就设置为其他像素或怎么的,下面看代码详解。

阈值化选项条件:像素值 > thresh条件:像素值 ≤ thresh
cv2.THRESH_BINARY设置为 maxval设置为 0
cv2.THRESH_BINARY_INV设置为 0设置为 maxval
cv2.THRESH_TRUNC截断为 thresh保持原始灰度值不变
cv2.THRESH_TOZERO保持原始灰度值不变设置为 0
cv2.THRESH_TOZERO_INV设置为 0保持原始灰度值不变

cv2.THRESH_BINARY

这里还先对图像作了灰度图处理,有利于对阈值操作。这里阈值处理后会返回两个值,一个是阈值,另一个就是处理好的图像。具体原理看上方表格

import cv2a=cv2.imread('img_2.png',0)
a=cv2.resize(a,(800,600))
_,binary=cv2.threshold(a,170,255,cv2.THRESH_BINARY)cv2.imshow('a',a)
cv2.imshow('binary',binary)
cv2.waitKey(0)

2 cv2.THRESH_BINARY_INV

这个就是上面的一个后面加了INV,其实就是上面处理好的图中,黑色变白色,白色变黑色,反转了一下。

import cv2a=cv2.imread('img_2.png',0)
a=cv2.resize(a,(800,600))
_,binaryinv=cv2.threshold(a,170,255,cv2.THRESH_BINARY_INV)cv2.imshow('a',a)
cv2.imshow('binary',binaryinv)
cv2.waitKey(0)

3 cv2.THRESH_TRUNC

这里设定的阈值为170,然后超过的就记作170,低于的就按照原像素值1

import cv2a=cv2.imread('img_2.png',0)
a=cv2.resize(a,(800,600))
_,trunc=cv2.threshold(a,170,255,cv2.THRESH_TRUNC)cv2.imshow('a',a)
cv2.imshow('binary',trunc)
cv2.waitKey(0)

4THRESH_TOZERO和THRESH_TOZERO_INV

保持原始灰度值不变设置为 0
设置为 0保持原始灰度值不变
import cv2a=cv2.imread('img_2.png',0)
a=cv2.resize(a,(800,600))
_,tozero=cv2.threshold(a,170,255,cv2.THRESH_TOZERO)
_,tozeroinv=cv2.threshold(a,170,255,cv2.THRESH_TOZERO_INV)
cv2.imshow('a',a)
cv2.imshow('binary',tozero)
cv2.imshow('binaryinv',tozeroinv)
cv2.waitKey(0)

五 图像平滑处理

这里有四种常用图像滤波方法可以进行图像平滑处理

下面我先对图片加上椒盐噪声。

1. ​均值滤波 (Mean Filtering)​

原理​:
对图像中每个像素点,取其邻域内(如3×3、5×5)所有像素的算术平均值作为该点的新值。

import random
import cv2def zs(src,n):c=src.copy()print(c.shape)for i in range(n):x=random.randint(1,c.shape[0]-1)y=random.randint(1,c.shape[1]-1)if random.randint(0,1) == 0:c[x,y]=255else:c[x,y]=0return ctu=cv2.imread('img_5.png')
ntu=zs(tu,10000)
jz=cv2.blur(ntu,(3,3))
cv2.imshow('tu',tu)
cv2.imshow('ntu',ntu)
cv2.imshow('jz',jz)
cv2.waitKey(0)

我们先定义了一个函数,对图像添加了椒盐噪声,然后进行了均值滤波处理

这里处理结果显然不是很好.

2 高斯滤波 (Gaussian Filtering)​

原理​:
对邻域内像素进行加权平均,权重由二维高斯函数生成,距离中心点越近权重越大

import random
import cv2def zs(src,n):c=src.copy()print(c.shape)for i in range(n):x=random.randint(1,c.shape[0]-1)y=random.randint(1,c.shape[1]-1)if random.randint(0,1) == 0:c[x,y]=255else:c[x,y]=0return ctu=cv2.imread('img_5.png')
ntu=zs(tu,10000)
jz=cv2.blur(ntu,(3,3))
gs=cv2.GaussianBlur(ntu,(3,3),0)
cv2.imshow('tu',tu)
cv2.imshow('ntu',ntu)
cv2.imshow('gs',gs)
cv2.waitKey(0)

3 方框滤波

  1. 核心计算逻辑

    • 对图像中每个像素的 3×3 邻域内所有像素值直接求和,​不进行归一化​(即不除以像素数量 9)。
    • 数学表达:output(x,y)=i=−1∑1​j=−1∑1​input(x+i,y+j)
  2. 与归一化方框滤波的区别

    • 归一化模式​(normalize=True):
      等价于均值滤波(cv2.blur()),输出邻域像素平均值,结果平滑但保留亮度范围。
    • 非归一化模式​(normalize=False):
      输出为邻域像素值之和,结果常因数值溢出呈现 ​全白或高亮区域​。
import random
import cv2def zs(src,n):c=src.copy()print(c.shape)for i in range(n):x=random.randint(1,c.shape[0]-1)y=random.randint(1,c.shape[1]-1)if random.randint(0,1) == 0:c[x,y]=255else:c[x,y]=0return ctu=cv2.imread('img_5.png')
ntu=zs(tu,10000)
jz=cv2.blur(ntu,(3,3))
fk1=cv2.boxFilter(ntu,-1,ksize=(3,3),normalize=True)
fk2=cv2.boxFilter(ntu,-1,ksize=(3,3),normalize=False)cv2.imshow('tu',tu)
cv2.imshow('ntu',ntu)
cv2.imshow('fk1',fk1)
cv2.imshow('fk2',fk2)
cv2.waitKey(0)

下面的第一张图我没有加归一化,这样的话就好第一种方法均值滤波差不多了。但加完之后图片就太模糊了。

中值滤波 (Median Filtering)​

原理​:
取邻域内所有像素值的中位数替代中心像素值。
计算步骤​:

  1. 提取邻域像素值
  2. 排序后取中间位置的值

适用场景​:

  • 高效去除椒盐噪声​(黑白点状噪声)
  • 需保留锐利边缘的场景
    特点​:
  • ✅ 完全消除孤立噪声点
  • ✅ 边缘保护能力极强
  • ❌ 计算开销较大(需排序)
import random
import cv2def zs(src,n):c=src.copy()print(c.shape)for i in range(n):x=random.randint(1,c.shape[0]-1)y=random.randint(1,c.shape[1]-1)if random.randint(0,1) == 0:c[x,y]=255else:c[x,y]=0return ctu=cv2.imread('img_5.png')
ntu=zs(tu,10000)
jz=cv2.blur(ntu,(3,3))
zz=cv2.medianBlur(ntu,5)
cv2.imshow('tu',tu)
cv2.imshow('ntu',ntu)
cv2.imshow('zz',zz)
cv2.waitKey(0)

从结果上看,这种方法对处理椒盐噪声是特别好的。

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

相关文章:

  • VSC遇到的问题:无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本。
  • QT+Yolov8 推理部署,ONNX模型 ,实例分割+目标检测
  • 计算机视觉CS231n学习(9)
  • VLMs开发——基于Qwen2.5-VL 实现视觉语言模型在目标检测中的层级结构与实现方法
  • 【CV 目标检测】R-CNN①——Overfeat
  • PyCharm性能优化与大型项目管理指南
  • Linux 路由表建立过程分析
  • 开疆智能Ethernet转ModbusTCP网关连接UR机器人配置案例
  • LeetCode 面试经典 150_数组/字符串_最后一个单词的长度(19_58_C++_简单)(反向遍历)
  • 百川开源大模型Baichuan-M2的医疗能力登顶第一?
  • 【机器人-开发工具】ROS 2 (4)Jetson Nano 系统Ubuntu22.04安装ROS 2 Humble版本
  • OpenBMC中C++策略模式架构、原理与应用
  • AI数据仓库的核心优势解析
  • 设计模式基础概念(行为模式):策略模式
  • 【java实现一个接口多个实现类通用策略模式】
  • [Oracle数据库] ORACLE基本DML操作
  • 【软件测试】自动化测试 — selenium快速上手
  • Java设计模式之《策略模式》
  • STM32L051C8与STM32L151C8的主要区别
  • visual studio调试cmake项目记录
  • 用飞算JavaAI一键生成电商平台项目:从需求到落地的高效实践
  • 远程影音访问:通过 cpolar 内网穿透服务使用 LibreTV
  • Mybatis学习笔记(九)
  • Spring Boot + Redis + 布隆过滤器防止缓存穿透
  • [已解决]当启动 Spring Boot 应用时出现 Using generated security password xxx提示
  • OpenCV 视频处理全解析
  • EI学术会议 | 可再生能源、智能电网、电力系统优化、能源存储技术
  • Linux系统Namespace隔离实战:dd/mkfs/mount/unshare命令组合应用
  • 缓存元数据损坏操作步骤(lvmcache修复)
  • 微软推出AI恶意软件检测智能体 Project Ire