NLM去噪算法的python实现

NLM全名non-Local Means——非局部均值,通过寻找图片中与当前像素相似的区域,计算出权重,再求和,即当前图像的去噪结果是图像中相似块的融合

原理非常简洁,以下图为例:
在这里插入图片描述
假设含噪声图像为 v v v,去噪图像为 u u u

那么输入输出的关系为:

u ( x ) = ∑ y ∈ I w ( x , y ) v ( y ) u(x)=\sum_{y\in I}^{}w(x,y)v(y) u(x)=yIw(x,y)v(y)

其中 y y y的取值范围是整幅图像, w w w是代表了图像块 x x x y y y的相似度,是一种权重,每个输出点都要对整个图像求权重,最后求整幅图像的加权和,其计算复杂度非常之高,想要实用就必须被简化,这里先介绍原始方法。

w w w的公式为:

w ( x , y ) = 1 Z ( x ) e x p ( − ∣ ∣ V ( y ) − V ( x ) ∣ ∣ 2 h 2 ) ) w(x,y)=\frac{1}{Z(x)}exp(-\frac{||V(y) - V(x)||^{2}}{h^{2}})) w(x,y)=Z(x)1exp(h2V(y)V(x)2))

h h h是控制去噪程度的系数,越大则去噪程度越高,图像也更模糊,具体取值应当以图像中的噪声水平为依据
V ( x ) V(x) V(x)是输入像素点 x x x的窗
V ( y ) V(y) V(y)是当前遍历到的像素点 y y y的窗
∣ ∣ V ( y ) − V ( x ) ∣ ∣ ||V(y) - V(x)|| V(y)V(x)就是两个窗内像素的均方误差

∣ ∣ V ( y ) − V ( x ) ∣ ∣ 2 = m e a n ( ( v ( x + z ) − v ( x + z ) ) 2 ) ||V(y) - V(x)||^{2}= mean((v(x+z)-v(x+z))^{2}) V(y)V(x)2=mean((v(x+z)v(x+z))2)

z z z代表归一化:

Z ( x ) = ∑ y e x p ( − ∣ ∣ V ( y ) − V ( x ) ∣ ∣ 2 h 2 ) ) Z(x)=\sum_{y}^{}exp(-\frac{||V(y) - V(x)||^{2}}{h^{2}})) Z(x)=yexp(h2V(y)V(x)2))

本文的代码限制了搜索的范围,不然实在是太慢了:

import cv2
import numpy as np
import math

img = cv2.imread('F:/hh/2.jpg')
img = cv2.resize(img,(500,500))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray= gray.astype('float32')/255
size = img.shape  # h w c

r = 1
search_range = 10
h = 0.05

sr = search_range
h2 = h*h
dest = gray.copy()   #python中的变量更像指针,不可直接赋值
div = -1 * (2*r+1)*(2*r+1) * h2;

for y in range(r , size[0] - r):
    print(y)
    for x in range(r , size[1]  - r):
        
        srcblock = gray[y-r:y+r+1,x-r:x+r+1]  #是y,x
        
        #限制了搜索范围,不然实在太慢了,做个试验而已
        y_start = max(y-search_range,r)
        x_start = max(x-search_range,r)
        y_end = min(y + search_range,size[0]- r - 1)
        x_end = min(x + search_range,size[1]- r - 1)

        w = np.zeros([y_end - y_start + 1,x_end - x_start + 1])
        
        for yi in range(y_start , y_end + 1):
            for xi in range(x_start , x_end + 1):
                #运动估计简化计算?
                refblock = gray[yi-r:yi+r+1,xi-r:xi+r+1]
                
                delta = np.sum(np.square(srcblock-refblock))
                #print(delta)
                w[yi-y_start,xi-x_start] = math.exp(delta/div) 
                #print(yi,xi)
                #time.sleep(1)
        

        dest[y,x] = np.sum(w * gray[y_start:y_end + 1,x_start:x_end + 1])/np.sum(w)
            
                
cv2.imshow('result',dest)

结果如下:
在这里插入图片描述

  • 4
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是使用贝叶斯优化一维时序信号NLM去噪Python代码: ```python import numpy as np from scipy import signal from skopt import gp_minimize def nlm_filter(signal_in, h, sigma): """Non-local means filter for 1D signal""" L = len(signal_in) signal_out = np.zeros(L) for i in range(L): w = np.exp(-(np.arange(L) - i) ** 2 / (2 * h ** 2)) w /= np.sum(w) for j in range(L): d = signal_in[j:j + L] - signal_in[i:i + L] d = np.sum(d ** 2 * w) signal_out[i] += np.exp(-d / (2 * sigma ** 2)) * signal_in[j] signal_out[i] /= np.sum(np.exp(-d / (2 * sigma ** 2)) * w) return signal_out def nlm_filter_loss(x, signal_in, signal_true): h, sigma = x signal_out = nlm_filter(signal_in, h, sigma) return np.mean((signal_out - signal_true) ** 2) def optimize_nlm_filter(signal_in, signal_true): """Optimize NLM filter using Bayesian optimization""" bounds = [(0.01, 2), (0.01, 2)] res = gp_minimize(nlm_filter_loss, bounds, args=(signal_in, signal_true), n_calls=50) h, sigma = res.x return nlm_filter(signal_in, h, sigma) ``` 其中,`nlm_filter`函数实现了一维时序信号的NLM去噪算法,`nlm_filter_loss`函数用于计算NLM去噪算法的损失函数,`optimize_nlm_filter`函数使用贝叶斯优化算法来寻找最优的NLM去噪超参数,并返回去噪后的信号。 使用方法如下: ```python # Generate noisy signal t = np.linspace(0, 10, 1000) signal_true = np.sin(t) signal_in = signal_true + np.random.normal(0, 0.1, len(t)) # Optimize NLM filter signal_out = optimize_nlm_filter(signal_in, signal_true) # Plot results import matplotlib.pyplot as plt plt.plot(t, signal_in, label='Noisy signal') plt.plot(t, signal_true, label='True signal') plt.plot(t, signal_out, label='NLM filtered signal') plt.legend() plt.show() ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进不去

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值