Opencv,for回圈等的C++代碼加速
一、使用OpenGL對Opencv進行加速
1. 什么是OpenGL?
OpenCL 是一個用于異構平臺(heterogeneous platform)下撰寫并行程式的框架. OpenCL 的開發者可以使用所有可用的兼容計算設備, 他們找到計算機上的相應設備,然后將合適的計算任務分配給這些設備,簡單理解就是利用顯卡高效的處理三維二維資料,
-
OpenCV開發者無須知道任何關于OpenCL的底層實作,因為OpenCV已經將OpenCL的細節隱藏在了 Transparent API中,
2. 什么是Transparent API?
Transparent API 是一種簡單的方法,其對現有代碼進行最小的更改,便可以將硬體加速無縫地添加到OpenCV代碼中,通過進行很小的更改, 可以使現有代碼提高數量級的加速,
-
Transparent API 主要是使用了OpenCL來進行加速,盡可能地呼叫硬體現有的最好資源來運行代碼(只加速部分代碼),如有GPU的情況下,就不使用CPU,所以一般情況下,可以達到加速的作用!
-
使用Transparent API 非常簡單,通過更改一個關鍵字,即可以獲得顯著的性能提升(如將Mat換成UMat),
3. 什么是UMat?
UMat(Unified Matrix)是OpenCV3.0引入的新特性,屬于OpenCV Transparent API(T-api or TAPI),主要用來提升性能,
-
UMat與Mat的最大不同在于,UMat盡可能地呼叫硬體現有的最好資源,如有GPU的情況下,就不使用CPU,所以一般情況下,可以達到加速的作用,
-
僅當對影像做一些昂貴計算時,Transparent API效果才顯著,因為,將影像移動到GPU中計算,這一程序本身也相當耗時的,
-
第一次運行代碼需要初始化硬體環境,所以UMat可能沒有CPU的Mat運算快,但隨后的計算就會快不少,
-
UMat.copyTo(Mat)很耗時,imshow(“UMat”,umat)時內部也要UMat.copyTo(Mat)把GPU的時間回傳到CPU,
-
因為UMat和Mat有著共同的基類InputOutputArray,所以大部分OpenCV的函式UMat都能使用,但是UMat自帶的方法沒有Mat豐富,比如說,UMat沒有data指標指向資料,沒有ptr<>方法,
UMat的使用方法:
Mat轉UMat:
方法1:
UMat img;
imread("image.jpg", 0).copyTo(img);
方法2:
Mat mat = imread("image.jpg", 0);
UMat umat;
mat.copyTo(umat);
方法3:
Mat mat = imread("image.jpg", 0);
UMat umat = mat.getUMat( flag );//flag可取:ACCESS_READ, ACCESS_WRITE, ACCESS_RW and ACCESS_FAST
UMat轉Mat:
Mat mat = umat.getMat( flag );
官方給的Mat與UMat速度測驗(C++ Demo):
#include "opencv2/opencv.hpp"
using namespace cv;
int main(int argc, char** argv)
{
// ******* No Transparent API(UMat) *******
double mat_start = static_cast<double>(getTickCount());
Mat img, gray;
img = imread(argv[1], IMREAD_COLOR);
cvtColor(img, gray, CV_BGR2GRAY);
GaussianBlur(gray, gray, Size(7,7), 1.5);
Canny(gray, gray, 0, 50);
std::cout << "Mat costs time: "<< static_cast<double>((getTickCount() - mat_start) / getTickFrequency()) << " s..."<< std::endl;
imshow("edges", gray);
//waitKey(0);
// ******* Transparent API(UMat) *******
double umat_start = static_cast<double>(getTickCount());
UMat uimg, ugray;
imread(argv[1], IMREAD_COLOR).copyTo(uimg);
cvtColor(uimg, ugray, COLOR_BGR2GRAY);
GaussianBlur(ugray, ugray, Size(7,7), 1.5);
Canny(ugray, ugray, 0, 50);
std::cout << "UMat costs time: " << static_cast<double>((getTickCount() - umat_start) / getTickFrequency()) << " s..." << std::endl;
imshow("edges_UMat", ugray);
waitKey(0);
return 0;
}
-
實際測驗后發現,除過第一次運算,后面的運算UMat至少快小數點后一個零,
4. OCL Module 和 Transparent API的區別 ?
-
在OpenCV3中,OCL module已經被舍棄,而是使用更易上手的Transparent API來替代 OCL module,因此只需要使用 UMat來替換Mat,而其余的代碼保持不變,即可實作加速,
二、使用OpenCV小技巧
- Opencv中32位和8位整形的運算時間大致相等---------所以用32位處理影像資料會更快,
三、Openmp的使用
假如我們有100萬條資料,把們把它切割成10份,再開辟10個執行緒分別計算,其實是非常麻煩的,而它看起來是有套路的,我們有什么辦法可以讓編譯器自動把一個串行的for回圈這種代碼轉成一個多執行緒的并行代碼呢, 這個時候就有一個工具,這個工具叫OpenMP (Open Multi-Processing)即共享存盤并行計算,
-
Openmp適用于電腦里面有多個CPU,或多個核,我就可以讓你的代碼從串行計算自動轉換為并行計算,它和我們用的執行緒不一樣,它提供了對并行演算法的高層抽象描述
Openmp的實質只是把我們手工切割執行緒這種程序給自動化了,但這種自動化方案的優點是它會自動根據你的CPU和比如回圈次數、里面計算的量自動計算要產生多少個執行緒,比如有1萬條資料,在八核電腦上開發,那就開八個執行緒,這樣如果把程式放在另外一臺電腦上,那臺電腦是4個執行緒,如果我在那個四臺電腦上開八個執行緒的話就會把速度拖慢,Openmp可以自動識別你的CPU的核數,到底是多少個并發,自動調節說創建多少個執行緒,當然,你也有一些方式去操縱它,比如限制最大執行緒數量,限制緩沖區大小,這些都是可以去限制的,
四、使用Qt小技巧
- OpenCV中的影像主要存盤在Mat類中,要讓其顯示在Qt的Label控制元件上,必須先將其轉換為Qt的QImage類,Mat類影像是按照BGR順序存盤的影像,而QImage是按照RGB順序存盤的,在型別轉換前需要將通道更改,
srcImg = imread("00.jpg");
cvtColor(srcImg, grayImg, CV_BGR2GRAY);
Mat temp;
QImage Qtemp;
if (!isGray)
{
cvtColor(srcImg, temp, CV_BGR2RGB);//BGR convert to RGB
Qtemp = QImage((const unsigned char*)(temp.data), temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
}
else
{
cvtColor(grayImg, temp, CV_GRAY2RGB);//GRAY convert to RGB
Qtemp = QImage((const unsigned char*)(temp.data), temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
}
ui.label->setPixmap(QPixmap::fromImage(Qtemp));
ui.label->resize(Qtemp.size());
ui.label->show();
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300074.html
標籤:其他
