NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享

论文名称:Parameter-Free Fast Pixelwise Non-Local Means Denoising

论文下载:IPOL Journal · Parameter-Free Fast Pixelwise Non-Local Means Denoisinghttps://www.ipol.im/pub/art/2014/120/

        之前分享了一篇是块级别的NLM denoising (NLM_B),这篇基于像素级的NLM denoising(NLM_P),主要有两种NLM_Pa和NLM_P。差别在于计算块间距离时,NLM_Pa使用的是Gaussian Euclidean norm,而NLM_P使用的是Euclidean norm。当然,和NLM_B不同的是,计算权重时,没有减2*sigma^2了,应该是原论文也没减,是《Non-Local Means Denoising》里减的IPOL Journal · Non-Local Means Denoising。

NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第1张图片

NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第2张图片

接下来介绍了基本算法的计算伪代码,并分析了计算复杂度,为后面优化做铺垫。

​​​​​​​NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第3张图片

 

        介绍了几种优化方法,针对NLM_P,由于其特殊性,可以使用积分图进行优化,复杂度可以减低,还介绍了基于傅里叶变换的优化,但图像较大时,计算复杂度就很高了,最后就是文章的重点方法SIL,计算复杂度可以降。OpenCV里的NLM系列函数(fastNlMeansDenoisingColored)应该就是参考这个方法。

NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第4张图片

NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第5张图片 

NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第6张图片 

NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第7张图片 

 

        由于参数和噪声强度有关,文章分析了下怎么设置最优的参数。 通过构造了两个数据集,以PSNR为标准,得到最优的参数。

NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第8张图片

最后分析对比了NLM_P和NLM_B的效果,从PSNR数据上看,NLM基本上是优于NLM-P/NLM-Pa,但主观效果是相当的 (感觉有点耍流氓)。

NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第9张图片

NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享_第10张图片

        论文公开了C代码(IPOL Journal · Parameter-Free Fast Pixelwise Non-Local Means Denoising),只有SIL那种方法,没有仔细研究了,如果实际会使用该算法的话,再来细看,如果只是看效果的话,可以调用OpenCV里的函数即可。

        另外,对于基础算法流程,用Python代码简单写了单通道的(计算权重那一步应该可以提前计算为表,之后查表就行),可以作为参考,根据这个可以扩展为彩色图像的,Python代码会很慢,代码参考了这篇博文非局部均值滤波-A non-local algorithm for image denoising_Nick Blog-CSDN博客1. 简介Non-Local Means顾名思义,这是一种非局部平均算法。何为局部平均滤波算法呢?那是在一个目标像素周围区域平滑取均值的方法,所以非局部均值滤波就意味着它使用图像中的所有像素,这些像素根据某种相似度进行加权平均。滤波后图像清晰度高,而且不丢失细节。2. 原理该算法使用自然图像中普遍存在的冗余信息来去噪声。与双线性滤波、中值滤波等利用图像局部信息来滤波不同,它利用了整幅图像进行去噪。即以图像块为单位在图像中寻找相似区域,再对这些区域进行加权平均平均,较好地滤除图像中的高斯噪声。2.1https://niecongchong.blog.csdn.net/article/details/111304042

def GaussianKernel(d, sigma):
    # Generate array
    ax = np.arange(-d // 2 + 1., d // 2 + 1.)
    # Generate 2D matrices by duplicating ax along two axes
    xx, yy = np.meshgrid(ax, ax)
    # kernel will be the gaussian over the 2D arrays
    kernel = np.exp(-(xx**2 + yy**2) / (2. * sigma**2))
    # Normalise the kernel
    final = kernel / kernel.sum()
    return final


def onLocalMeansGray_NLMP(image, h=10, templateWindowSize=7, searchWindow=21):
    height, width = image.shape[0], image.shape[1]
    patchWin = int(templateWindowSize / 2)
    searchWind = int(searchWindow / 2)

    # Padding the image
    padLength = patchWin + searchWind
    img = cv2.copyMakeBorder(image, padLength, padLength, padLength, padLength, cv2.BORDER_CONSTANT, value=255)

    # output image
    outImage = np.zeros((height, width), dtype='float')

    # generate gaussian kernel matrix of 7*7
    kernel = GaussianKernel(templateWindowSize, 1)

    # Run the non-local means for each pixel
    for j in range(height):
        for i in range(width):
            padj = j + padLength
            padi = i + padLength
            centerPatch = img[padj - patchWin: padj + patchWin + 1, padi - patchWin: padi + patchWin + 1]
            sumPixel = 0
            sumWeight = 0
            # Apply Gaussian weighted square distance between patches of 7*7 in a window of 21*21
            for r in range(padj - searchWind, padj + searchWind):
                for c in range(padi - searchWind, padi + searchWind):
                    otherPatch = img[r - patchWin: r + patchWin + 1, c - patchWin: c + patchWin + 1]
                    diff = centerPatch - otherPatch
                    distance_2 = np.multiply(diff, diff)
                    pixelWeight = np.sum(np.multiply(kernel, distance_2))
                    pixelWeight = np.exp(pixelWeight / (h**2))
                    sumWeight = sumWeight + pixelWeight
                    sumPixel = sumPixel + pixelWeight * img[r, c]

            outImage[j, i] = sumPixel / sumWeight
    outImage = np.clip(outImage, 0, 255)
    outImage = outImage.astype(np.uint8)
    return outImage

你可能感兴趣的:(图像细节,图像处理,opencv,python)