简体   繁体   English

生成的高斯 kernel 在 C++ 中用 opencv 将图像饱和为白色

[英]Generated gaussian kernel saturates the image to white color with opencv in C++

I'm trying to implement a function that gives me the Gaussian kernel given a certain standard deviation and dimensions.我正在尝试实现一个 function,在给定特定标准偏差和维度的情况下,它会给出高斯 kernel。 The output of the function seems correct, but when I apply it using the cv::filter2D function the result I obtain is quite strange. function 的 output 似乎是正确的,但是当我使用 cv::filter2D function 应用它时,我得到的结果很奇怪。 The values saturate to maximum, giving a white color.这些值饱和到最大值,呈现白色。

The implementation of the function that generates the kernel is the following:生成 kernel 的 function 的实现如下:

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

All is being done with greyscale pictures.所有这些都是用灰度图片完成的。 I expect the error to be related to the codification used in the kernel matrix, but I have tested some stuff and received no result.我预计错误与 kernel 矩阵中使用的编码有关,但我已经测试了一些东西但没有收到任何结果。

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

Image: Link to image图片:图片链接

Part of the code related to reading or modifications of the 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);

The cause of the problem is setting the ddepth argument of cv::filter2D to CV_32F .问题的原因是将cv::filter2Dddepth参数设置为CV_32F

Setting the argument value to -1 solves the issue:将参数值设置为-1可解决问题:

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

Setting ddepth argument to CV_32F causes the output type of cv::filter2D to be CV_32F (pixels of type float ).ddepth参数设置为CV_32F会导致 output 类型的cv::filter2DCV_32F (类型为float的像素)。

The values of the output are in range [0, 255] (same range as the input). output 的值在 [0, 255] 范围内(与输入范围相同)。
OpenCV convention for pixels of type CV_32F (float) is that black is 0 and white is 1 . OpenCV CV_32F (浮点)类型像素的约定是黑色为0白色为1 Values above 1.0 are also white.高于 1.0 的值也是白色的。

There are 3 relevant solutions I can think of:我能想到 3 个相关的解决方案:

  • Keeping the type of the output CV_8U (same as the input), by setting ddepth to -1 .通过将ddepth设置为-1来保持 output CV_8U的类型(与输入相同)。
  • Dividing the kernel by 255: customKernel /= 255.0f;将 kernel 除以 255: customKernel /= 255.0f; . .
  • Dividing the output image by 255: clean_1 /= 255.0f;将output图像除以255: clean_1 /= 255.0f; . .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM