Gabor的OpenCV程式碼

查志強發表於2014-11-25

【原文:http://blog.csdn.net/pi9nc/article/details/8618579

    最近弄人臉識別,用到Gabor卷積核,但網上的程式碼似乎沒有和我心意的,於是參考了自己寫了下!參考了Zhou Mian以及matlab的Gabor實現程式碼的程式碼。雖然OpenCV的imporc下面有個gabor.cpp,但那個是一般形式的公式,不是用來做人臉識別的,可以參考文獻A review on Gabor wavelets for face recognition,又說到。上程式碼和連結地址!下載地址~

   目前程式碼未經過更多的測試,不少功能為加入,但可以滿足許多人的使用和參考了吧,很多人肯定非常非常需要,先開源下,歡迎指出錯誤之處。

  1. //GaborFR.h  
  1. #pragma once  
  2. #include "opencv2\opencv.hpp"  
  3. #include <vector>  
  4. using namespace std;  
  5. using namespace cv;  
  6. class GaborFR  
  7. {  
  8. public:  
  9.     GaborFR();  
  10.     static Mat  getImagGaborKernel(Size ksize, double sigma, double theta,   
  11.                                     double nu,double gamma=1, int ktype= CV_32F);  
  12.     static Mat  getRealGaborKernel( Size ksize, double sigma, double theta,   
  13.                                     double nu,double gamma=1, int ktype= CV_32F);  
  14.     static Mat  getPhase(Mat &real,Mat &imag);  
  15.     static Mat  getMagnitude(Mat &real,Mat &imag);  
  16.     static void getFilterRealImagPart(Mat& src,Mat& real,Mat& imag,Mat &outReal,Mat &outImag);  
  17.     static Mat  getFilterRealPart(Mat& src,Mat& real);  
  18.     static Mat  getFilterImagPart(Mat& src,Mat& imag);  
  19.   
  20.     void        Init(Size ksize=Size(19,19), double sigma=2*CV_PI,  
  21.                     double gamma=1, int ktype=CV_32FC1);  
  22. private:  
  23.     vector<Mat> gaborRealKernels;  
  24.     vector<Mat> gaborImagKernels;  
  25.     bool isInited;  
  26. };  

  1. #include "stdafx.h"  
  2. #include "GaborFR.h"  
  3. GaborFR::GaborFR()  
  4. {  
  5.     isInited = false;  
  6. }  
  7. void GaborFR::Init(Size ksize, double sigma,double gamma, int ktype)  
  8. {  
  9.     gaborRealKernels.clear();  
  10.     gaborImagKernels.clear();  
  11.     double mu[8]={0,1,2,3,4,5,6,7};  
  12.     double nu[5]={0,1,2,3,4};  
  13.     int i,j;  
  14.     for(i=0;i<5;i++)  
  15.     {  
  16.         for(j=0;j<8;j++)  
  17.         {  
  18.             gaborRealKernels.push_back(getRealGaborKernel(ksize,sigma,mu[j]*CV_PI/8,nu[i],gamma,ktype));  
  19.             gaborImagKernels.push_back(getImagGaborKernel(ksize,sigma,mu[j]*CV_PI/8,nu[i],gamma,ktype));  
  20.         }  
  21.     }  
  22.     isInited = true;  
  23. }  
  24. Mat GaborFR::getImagGaborKernel(Size ksize, double sigma, double theta, double nu,double gamma, int ktype)  
  25. {  
  26.     double  sigma_x     = sigma;  
  27.     double  sigma_y     = sigma/gamma;  
  28.     int     nstds       = 3;  
  29.     double  kmax        = CV_PI/2;  
  30.     double  f           = cv::sqrt(2.0);  
  31.     int xmin, xmax, ymin, ymax;  
  32.     double c = cos(theta), s = sin(theta);  
  33.     if( ksize.width > 0 )  
  34.     {  
  35.         xmax = ksize.width/2;  
  36.     }  
  37.     else//這個和matlab中的結果一樣,預設都是19 !  
  38.     {  
  39.         xmax = cvRound(std::max(fabs(nstds*sigma_x*c), fabs(nstds*sigma_y*s)));  
  40.     }  
  41.     if( ksize.height > 0 )  
  42.     {  
  43.         ymax = ksize.height/2;  
  44.     }  
  45.     else  
  46.     {  
  47.         ymax = cvRound(std::max(fabs(nstds*sigma_x*s), fabs(nstds*sigma_y*c)));  
  48.     }  
  49.     xmin = -xmax;  
  50.     ymin = -ymax;  
  51.     CV_Assert( ktype == CV_32F || ktype == CV_64F );  
  52.     float*  pFloat;  
  53.     double* pDouble;  
  54.     Mat kernel(ymax - ymin + 1, xmax - xmin + 1, ktype);  
  55.     double k        =   kmax/pow(f,nu);  
  56.     double scaleReal=   k*k/sigma_x/sigma_y;  
  57.     forint y = ymin; y <= ymax; y++ )  
  58.     {  
  59.         if( ktype == CV_32F )  
  60.         {  
  61.             pFloat = kernel.ptr<float>(ymax-y);  
  62.         }  
  63.         else  
  64.         {  
  65.             pDouble = kernel.ptr<double>(ymax-y);  
  66.         }  
  67.         forint x = xmin; x <= xmax; x++ )  
  68.         {  
  69.             double xr = x*c + y*s;  
  70.             double v = scaleReal*exp(-(x*x+y*y)*scaleReal/2);  
  71.             double temp=sin(k*xr);  
  72.             v   =  temp*v;  
  73.             if( ktype == CV_32F )  
  74.             {  
  75.                 pFloat[xmax - x]= (float)v;  
  76.             }  
  77.             else  
  78.             {  
  79.                 pDouble[xmax - x] = v;  
  80.             }  
  81.         }  
  82.     }  
  83.     return kernel;  
  84. }  
  85. //sigma一般為2*pi  
  86. Mat GaborFR::getRealGaborKernel( Size ksize, double sigma, double theta,   
  87.     double nu,double gamma, int ktype)  
  88. {  
  89.     double  sigma_x     = sigma;  
  90.     double  sigma_y     = sigma/gamma;  
  91.     int     nstds       = 3;  
  92.     double  kmax        = CV_PI/2;  
  93.     double  f           = cv::sqrt(2.0);  
  94.     int xmin, xmax, ymin, ymax;  
  95.     double c = cos(theta), s = sin(theta);  
  96.     if( ksize.width > 0 )  
  97.     {  
  98.         xmax = ksize.width/2;  
  99.     }  
  100.     else//這個和matlab中的結果一樣,預設都是19 !  
  101.     {  
  102.         xmax = cvRound(std::max(fabs(nstds*sigma_x*c), fabs(nstds*sigma_y*s)));  
  103.     }  
  104.   
  105.     if( ksize.height > 0 )  
  106.         ymax = ksize.height/2;  
  107.     else  
  108.         ymax = cvRound(std::max(fabs(nstds*sigma_x*s), fabs(nstds*sigma_y*c)));  
  109.     xmin = -xmax;  
  110.     ymin = -ymax;  
  111.     CV_Assert( ktype == CV_32F || ktype == CV_64F );  
  112.     float*  pFloat;  
  113.     double* pDouble;  
  114.     Mat kernel(ymax - ymin + 1, xmax - xmin + 1, ktype);  
  115.     double k        =   kmax/pow(f,nu);  
  116.     double exy      =   sigma_x*sigma_y/2;  
  117.     double scaleReal=   k*k/sigma_x/sigma_y;  
  118.     int    x,y;  
  119.     for( y = ymin; y <= ymax; y++ )  
  120.     {  
  121.         if( ktype == CV_32F )  
  122.         {  
  123.             pFloat = kernel.ptr<float>(ymax-y);  
  124.         }  
  125.         else  
  126.         {  
  127.             pDouble = kernel.ptr<double>(ymax-y);  
  128.         }  
  129.         for( x = xmin; x <= xmax; x++ )  
  130.         {  
  131.             double xr = x*c + y*s;  
  132.             double v = scaleReal*exp(-(x*x+y*y)*scaleReal/2);  
  133.             double temp=cos(k*xr) - exp(-exy);  
  134.             v   =   temp*v;  
  135.             if( ktype == CV_32F )  
  136.             {  
  137.                 pFloat[xmax - x]= (float)v;  
  138.             }  
  139.             else  
  140.             {  
  141.                 pDouble[xmax - x] = v;  
  142.             }  
  143.         }  
  144.     }  
  145.     return kernel;  
  146. }  
  147. Mat GaborFR::getMagnitude(Mat &real,Mat &imag)  
  148. {  
  149.     CV_Assert(real.type()==imag.type());  
  150.     CV_Assert(real.size()==imag.size());  
  151.     int ktype=real.type();  
  152.     int row = real.rows,col = real.cols;  
  153.     int i,j;  
  154.     float*  pFloat,*pFloatR,*pFloatI;  
  155.     double* pDouble,*pDoubleR,*pDoubleI;  
  156.     Mat     kernel(row, col, real.type());  
  157.     for(i=0;i<row;i++)  
  158.     {  
  159.         if( ktype == CV_32FC1 )  
  160.         {  
  161.             pFloat = kernel.ptr<float>(i);  
  162.             pFloatR= real.ptr<float>(i);  
  163.             pFloatI= imag.ptr<float>(i);  
  164.         }  
  165.         else  
  166.         {  
  167.             pDouble = kernel.ptr<double>(i);  
  168.             pDoubleR= real.ptr<double>(i);  
  169.             pDoubleI= imag.ptr<double>(i);  
  170.         }  
  171.         for(j=0;j<col;j++)  
  172.         {  
  173.             if( ktype == CV_32FC1 )  
  174.             {  
  175.                 pFloat[j]= sqrt(pFloatI[j]*pFloatI[j]+pFloatR[j]*pFloatR[j]);  
  176.             }  
  177.             else  
  178.             {  
  179.                 pDouble[j] = sqrt(pDoubleI[j]*pDoubleI[j]+pDoubleR[j]*pDoubleR[j]);  
  180.             }  
  181.         }  
  182.     }  
  183.     return kernel;  
  184. }  
  185. Mat GaborFR::getPhase(Mat &real,Mat &imag)  
  186. {  
  187.     CV_Assert(real.type()==imag.type());  
  188.     CV_Assert(real.size()==imag.size());  
  189.     int ktype=real.type();  
  190.     int row = real.rows,col = real.cols;  
  191.     int i,j;  
  192.     float*  pFloat,*pFloatR,*pFloatI;  
  193.     double* pDouble,*pDoubleR,*pDoubleI;  
  194.     Mat     kernel(row, col, real.type());  
  195.     for(i=0;i<row;i++)  
  196.     {  
  197.         if( ktype == CV_32FC1 )  
  198.         {  
  199.             pFloat = kernel.ptr<float>(i);  
  200.             pFloatR= real.ptr<float>(i);  
  201.             pFloatI= imag.ptr<float>(i);  
  202.         }  
  203.         else  
  204.         {  
  205.             pDouble = kernel.ptr<double>(i);  
  206.             pDoubleR= real.ptr<double>(i);  
  207.             pDoubleI= imag.ptr<double>(i);  
  208.         }  
  209.         for(j=0;j<col;j++)  
  210.         {  
  211.             if( ktype == CV_32FC1 )  
  212.             {  
  213. //              if(pFloatI[j]/(pFloatR[j]+pFloatI[j]) > 0.99)  
  214. //              {  
  215. //                  pFloat[j]=CV_PI/2;  
  216. //              }  
  217. //              else  
  218. //              {  
  219. //                  pFloat[j] = atan(pFloatI[j]/pFloatR[j]);  
  220.                 pFloat[j] = asin(pFloatI[j]/sqrt(pFloatR[j]*pFloatR[j]+pFloatI[j]*pFloatI[j]));  
  221. /*              }*/  
  222. //              pFloat[j] = atan2(pFloatI[j],pFloatR[j]);  
  223.             }//CV_32F  
  224.             else  
  225.             {  
  226.                 if(pDoubleI[j]/(pDoubleR[j]+pDoubleI[j]) > 0.99)  
  227.                 {  
  228.                     pDouble[j]=CV_PI/2;  
  229.                 }  
  230.                 else  
  231.                 {  
  232.                     pDouble[j] = atan(pDoubleI[j]/pDoubleR[j]);  
  233.                 }  
  234. //              pDouble[j]=atan2(pDoubleI[j],pDoubleR[j]);  
  235.             }//CV_64F  
  236.         }  
  237.     }  
  238.     return kernel;  
  239. }  
  240. Mat GaborFR::getFilterRealPart(Mat& src,Mat& real)  
  241. {  
  242.     CV_Assert(real.type()==src.type());  
  243.     Mat dst;  
  244.     Mat kernel;  
  245.     flip(real,kernel,-1);//中心鏡面  
  246. //  filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_CONSTANT);  
  247.     filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_REPLICATE);  
  248.     return dst;  
  249. }  
  250. Mat GaborFR::getFilterImagPart(Mat& src,Mat& imag)  
  251. {  
  252.     CV_Assert(imag.type()==src.type());  
  253.     Mat dst;  
  254.     Mat kernel;  
  255.     flip(imag,kernel,-1);//中心鏡面  
  256. //  filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_CONSTANT);  
  257.     filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_REPLICATE);  
  258.     return dst;  
  259. }  
  260. void GaborFR::getFilterRealImagPart(Mat& src,Mat& real,Mat& imag,Mat &outReal,Mat &outImag)  
  261. {  
  262.     outReal=getFilterRealPart(src,real);  
  263.     outImag=getFilterImagPart(src,imag);  
  264. }  

main

  1. // Win32TestPure.cpp : 定義控制檯應用程式的入口點。  
  2. #include "stdafx.h"  
  3. #include <vector>  
  4. #include <deque>  
  5. #include <iomanip>  
  6. #include <stdexcept>  
  7. #include <string>  
  8. #include <iostream>  
  9. #include <fstream>  
  10. #include <direct.h>//_mkdir()  
  11. #include "opencv2\opencv.hpp"  
  12. #include "GaborFR.h"  
  13. using namespace std;  
  14. using namespace cv;  
  15. int main()  
  16. {   
  17.     //Mat M = getGaborKernel(Size(9,9),2*CV_PI,u*CV_PI/8, 2*CV_PI/pow(2,CV_PI*(v+2)/2),1,0);  
  18.     Mat saveM;  
  19.     //s8-4  
  20.     //s1-5  
  21.     //s1中年男人  
  22.     Mat I=imread("H:\\pic\\s1-5.bmp",-1);  
  23.     normalize(I,I,1,0,CV_MINMAX,CV_32F);  
  24.     Mat showM,showMM;Mat M,MatTemp1,MatTemp2;  
  25.     Mat line;  
  26.     int iSize=50;//如果數值比較大,比如50則接近論文中所述的情況了!估計大小和處理的源影象一樣!  
  27.     for(int i=0;i<8;i++)  
  28.     {  
  29.         showM.release();  
  30.         for(int j=0;j<5;j++)  
  31.         {  
  32.             Mat M1= GaborFR::getRealGaborKernel(Size(iSize,iSize),2*CV_PI,i*CV_PI/8+CV_PI/2, j,1);  
  33.             Mat M2 = GaborFR::getImagGaborKernel(Size(iSize,iSize),2*CV_PI,i*CV_PI/8+CV_PI/2, j,1);  
  34.             //加了CV_PI/2才和大部分文獻的圖形一樣,不知道為什麼!  
  35.             Mat outR,outI;  
  36.             GaborFR::getFilterRealImagPart(I,M1,M2,outR,outI);  
  37. //          M=GaborFR::getPhase(M1,M2);  
  38. //          M=GaborFR::getMagnitude(M1,M2);  
  39. //          M=GaborFR::getPhase(outR,outI);  
  40. //          M=GaborFR::getMagnitude(outR,outI);  
  41.  //         M=GaborFR::getMagnitude(outR,outI);  
  42. //          MatTemp2=GaborFR::getPhase(outR,outI);  
  43. //          M=outR;  
  44.              M=M1;  
  45.             //      resize(M,M,Size(100,100));  
  46.             normalize(M,M,0,255,CV_MINMAX,CV_8U);  
  47.             showM.push_back(M);  
  48.             line=Mat::ones(4,M.cols,M.type())*255;  
  49.             showM.push_back(line);  
  50.         }  
  51.         showM=showM.t();  
  52.         line=Mat::ones(4,showM.cols,showM.type())*255;  
  53.         showMM.push_back(showM);  
  54.         showMM.push_back(line);  
  55.     }  
  56.     showMM=showMM.t();  
  57. //  bool flag=imwrite("H:\\out.bmp",showMM);  
  58.     imshow("saveMM",showMM);waitKey(0);  
  59.     return 0;  
  60. }//endof   main()  

一下圖片可能和程式實際執行結果有點不同,圖片只是示意圖,程式碼暫時沒問題。需要考慮的是iSize大小問題,首先iSize要用奇數,然後大部分文獻iSize都比較大,好像是100左右,但沒看到他們描述過卷積核的大小。




相關文章