【发布时间】:2017-10-23 19:57:48
【问题描述】:
作为前言,这是一道作业题,但我已经完成了,只是速度很慢。这对报告无关紧要。但无论如何我都在努力加快速度。
所以我正在尝试对图像应用高斯模糊
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);
在同一张图片上耗时不到四分之一秒。
我可以做些什么来加快这个过程?我已经阅读了一些关于应用两个一维过滤器的信息,但老实说,我不能很好地理解它。我还阅读了一些关于对图像和过滤器进行 FFT,将它们相乘,然后进行 IFFT 的内容,但我认为这不是我想要在这里做的:我发现提到的资源只是当涉及到更大的过滤器时,效率会更高。
【问题讨论】:
-
我对 OpenCV 一无所知,但您的代码将为图像中的每个像素调用
inputImage.at<uchar>(imagePoint)二十五次。如果 OpenCV 不会为您提供指向像素数组的原始指针,也许您可以创建自己的原始数组,并通过调用inputImage.at<uchar>(imagePoint)来填充它,每个像素只需 一次 次。 -
还值得注意的是,OpenCV 将在 GPU 可用时利用它们,这对于卷积等操作可以显着加快。要更直接地与 OpenCV 进行比较,您可以尝试禁用该优化。
-
在下面查看@CostantinoGrana 的答案。真正要杀死你的是#3。我的建议:切换循环的顺序,使用
Mat.ptr而不是at获取指向整行的指针,然后重新测量以查看您还需要/想要优化多少。我认为下一步是重写为线性可分离过滤器。即:两次通过:一次在行上,一次在列上。
标签: c++ image-processing opencv3.0