【发布时间】:2015-07-20 09:33:53
【问题描述】:
这是我尝试针对 GPU 优化的函数。 gpu::blur 在这段代码中花费了很长时间。当我运行此代码的普通 CPU 版本时,执行 30 张图像大约需要 1.5 秒(frameToProcess 包含 30 张图像)。当我运行这段代码(它使用 gpu:: 函数和 GpuMat )时,它需要超过 30 秒。如果我评论 gpu::blur 行,它只需要 0.5 秒来执行。请帮我找出 GPU 版本有什么问题。
void getContourCenters(vector<gpu::GpuMat> &framesToProcess, vector<pointI>& contourCenter)
{
size_t j = 0;
for (int i = 1; i < framesToProcess.size(); i++)
{
gpu::GpuMat tempDifferenceImage, tempThresholdImage, tempBlurredImage;
vector< vector<Point> > contours;
vector<Vec4i> hierarchy;
Rect objectBoundingRectangle = Rect(0, 0, 0, 0);
gpu::absdiff(framesToProcess[i - 1], framesToProcess[i], tempDifferenceImage);
gpu::threshold(tempDifferenceImage, tempThresholdImage, SENSITIVITY_VALUE, 255, THRESH_BINARY);
gpu::blur(tempThresholdImage, tempBlurredImage, Size(BLUR_SIZE, BLUR_SIZE));
Mat contourImage( tempBlurredImage );
findContours(contourImage, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for (int k = 0; k < contours.size(); ++k)
{
objectBoundingRectangle = boundingRect(contours[k]);
int xpos = objectBoundingRectangle.x + objectBoundingRectangle.width / 2;
int ypos = objectBoundingRectangle.y + objectBoundingRectangle.height / 2;
contourCenter.push_back(mp(xpos, ypos, j++));
}
}
}
BLUR_SIZE 是一个值为 50 的常数。图像大小为 992 X 1000,CV_8UC1 类型的图像。我在 Nvidia Tegra K1 上运行。这是另一个版本的代码:
void getContourCenters(vector<Mat> &framesToProcess, vector<pointI>& contourCenter)
{
size_t j = 0;
for (int i = 1; i < framesToProcess.size(); i++)
{
Mat tempDifferenceImage, tempThresholdImage;
vector< vector<Point> > contours;
vector<Vec4i> hierarchy;
Rect objectBoundingRectangle = Rect(0, 0, 0, 0);
absdiff(framesToProcess[i - 1], framesToProcess[i], tempDifferenceImage);
threshold(tempDifferenceImage, tempThresholdImage, SENSITIVITY_VALUE, 255, THRESH_BINARY);
blur(tempThresholdImage, tempThresholdImage, Size(BLUR_SIZE, BLUR_SIZE));
findContours(tempThresholdImage, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for (int k = 0; k < contours.size(); ++k)
{
objectBoundingRectangle = boundingRect(contours[k]);
int xpos = objectBoundingRectangle.x + objectBoundingRectangle.width / 2;
int ypos = objectBoundingRectangle.y + objectBoundingRectangle.height / 2;
contourCenter.push_back(mp(xpos, ypos, j++));
}
}
}
此代码在同一台机器上执行需要 1.5 秒。我想为GPU优化这段代码,写了上面提到的版本,花了30多秒。
【问题讨论】:
-
请添加一些信息:BLUR_SIZE 的大小、frameToProcess 中图像的大小、使用的硬件。
-
-
您使用的是由 nvidia 提供的
OpenCV 4 Tegra二进制文件吗?它具有从某种 tegra 库调用的内置 tegra 函数,这比 OpenCV CUDA 支持快得多。 -
此外,如果您不使用 tegra 而使用
IPP(例如在标准英特尔 pc 上),它也会使用显卡,这再次比 OpenCV CUDA 支持更有效。 -
澄清:“cpu”版本内部有类似
if tegra_support: call super_fast_special_tegra_library_function的东西(看看开源代码)。至少 sobel 滤波器是这样,但我很确定高斯滤波器也是如此。