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