OpenCV2学习笔记(二十一):GPU模块小记

接触一下OpenCV里一个之前没有接触的模块:GPU。这里只是根据教程和网上一些文章进行简单的记叙,欢迎大家批评指正。

注:在使用GPU模块之前,需要确认在使用CMake编译OpenCV时,勾选了选项WITH_CUDA和WITH_TBB使其生效生效。

OpenCV2学习笔记(二十一):GPU模块小记_第1张图片

OpenCV2学习笔记(二十一):GPU模块小记_第2张图片

若以上配置已经完成,在使用GPU模块的函数之前,还做一下检查:调用函数gpu::getCudaEnabledDeviceCount,如果你在使用的OpenCV模块编译时不支持GPU,这个函数返回值为0;否则返回值为已安装的CUDA设备的数量。

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而不是OpenCV中使用的cv::Mat,其他的函数命名和CPU模块中相同。OpenCV中GPU模块函数的使用步骤如下:

1.验证OpenCV是否已启用GPU模块。

2.上传待处理数据到GPU (Mat --> GpuMat)。

3.调用OpenCV支持的GPU的处理函数。

4.下载处理结果到CPU (GpuMat ---> Mat)。

根据http://blog.csdn.net/yang_xian521/article/details/7249532 所提到的,一个问题是对于2.0的GPU模块,多通道的函数支持的并不好,推荐使用GPU模块处理灰度的图像。有些情况下,使用GPU模块的运行速度还不及CPU模块下的性能,所以可以认为,GPU模块相对而言还不够成熟,需要进一步优化。很重要的一个原因就是内存管理部分和数据转换部分对于GPU模块而言消耗了大量的时间。

一段自带的示例代码如下,实现求矩阵转置的功能:

#include <iostream>
#include "cvconfig.h"
#include "opencv2/core/core.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/core/internal.hpp" // For TBB wrappers

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

struct Worker { void operator()(int device_id) const; };

int main()
{
    int num_devices = getCudaEnabledDeviceCount();
    if (num_devices < 2)
    {
        std::cout << "Two or more GPUs are required\n";
        return -1;
    }
    for (int i = 0; i < num_devices; ++i)
    {
        DeviceInfo dev_info(i);
        if (!dev_info.isCompatible())
        {
            std::cout << "GPU module isn't built for GPU #" << i << " ("
                 << dev_info.name() << ", CC " << dev_info.majorVersion()
                 << dev_info.minorVersion() << "\n";
            return -1;
        }
    }

    // Execute calculation in two threads using two GPUs
    int devices[] = {0, 1};
    parallel_do(devices, devices + 2, Worker());

    return 0;
}


void Worker::operator()(int device_id) const
{
    setDevice(device_id);

    Mat src(1000, 1000, CV_32F);
    Mat dst;

    RNG rng(0);
    rng.fill(src, RNG::UNIFORM, 0, 1);

    // CPU works
    transpose(src, dst);

    // GPU works
    GpuMat d_src(src);
    GpuMat d_dst;
    transpose(d_src, d_dst);

    // Check results
    bool passed = norm(dst - Mat(d_dst), NORM_INF) < 1e-3;
    std::cout << "GPU #" << device_id << " (" << DeviceInfo().name() << "): "
        << (passed ? "passed" : "FAILED") << endl;

    // Deallocate data here, otherwise deallocation will be performed
    // after context is extracted from the stack
    d_src.release();
    d_dst.release();
}

CUDA的基本使用方法:http://www.cnblogs.com/dwdxdy/archive/2013/08/07/3244508.html

参考原文:http://blog.csdn.net/yang_xian521/article/details/7249532

你可能感兴趣的:(C++,CUDA,opencv,GPU,TBB)