【问题标题】:simulate isotropic linear diffusion smoothing模拟各向同性线性扩散平滑
【发布时间】:2022-04-04 20:06:59
【问题描述】:

我想应用我在标题中命名的降噪滤波器,它基于以下等式:

其中d = 1 是一个标量常数扩散参数,I(x, y) 是初始噪声图像,u(x, y, t) 是在扩散时间t 之后获得的图像5, 10 and 30。但是,为了在 OpenCV 中实现这一点,我对使用哪个函数以及如何使用感到很困惑。我觉得这很简单,但由于某种原因我很困惑。有人有想法吗?

这是一个示例图像:

然后我想将其与高斯过滤方法进行比较,该方法根据以下内容:

其中G√2t (x, y) 是高斯核。这证明了用td = 1 执行一段时间的各向同性线性扩散完全等同于用σ = √(2t) 执行高斯平滑

我有一个应用高斯滤波的函数:

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);
}

但我在实施第一种情况时遇到了困难。

【问题讨论】:

    标签: opencv filtering smoothing


    【解决方案1】:

    这应该可以按预期工作。这是基于:

    代码:

    #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;
    }
    

    结果:

    让我知道它是否适合你

    【讨论】:

    • 嗨@Miki 感谢您的回答和您的时间。我将在返回工作站后立即尝试。但是有一个问题,由于您的方法基于 Perona-Malik 方法,因此它不是模拟等距线性平滑,而是模拟各向异性非线性,对吗?
    • @theodore 它是各向同性的! P&M:I += lambda * (g(dN).*dN + g(dS).*dS + g(dE).*dE + g(dW).*dW),其中dN是图像在北方向的空间导数,以此类推。函数 g 决定了扩散的行为。如果g(x) = 1(如本例所示)这是标准的各向同性扩散。
    • 好的我看到运行你的代码就像你说的那样工作。但是,我想验证一些事情。据我了解g 函数对应于扩散参数d 对吗?如果是,那么您的代码可以更正确地转换为img += lambda *d* lap;,其中d 为1。此外,iter 变量代表扩散时间t 参数,对吧?但是,如果我为 iter 使用 5 值,它应该对应于高斯平滑的 σ = √(2t) = 3.2 并且两者都应该给我相同的结果,但它们没有。同样在我的初始公式中没有任何lambda
    • 变量提到了如何添加到计算中。最后,您正在使用拉普拉斯滤波器来获得导数,我可以使用 sobel 或 scharr 滤波器来获得导数吗?这会改变什么吗?或者我将使用哪种方法来获得它并不重要。
    • @theodore img += lambda *d* lap 正确。 iter 正确。 如果我使用...实际上不知道。 lambda 在 P&M 的公式中,您可以将其固定为默认值 0.25。你需要拉普拉斯算子,你可以用 Sobel 计算它,但我看不出一个很好的理由。告诉我
    猜你喜欢
    • 1970-01-01
    • 2013-01-20
    • 2012-06-03
    • 2014-05-26
    • 2015-11-08
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    相关资源
    最近更新 更多