当前位置: 首页 > 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.lryc.cn/news/621176.html

相关文章:

  • 数据结构之顺序表相关算法题
  • latex 中破折号的输入
  • 【PCB设计经验】3D模型在线预览!效率便捷!
  • 【浅学】tflite-micro + ESP32S3 + VScode + ESP-IDF 基于例程快速实现自己的图像分类模型训练部署全流程
  • Python学习-----3.基础语法(2)
  • 异步同步,阻塞非阻塞,reactor/proactor
  • spring boot配置es
  • CPP模板编程
  • Redis7学习--持久化机制 RDB与AOF
  • 汽车生产线白皮书:稳联技术Profinet转Ethernet IP网关通信高效性
  • StarRocks优化统计分析
  • Redis入门到实战教程,深度透析redis
  • 零信任架构(Zero Trust Architecture, ZTA)(通过动态验证和最小权限控制,实现对所有访问请求的严格授权和持续监控)
  • Java应用架构实战指南:主流模式解析与Spring落地实践
  • diffusers库学习--pipeline,模型,调度器的基础使用
  • Docker exec进入容器命令的入门教程
  • 使用正则表达式 \s+ 作为分隔符处理字符串
  • 【cmake】编译cpp文件,安装MinGW
  • Python 进阶详解:正则表达式与 JSON —— 文本处理与数据交换的核心技能
  • K8s-持久化存储
  • 第1节:多模态大模型入门(多模态大模型基础教程)
  • 安装 Nginx
  • Spring Boot + Redis + 布隆过滤器防止缓存穿透
  • UML函数原型中constraint的含义,有啥用?
  • 读《精益数据分析》:移情(Empathy)—— 验证真实需求,避免伪需求陷阱
  • 加密货币交易所开发:如何打造安全、高并发的数字资产交易平台?
  • 7、C 语言数组进阶知识点总结
  • 分布式事务、锁、链路追踪
  • Mybatis学习笔记(九)
  • C#WPF实战出真汁01--搭建项目三层架构