一、利用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. Microsoft 2013 新技术学习笔记 三

    什么是代码结构的组织?asp.net MVC 5 默认创建出的几个目录的标准含义分别如下: Controllers目录存放MVC模式中的Controler Models目录存放MVC模式中的Model ...

  2. [转]UML八大误解

    潘加宇 本文删节版发表于<程序员>2013年11期 UML(统一建模语言)是软件建模的表示法标准.我从2002年开始专门从事研究和推广UML的工作,在为软件组织提供UML相关需求和设计技能 ...

  3. Go加密解密之RSA[转]

    安全总是很重要的,各个语言对于通用的加密算法都会有实现.前段时间,用Go实现了RSA和DES的加密解密,在这分享一下.(对于RSA和DES加密算法本身,请查阅相关资料) 在PHP中,很多功能经常是一个 ...

  4. 经典SQL语句大全(网络资源共享)

    下列语句部分是Mssql语句,不可以在access中使用.  SQL分类: DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE)  DML—数据操纵语言(SELECT,DELET ...

  5. 强(strong)、软(soft)、弱(weak)、虚(phantom)引用

    https://github.com/Androooid/treasure/blob/master/source/lightsky/posts/mat_usage.md 1.1 GC Root JAV ...

  6. java攻城狮之路(Android篇)--与服务器交互

    一.图片查看器和网页源码查看器 在输入地址的是不能输入127.0.0.1 或者是 localhost.ScrollView :可以看成一个滚轴 可以去包裹很多的控件在里面 练习1(图片查看器): pa ...

  7. AjaxControlToolKit--TabContainer控件的介绍

    1.       Introduction: Tab本身就应该是个以页签形式显示组织网页内容的一个控件.在AJAX Control Tool Kit的控件中有TabContainer控件,它是一些Ta ...

  8. 超实用的JavaScript技巧及最佳实践(上)

    在这篇文章中,作者将会向大家分享JavaScript开发的小技巧.最佳实践等非常实用的内容,不管你是前端开发者还是服务端开发者,都应该来看看这些小技巧,它们绝对会让你受益的. 文中所提供的代码片段都已 ...

  9. VS2008简体中文正式版序列号-试用到期解决

    VS2008简体中文正式版序列号 VS2008简体中文正式版序列号 1.Visual Studio 2008 Professional Edition:XMQ2Y-4T3V6-XJ48Y-D3K2V- ...

  10. Web离线存储的几种方式

    随着HTML5的正式定稿,我们也可以大量使用HTML离线网络应用程序的特性. #1.Application Cache Application Cache 可以很简单让我们的WebApp具有离线的能力 ...