【OpenCV-Python】教程:8-1 图像去噪 Image Denoising

news/2024/11/15 2:10:03/

OpenCV Python 图像去噪 Image Denoising

【目标】

  • 非局部均值去噪算法去除图像中的噪声。
  • cv2.fastNlMeansDenoising() , cv2.fastNlMeansDenoisingColored() etc.

【理论】

在前面的章节中,我们已经看到了许多图像平滑技术,如高斯模糊,中值模糊等,它们在一定程度上很好地去除少量的噪声。在这些技术中,我们在像素周围取一个小的邻域,并进行一些操作,如高斯加权平均,值的中值等来替换中心元素。简而言之,一个像素的噪声去除是局部的。

噪声有一个特性。噪声通常被认为是一个均值为零的随机变量。考虑一个有噪声的像素,p=p0+np=p_0+np=p0+n,其中p0p_0p0是像素的真实值,nnn是像素中的噪声。您可以从不同的图像中获取大量相同的像素(例如NNN)并计算它们的平均值。理想情况下,你应该得到p=p0p=p_0p=p0,因为噪声的均值为零。

您可以通过一个简单的设置自己验证它。将静态相机固定在某个位置几秒钟。这将为您提供大量的帧,或同一场景的大量图像。然后写一段代码来找到视频中所有帧的平均值(这对你来说应该太简单了)。比较最终结果和第一帧。你可以看到噪音减少了。不幸的是,这种简单的方法对相机和场景运动不健壮。通常只有一个噪点图像可用。

想法很简单,我们需要一组相似的图像来平均噪声。考虑图像中的一个小窗口(比如5x5窗口)。同样的补丁很有可能出现在图像中的其他地方。有时在它周围的一个小社区。把这些相似的补丁放在一起并找出它们的平均值怎么样?对于特定的窗口,这是可以的。请看下面的示例图片:

在这里插入图片描述

图中的蓝色斑块看起来很相似。绿色的斑块看起来很相似。所以我们取一个像素,在它周围取一个小窗口,在图像中搜索相似的窗口,平均所有的窗口,然后用我们得到的结果替换像素。这种方法是非局部均值去噪。与我们之前看到的模糊技术相比,它需要更多的时间,但它的结果非常好。更多细节和在线演示可以在附加资源的第一个链接中找到。

对于彩色图像,将图像转换为CIELAB色彩空间,然后分别去噪L分量和AB分量。

现在我们将同样的方法应用到视频中。第一个参数是噪声帧的列表。第二个参数imgToDenoiseIndex指定我们需要去噪的帧,为此我们将帧的索引传递到输入列表中。第三个是temporalWindowSize,它指定用于去噪的附近帧的数量。它应该是奇数。在这种情况下,总共使用了temporalWindowSize帧,其中中心帧是要去噪的帧。例如,您传递了一个5帧的列表作为输入。让imgToDenoiseIndex = 2和temporalWindowSize = 3。然后利用帧1、帧2和帧3对帧2进行去噪。

【代码】

在这里插入图片描述

import numpy as np 
import cv2 
from matplotlib import pyplot as plt img = cv2.imread("assets/die.png")dst = cv2.fastNlMeansDenoisingColored(img, None, 10, 10, 7, 21)cv2.imshow("src image", img)
cv2.imshow("denoised image", dst)cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

import numpy as np 
import cv2 
from matplotlib import pyplot as plt cap = cv2.VideoCapture("assets/vtest.avi")# 连续读入帧
img = [cap.read()[1] for i in range(5)]# 转换灰度
gray = [cv2.cvtColor(i, cv2.COLOR_BGR2GRAY) for i in img]
gray = [np.float64(i) for i in gray]
noise = np.random.randn(*gray[1].shape)*10# 添加噪声到图像中
noisy = [i+noise for i in gray]# 转换为 uint8
noisy = [np.uint8(np.clip(i, 0, 255)) for i in noisy]gray_back = [np.uint8(np.clip(i, 0, 255)) for i in gray]# 参考连续5帧为第3帧降噪
dst = cv2.fastNlMeansDenoisingMulti(noisy, 2, 5, None, 4, 7, 35)cv2.imshow("gray", gray_back[2])
cv2.imshow("noisy", noisy[2])
cv2.imshow("dst", dst)cv2.waitKey(0)
cv2.destroyAllWindows()

【接口】

  • fastNlMeansDenoisingColored
cv2.fastNlMeansDenoisingColored(	src[, dst[, h[, hColor[, templateWindowSize[, searchWindowSize]]]]]	) ->	dst

修改彩色图像的fastnlmeans降噪函数。

  • src: 8位3通道图像
  • dst: 输出结果图像
  • templateWindowSize: 模板 patch 大小,奇数,推荐为7
  • searchWindowSize: 窗口大小(以像素为单位),用于计算给定像素的加权平均。奇数。更大的searchWindowsSize -更长的去噪时间。推荐值21像素
  • h: 亮度组件滤光强度调节参数。较大的h值可以完美地去除噪声,但也可以去除图像细节,较小的h值保留了细节,但也保留了一些噪声
  • hColor: 和h一样,只是颜色分量不同。对于大多数图像,值等于10将足以消除彩色噪声,不扭曲颜色

该函数将图像转换为CIELAB颜色空间,然后使用fastnlmeans降噪函数对给定h参数的L和AB分量分别进行降噪。

  • fastNlMeansDenoisingMulti
cv2.fastNlMeansDenoisingMulti(	srcImgs, imgToDenoiseIndex, temporalWindowSize[, dst[, h[, templateWindowSize[, searchWindowSize]]]]	) ->	dst
cv2.fastNlMeansDenoisingMulti(	srcImgs, imgToDenoiseIndex, temporalWindowSize, h[, dst[, templateWindowSize[, searchWindowSize[, normType]]]]	) ->	dst

利用多帧图像进行降噪

  • srcImgs: 8位,单通道,二通道,三通道,四通道图像序列
  • imgToDenoiseIndex: 需要降噪图像的序号
  • temporalWindowSize: 目标图像周围图像个数
  • dst: 输出与srcImgs图像大小和类型相同的图像。
  • templatewindowsize: 用于计算权重的模板补丁的像素大小。应该是奇数。推荐值7像素
  • searchWindowSize: 窗口大小(以像素为单位),用于计算给定像素的加权平均。应该是奇数。线性影响性能:更大的searchWindowsSize -更长的去噪时间。推荐值21像素
  • h: 参数调节过滤强度。较大的h值可以完美地去除噪声,但也可以去除图像细节,较小的h值保留了细节,但也保留了一些噪声

【参考】

  1. OpenCV: Image Denoising
  2. http://www.ipol.im/pub/art/2011/bcm_nlm/ (It has the details, online demo etc. Highly recommended to visit. Our test image is generated from this link)
  3. Online course at coursera (First image taken from here)
  4. Denoising

http://www.ppmy.cn/news/7051.html

相关文章

【HTML】2023跨年烟花代码

*2022年圣诞节到来啦,很高兴这次我们又能一起度过~ 📂文章目录前言效果展示一、夜景烟花绽放动画效果HTML源码2023年(新年)春节倒计时代码源码2023除夕倒计时效果展示源码宇宙星空-效果展示1.源码2.思路3.步骤(js部分)更多干货🚀前言 时光荏苒…

Ubuntu系统中文乱码的解决办法

Ubuntu系统中文乱码的解决办法 文章目录Ubuntu系统中文乱码的解决办法1. 安装中文语言2. 安装语言设置的命令locale3. 安装中文的相关字体4. 修改语言的环境变量4.1 环境变量一4.2 设置二5. 正式配置语言后记最近在docker上pull下面的Ubuntu镜像运行后发现中文出现了乱码情况&a…

浅谈图数据库1:什么是图?

目录 一、图是什么? 二、“图”源自哪里? 三、加权图是什么? 四、有向图是什么? 五、图能给我们带来什么? 一、图是什么? 说到“图” 大部分人首先想到的是这样滴——图像 ​或者是 饼状图 折线图…

Java8新特性Stream流

一、Stream的介绍 ​ Stream不是集合元素,也不是数据结构,并不保存数据,它是有关算法和计算的,使用起来更像一个高级的迭代器,我们只需要给出需要对其流中的元素执行什么操作,Stream就会隐式的在内部进行遍…

服务调用方式

1.1.RPC和HTTP 无论是微服务还是SOA,都面临着服务间的远程调用。那么服务间的远程调用方式有哪些呢? 常见的远程调用方式有以下2种: RPC:Remote Produce Call远程过程调用,类似的还有RMI。自定义数据格式&#xff0c…

事务日志undo log

事务日志undo log 1 Undo日志的作用 作用1:回滚数据 逻辑上恢复,之前插入了一条数据,已经开辟了物理空间,回滚只是将该数据删除,物理空间还存在。 作用2:MVCC 2 Undo存储结构 mysql> show variables …

【C语言进阶】指针的进阶

在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念: 1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。 2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。 3. 指针是有类型&#…

MyBatis一级缓存和二级缓存

缓存的作用 在 Web 系统中,最重要的操作就是查询数据库中的数据。但是有些时候查询数据的频率非常高,这是很耗费数据库资源的,往往会导致数据库查询效率极低,影响客户的操作体验。于是可以将一些变动不大且访问频率高的数据&…