【问题标题】:gpu::blur function takes significantly more timegpu::blur 函数需要更多时间
【发布时间】: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 滤波器是这样,但我很确定高斯滤波器也是如此。

标签: c++ opencv gpu


【解决方案1】:

所以正如我的 cmets 中所述,OpenCV 已经优化了 Tegra 支持(如果使用了 opencv4tegra 库),所以很可能您的 OpenCV GPU 功能并不是真的“慢”,而是您的“CPU”版本实际上非常快,因为它在内部调用了一些 tegra 优化的函数(而不是使用 CPU)。

http://on-demand.gputechconf.com/gtc/2013/presentations/S3411-OpenCV-For-Tegra.pdf可以看出opencv4tegra有几个优化,包括

  1. NEON SIMD 指令
  2. GLSL 算法,使用 opengl 着色器加速处理
  3. Tegra 硬件优化

它们都使用相同的已知“CPU”API。

其他详情请见http://docs.opencv.org/opencv2refman-tegra.pdf

在当前 OpenCV 版本中针对 Tegra 平台优化的 OpenCV 函数列表。优化 涵盖了为以下每个函数指定的最流行的数据类型和操作模式。当一个优化 在数据类型或模式上调用函数 不是 被优化覆盖,调用原始实现。

  • cv::absdiff
  • cv::add
  • cv::addWeighted
  • cv::bitwise_and
  • cv::bitwise_not
  • cv::bitwise_or
  • cv::bitwise_xor
  • cv::compare
  • cv::countNonZero
  • cv::Mat::dot
  • cv::inRange
  • cv::max
  • cv::mean
  • cv::meanStdDev
  • cv::合并
  • cv::min
  • cv::minMaxLoc
  • cv::phase
  • cv::reduce
  • cv::split
  • cv::subtrac
  • cv::sum
  • cv::Mat::convertTo

  • cv::blur

  • cv::boxFilter
  • cv::Canny
  • cv::cvtColor
  • cv::扩张
  • cv::erode
  • cv::filter2D
  • cv::GaussianBlur
  • cv::积分
  • cv::matchTemplate
  • cv::medianBlur
  • cv::pyrDown
  • cv::pyrUp
  • cv::resize
  • cv::Scharr
  • cv::Sobel
  • cv::阈值
  • cv::warpAffine
  • cv::warpPerspective

  • cv::FAST

  • cv::calcOpticalFlowPyrLK

  • cv::buildOpticalFlowPyramid

  • cv::detail::createLaplacePyr

  • cv::detail::normalizeUsingWeightMap
  • cv::detail::BestOf2NearestMatcher::match

  • cv::findCirclesGrid

在文档中标记了哪些功能是 GPU 驱动的

【讨论】:

  • 我安装了 nvidia 网站上提供的 opencv 版本,并按照安装说明进行操作。正如我所见, blur cv::blur 已经针对 GPU 进行了优化。但是为什么调用显式 gpu 模块需要更长的时间?
  • 因为 gpu 模块不使用 tegra 优化,而只使用 cuda 并且只使用 (afaik) cuda 1.2 或 sth。 ...此外,opencv cuda 功能还有一些开销。再说一遍:可能 tegra 优化做得很好(由 nvidia 自己完成 - 封闭源代码)。
  • 感谢您的洞察力... :)
猜你喜欢
  • 2019-04-29
  • 1970-01-01
  • 2017-08-30
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多