OpenCV3.x中UMat對象介紹與使用

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相關技術文章,本人會用不停止!!!

發佈了269 篇原創文章 · 獲贊 1318 · 訪問量 365萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章