1. 程式人生 > >OpenCV3 比較CPU, OpenCL,cuda效能

OpenCV3 比較CPU, OpenCL,cuda效能

#include <iostream>
 
#include <opencv2/opencv.hpp>
#include <opencv2/core/ocl.hpp>
#include <opencv2/core/cuda.hpp>
#include <opencv2/cudaobjdetect.hpp>
#include <opencv2/cudaimgproc.hpp>
 
 
int main(int argc, char**argv) {
    std::cout << "OpenCV version=" << std::hex << CV_VERSION << std::dec << std::endl;
 
    cv::Mat frame;
    cv::UMat uframe, uFrameGray;
    cv::cuda::GpuMat image_gpu, image_gpu_gray;
    cv::VideoCapture capture("path_to_the_video");
 
    bool useOpenCL = (argc == 2);
    std::cout << "Use OpenCL=" << useOpenCL << std::endl;
    cv::ocl::setUseOpenCL(useOpenCL);
 
    bool useCuda = (argc == 3);
    std::cout << "Use CUDA=" << useCuda << std::endl;
 
    cv::Ptr<cv::CascadeClassifier> cascade = cv::makePtr<cv::CascadeClassifier>("data/lbpcascades/lbpcascade_frontalface_at.xml");
    cv::Ptr<cv::cuda::CascadeClassifier> cascade_gpu = cv::cuda::CascadeClassifier::create("data/lbpcascades/lbpcascade_frontalface_at.xml");
 
    double time = 0.0;
    int nb = 0;
    if(capture.isOpened()) {
        for(;;) {
            capture >> frame;
            if(frame.empty() || nb >= 1000) {
                break;
            }
 
            std::vector<cv::Rect> faces;
            double t = 0.0;
            if(!useCuda) {
                t = (double) cv::getTickCount();
                frame.copyTo(uframe);
                cv::cvtColor(uframe, uFrameGray, CV_BGR2GRAY);
                cascade->detectMultiScale(uFrameGray, faces);
                t = ((double) cv::getTickCount() - t) / cv::getTickFrequency();
            } else {
                t = (double) cv::getTickCount();
                image_gpu.upload(frame);
                cv::cuda::cvtColor(image_gpu, image_gpu_gray, CV_BGR2GRAY);
                cv::cuda::GpuMat objbuf;
                cascade_gpu->detectMultiScale(image_gpu_gray, objbuf);
                cascade_gpu->convert(objbuf, faces);
                t = ((double) cv::getTickCount() - t) / cv::getTickFrequency();
            }
 
            time += t;
            nb++;
 
            for(std::vector<cv::Rect>::const_iterator it = faces.begin(); it != faces.end(); ++it) {
                cv::rectangle(frame, *it, cv::Scalar(0,0,255));
            }
            std::stringstream ss;
            ss << "FPS=" << (nb / time);
            cv::putText(frame, ss.str(), cv::Point(30, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0,0,255));
 
            cv::imshow("Frame", frame);
            char c = cv::waitKey(30);
            if(c == 27) {
                break;
            }
        }
    }
 
    std::cout << "Mean time=" << (time / nb) << " s" << " ; Mean FPS=" << (nb / time) << " ; nb=" << nb << std::endl;
    system("pause");
    return 0;
}

lbpcascade_frontalface_at.xml  檔案可以百度搜索就能下載到,是一個級聯分類器訓練好的模型,用於識別人臉正面,很常用。具體資料可以參考http://blog.csdn.net/yang_xian521/article/details/6973667

只需要將

 cv::VideoCapture capture("path_to_the_video");​​​​​​​

 cv::Ptr<cv::CascadeClassifier> cascade = cv::makePtr<cv::CascadeClassifier>("data/lbpcascades/lbpcascade_frontalface_at.xml");
 cv::Ptr<cv::cuda::CascadeClassifier> cascade_gpu = cv::cuda::CascadeClassifier::create("data/lbpcascades/lbpcascade_frontalface_at.xml");

結果很意外,opencl基本沒有加速效果,而cuda加速效果很明顯

OpenCV3的GPU模組需要手動重新編譯才可以使用。本文介紹了編譯OpenCV3.2.0+ GPU模組的方法

Reference: