OpenCV实现图像噪声、去噪基本方法

一、噪声分类

1、高斯噪声

指服从高斯分布(正态分布)的一类噪声,其产生的主要原因是由于相机在拍摄时视场较暗且亮度不均匀造成的,同时相机长时间工作使得温度过高也会引起高斯噪声,另外电路元器件白身噪声和互相影响也是造成高斯噪声的重要原因之一。

概率密度函数(PDF)如下:

初始图片:

注意加噪声时,不能直接将 noise+img,不然最终出来的是一片空白和零星几个噪点,原因在于cv2.imshow输入要求是 0-1 float 或者 0-255 int。

代码:

import cv2
import random
import numpy as np
img = cv2.imread('A.png')

# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255   

cv2.imshow('Gauss noise',img)
cv2.waitKey(0)

3)高斯滤波

高斯滤波是一种线性平滑滤波,一般用于消除高斯噪声。对于每一个像素点的值,是由其本身和邻域内的其他像素值经过加权平均后得到。

二维高斯函数:

具体过程:

代码:使用cv2.GaussianBlur()函数

注意高斯模糊半径不能为偶数

滤波结果:

2、泊松噪声

简言之就是符合泊松分布的噪声模型,又称散粒噪声。

使用**np.random.poisson()**函数

import cv2
import random
import numpy as np
img = cv2.imread('A.png')

# 产生泊松噪声
noise = np.random.poisson(lam=20,size=img.shape).astype('uint8')

# 加上噪声
img = img + noise
np.clip(img,0,255)
img = img/255

cv2.imshow('Poisson noise',img)
cv2.waitKey(0)

λ值越大,噪声程度越深。

3、椒盐噪声

椒盐噪声又称为脉冲噪声,是在图像上随机出现黑色白色的像素,顾名思义就是椒盐噪声 = 椒噪声(值为0,黑色) + 盐噪声(值为255,白色)

直接上代码:

import cv2
import random
import numpy as np
img = cv2.imread('A.png')

# 转化成向量
x = img.reshape(1,-1)  
# 设置信噪比
SNR = 0.85
# 得到要加噪的像素数目
noise_num = x.size * (1-SNR)
# 得到需要加噪的像素值的位置
list = random.sample(range(0,x.size),int(noise_num))

for i in list:
    if random.random() >= 0.5:
        x[0][i] = 0
    else:
        x[0][i] = 255
img1 = x.reshape(img.shape)

cv2.imshow('salt&pepper noise',img1)
cv2.waitKey(0)

SNR越小,噪声越大。

4、瑞利噪声

一般是由由信道不理想引起的,它与信号的关系是相乘,信号在它在,信号不在他也就不在。

瑞利密度对倾斜形状直方图的建模非常有用。

在生成瑞利噪声的时候,其实采用的是**np.random.rayleigh()** 方法生成,而这个方法就是根据第二个公式来的,所以只需要指定1个参数,得到的分布和第一个公式相比本质是相同的。

代码:

import cv2
import random
import numpy as np
img = cv2.imread('A.png')

# 产生瑞利噪声
sigma = 70.0
noise = np.random.rayleigh(sigma, size=img.shape)
# 可以试试下面这个效果
# noise = np.random.rayleigh(img, size=img.shape)

# 加上噪声
img = img + noise
np.clip(img,0,255)
img = img/255

cv2.imshow('Rayleigh noise',img)
cv2.waitKey(0)
print(img.shape)

5、爱尔兰(伽马)噪声

概率密度函数(PDF)如下:(b是一个正整数)

指数分布和卡方分布其实可以看成是伽马分布的特殊形式。

b = 1时:指数分布;

b =n/2,a = 1/2时:卡方分布。

代码:

noise = np.random.gamma(shape=10.0,scale=10.0,size=img.shape)
#其他部分同上

6、均匀噪声

noise = np.random.uniform(50,100,img.shape)
#其他部分同上

二、去噪方法

1、均值滤波

1.1 算术平均滤波

import cv2
import random
import numpy as np
img = cv2.imread('A.png')

# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255   

# 算术平均滤波
img1 = np.transpose(img,(2,0,1))  #转换成[channel,H,W]形式
m = 3   #定义滤波核大小
n = 3
rec_img = np.zeros((img1.shape[0],img1.shape[1]-m+1,img1.shape[2]-n+1))
for channel in range(rec_img.shape[0]):
    for i in range(rec_img[channel].shape[0]):
        for j in range(rec_img[channel].shape[1]):
            rec_img[channel][i,j] = img1[channel][i:i+m,j:j+n].sum()/(m*n)
rec_img = np.transpose(rec_img,(1,2,0))

cv2.imshow('average',rec_img)
cv2.waitKey(0)

具体过程可以配合下图理解

去噪效果:

1.2 几何均值滤波

import cv2
import random
import numpy as np
img = cv2.imread('A.png')

# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255   

# 几何均值滤波
img1 = np.transpose(img,(2,0,1))  #转换成[channel,H,W]形式
m = 3   #定义滤波核大小
n = 3
rec_img = np.zeros((img1.shape[0],img1.shape[1]-m+1,img1.shape[2]-n+1))
for channel in range(rec_img.shape[0]):
    for i in range(rec_img[channel].shape[0]):
        for j in range(rec_img[channel].shape[1]):
            rec_img[channel][i,j] = np.power(np.prod(img1[channel][i:i+m,j:j+n]),1/(m*n))
rec_img = np.transpose(rec_img,(1,2,0))

cv2.imshow('average',rec_img)
cv2.waitKey(0)

去噪效果:

几何均值滤波对0值是非常敏感,缺陷也很明显,那就是当窗口内像素只要有一个值为0,则其计算得到的值就是0。

1.3 谐波平均滤波

rec_img[channel][i,j] = 1/(np.power(img1[channel][i:i+m,j:j+n],-1).sum())*(m*n)
# 其余部分同上

该方法既能处理盐粒噪声,又能处理类似于于高斯噪声的其他噪声,但是不能处理胡椒噪声

2、统计排序滤波

2.1 中值滤波

我们非常熟悉的一种去噪方法,它是用像素邻域中的灰度中值来代替像素的值。

代码:

import cv2
import random
import numpy as np
img = cv2.imread('A.png')

# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255   

# 中值滤波
img1 = np.transpose(img,(2,0,1))  #转换成[channel,H,W]形式
m = 3   #定义滤波核大小
n = 3
rec_img = np.zeros((img1.shape[0],img1.shape[1]-m+1,img1.shape[2]-n+1))
for channel in range(rec_img.shape[0]):
    for i in range(rec_img[channel].shape[0]):
        for j in range(rec_img[channel].shape[1]):
            rec_img[channel][i,j] = np.median(img1[channel][i:i+m,j:j+n])
rec_img = np.transpose(rec_img,(1,2,0))

cv2.imshow('median',rec_img)
cv2.waitKey(0)

去噪效果:

或者直接使用cv2.medianBlur()函数

import cv2
import random
import numpy as np
img = cv2.imread('A.png')

# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = np.uint8(img)

# 中值滤波
rec_img = cv2.medianBlur(img,3)

cv2.imshow('median',rec_img)
cv2.waitKey(0)

2.2 最大值和最小值滤波

代码:

rec_img[channel][i,j] = (np.amax(img1[channel][i:i+m,j:j+n]) + np.amin(img1[channel][i:i+m,j:j+n]))/2

对高斯噪声处理的滤波效果:

2.4 修正阿尔法均值滤波

处理方法:在邻域 S x y S_{xy} Sxy​ 内删除 d / 2 d/2 d/2个最低灰度值和 d / 2 d/2 d/2个最高灰度值。 g R ( r , c ) g_{R}(r,c) gR​(r,c)表示 S x y S_{xy} Sxy​ 中剩下的 m n − d mn-d mn−d个像素。

d = 0 d=0 d=0: 变成算术平均滤波

d = m n − 1 d=mn-1 d=mn−1:中值滤波

代码:

import cv2
import random
import numpy as np
img = cv2.imread('A.png')

# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255   

# 修正阿尔法均值滤波
img1 = np.transpose(img,(2,0,1))  #转换成[channel,H,W]形式
m = 3  #定义滤波核大小
n = 3
d = 4    #d取偶数
rec_img = np.zeros((img1.shape[0],img1.shape[1]-m+1,img1.shape[2]-n+1))
for channel in range(rec_img.shape[0]):
    for i in range(rec_img[channel].shape[0]):
        for j in range(rec_img[channel].shape[1]):
            img2 = np.sort(np.ravel(img1[channel][i:i+m,j:j+n]))  #np.ravel():多维数组变成一维数组
            rec_img[channel][i,j] = (img2[int(d/2):-int(d/2)].sum())*(1/(m*n-d))
rec_img = np.transpose(rec_img,(1,2,0))

cv2.imshow('alpha average',rec_img)
cv2.waitKey(0)

去噪效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/183070.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

土地利用数据技术服务

一、背景介绍 土地是人类赖以生存与发展的重要资源和物质保障,在“人口-资源-环境-发展(PRED)”复合系统 中,土地资源处于基础地位。随着现代社会人口的不断增长以及工业化、城市化进程的加速&a…

nvm切换版本之后npm用不了

原因是 nvm只给你安了对应的node没给你安装对应的node版本的npm 解决办法如下 1找到你安装的node版本号 然后去官网下载对应的版本包 这个网址就是node官网的版本列表 Index of /download/release/ 2下载后解压 把根目录这俩复制到自己的nvm安装目录下 还有那个node_modul…

Vue学习之路------指令

Vue指令 vue会根据不同的指令&#xff0c;针对标签实现不同的功能 指令:带有v-前缀的特殊标签属性 1&#xff1a;v-html&#xff1a;指令 <div v-html"msg"></div> 2&#xff1a;v-show 作用&#xff1a;控制元素显示隐藏 语法&#xff1a;v-show&quo…

解决:javax.websocket.server.ServerContainer not available 报错问题

原因&#xff1a; 用于扫描带有 ServerEndpoint 的注解成为 websocket&#xff0c;该方法是 服务器端点出口&#xff0c;当进行 SpringBoot 单元测试时&#xff0c;并没有启动服务器&#xff0c;所以当加载到这个bean时会报错。 解决方法&#xff1a; 加上这个注解内容 Spr…

顺序表基本操作全面解析

文章目录 1.线性表2.顺序表分类2.1 静态顺序表2.2 动态顺序表 3. 顺序表各接口实现1. 定义结构体(Seqlist)2. 结构体初始化(SLInit)3.检查容量 (SLCheckCapacity)4.打印数据 (SLPrintf)5.插入操作5.1 从数据头部插入(SLPushFront)5.2 从数据尾部插入(SLPushBack)5.3 从任意下标…

ELK企业级日志分析平台——kibana数据可视化

部署 新建虚拟机server5&#xff0c;部署kibana [rootelk5 ~]# rpm -ivh kibana-7.6.1-x86_64.rpm [rootelk5 ~]# cd /etc/kibana/[rootelk5 kibana]# vim kibana.ymlserver.host: "0.0.0.0"elasticsearch.hosts: ["http://192.168.56.11:9200"]i18n.local…

项目管理套路:看这一篇绝对够用❤️

写论文必不可少的&#xff0c;就是创建代码并进行实验。好的项目管理可以让实验进行得更加顺利。本篇博客以一次项目实践为例&#xff0c;介绍项目管理的方法&#xff0c;以及可能遇到的问题&#xff0c;并提供一些可行的解决方案。 目录 项目管理工具开始第一步版本管理十分关…

ATFX汇市:11月美联储会议纪要提振美指,但中期跌势或将延续

ATFX汇市&#xff1a;11月21日公布的11月美联储利率决议会议纪要提到&#xff1a;过去一年通胀有所缓和&#xff0c;但目前通胀仍然高得令人无法接受&#xff0c;远高于委员会 2% 的长期目标&#xff1b;在消费者支出激增的推动下&#xff0c;第三季度实际 GDP 出人意料地强劲增…

【C++干货铺】适配器 | stack | queue

个人主页点击直达&#xff1a;小白不是程序媛 C系列学习专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 stack的介绍和使用 stack的介绍 stack的使用 queue的介绍和使用 queue的介绍 queue的使用 容器适配器 什么是适配器 STL中stack和queue的底层结构 d…

Python 使用XlsxWriter操作Excel

在数据处理和报告生成的领域中&#xff0c;Excel 文件一直是广泛使用的标准格式。为了让 Python 开发者能够轻松创建和修改 Excel 文件&#xff0c;XlsxWriter 库应运而生。XlsxWriter 是一个功能强大的 Python 模块&#xff0c;专门用于生成 Microsoft Excel 2007及以上版本&a…

外部中断为什么会误触发?

今天在写外部中断的程序的时候&#xff0c;发现中断特别容易受到干扰&#xff0c;我把手放在对应的中断引脚上&#xff0c;中断就一直触发&#xff0c;没有停过。经过一天的学习&#xff0c;找到了几个解决方法&#xff0c;所以写了这篇笔记。如果你的中断也时不时会误触发&…

人工智能教程(一):基础知识

目录 前言 什么是人工智能&#xff1f; 教学环境搭建 向量和矩阵 前言 如果你是关注计算机领域最新趋势的学生或从业者&#xff0c;你应该听说过人工智能、数据科学、机器学习、深度学习等术语。作为人工智能系列文章的第一篇&#xff0c;本文将解释这些术语&#xff0c;并搭…

Spring事务的实现方式和实现原理;事务声明的方式,Spring的事务传播行为,spring事务的实现原理

Spring事务的实现方式和实现原理 Spring事务的本质其实就是数据库对事务的支持&#xff0c;没有数据库的事务支持&#xff0c;spring是无法提供事务功能的。真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。 什么是事务 数据库事务是指作为单个逻辑工作单元执…

Ubuntu安装CUDA驱动

Ubuntu安装CUDA驱动 前言官网安装确认安装版本安装CUDA Toolkit 前言 CUDA驱动一般指CUDA Toolkit&#xff0c;可通过Nvidia官网下载安装。本文介绍安装方法。 官网 CUDA Toolkit 最新版&#xff1a;CUDA Toolkit Downloads | NVIDIA Developer CUDA Toolkit 最新版文档&…

【【Linux系统下常用指令学习 之 二 】】

Linux系统下常用指令学习 之 二 文件查询和搜索 文件的查询和搜索也是最常用的操作&#xff0c;在嵌入式 Linux 开发中常常需要在 Linux 源码文件中查询某个文件是否存在&#xff0c;或者搜索哪些文件都调用了某个函数等等。 1、命令 find find 命令用于在目录结构中查找文件…

Dubbo3使用Zookeeper作为注册中心的方案讨论!详解DubboAdmin与PrettyZoo来监控服务的优劣!

文章目录 一&#xff1a;Dubbo注册中心的基本使用 二&#xff1a;Zookeeper注册中心的使用 1&#xff1a;依赖引入 2&#xff1a;实际开发 三&#xff1a;Zookeeper作为注册中心的使用展示 1&#xff1a;启动注册Zookeeper服务 2&#xff1a;引入注册中心 (一)&#xf…

Qt实现自定义IP地址输入控件(百分百还原Windows 10网络地址输入框)

在开发网络相关的程序时,我们经常需要输入IP地址,例如源地址和目标地址。Qt提供了一些基础的控件,如QLineEdit,但是它们并不能满足我们对IP地址输入的要求,例如限制输入的格式、自动跳转到下一个输入框、处理回车和退格键等。因此,我们需要自己编写一个自定义的IP地址输入…

【MySQL】内连接和外连接

内连接和外连接 前言正式开始内连接外连接左外连接右外连接 前言 前一篇讲多表查询的时候讲过笛卡尔积&#xff0c;其实笛卡尔积就算一种连接&#xff0c;不过前一篇讲的时候并没有细说连接相关的内容&#xff0c;本篇就来详细说说表的连接有哪些。 本篇博客中主要用到的还是…

设计模式之建造者(Builder)模式

目录 1、什么是建造者Builder模式&#xff1f; 2、建造者Builder模式的利与弊 3、建造者Builder模式的应用场景 4、建造者模式中的指导者&#xff08;Director&#xff09;有什么作用&#xff1f; 5、建造者Builder模式与其他模式的关系 小结 1、什么是建造者Builder模式…

【华为OD题库-037】跳房子2-java

题目 跳房子&#xff0c;也叫跳飞机&#xff0c;是一种世界性的儿童游戏游戏。参与者需要分多个回合按顺序跳到第1格直到房子的最后一格&#xff0c;然后获得一次选房子的机会&#xff0c;直到所有房子被选完&#xff0c;房子最多的人获胜。 跳房子的过程中&#xff0c;如果有踩…