c++ - 具有可分离内核的2D模糊卷积

标签 c++ arrays opencv

我正在尝试使用自定义float数组进行模糊卷积。

我的数组定义为float array[width*height]。我编辑了these函数,以便它可以与自定义数组一起使用,而不仅限于OpenCV cv::Mat
我的代码如下所示:

int reflect(int M, int x)
{
    if(x < 0)
    {
        return -x - 1;
    }
    if(x >= M)
    {
        return 2*M - x - 1;
    }

    return x;
}

void separable2DConvolution(float * data, Size dataSize, float *kernel, int kernelSize)
{
    // make copy of original image
    float * dataCopy = new float[dataSize.width()*dataSize.height()];
    memcpy(dataCopy, data, dataSize.width()*dataSize.height());
    float * temp = new float[dataSize.width()*dataSize.height()];
    memcpy(temp, data, dataSize.width()*dataSize.height());

    float sum;
    int x1, y1;
    int kernelRadius = floor(kernelSize/2);

    // along y - direction
    for(int y = 0; y < dataSize.height(); y++){
        for(int x = 0; x < dataSize.width(); x++){
            sum = 0.0;
            for(int i = -kernelRadius; i <= kernelRadius; i++){
                y1 = reflect(dataSize.height(), y - i);
                sum = sum + kernel[i + kernelRadius]*dataCopy[y1*x+y1];
            }
            temp[y*x+y] = sum;
        }
    }

    // along x - direction
    for(int y = 0; y < dataSize.height(); y++){
        for(int x = 0; x < dataSize.width(); x++){
            sum = 0.0;
            for(int i = -kernelRadius; i <= kernelRadius; i++){
                x1 = reflect(dataSize.width(), x - i);
                sum = sum + kernel[i + kernelRadius]*temp[x1*y+x1];
            }
            data[x*y+y] = sum;
        }
    }

    delete [] temp;
    delete [] dataCopy;
}

数组以separable2DConvolution的形式传递给dataSize是具有定义的宽度和高度的自定义类(均为有效且大于0),kernel归一化的高斯数组(几乎与cv::getGaussianKernel中的一个一致),并且kernelSize是高斯数组的大小(我使用的是11号)。

我使用此函数从 OpenCV 替换cv::sepFilter2D,但是输出有所不同。使用函数后,我将转换图像以查看差异。

OpenCV输出具有(如预期的那样)“模糊”的值,但是在将相同的输入传递给我的函数的情况下,前三分之一是有噪点的(根本没有模糊),而图像的另一部分是完整的。

我的代码有什么问题?

谢谢您的帮助!

最佳答案

您用于保存像素总和的下标是错误的。 temp[y*x+y]将第一列的所有结果写入第一个像素(temp[0])。许多其他像素将保持不变。您可能需要temp[y * dataSize.width() + x],在下一个循环中以及在计算下标以读取像素值时对data[x*y+y]进行类似的更改。

无关的,您不需要对位图进行memcpy进行复制,因为您应该写入图像中的每个像素。您根本不需要dataCopy,因为原始data数组尚未更改。

对于整数,使用floor是多余的。由于kernelSize是肯定的,因此您只能说int kernelRadius = kernelSize / 2;,因为这会舍入。

关于c++ - 具有可分离内核的2D模糊卷积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59991103/

相关文章:

c++ - std::getline 不适用于函数内部

c++ - vector emplace_back 困惑

c++ - 是否有异步C++ HTTP框架可用?

c - C中指向结构和数组的指针

java - 我的java数组有一个错误(将字母等级存储在数组中)

c++ - Cmake OpenCV 无法指定链接库

c++ - protocol buffers + zlib = 未解析的外部符号

javascript - 如何使用underscore.js创建一个组

opencv - 如何在 Raspbian 上编译和构建 openCV

opencv - 使用 scikit-image/opencv 获取蓝色轮廓