'simulate isotropic linear diffusion smoothing

I want to apply the de-noising filter I named in the title which is based on the following equations:

enter image description here

where d = 1 is a scalar constant diffusivity parameter, I(x, y) is the initial noisy image, and u(x, y, t) is the image obtained after a diffusion time t lets say 5, 10 and 30. However, I am quite confused about which function to use and how, in order to achieve this in OpenCV. I have the feeling that it is quite simple but for some reason I am confused. Does anyone have an idea?

Here is a sample image:

enter image description here

I want then to compare it with a gaussian filtering approach which according the following:

enter image description here

where G√2t (x, y) is the Gaussian kernel. This proves that performing isotropic linear diffusion for a time t with d = 1 is exactly equivalent to performing Gaussian smoothing with a σ = √(2t)

I have a function that applies the gaussian filtering:

void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, const float sigma, const int ksize_x = 0, const int ksize_y = 0)
{
    int ksize_x_ = ksize_x, ksize_y_ = ksize_y;

    // Compute an appropriate kernel size according to the specified sigma
    if (sigma > ksize_x || sigma > ksize_y || ksize_x == 0 || ksize_y == 0)
    {
        ksize_x_ = (int)ceil(2.0f*(1.0f + (sigma - 0.8f) / (0.3f)));
        ksize_y_ = ksize_x_;
    }

    // The kernel size must be and odd number
    if ((ksize_x_ % 2) == 0)
    {
        ksize_x_ += 1;
    }

    if ((ksize_y_ % 2) == 0)
    {
        ksize_y_ += 1;
    }

    // Perform the Gaussian Smoothing
    GaussianBlur(src, dst, Size(ksize_x_, ksize_y_), sigma, sigma, BORDER_DEFAULT);

    // show result
    std::ostringstream out;
    out << std::setprecision(1) << std::fixed << sigma;
    String title = "sigma: " + out.str();
    imshow(title, dst);
    imwrite("gaussian/" + title + ".png", dst);

    waitKey(260);
}

but I have difficulties implementing the first case.



Solution 1:[1]

This should work as expected. This is based on:

Code:

#include <opencv2\opencv.hpp>
using namespace cv;

void ilds(const Mat1b& src, Mat1b& dst, int iter = 10, double diffusivity = 1.0, double lambda = 0.1)
{
    Mat1f img;
    src.convertTo(img, CV_32F);
    lambda = fmax(0.001, std::fmin(lambda, 0.25)); // something in [0, 0.25] by default should be 0.25
    while (iter--)
    {
        Mat1f lap;
        Laplacian(img, lap, CV_32F);
        img += lambda * diffusivity * lap;
    }

    img.convertTo(dst, CV_8U);
}

int main() {

    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
    Mat1b res_ilds;
    ilds(img, res_ilds);

    imshow("ILDS", res_ilds);
    waitKey();

    return 0;
}

Result:

enter image description here

Let me know if it works for you

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1