opencv3UMat介绍,以及测试比较opencl,cuda性能
来源:互联网 发布:微信数据怎么放到sd卡 编辑:程序博客网 时间:2024/05/21 18:44
在opencv中,已经嵌入了opencl运行的方式,通过使用UMat对象,opencv会自动在支持OpenCL的设备上使用GPU运算,在不支持OpenCL的设备仍然使用CPU运算,这样就避免了程序运行失败,而且统一了接口。
一般正常基于CPU的读写视频一帧图像代码如下:
cv::Mat inMat, outMat;vidInput >> inMat;cv::cvtColor(inMat, outMat, cv::COLOR_RGB2GRAY);vidOutput << outMat;基于OpenCL的GPU方式读写视频一帧图像代码如下:
cv::Mat inMat, outMat;vidInput >> inMat;cv::ocl::oclMat inOclMat(inMat);cv::ocl::oclMat outOclMat;cv::ocl::cvtColor(inOclMat, outOclMat, cv::COLOR_RGB2GRAY);outMat = outOclMat;vidOutput << outMat;
上述代码通过添加ocl前缀空间实现OpenCL支持设备的GPU运算能力提高。但是上述代码在不支持OpenCL的平台上还会运行失败,使用起来及其不方便。对开发者来说不是统一API和底层透明。
而如果在OpenCV3中使用UMat,则如下:
cv::UMat inMat, outMat;vidInput >> inMat;cv::cvtColor(inMat, outMat, cv::COLOR_RGB2GRAY);vidOutput << outMat;这样就无需像OpenCV2中那样通过显式声明的调用方式。很明显UMat与Mat极其类似。而且两者之间是可以相互转换的。
从UMat中获取Mat对象使用UMat的get方法UMat::getMat(int access_flags)支持的FLAG如下:
- ACCESS_READ
- ACCESS_WRITE
- ACCESS_RW
- ACCESS_MASK
- ACCESS_FAST
最常用的就是读写,注意当使用这种方式的时候UMat对象将会被LOCK直到CPU使用获取Mat对象完成操作,销毁临时Mat对象之后,UMat才可以再被使用。
所以我会直接使用cv::CopyTo(),可能这样做会减少错误,但不知道会有什么影响
cv::UMat aMat;cv::Mat bMat;bMat.CopyTo(aMat);aMat.CopyTo(bMat);
UMat不能提取其中某个特定元素的值,毕竟已经存到gpu中了,提取方法是先转换成Mat,再提取,下面提供一种提取方法
UMat test_umat;test_umat.getMat(ACCESS_READ).at<uchar>(row, column);注意,不要过多地进行Mat和UMat之间地转化,因为内存显存之间传递信息耗时很大,这是像我这种初学者,很容易犯的错误。
之后我打算用一段程序测试OpenCL和CUDA的性能,程序如下:
#include <iostream>#include <opencv2/opencv.hpp>#include <opencv2/core/ocl.hpp>#include <opencv2/core/cuda.hpp>#include <opencv2/cudaobjdetect.hpp>#include <opencv2/cudaimgproc.hpp>int main(int argc, char**argv) { std::cout << "OpenCV version=" << std::hex << CV_VERSION << std::dec << std::endl; cv::Mat frame; cv::UMat uframe, uFrameGray; cv::cuda::GpuMat image_gpu, image_gpu_gray; cv::VideoCapture capture("path_to_the_video"); bool useOpenCL = (argc == 2); std::cout << "Use OpenCL=" << useOpenCL << std::endl; cv::ocl::setUseOpenCL(useOpenCL); bool useCuda = (argc == 3); std::cout << "Use CUDA=" << useCuda << std::endl; cv::Ptr<cv::CascadeClassifier> cascade = cv::makePtr<cv::CascadeClassifier>("data/lbpcascades/lbpcascade_frontalface_at.xml"); cv::Ptr<cv::cuda::CascadeClassifier> cascade_gpu = cv::cuda::CascadeClassifier::create("data/lbpcascades/lbpcascade_frontalface_at.xml"); double time = 0.0; int nb = 0; if(capture.isOpened()) { for(;;) { capture >> frame; if(frame.empty() || nb >= 1000) { break; } std::vector<cv::Rect> faces; double t = 0.0; if(!useCuda) { t = (double) cv::getTickCount(); frame.copyTo(uframe); cv::cvtColor(uframe, uFrameGray, CV_BGR2GRAY); cascade->detectMultiScale(uFrameGray, faces); t = ((double) cv::getTickCount() - t) / cv::getTickFrequency(); } else { t = (double) cv::getTickCount(); image_gpu.upload(frame); cv::cuda::cvtColor(image_gpu, image_gpu_gray, CV_BGR2GRAY); cv::cuda::GpuMat objbuf; cascade_gpu->detectMultiScale(image_gpu_gray, objbuf); cascade_gpu->convert(objbuf, faces); t = ((double) cv::getTickCount() - t) / cv::getTickFrequency(); } time += t; nb++; for(std::vector<cv::Rect>::const_iterator it = faces.begin(); it != faces.end(); ++it) { cv::rectangle(frame, *it, cv::Scalar(0,0,255)); } std::stringstream ss; ss << "FPS=" << (nb / time); cv::putText(frame, ss.str(), cv::Point(30, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0,0,255)); cv::imshow("Frame", frame); char c = cv::waitKey(30); if(c == 27) { break; } } } std::cout << "Mean time=" << (time / nb) << " s" << " ; Mean FPS=" << (nb / time) << " ; nb=" << nb << std::endl; system("pause"); return 0;}
lbpcascade_frontalface_at.xml文件可以百度搜索就能下载到,是一个级联分类器训练好的模型,用于识别人脸正面,很常用。具体资料可以参考http://blog.csdn.net/yang_xian521/article/details/6973667
只需要将
cv::VideoCapture capture("path_to_the_video");
这里填入你想检测的视频的地址,时长最好在十几秒,情况视你的处理器情况所定。
再将
cv::Ptr<cv::CascadeClassifier> cascade = cv::makePtr<cv::CascadeClassifier>("data/lbpcascades/lbpcascade_frontalface_at.xml"); cv::Ptr<cv::cuda::CascadeClassifier> cascade_gpu = cv::cuda::CascadeClassifier::create("data/lbpcascades/lbpcascade_frontalface_at.xml");
两处填入下载好的xml文件的地址即可运行
运行方式为
g++ -o 文件名 文件名.cpp `pkg-config opencv --cflags --libs`
此处要链接上opencv的库,注意不要少了`这个符号,它在键盘数字1旁边。
如果额外输入一个参数,程序将利用opencl进行加速,如果额外输入两个,程序将利用cuda进行加速,没有额外参数,将正常运行
我的结果很意外,opencl基本没有加速效果,而cuda加速效果很明显,不知道原因在哪里
阅读全文
0 0
- opencv3UMat介绍,以及测试比较opencl,cuda性能
- OpenCL和CUDA简单比较
- CUDA与OpenCL编程框架的比较
- OpenCL和CUDA的使用比较
- CUDA和OpenCL异同点比较
- OpenCL & CUDA
- OpenCL、CUDA
- cuda性能测试
- CUDA性能测试
- GPGPU OpenCL/CUDA 高性能编程的10大注意事项
- GPGPU OpenCL/CUDA 高性能编程的10大注意事项
- CUDA体绘制-opencl体绘制结果对比,以及opencl梯度数据的输入结果
- 【并行计算-CUDA开发】GPGPU OpenCL/CUDA 高性能编程的10大注意事项
- Remoting、Reflection以及本地调用的性能测试比较
- 转:几种基于HTTP协议的RPC性能比较,以及ICE接口性能测试比较
- CUDA 与 OpenCL 区别
- OpenCL 与 CUDA
- Opencl和CUDA
- Tomcat 的 JDBC 连接池
- first one
- python︱用pyodbc连接数据库
- 二叉排序树与平衡二叉树
- mysql各种引擎特性对比表
- opencv3UMat介绍,以及测试比较opencl,cuda性能
- Vue+axios 实现http拦截及路由拦截实例
- 程序员最核心的竞争力是什么?
- android隐藏标题栏
- java 独立存储线程变量技术——ThreadLocal
- 利用CombineFileInputFormat合并小文件
- GPIO 输入—按键检测
- protobuf入门教程(四):repeated限定修饰符
- 数据类型及数据结构资料