Opencv直方图计算是否需要Gpu加速?

时间:2022-08-11 16:31:54

        众所周知,Gpu加速技术对图像处理具有很大的影响,在前面的博客中点击打开链接通过对比验证了Gpu加速技术对图像滤波的高效率。但是Gpu技术并不是万能的,本文通过比较发现Gpu计算直方图的效率并没有传统计算方法效率高。下面表格是对比结果,时间是通过运行20次求平均值而得,后面给出相应的比较代码。由结果可以看出Cpu计算直方图是运行效率更高,当对图片数据库进行训练时,如果有5000幅图片需要处理,采用Cpu计算方式可以节省75分钟左右的时间,节省的时间还是相当可观的。

Gpu与Cpu计算直方图效率对比
方式 Cpu内存 Gpu内存
效率 0.855328s 1.71659s

测试图片如下所示,大小为400*300,在测试前程序中会转为灰度图。

Opencv直方图计算是否需要Gpu加速?
利用histEven函数在Gpu内存中计算直方图,运行20次后平均运行时间为1.71659s。下面的代码有的头文件不是必须的。

#include <stdio.h>
#include <tchar.h>
#include <afxwin.h>
#include <opencv.hpp>
#include <opencv2/gpu/gpu.hpp>
#include <fstream>
#include <algorithm>
#include "my_function.h"
#include <memory>
#include<vector>

#define pi 3.14156
#define CLASSNUM 102
#define TR_NUM 15
#define TE_NUM 15
using namespace std ;
using namespace cv ;
using namespace cv::gpu;
int _tmain(int argc, _TCHAR* argv[])
{
Mat img = imread("sunflower.jpg",0);//读取图 像 文件
Ptr<FilterEngine_GPU> FDct[11][11];
GpuMat dst_gpu, src_gpu;
Mat kd;
Mat dst;
double fmin,fmax;
DctFilter(kd,11);//建立DCT变换滤波器
for(int i=0;i<11;i++)
for(int j=0;j<11;j++)
FDct[i][j]= createSeparableLinearFilter_GPU(CV_8U,CV_32F, kd.col(i), kd.col(j));//构造Opencv滤波器类对象
double t = (double)cvGetTickCount();
src_gpu.upload(img);//上传数据到Gpu内存中
for(int k=0;k<20;k++)
{
for(int u=0;u<11;u++)
for(int v=0;v<11;v++)
{
FDct[u][v]->apply(src_gpu,dst_gpu); //执行滤波操作
normalize(dst_gpu,dst_gpu,255.0,0.0,NORM_MINMAX);//滤波后矩阵数值范围规范化到0~255
dst_gpu.convertTo(dst_gpu,CV_8U);//histEven函数需要CV_8U, CV_16U, or CV_16S数据类型
histEven(dst_gpu,dst_gpu,10,0,255);//在Gpu内存中计算直方图
normalize(dst_gpu,dst_gpu,1.0,0.0,NORM_MINMAX);//对直方图统计值规范化到0~1之间
dst_gpu.download(dst);//从Gpu内存中读取数据
}
}
t=(double)cvGetTickCount()-t;
printf( "run time = %gs\n", t/(cvGetTickFrequency()*1000000)/20 );
system("pause");
}

利用 calcHist 函数在电脑内存中计算直方图,运行20次后平均运行时间为0.855328s。下面的代码有的头文件不是必须的。

#include <stdio.h>
#include <tchar.h>
#include <afxwin.h>
#include <opencv.hpp>
#include <opencv2/gpu/gpu.hpp>
#include <fstream>
#include <algorithm>
#include "my_function.h"
#include <memory>
#include<vector>
#define pi 3.14156
#define CLASSNUM 102
#define TR_NUM 15
#define TE_NUM 15
using namespace std ;
using namespace cv ;
using namespace cv::gpu;
int _tmain(int argc, _TCHAR* argv[])
{
Mat img = imread("sunflower.jpg",0);//读取图 像 文件
Ptr<FilterEngine_GPU> FDct[11][11];
GpuMat dst_gpu, src_gpu;
Mat kd;
Mat dst;
double fmin,fmax;
DctFilter(kd,11);//建立DCT变换滤波器
for(int i=0;i<11;i++)
for(int j=0;j<11;j++)
FDct[i][j]= createSeparableLinearFilter_GPU(CV_8U,CV_32F, kd.col(i), kd.col(j));//构造Opencv滤波器类对象
double t = (double)cvGetTickCount();
src_gpu.upload(img);//上传数据到Gpu内存中
for(int k=0;k<20;k++)
{
for(int u=0;u<11;u++)
for(int v=0;v<11;v++)
{
FDct[u][v]->apply(src_gpu,dst_gpu);//执行滤波操作
dst_gpu.download(dst);//从Gpu内存中读取数据
minMaxIdx(dst,&fmin,&fmax);
dst.convertTo(dst,CV_8U,255.0/(fmax-fmin),-255.0*fmin/(fmax-fmin));//滤波后矩阵数值范围规范化到0~255
int histSize[] = {10};
float hranges[] = { 0, 256 };
const float* ranges[] = { hranges };
MatND hist;
int channels[] = {0};
calcHist( &dst, 1, channels, Mat(), // do not use mask
hist, 1, histSize, ranges,
true, // the histogram is uniform
false );
double maxVal=0;
minMaxLoc(hist, 0, &maxVal, 0, 0);
hist=hist.mul(1.0f/maxVal);//对直方图统计值规范化到0~1之间
}
}
t=(double)cvGetTickCount()-t;
printf( "run time = %gs\n", t/(cvGetTickFrequency()*1000000)/20.0 );
system("pause");