使用高斯模糊的图像卷积,可能加速吗?

时间:2017-10-23 19:57:48

标签: c++ image-processing opencv3.0

作为序言,这是一个家庭作业问题,但我已经完成了它,它只是很慢。这与报告无关。但无论如何我都想加快速度。

所以我试图将高斯模糊应用于图像

const unsigned char KERNAL_SIZE = 5;
const unsigned char KERNAL_MEAN = KERNAL_SIZE / 2;
const unsigned char GaussianBlurKernal[KERNAL_SIZE][KERNAL_SIZE] =
{ { 1, 4, 7, 4, 1 },
{ 4, 16, 26, 16, 4 },
{ 7, 26, 41, 26, 7 },
{ 4, 16, 26, 16, 4 },
{ 1, 4, 7, 4, 1 }
};
const int GAUSSIAN_KERNAL_SIZE = 273;

并浏览以下代码:

Mat CustomGuassianBlur(const Mat & inputImage)
{
    Size maxSize = inputImage.size();
    Mat outputImage(maxSize, CV_8UC1, Scalar(0, 0, 0));
    for (int i = 0; i < maxSize.width; i++)
    {
        for (int j = 0; j < maxSize.height; j++)
        {
            unsigned int sum = 0;
            for (int k = -KERNAL_MEAN; k <= KERNAL_MEAN; k++)
            {
                for (int l = -KERNAL_MEAN; l <= KERNAL_MEAN; l++)
                {
                    Point imagePoint = { (i + l + maxSize.width) % maxSize.width, (j + k + maxSize.height) % maxSize.height };
                    sum = sum + inputImage.at<uchar>(imagePoint) * GaussianBlurKernal[k + KERNAL_MEAN][l + KERNAL_MEAN];
                }
            }
            sum = sum / GAUSSIAN_KERNAL_SIZE;
            outputImage.at<uchar>(j, i) = uchar(sum);
        }
    }
return outputImage;
}

过滤器大约需要8秒钟。我正在尝试近似的OpenCV代码:

GaussianBlur(src_gray, detected_edges, Size(5, 5), 0, 0);

在同一张图片上不到四分之一秒。

我可以做些什么来加快这个过程?我已经阅读了一些关于应用两个1-d滤波器的内容,但老实说我真的无法理解这一切。我还读过一些关于对图像和滤波器进行FFT,乘以它们然后进行IFFT的看法,但我不认为我想在这里做什么:我发现提到的资源只是'在更大的过滤器方面更有效率。

2 个答案:

答案 0 :(得分:3)

我的几分钱:

  1. 请调用您的索引变量rc,以便了解行和列是什么。从长远来看,它会对你有所帮助。
  2. 籽粒?难道这不是内核吗?或者这是另一种语言吗?
  3. 记住您的缓存:您的矩阵按行主顺序存储,因此每行都会遍历每一列。
  4. 如果您的内核大小已修复,请展开内部双循环。
  5. 如果您的内核大小必须更改,请在一个内部循环中使用cv::Mat::ptr()的当前行的地址,以至少在列索引中保存一些计算。
  6. 模数宽度和高度听起来不对。您正在使用环形图像表示。不寻常的。

答案 1 :(得分:3)

除了@CostantinoGrana的答案之外,我想指出2D高斯平滑是线性可分的。您可以使用2个1D内核,而不是使用2D内核 - 首先通过行,第二个通过列。

此外,如果您可以访问多个核心,则可以并行对行/列执行1D过滤。请参阅cv::parallel_for_构造。