GPU 初探

 OpenCV是由Intel、Willow Garage主導開發的開源計算機視覺庫,輕量而且高效,包括一系列C函數和少量C++類,是圖像處理和計算

機視覺方面的通用算法,支持Windows、Linux、Mac OS三大平臺,迄今已有數千名開發人員從事相關工作,下載量超過200萬。該項目早在

1999年1月就開始啓動,2009年10月1日發佈了2.0正式版。
 NVIDIA表示,OpenCV面向的都是計算密集型大型應用,很多都需要強勁的實時性能,而有了CUDA GPU加速的支持,開發人員可在更高

分辨率的圖像上實時運行更精確的OpenCV算法,同時降低功耗,比如新的OpenCV深度計算引擎藉助GPU加速就要比單純在CPU上運行快5-10倍,

同時這也有利於開發更新、更主流的計算機視覺應用程序。
 OpenCV的GPU模塊只支持NVIDIA的顯卡,原因是該部分是基於NVIDIA的CUDA和NVIDIA的NPP模塊實現的。而該模塊的好處在於使用GPU

模塊無需安裝CUDA工具,也無需學習GPU編程,因爲不需要編寫GPU相關的代碼。但如果你想重新編譯OpenCV的GPU模塊的話,還是需要CUDA的

toolkit。
 由於GPU模塊的發展,使大部分函數使用起來和之前在CPU下開發非常類似。首先,就是把GPU模塊鏈接到你的工程中,幷包含必要的

頭文件gpu.hpp。其次,就是GPU模塊下的數據結構,原本在cv名字空間中的現在都在gpu名字空間中,使用時可以gpu::和cv::來防止混淆

。在GPU模塊中,矩陣的名字爲GpuMat,而不是之前的Mat,其他的函數名字和CPU模塊中相同,不同的是,現在的參數輸入不再是Mat,而是

GpuMat。對於2.0的GPU模塊,多通道的函數支持的並不好,推薦使用GPU模塊處理灰度的圖像。有些情況下,使用GPU模塊的運行速度並不及

CPU模塊下的性能,GPU模塊相對而言還不夠成熟,需要進一步優化。很重要的一個原因就是內存管理部分和數據轉換部分對於GPU模塊而言消

耗了大量的時間。
 需要注意的是,在所有使用GPU模塊的函數之前,最好需要調用函數gpu::getCudaEnabledDeviceCount,如果你在使用的OpenCV模塊

編譯時不支持GPU,這個函數返回值爲0;否則返回值爲已安裝的CUDA設備的數量。使用GPU模塊,需要在用CMake編譯OpenCV時使其中的

WITH_CUDA和WITH_TBB的宏生效,爲ON。

下面是一個opencv GPU例程(highgui_gpu.cpp)
// GPUTest.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"

#include <iostream>
#include <string>

#include <opencv2/core/core.hpp>
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"

using namespace std;
using namespace cv;
using namespace cv::gpu;

struct Timer
{
    Timer(const string& msg_)
    {
        msg = msg_;

        tm.reset();
        tm.start();
    }

    ~Timer()
    {
        tm.stop();
        cout << msg << " " << tm.getTimeMilli() << " ms\n";
    }

    string msg;
    TickMeter tm;
};

int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        cout << "Usage: " << argv[0] << " image" << endl;
        return -1;
    }

    try
    {
        bool haveCuda = getCudaEnabledDeviceCount() > 0;

        const string openGlMatWnd = "OpenGL Mat";
        const string openGlBufferWnd = "OpenGL GlBuffer";
        const string openGlTextureWnd = "OpenGL GlTexture";
        const string openGlGpuMatWnd = "OpenGL GpuMat";
        const string matWnd = "Mat";

        namedWindow(openGlMatWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE);
        namedWindow(openGlBufferWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE);
        namedWindow(openGlTextureWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE);
        if (haveCuda)
            namedWindow(openGlGpuMatWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE);
        namedWindow("Mat", WINDOW_AUTOSIZE);

        Mat img = imread(argv[1]);

        if (haveCuda)
            setGlDevice();

        setOpenGlContext(openGlBufferWnd);
        GlBuffer buf(img, GlBuffer::TEXTURE_BUFFER);

        setOpenGlContext(openGlTextureWnd);
        GlTexture tex(img);

        GpuMat d_img;
        if (haveCuda)
            d_img.upload(img);

        cout << "=== First call\n\n";

        {
            Timer t("OpenGL Mat      ");
            imshow(openGlMatWnd, img);
        }
        {
            Timer t("OpenGL GlBuffer ");
            imshow(openGlBufferWnd, buf);
        }
        {
            Timer t("OpenGL GlTexture");
            imshow(openGlTextureWnd, tex);
        }
        if (haveCuda)
        {
            Timer t("OpenGL GpuMat   ");
            imshow(openGlGpuMatWnd, d_img);
        }
        {
            Timer t("Mat             ");
            imshow(matWnd, img);
        }

        waitKey();

        cout << "\n=== Second call\n\n";

        {
            Timer t("OpenGL Mat      ");
            imshow(openGlMatWnd, img);
        }
        {
            Timer t("OpenGL GlBuffer ");
            imshow(openGlBufferWnd, buf);
        }
        {
            Timer t("OpenGL GlTexture");
            imshow(openGlTextureWnd, tex);
        }
        if (haveCuda)
        {
            Timer t("OpenGL GpuMat   ");
            imshow(openGlGpuMatWnd, d_img);
        }
        {
            Timer t("Mat             ");
            imshow(matWnd, img);
        }

        cout << "\n";

        waitKey();
    }
    catch(const exception& e)
    {
        cout << e.what() << endl;
    }

 system("pause");
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章