一、利用OpenCV中提供的GPU模块

  目前,OpenCV中已提供了许多GPU函数,直接使用OpenCV提供的GPU模块,可以完成大部分图像处理的加速操作。

  基本使用方法,请参考:http://www.cnblogs.com/dwdxdy/p/3244508.html

  该方法的优点是使用简单,利用GpuMat管理CPU与GPU之间的数据传输,而且不需要关注内核函数调用参数的设置,使用过程中,只需要关注处理的逻辑操作。

  缺点是受限于OpenCV库的发展和更新,当需要完成一些自定义的操作时(OpenCV中没有提供相应的库),难以满足应用的需求,需要自己实现自定义操作的并行实现。此外,针对一些特殊需求,OpenCV提供并行处理函数,其性能优化并不是最优的,在具体的应用时,可能需要进一步优化,提高性能。

二、单独使用Cuda API编程

  利用Cuda Runtime API、Cuda Driver API实现一些操作的并行加速,使用过程需要管理CPU与GPU之间的数据传输,内核函数调用参数的设置,内核函数的优化等。

  优点是处理过程受控于用户,用户可以实现更多的并行加速处理操作。

  缺点是使用复杂,代码编写量较多,需要熟悉Cuda相关资料和API接口。下面是简单的示例程序:

__global__ void swap_rb_kernel(const uchar3* src,uchar3* dst,int width,int height)
{
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.x + blockIdx.y * blockDim.y; if(x < width && y < height)
{
uchar3 v = src[y * width + x];
dst[y * width + x].x = v.z;
dst[y * width + x].y = v.y;
dst[y * width + x].z = v.x;
}
} void swap_rb_caller(const uchar3* src,uchar3* dst,int width,int height)
{
dim3 block(,);
dim3 grid((width + block.x - )/block.x,(height + block.y - )/block.y); swap_rb_kernel<<<grid,block,>>>(src,dst,width,height);
cudaThreadSynchronize();
} int main()
{
Mat image = imread("lena.jpg");
imshow("src",image); size_t memSize = image.cols*image.rows*sizeof(uchar3);
uchar3* d_src = NULL;
uchar3* d_dst = NULL;
CUDA_SAFE_CALL(cudaMalloc((void**)&d_src,memSize));
CUDA_SAFE_CALL(cudaMalloc((void**)&d_dst,memSize));
CUDA_SAFE_CALL(cudaMempcy(d_src,image.data,memSize,cudaMemcpyHostToDevice)); swap_rb_caller(d_src,d_dst,image.cols,image.rows); CUDA_SAFE_CALL(cudaMempcy(image.data,d_dst,memSize,cudaMemcpyDeviceToHost));
imshow("gpu",image);
waitKey(); CUDA_SAFE_CALL(cudaFree(d_src));
CUDA_SAFE_CALL(cudaFree(d_dst));
return ;
}

  上述代码中,使用cudaMalloc,cudaMemcpy,cudaFree管理内存的分配、传输和释放。

  注意:若image.data包含字节对齐的空白数据,上述程序无法完成正常的处理操作。

三、利用OpenCV中提供接口,并结合Cuda API编程

  利用OpenCV已经提供的部分接口,完成一些Cuda编程的基本处理,简化编程的复杂程度;只是根据自己业务需求,自定义内核函数或扩展OpenCV已提供的内核函数。这样既可以充分利用OpenCV的特性,又可以满足业务的不同需求,使用方便,且易于扩展。下面是简单的示例程序:

//swap_rb.cu
#include <opencv2/core/cuda_devptrs.hpp>
using namespace cv;
using namespace cv::gpu;
//自定义内核函数
__global__ void swap_rb_kernel(const PtrStepSz<uchar3> src,PtrStep<uchar3> dst)
{
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y; if(x < src.cols && y < src.rows)
{
uchar3 v = src(y,x);
dst(y,x) = make_uchar3(v.z,v.y,v.x);
}
} void swap_rb_caller(const PtrStepSz<uchar3>& src,PtrStep<uchar3> dst,cudaStream_t stream)
{
dim3 block(,);
dim3 grid((src.cols + block.x - )/block.x,(src.rows + block.y - )/block.y); swap_rb_kernel<<<grid,block,,stream>>>(src,dst);
if(stream == )
cudaDeviceSynchronize();
}
//swap_rb.cpp
#include <opencv2/gpu/gpu.hpp>
#include <opencv2/gpu/stream_accessor.hpp>
using namespace cv;
using namespace cv::gpu; void swap_rb_caller(const PtrStepSz<uchar3>& src,PtrStep<uchar3> dst,cudaStream_t stream); void swap_rb(const GpuMat& src,GpuMat& dst,Stream& stream = Stream::Null())
{
CV_Assert(src.type() == CV_8UC3);
dst.create(src.size(),src.type());
cudaStream_t s = StreamAccessor::getStream(stream);
swap_rb_caller(src,dst,s);
}
//main.cpp
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/gpu/gpu.hpp>
using namespace cv;
using namespace cv::gpu;
void swap_rb(const GpuMat& src,GpuMat& dst,Stream& stream = Stream::Null());
int main()
{
Mat image = imread("lena.jpg");
imshow("src",image);
GpuMat gpuMat,output; gpuMat.upload(image);
swap_rb(gpuMat,output);
output.download(image); imshow("gpu",image);
waitKey();
return ;
}

  swap_rb.cu文件定义了内核函数和内核函数的调用函数,在调用函数中,设置内核函数的调用参数。

  swap_rb.cpp文件定义了并行操作的入口函数,即主程序完成并行操作的需要调用的函数,其主要是封装内核函数的调用函数,并添加输入参数的验证、根据输入参数选择不同内核函数等操作。

  main.cpp文件主程序,完成数据的输入、业务的处理和数据的输出。

总结

  编程简易性和可控性是相对的,编程越方便,就越不容易控制。实际应用过程中,应当寻求编程简易性和可控性的平衡点,应根据应用需求,选取适当的方法,一般建议采用方法三。

【OpenCV & CUDA】OpenCV和Cuda结合编程的更多相关文章

  1. 《CUDA并行程序设计:GPU编程指南》

    <CUDA并行程序设计:GPU编程指南> 基本信息 原书名:CUDA Programming:A Developer’s Guide to Parallel Computing with ...

  2. CUDA 8的混合精度编程

    CUDA 8的混合精度编程 Volta和Turing GPU包含 Tensor Cores,可加速某些类型的FP16矩阵数学运算.这样可以在流行的AI框架内更快,更轻松地进行混合精度计算.要使用Ten ...

  3. 【OpenCV入门教程之一】 安装OpenCV:OpenCV 3.0 +VS 2013 开发环境配置

    图片太多,具体过程参照: [OpenCV入门教程之一] 安装OpenCV:OpenCV 3.0.OpenCV 2.4.8.OpenCV 2.4.9 +VS 开发环境配置 说下我这边的设置: 选择deb ...

  4. [OpenCV] Install OpenCV 3.3 with DNN

    OpenCV 3.3 Aug 3, 2017 OpenCV 3.3 has been released with greatly improved Deep Learning module and l ...

  5. 【CUDA开发】CUDA面内存拷贝用法总结

    [CUDA开发]CUDA面内存拷贝用法总结 标签(空格分隔): [CUDA开发] 主要是在调试CUDA硬解码并用D3D9或者D3D11显示的时候遇到了一些代码,如下所示: CUdeviceptr g_ ...

  6. 【并行计算-CUDA开发】CUDA软件架构与Nvidia硬件对应关系

    前面扯了很多,不过大多都是在讲CUDA 在软体层面的东西:接下来,虽然Heresy 自己也不熟,不过还是来研究一下硬体的部分吧-毕竟要最佳化的时候,好像还是要大概知道一下相关的东西的.这部分主要参考资 ...

  7. ffmpeg+cuda+opencv

    为了让ffmpeg使用gpu进行解码,可以按以下步骤: 1 下载nvidia官网提供的ffmpeg,编译安装 https://developer.nvidia.com/ffmpeg 注意原来的选项上还 ...

  8. CUDA+OpenCV 绘制朱利亚(Julia)集合图形

    Julia集中的元素都是经过简单的迭代计算得到的,很适合用CUDA进行加速.对一个600*600的图像,需要进行360000次迭代计算,所以在CUDA中创建了600*600个线程块(block),每个 ...

  9. opencv 4.0 + linux + cuda静态编译

    #下载最新的opencv git clone "https://github.com/opencv/opencv.git" git clone "https://gith ...

  10. Pitfalls of using opencv GpuMat data in CUDA kernel code

    Please note that cv::cuda::GpuMat and cv::Mat using different memory allocation method. cv::cuda::Gp ...

随机推荐

  1. Win7“当前用户没有安装Microsoft Office"

    故障:在win7 win10系统已安装office2007~但打开word excel应用程序时提示"当前用户没有安装Microsoft Office". 原因:office200 ...

  2. php 碎片笔记

    1.修改 php.ini 加载路径 添加环境变量 ,新建系统变量 PHPRC ,配置如下: 检验: 通过phpinfo(),查看系统配置 Loaded Configuration File ,识别系统 ...

  3. 安卓开发笔记——关于图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)

    在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...

  4. Simple Molecules(简单)

    Simple Molecules time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  5. Ip 地址

    访问 ip.mayfirst.org可以显示你的ip地址,如果你可以联网的话.

  6. SQL SERVER 使用select和union插入多条数据

    insert into A(A) select '2' union select '3' union select '100' go select * from A

  7. MYSQL开发性能研究——批量插入的优化措施

    一.我们遇到了什么问题 在标准SQL里面,我们通常会写下如下的SQL insert语句. INSERT INTO TBL_TEST (id) VALUES(1);   很显然,在MYSQL中,这样的方 ...

  8. 利用SVN工具下载OpenCore代码

    OpenCore原来使用的是CVS管理代码的.从09年起,更换用SVN管理代码,大家可以用TortoiseSVN软件下载代码,网址是:http://tortoisesvn.net/,安装后tortoi ...

  9. Linux下grep显示前后几行信息

    Linux下grep显示前后几行信息 标准unix/linux下的grep通过下面參数控制上下文 grep -C 5 foo file 显示file文件里匹配foo字串那行以及上下5行grep -B ...

  10. 深入理解javascript事件

    .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier ...