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;
上述代碼通過添加ocl前綴空間實現OpenCL支持設備的GPU運算能力提高。但是上述代碼在不支持OpenCL的平臺上還會運行失敗,使用起來及其不方便。對開發者來說不是統一API和底層透明。
於是OpenCV在3.0版本中開始引入了T-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;
}
特別注意
代碼基於VS2015與OpenCV3.1實現,歡迎大家繼續關注本人博客!分享有用實用的圖像處理技術與OpenCV相關技術文章,本人會用不停止!!!