基于Qt的Opencv代码加速
Posted 会飞的毛毛虫_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Qt的Opencv代码加速相关的知识,希望对你有一定的参考价值。
Opencv,for循环等的C++代码加速
一、使用OpenGL对Opencv进行加速
1. 什么是OpenGL?
OpenCL 是一个用于异构平台(heterogeneous platform)下编写并行程序的框架. OpenCL 的开发者可以使用所有可用的兼容计算设备, 他们找到计算机上的相应设备,然后将合适的计算任务分配给这些设备。简单理解就是利用显卡高效的处理三维二维数据。
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;
}
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和比如循环次数、里面计算的量自动计算要产生多少个线程。比如有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();
以上是关于基于Qt的Opencv代码加速的主要内容,如果未能解决你的问题,请参考以下文章