OpenCV3.x中UMat介绍与使用
OpenCV3中引入了一个新的图像容器对象UMat,它跟Mat有着多数相似的功能和相同的API函数,但是代表的意义却太不一样。要说到UMat对象的来龙去脉,必须首先从OpenCL来开始说,OpenCL是一个面向异构系统通用的并行编程标准,这个标准最早是苹果公司提出,后来变成了一个国际标准,目的是通过它开发通用的GPU计算软件,中国的华为是该标准的成员之一。说的直白点就是如果CPU或者GPU支持OpenCL标准,就可以通过OpenCL相关编程实现使用GPU计算。OpenCV2.x开始支持它,不过那个时候这个功能很不好用,大致一般正常基于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;
而且上述代码在不支持OpenCL的平台上还会运行失败,使用起来及其不方便。对开发者来说不是统一API和底层透明。
于是OpenCV在3.0版本中开始引入了T-API(Transparent API)设计理念,即通过设计一套对开发者来说底层透明,接口统一的API调用方式,避免由于系统不支持OpenCL而导致程序运行失败,这个就是UMat图像容器类型。通过使用UMat对象,OpenCV会自动在支持OpenCL的设备上使用GPU运算,在不支持OpenCL的设备仍然使用CPU运算,这样就避免了程序运行失败,而且统一了接口。上述代码在OpenCV3中使用UMat改下如下:
cv::UMat inMat, outMat;vidInput >> inMat;cv::cvtColor(inMat, outMat, cv::COLOR_RGB2GRAY);vidOutput << outMat;
这样就无需像OpenCV2中那样通过显式声明的调用方式。很明显UMat与Mat极其类似。而且两者之间是可以相互转换的。
Mat与UMat相互转换
从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才可以再被使用。
从Mat中获取UMat
通过Mat::getUMat()之后就获取一个UMat对象,同样在UMat对象操作期间,作为父对象Mat也会被LOCK直到子对象UMat销毁之后才可以继续使用。
OpenCV的官方文档说不鼓励在一个方法和一段代码中同时使用Mat与UMat两种方式,因为这样做真的非常危险。此外Mat与UMat还可以相互拷贝,但是这种方式也不是OpenCV官方提倡与推荐的,所以尽量别用这种方式。
代码示例与演示
使用UMat读取视频并将视频每一帧转换为灰度显示
#include <opencv2/opencv.hpp>#include <opencv2/tracking.hpp>#include <iostream>using namespace cv;using namespace std;int main(int argc, char** argv) { VideoCapture capture; capture.open("D:/vcprojects/images/sample.mp4"); if (!capture.isOpened()) { printf("could not load video data...n"); return -1; } // UMat方式读取视频,转为灰度显示-自动启用GPU计算 // 如果显卡支持OpenCL UMat frame, gray; namedWindow("UMat Demo", CV_WINDOW_AUTOSIZE); while (capture.read(frame)) { cvtColor(frame, gray, COLOR_BGR2GRAY); imshow("UMat Demo", gray); char c = waitKey(100); if (c == 27) { break; } } // 释放资源 capture.release(); waitKey(0); return 0;}
此外小编基于OpenCV扩展模块使用UMat实现多对象跟踪跟Mat版本相比较,在本人的笔记本上明显可以看到速度得到提升。视频读取与多对象跟踪效果显示如下:
- Core-periphery decomposition--核心-外围模型R代码整理
- 停止数据库没有响应的问题分析(r9笔记第51天)
- Hive——巧用transform处理复杂的字符串问题
- 停止数据库没有响应的问题分析(r9笔记第50天)
- 一个SQL语句引发的ORA-00600错误排查(一) (r9笔记第64天)
- 一个SQL语句引发的ORA-00600错误排查(二)(r9笔记第65天)
- 关于all_procedures的问题分析 (r9笔记第61天)
- 半自动化搭建Data Guard的想法和实践(一) (r9笔记第74天)
- Go语言位操作实例
- 通过Snapshot Standby来精确评估SQL性能 (r9笔记第73天)
- mongodb11天之屠龙宝刀(三)基本操作:增删改查与mysql对比
- Go语言 实现bitmap
- 最近的几个技术问题总结和答疑(八) (r9笔记第72天)
- Java基础-day05-代码题
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 解决Centos8无法安装docker的问题
- 正则表达式
- Python函数详解一(函数参数、变量作用域)
- Java9改进try-with-resources语法
- 如何用Python实现网页转PDF
- LeetCode 242. 有效的字母异位词
- 再见Excel!最强国产开源在线表格Luckysheet走红GitHub
- 快速学习Python之迭代器和生成器
- js事件冒泡
- Deepin创建应用快捷方式
- SecureCRT下Python脚本编写
- 一篇文章上手Vue3中新增的API
- 先电OpenStack卸载脚本
- 先电OpenStack之neutron-vlan脚本
- 【7】进大厂必须掌握的面试题-Java面试-Jsp