【问题标题】:Using OpenCL and GPU is not increasing fps performance of my Camera使用 OpenCL 和 GPU 不会提高我的相机的 fps 性能
【发布时间】:2014-10-31 11:08:52
【问题描述】:

我使用 OpenCV 和 Visual Studio 2012 编译了这个简单的颜色跟踪图像处理程序。 首先,我使用 CPU 编译它。 程序:

#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <time.h>

using namespace cv;
using namespace std;

 int main( int argc, char** argv )
 {
    time_t t= time(0);
    VideoCapture cap(0); //capture the video from web cam

    if ( !cap.isOpened() )  // if not success, exit program
    {
         cout << "Cannot open the web cam" << endl;
         return -1;
    }
     double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
   double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video

    cout << "Frame size : " << dWidth << " x " << dHeight << endl;

    namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"

  int iLowH = 0;
 int iHighH = 179;

  int iLowS = 0; 
 int iHighS = 255;

  int iLowV = 0;
 int iHighV = 255;

  //Create track bars in "Control" window
 cvCreateTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179)
 cvCreateTrackbar("HighH", "Control", &iHighH, 179);

  cvCreateTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
 cvCreateTrackbar("HighS", "Control", &iHighS, 255);

  cvCreateTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255)
 cvCreateTrackbar("HighV", "Control", &iHighV, 255);

    int fps=0;
    int cur=0;
    while (true)
    {
    fps++;
        t=time(0);
        struct tm *tmp = gmtime(&t);

        int h= (t/360) %24;
        int m= (t/60) %60;
        int s = t%60;
        if(cur !=s)
        {
            cout<<fps<<endl;
            fps=0;
            cur=s;
        }
        Mat imgOriginal;

        bool bSuccess = cap.read(imgOriginal); // read a new frame from video

         if (!bSuccess) //if not success, break loop
        {
             cout << "Cannot read a frame from video stream" << endl;
             break;
        }

    Mat imgHSV;

   cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV

  Mat imgThresholded;

   inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded); //Threshold the image

  //morphological opening (remove small objects from the foreground)
  erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
  dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) ); 

   //morphological closing (fill small holes in the foreground)
  dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) ); 
  erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );

   imshow("Thresholded Image", imgThresholded); //show the thresholded image
  imshow("Original", imgOriginal); //show the original image

        if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
       {
            cout << "esc key is pressed by user" << endl;
            break; 
       }
    }

   return 0;

}

我的相机的 fps 为 16。 然后我使用 OpenCL(GPU 支持)编译了这个程序。 程序:

#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/ocl/ocl.hpp>
#include <time.h>

using namespace cv;
using namespace std;

 int main( int argc, char** argv )
 {
    time_t t= time(0);
    VideoCapture cap(0); //capture the video from web cam

    if ( !cap.isOpened() )  // if not success, exit program
    {
         cout << "Cannot open the web cam" << endl;
         return -1;
    }
     double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
   double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video

    cout << "Frame size : " << dWidth << " x " << dHeight << endl;

    namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"

  int iLowH = 0;
 int iHighH = 179;

  int iLowS = 0; 
 int iHighS = 255;

  int iLowV = 0;
 int iHighV = 255;

  //Create track bars in "Control" window
 cvCreateTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179)
 cvCreateTrackbar("HighH", "Control", &iHighH, 179);

  cvCreateTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
 cvCreateTrackbar("HighS", "Control", &iHighS, 255);

  cvCreateTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255)
 cvCreateTrackbar("HighV", "Control", &iHighV, 255);

    int fps=0;
    int cur=0;
    while (true)
    {
    fps++;
        t=time(0);
        struct tm *tmp = gmtime(&t);

        int h= (t/360) %24;
        int m= (t/60) %60;
        int s = t%60;
        if(cur !=s)
        {
            cout<<fps<<endl;
            fps=0;
            cur=s;
        }
        Mat imgOriginal;

        bool bSuccess = cap.read(imgOriginal); // read a new frame from video

         if (!bSuccess) //if not success, break loop
        {
             cout << "Cannot read a frame from video stream" << endl;
             break;
        }

    Mat imgHSV;

   cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV

  Mat imgThresholded;

   inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded); //Threshold the image

  //morphological opening (remove small objects from the foreground)
    ocl::oclMat alpha(imgThresholded);
    ocl::erode(alpha,alpha, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
    ocl::dilate( alpha, alpha, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) ); 

   //morphological closing (fill small holes in the foreground)
    ocl::dilate( alpha, alpha, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) ); 
    ocl::erode(alpha, alpha, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
    imgThresholded = Mat(alpha);
   imshow("Thresholded Image", imgThresholded); //show the thresholded image
  imshow("Original", imgOriginal); //show the original image

        if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
       {
            cout << "esc key is pressed by user" << endl;
            break; 
       }
    }

   return 0;

}

但现在我得到一个 fps = 10 。请有人告诉为什么会发生这种情况。 我在某处读到 GPU 支持提高了 fps 性能。我使用的显卡是 AMD RAEDON。

【问题讨论】:

  • if (waitKey(30) == 27), 30ms 意味着 33 FPS max already 。 5ms 应该也可以工作,给你更多的 fps
  • 哪个显卡? HD7730 GDDR3 还是 R9-295x2?
  • 高清 8730M @huseyintugrulbuyukisik

标签: opencv image-processing opencl gpu


【解决方案1】:

GPU 专为大吞吐量而设计,但将数据从 CPU 内存移动到 GPU 内存需要大量时间。您不应该认为 GPU 总是在提高 fps。这一切都取决于 GPU 的能力如何获得。

在您的情况下,您似乎为每一帧做了很少的工作。所以我的猜测是,您的系统大部分时间都在使用将帧移动到 GPU 并将结果移回。

【讨论】:

  • 一次传输多帧
  • 您也可以尝试在 GPU 处理前一帧时使用 CPU 从视频中读取新帧。您可以通过将帧读取代码移动到最后一个ocl::erode 之后和阻止读取Mat(alpha) 之前来尝试此操作。这不是绝对的方法,因为编译器可能会移动代码,但在你的情况下我肯定会尝试。
【解决方案2】:

(正如maZZZu评论的那样)

您正在进行串行计算。添加流水线。然后,当捕获一帧时,opencl 会同时计算最后一帧。您可以重叠更多步骤,例如:

  • 获取视频数据
  • 复制到gpu
  • 计算
  • 进入CPU
  • 可视化?

那么只有最耗时的步骤才会在 FPS 上可见。如果复制到 gpu 需要 20ms,那么其他的将被隐藏,程序将显示 50FPS。

- Time 1: get video data 1
- (Time 2: get video data 2) and (copy data 1 to gpu)
- (Time 3: get video data 3) and (copy data 2 to gpu) and (compute data 1)
- (Time 4: get video data 4) and (copy data 3 to gpu) and (compute data 2) and ..
- (Time 5: get video data 5) and (copy data 4 to gpu) and (compute data 3) and ..
- (Time 6: get video data 6) and (copy data 5 to gpu) and (compute data 4) and ..
- (Time 7: get video data 8) and (copy data 6 to gpu) and (compute data 5) and ..

因此,如果复制到 gpu 需要 %45 并且返回结果需要 %45 时间,则 FPS 应该增加 %90,而只需将其中一个隐藏在另一个后面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多