【问题标题】:Generated gaussian kernel saturates the image to white color with opencv in C++生成的高斯内核使用 C++ 中的 opencv 将图像饱和为白色
【发布时间】:2021-11-19 03:00:55
【问题描述】:

我正在尝试实现一个函数,该函数在给定特定标准偏差和维度的情况下为我提供高斯核。该函数的输出似乎是正确的,但是当我使用 cv::filter2D 函数应用它时,我得到的结果很奇怪。值饱和到最大值,呈现白色。

生成内核的函数实现如下:

    cv::Mat gaussKernel(int kernel_size, float stdDev)
    {
        // For now, only odd kernel_size values
        std::default_random_engine generator;
        std::normal_distribution<float> distribution(0, stdDev);
        float sum_term {0};
        cv::Mat kernel = cv::Mat::zeros(kernel_size, kernel_size, CV_32F);


        // Create kernel
        for (int i = -kernel_size/2; i <= kernel_size/2; i++)
        {
            for (int j = -kernel_size/2; j <= kernel_size/2; j++)
            {
                kernel.at<float>(i + kernel_size/2,j + kernel_size/2) = std::exp(-(pow(i,2) + pow(j,2))/(2*pow(stdDev,2)));
                sum_term += kernel.at<float>(i + kernel_size/2,j + kernel_size/2);
            }
        }

        kernel /= sum_term;

        std::cout << "The kernel is:   " << std::endl;
        for (int i = 0; i < kernel.rows; i++)
        {
            std::cout << "    ";
            for (int j = 0; j < kernel.cols; j++)
            {
                std::cout << kernel.at<float>(i,j) << ", ";
            }
            std::cout << std::endl;
        }

        return kernel;
    }

一切都是用灰度图片完成的。我预计该错误与内核矩阵中使用的编码有关,但我测试了一些东西并没有收到任何结果。

--编辑: stdDev 的值 = 1; kernel_size 的值 = 3;

图片: Link to image

与读取或修改图片相关的部分代码:

std::string dir {"../resources/ORings/ORing01.jpg"};
cv::Mat original, customKernel;
original = cv::imread(dir);

cv::Mat noisy = original.clone();
cv::Mat clean_1 = original.clone();

customKernel = gauss::gaussKernel(kernel_size, 1);
noisy = gauss::addGaussianNoise(noisy, SNR);
cv::filter2D(clean_1, clean_1, CV_32F, customKernel, cv::Point(-1,-1), 0, cv::BORDER_DEFAULT);

【问题讨论】:

  • 问题不可重现。请发布kernel_sizestdDev 的值。请发布示例输入图像,以及您用于读取图像和应用过滤器的代码。
  • @Rotem 我刚刚添加了所需的信息。

标签: c++ opencv image-processing gaussian gaussianblur


【解决方案1】:

问题的原因是将cv::filter2Dddepth参数设置为CV_32F

将参数值设置为-1 即可解决问题:

cv::filter2D(clean_1, clean_1, -1, customKernel, cv::Point(-1,-1), 0, cv::BORDER_DEFAULT);

ddepth 参数设置为CV_32F 会导致cv::filter2D 的输出类型为CV_32Ffloat 类型的像素)。

输出的值在 [0, 255] 范围内(与输入的范围相同)。
对于CV_32F(浮点)类型的像素,OpenCV 约定黑色是0,白色是1。大于 1.0 的值也是白色的。

我能想到 3 个相关的解决方案:

  • 通过将ddepth 设置为-1,保持输出CV_8U 的类型(与输入相同)。
  • 将内核除以 255:customKernel /= 255.0f;
  • 将输出图像除以 255:clean_1 /= 255.0f;

【讨论】:

  • 确实如此。第四种解决方案:使用更好的图像显示实用程序,不会使图像意外饱和。 ;)
  • @CrisLuengo 你说得对,1 以上的像素饱和是cv::imshow 的行为。我一直忘记它不是 MATLAB :)
猜你喜欢
  • 2018-06-22
  • 2016-05-02
  • 2021-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-09
  • 2013-09-27
  • 2016-07-13
相关资源
最近更新 更多