matlab、opencv、opencv+gpu滤波运行速度的比较

         本实验是在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滤波运行速度的比较_第1张图片

现在分别给出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高约一倍。


opencv+GPU平台
矩阵数据类型转换函数

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。图像滤波的运行效率比前面任意一种方式都低很多。







你可能感兴趣的:(效率,matlab,opencv,GPU加速,图像滤波速度)