基于Qt的代码加速(含Opencv)

一、使用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();
  • QGraphicsView要比QLabel在显示图像方面效率更高。
  • 众所周知,使用QLabel的setPixmap()就可以将图片显示出来,但使用QLabel很耗费CPU,播放画面过多有卡卡的感觉,drawPixmap()使用GPU处理,相对减轻了CPU的负担。QPainter使用drawImage()函数的地方效率不如为drawPixmap();
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@会飞的毛毛虫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值