本实验是在win7 64位操作系统下测试,软件版本信息如下:Visual Studio2010、matlab2010a、opencv2.4.9。要使用opencv中的GPU模块,必须先对opencv利用cmake进行从新编译,具体步骤见网友贴吧http://tieba.baidu.com/p/3329042929。
实验内容是对一张300*400的灰度图(程序中对原图转灰度图)片进行11*11的DCT变换,一共有121个11*11DCT模版。每个模版对应11*11个不同频域值的系数,因为11*11的图像进行DCT离散变换会产生11*11个离散频域值,每个值都由对应的11*11尺寸的DCT模版来滤波求得。实验对这个过程重复20次,然后求平均值得到300*400的图片进行11*11DCT扫描滤波所需要的时间。下面实验采用的图片:
现在分别给出matlab、opencv、opencv+GPU、C语言自己编写滤波代码条件下的测试结果和源代码。
Matlab | Opencv | Opencv+GPU | 编写C语言函数 | |
Debug | 775.3ms | 1.1216s | 88.3ms | 太长 |
Release | 368.2ms | 82.3ms | 10.7966s |
matlab平台
下面是matlab测试代码
余弦滤波器产生函数,尺寸为11*11,一共121个
function d = DctFilter(size)
% Generates Dct filters.
for u=1:size
for v=1:size
for i=1:size
for j=1:size
pu=sqrt(2/size);
pv=sqrt(2/size);
if u==1
pu=sqrt(1/size);
end
if v==1
pv=sqrt(1/size);
end
d(u,v,i,j)=pu*pv*cos((i-0.5)*pi/size*(u-1))*cos((j-0.5)*pi/size*(v-1));
end
end
end
end
end
matlab主函数
I=imread('te.jpg');
I=rgb2gray(I);
I=double(I);
dct_filter=DctFilter(11);
t=zeros(20,1);
for n=1:20
tic
for p=1:11
for q=1:11
tmp=conv2(I,squeeze(dct_filter(p,q,:,:)),'valid');
end
end
t(n)=toc;
end
time=sum(t)/20
实验结果表明对300*400图片进行模版尺寸为11*11扫描滤波时每次耗时775.3ms
opencv平台
利用opencv自带的滤波函数进行滤波
矩阵数据类型转换函数
void im2single(Mat& src,Mat& dst)
{
int type;
type=src.type();
dst.create(src.size(),CV_32F);
switch (type)
{
case CV_8U:
src.convertTo(dst,CV_32F,1.0f/255,0);
/*src.convertTo(dst,CV_32F);
dst=dst.mul(1.0f/255); */
break;
}
}
测试主函数
#include <stdio.h>
#include <opencv.hpp>
#include "opencv2/gpu/gpu.hpp"
#include <math.h>
using namespace cv;
using namespace std;
void main()
{
float d[11][11]={};
int u,v,num,i,j,h,w;
double dmin,dmax;
float pi=3.14;
Ptr<FilterEngine> FDct[11][11];
Mat src;
Mat src_gray,dst,gray_f;
Mat kd(11,11,CV_32F);
src=imread("te.jpg");
cvtColor(src,src_gray,CV_BGR2GRAY);
im2single(src_gray,gray_f);
Size sz=src_gray.size();
h=sz.height;
w=sz.width;
dst=Mat::zeros(Size(w,h),CV_32F);
float pu;
for(u=0;u<11;u++)
for(i=0;i<11;i++)
{
pu=sqrt(2.0/11);
if(u==0)
pu=sqrt(1.0/11);
kd.at<float>(i,u)=pu*cos((i+0.5)*pi/11*u);
} //建立DCT滤波器的分离单维模版
for(i=0;i<11;i++)
for(j=0;j<11;j++)
FDct[i][j]= createSeparableLinearFilter(src_gray.type(),dst.type(), kd.col(i), kd.col(j)); //建立可分离的DCT滤波函数
double t = (double)cvGetTickCount();
for(num=0;num<20;num++)
for(u=0;u<11;u++)
for(v=0;v<11;v++)
FDct[u][v]->apply(src_gray,dst); //执行滤波操作
t = (double)cvGetTickCount() - t;
minMaxIdx(dst,&dmin,&dmax);
dst.convertTo(dst,CV_32F,1.0f/(dmax-dmin),-dmin/(dmax-dmin));
imshow( "source_window", dst );
printf( "run time = %gs\n", t/(cvGetTickFrequency()*1000000)/20 );
cvWaitKey(0);
}
实验结果表明对300*400图片进行模版尺寸为11*11扫描滤波时在release状态下每次耗时368.2ms,在debug状态下每次耗时1.1216s。可以看出opencv图像滤波运行效率比matlab高约一倍。
矩阵数据类型转换函数
void im2single(Mat& src,Mat& dst)
{
int type;
type=src.type();
dst.create(src.size(),CV_32F);
switch (type)
{
case CV_8U:
src.convertTo(dst,CV_32F,1.0f/255,0);
/*src.convertTo(dst,CV_32F);
dst=dst.mul(1.0f/255); */
break;
}
}
#include <stdio.h>
#include <opencv.hpp>
#include "opencv2/gpu/gpu.hpp"
#include <math.h>
using namespace cv;
using namespace std;
using namespace cv::gpu;
void main()
{
float d[11][11]={};
int u,v,num,i,j,h,w;
double dmin,dmax;
float pi=3.14;
Ptr<FilterEngine_GPU> FDct[11][11];
//GPU滤波函数,11*11的DCT变换模版
Mat src;
Mat src_gray,dst,gray_f;
Mat kd(11,11,CV_32F);
src=imread("te.jpg");
cvtColor(src,src_gray,CV_BGR2GRAY);
im2single(src_gray,gray_f);
GpuMat dst_gpu, src_gpu;
//GPU模块下矩阵数据类型
src_gpu.upload(gray_f);
Size sz=src_gray.size();
h=sz.height;
w=sz.width;
dst=Mat::zeros(Size(w,h),CV_32F);
float pu;
for(u=0;u<11;u++)
for(i=0;i<11;i++)
{
pu=sqrt(2.0/11);
if(u==0)
pu=sqrt(1.0/11);
kd.at<float>(i,u)=pu*cos((i+0.5)*pi/11*u);
}
for(i=0;i<11;i++)
for(j=0;j<11;j++)
FDct[i][j]= createSeparableLinearFilter_GPU(gray_f.type(),dst.type(), kd.col(i), kd.col(j));
double t = (double)cvGetTickCount();
for(num=0;num<20;num++)
for(u=0;u<11;u++)
for(v=0;v<11;v++)
FDct[u][v]->apply(src_gpu,dst_gpu);
//执行滤波操作
t = (double)cvGetTickCount() - t;
dst_gpu.download(dst);
minMaxIdx(dst,&dmin,&dmax);
dst.convertTo(dst,CV_32F,1.0f/(dmax-dmin),-dmin/(dmax-dmin));
imshow( "source_window", dst );
printf( "run time = %gs\n", t/(cvGetTickFrequency()*1000000)/20 );
cvWaitKey(0);
}
实验结果表明对300*400图片进行模版尺寸为11*11扫描滤波时在release状态下每次耗时82.3ms,在debug状态下每次耗时88.3ms。可以看出opencv+gpu图像滤波运行效率比matlab高约9倍,比单独的opencv高出约4倍。
C语言编写滤波函数
产生余弦变换Dct滤波器,尺寸为11*11,一共121个
void DctFilter( float d[11][11][11][11], int size )
{
float pi=3.14;
float pu,pv;
int u,v,i,j;
for(u=0;u<size;u++)
for(v=0;v<size;v++)
for(i=0;i<size;i++)
for(j=0;j<size;j++)
{
pu=sqrt(2.0/size);
pv=sqrt(2.0/size);
if(u==0)
pu=sqrt(1.0/size);
if(v==0)
pv=sqrt(1.0/size);
d[u][v][i][j]=pu*pv*cos((i+0.5)*pi/size*u)*cos((j+0.5)*pi/size*v);
}
}
矩阵数据类型转换函数
void im2single(Mat& src,Mat& dst)
{
int type;
type=src.type();
dst.create(src.size(),CV_32F);
switch (type)
{
case CV_8U:
src.convertTo(dst,CV_32F,1.0f/255,0);
/*src.convertTo(dst,CV_32F);
dst=dst.mul(1.0f/255); */
break;
}
}
滤波执行函数
void imfilter(Mat& src_gray,Mat& dst,float d[11][11])
{
int h,w;
float tmp;
Size sz=src_gray.size();
h=sz.height;
w=sz.width;
//dst.create(size(h-10,w-10),src_gray.type);
dst=Mat::zeros(Size(w-10,h-10),src_gray.type());
int i,j,m,n;
for(i=5;i<h-6;i++)
{
for(j=5;j<w-6;j++)
{
for(m=-5;m<6;m++)
for(n=-5;n<6;n++)
{
dst.at<float>(i-5,j-5)+=src_gray.at<float>(i+m,j+n)*d[m+5][n+5];
}
}
}
}
测试函数:
在Release状态下测试,在Debug状态下运行会比Release状态下慢很多。
#include <stdio.h>
#include <opencv.hpp>
#include "opencv2/gpu/gpu.hpp"
#include <math.h>
using namespace cv;
using namespace std;
void main()
{
float d[11][11][11][11]={};
int u,v,num;
double dmin,dmax;
Mat src;
Mat src_gray,dst,gray_f;
src=imread("te.jpg");
cvtColor(src,src_gray,CV_BGR2GRAY);
DctFilter(d,11); //产生DCT滤波模版
im2single(src_gray,gray_f); //将原始数据转化为单精度类型
double t = (double)cvGetTickCount();
for(num=0;num<20;num++)
for(u=0;u<11;u++)
for(v=0;v<11;v++)
imfilter(gray_f,dst,d[u][v]); //对每个Dct模版进行滤波操作
t = (double)cvGetTickCount() - t;
minMaxIdx(dst,&dmin,&dmax);
dst.convertTo(dst,CV_32F,1.0f/(dmax-dmin),-dmin/(dmax-dmin));
imshow( "source_window", dst );
printf( "run time = %gs\n", t/(cvGetTickFrequency()*1000000)/20 );
cvWaitKey(0);
}
由于代码效率明显很低,只测试了release条件下对300*400图片进行模版尺寸为11*11扫描滤波时在release状态下每次耗时10.7966s。图像滤波的运行效率比前面任意一种方式都低很多。