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、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。圖像濾波的運行效率比前面任意一種方式都低很多。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章