本实验是在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 endmatlab主函数
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。图像滤波的运行效率比前面任意一种方式都低很多。