NLM_ P-parameter-free fast pixelwise non local means denoising sharing

Paper name: parameter free fast pixelwise non local means denoising

Paper Download: IPOL Journal · Parameter-Free Fast Pixelwise Non-Local Means Denoisinghttps://www.ipol.im/pub/art/2014/120/

Previously, I shared an article on NLM denoising (NLM_B) at the block level. This article is based on NLM denoising(NLM_P) at the pixel level. There are mainly two NLMS_ PA and NLM_ P. The difference is that when calculating the distance between blocks, NLM_Pa uses Gaussian Euclidean norm, while NLM_ P uses Euclidean norm. Of course, and NLM_ B the difference is that when calculating the weight, there is no reduction of 2*sigma^2. It should be that there is no reduction in the original paper, which is reduced in non local means denoising IPOL Journal · Non-Local Means Denoising.

 

Next, the calculation pseudo code of the basic algorithm is introduced, and the calculation complexity is analyzed to pave the way for the later optimization.

Several optimization methods are introduced for NLM_P. Due to its particularity, the integral graph can be used for optimization, and the complexity can be reduced. The optimization based on Fourier transform is also introduced, but when the image is large, the computational complexity is very high. Finally, the key method SIL of the article can reduce the computational complexity. The NLM series functions in OpenCV (fastnlmeans denoising colored) should refer to this method.

 

 

Because the parameters are related to the noise intensity, this paper analyzes how to set the optimal parameters. By constructing two data sets and taking PSNR as the standard, the optimal parameters are obtained.

Finally, NLM is analyzed and compared_ P and NLM_ From the PSNR data, NLM is basically better than NLM-P/NLM-Pa, but the subjective effect is quite good (I feel a little rogue).

 

The paper discloses the C code( IPOL Journal · Parameter-Free Fast Pixelwise Non-Local Means Denoising ), there is only the SIL method, which has not been studied carefully. If you can actually use the algorithm, take a closer look. If you just look at the effect, you can call the functions in OpenCV.

In addition, for the basic algorithm flow, the single channel is simply written in Python code (the step of calculating the weight should be calculated as a table in advance, and then look up the table). It can be used as a reference. According to this, which can be extended to color images, the python code will be very slow. The code refers to this blog post Nonlocal mean filtering-a non local algorithm for image denoising_ Nick blog CSDN blog 1 Introduction non local means, as the name suggests, is a non local average algorithm. What is the local average filtering algorithm? That is the method of smoothing the mean value around a target pixel, so nonlocal mean filtering means that it uses all pixels in the image, which are weighted and averaged according to a certain similarity. The filtered image has high definition and does not lose details. 2. Principle the algorithm uses the redundant information commonly existing in natural images to remove noise. Different from bilinear filtering and median filtering, which use the local information of the image to filter, it uses the whole image for denoising. That is to find similar regions in the image in the unit of image block, and then weighted average these regions to better filter out the Gaussian noise in the image. two point one https://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

 

 

Keywords: Python OpenCV image processing

Added by bogdan on Sat, 29 Jan 2022 20:11:10 +0200