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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值