Gabor的OpenCV程式碼
【原文: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,又說到。上程式碼和連結地址!下載地址~
目前程式碼未經過更多的測試,不少功能為加入,但可以滿足許多人的使用和參考了吧,很多人肯定非常非常需要,先開源下,歡迎指出錯誤之處。
- //GaborFR.h
- #pragma once
- #include "opencv2\opencv.hpp"
- #include <vector>
- using namespace std;
- using namespace cv;
- class GaborFR
- {
- public:
- GaborFR();
- static Mat getImagGaborKernel(Size ksize, double sigma, double theta,
- double nu,double gamma=1, int ktype= CV_32F);
- static Mat getRealGaborKernel( Size ksize, double sigma, double theta,
- double nu,double gamma=1, int ktype= CV_32F);
- static Mat getPhase(Mat &real,Mat &imag);
- static Mat getMagnitude(Mat &real,Mat &imag);
- static void getFilterRealImagPart(Mat& src,Mat& real,Mat& imag,Mat &outReal,Mat &outImag);
- static Mat getFilterRealPart(Mat& src,Mat& real);
- static Mat getFilterImagPart(Mat& src,Mat& imag);
- void Init(Size ksize=Size(19,19), double sigma=2*CV_PI,
- double gamma=1, int ktype=CV_32FC1);
- private:
- vector<Mat> gaborRealKernels;
- vector<Mat> gaborImagKernels;
- bool isInited;
- };
- #include "stdafx.h"
- #include "GaborFR.h"
- GaborFR::GaborFR()
- {
- isInited = false;
- }
- void GaborFR::Init(Size ksize, double sigma,double gamma, int ktype)
- {
- gaborRealKernels.clear();
- gaborImagKernels.clear();
- double mu[8]={0,1,2,3,4,5,6,7};
- double nu[5]={0,1,2,3,4};
- int i,j;
- for(i=0;i<5;i++)
- {
- for(j=0;j<8;j++)
- {
- gaborRealKernels.push_back(getRealGaborKernel(ksize,sigma,mu[j]*CV_PI/8,nu[i],gamma,ktype));
- gaborImagKernels.push_back(getImagGaborKernel(ksize,sigma,mu[j]*CV_PI/8,nu[i],gamma,ktype));
- }
- }
- isInited = true;
- }
- Mat GaborFR::getImagGaborKernel(Size ksize, double sigma, double theta, double nu,double gamma, int ktype)
- {
- double sigma_x = sigma;
- double sigma_y = sigma/gamma;
- int nstds = 3;
- double kmax = CV_PI/2;
- double f = cv::sqrt(2.0);
- int xmin, xmax, ymin, ymax;
- double c = cos(theta), s = sin(theta);
- if( ksize.width > 0 )
- {
- xmax = ksize.width/2;
- }
- else//這個和matlab中的結果一樣,預設都是19 !
- {
- xmax = cvRound(std::max(fabs(nstds*sigma_x*c), fabs(nstds*sigma_y*s)));
- }
- if( ksize.height > 0 )
- {
- ymax = ksize.height/2;
- }
- else
- {
- ymax = cvRound(std::max(fabs(nstds*sigma_x*s), fabs(nstds*sigma_y*c)));
- }
- xmin = -xmax;
- ymin = -ymax;
- CV_Assert( ktype == CV_32F || ktype == CV_64F );
- float* pFloat;
- double* pDouble;
- Mat kernel(ymax - ymin + 1, xmax - xmin + 1, ktype);
- double k = kmax/pow(f,nu);
- double scaleReal= k*k/sigma_x/sigma_y;
- for( int y = ymin; y <= ymax; y++ )
- {
- if( ktype == CV_32F )
- {
- pFloat = kernel.ptr<float>(ymax-y);
- }
- else
- {
- pDouble = kernel.ptr<double>(ymax-y);
- }
- for( int x = xmin; x <= xmax; x++ )
- {
- double xr = x*c + y*s;
- double v = scaleReal*exp(-(x*x+y*y)*scaleReal/2);
- double temp=sin(k*xr);
- v = temp*v;
- if( ktype == CV_32F )
- {
- pFloat[xmax - x]= (float)v;
- }
- else
- {
- pDouble[xmax - x] = v;
- }
- }
- }
- return kernel;
- }
- //sigma一般為2*pi
- Mat GaborFR::getRealGaborKernel( Size ksize, double sigma, double theta,
- double nu,double gamma, int ktype)
- {
- double sigma_x = sigma;
- double sigma_y = sigma/gamma;
- int nstds = 3;
- double kmax = CV_PI/2;
- double f = cv::sqrt(2.0);
- int xmin, xmax, ymin, ymax;
- double c = cos(theta), s = sin(theta);
- if( ksize.width > 0 )
- {
- xmax = ksize.width/2;
- }
- else//這個和matlab中的結果一樣,預設都是19 !
- {
- xmax = cvRound(std::max(fabs(nstds*sigma_x*c), fabs(nstds*sigma_y*s)));
- }
- if( ksize.height > 0 )
- ymax = ksize.height/2;
- else
- ymax = cvRound(std::max(fabs(nstds*sigma_x*s), fabs(nstds*sigma_y*c)));
- xmin = -xmax;
- ymin = -ymax;
- CV_Assert( ktype == CV_32F || ktype == CV_64F );
- float* pFloat;
- double* pDouble;
- Mat kernel(ymax - ymin + 1, xmax - xmin + 1, ktype);
- double k = kmax/pow(f,nu);
- double exy = sigma_x*sigma_y/2;
- double scaleReal= k*k/sigma_x/sigma_y;
- int x,y;
- for( y = ymin; y <= ymax; y++ )
- {
- if( ktype == CV_32F )
- {
- pFloat = kernel.ptr<float>(ymax-y);
- }
- else
- {
- pDouble = kernel.ptr<double>(ymax-y);
- }
- for( x = xmin; x <= xmax; x++ )
- {
- double xr = x*c + y*s;
- double v = scaleReal*exp(-(x*x+y*y)*scaleReal/2);
- double temp=cos(k*xr) - exp(-exy);
- v = temp*v;
- if( ktype == CV_32F )
- {
- pFloat[xmax - x]= (float)v;
- }
- else
- {
- pDouble[xmax - x] = v;
- }
- }
- }
- return kernel;
- }
- Mat GaborFR::getMagnitude(Mat &real,Mat &imag)
- {
- CV_Assert(real.type()==imag.type());
- CV_Assert(real.size()==imag.size());
- int ktype=real.type();
- int row = real.rows,col = real.cols;
- int i,j;
- float* pFloat,*pFloatR,*pFloatI;
- double* pDouble,*pDoubleR,*pDoubleI;
- Mat kernel(row, col, real.type());
- for(i=0;i<row;i++)
- {
- if( ktype == CV_32FC1 )
- {
- pFloat = kernel.ptr<float>(i);
- pFloatR= real.ptr<float>(i);
- pFloatI= imag.ptr<float>(i);
- }
- else
- {
- pDouble = kernel.ptr<double>(i);
- pDoubleR= real.ptr<double>(i);
- pDoubleI= imag.ptr<double>(i);
- }
- for(j=0;j<col;j++)
- {
- if( ktype == CV_32FC1 )
- {
- pFloat[j]= sqrt(pFloatI[j]*pFloatI[j]+pFloatR[j]*pFloatR[j]);
- }
- else
- {
- pDouble[j] = sqrt(pDoubleI[j]*pDoubleI[j]+pDoubleR[j]*pDoubleR[j]);
- }
- }
- }
- return kernel;
- }
- Mat GaborFR::getPhase(Mat &real,Mat &imag)
- {
- CV_Assert(real.type()==imag.type());
- CV_Assert(real.size()==imag.size());
- int ktype=real.type();
- int row = real.rows,col = real.cols;
- int i,j;
- float* pFloat,*pFloatR,*pFloatI;
- double* pDouble,*pDoubleR,*pDoubleI;
- Mat kernel(row, col, real.type());
- for(i=0;i<row;i++)
- {
- if( ktype == CV_32FC1 )
- {
- pFloat = kernel.ptr<float>(i);
- pFloatR= real.ptr<float>(i);
- pFloatI= imag.ptr<float>(i);
- }
- else
- {
- pDouble = kernel.ptr<double>(i);
- pDoubleR= real.ptr<double>(i);
- pDoubleI= imag.ptr<double>(i);
- }
- for(j=0;j<col;j++)
- {
- if( ktype == CV_32FC1 )
- {
- // if(pFloatI[j]/(pFloatR[j]+pFloatI[j]) > 0.99)
- // {
- // pFloat[j]=CV_PI/2;
- // }
- // else
- // {
- // pFloat[j] = atan(pFloatI[j]/pFloatR[j]);
- pFloat[j] = asin(pFloatI[j]/sqrt(pFloatR[j]*pFloatR[j]+pFloatI[j]*pFloatI[j]));
- /* }*/
- // pFloat[j] = atan2(pFloatI[j],pFloatR[j]);
- }//CV_32F
- else
- {
- if(pDoubleI[j]/(pDoubleR[j]+pDoubleI[j]) > 0.99)
- {
- pDouble[j]=CV_PI/2;
- }
- else
- {
- pDouble[j] = atan(pDoubleI[j]/pDoubleR[j]);
- }
- // pDouble[j]=atan2(pDoubleI[j],pDoubleR[j]);
- }//CV_64F
- }
- }
- return kernel;
- }
- Mat GaborFR::getFilterRealPart(Mat& src,Mat& real)
- {
- CV_Assert(real.type()==src.type());
- Mat dst;
- Mat kernel;
- flip(real,kernel,-1);//中心鏡面
- // filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_CONSTANT);
- filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_REPLICATE);
- return dst;
- }
- Mat GaborFR::getFilterImagPart(Mat& src,Mat& imag)
- {
- CV_Assert(imag.type()==src.type());
- Mat dst;
- Mat kernel;
- flip(imag,kernel,-1);//中心鏡面
- // filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_CONSTANT);
- filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_REPLICATE);
- return dst;
- }
- void GaborFR::getFilterRealImagPart(Mat& src,Mat& real,Mat& imag,Mat &outReal,Mat &outImag)
- {
- outReal=getFilterRealPart(src,real);
- outImag=getFilterImagPart(src,imag);
- }
main
- // Win32TestPure.cpp : 定義控制檯應用程式的入口點。
- #include "stdafx.h"
- #include <vector>
- #include <deque>
- #include <iomanip>
- #include <stdexcept>
- #include <string>
- #include <iostream>
- #include <fstream>
- #include <direct.h>//_mkdir()
- #include "opencv2\opencv.hpp"
- #include "GaborFR.h"
- using namespace std;
- using namespace cv;
- int main()
- {
- //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);
- Mat saveM;
- //s8-4
- //s1-5
- //s1中年男人
- Mat I=imread("H:\\pic\\s1-5.bmp",-1);
- normalize(I,I,1,0,CV_MINMAX,CV_32F);
- Mat showM,showMM;Mat M,MatTemp1,MatTemp2;
- Mat line;
- int iSize=50;//如果數值比較大,比如50則接近論文中所述的情況了!估計大小和處理的源影象一樣!
- for(int i=0;i<8;i++)
- {
- showM.release();
- for(int j=0;j<5;j++)
- {
- Mat M1= GaborFR::getRealGaborKernel(Size(iSize,iSize),2*CV_PI,i*CV_PI/8+CV_PI/2, j,1);
- Mat M2 = GaborFR::getImagGaborKernel(Size(iSize,iSize),2*CV_PI,i*CV_PI/8+CV_PI/2, j,1);
- //加了CV_PI/2才和大部分文獻的圖形一樣,不知道為什麼!
- Mat outR,outI;
- GaborFR::getFilterRealImagPart(I,M1,M2,outR,outI);
- // M=GaborFR::getPhase(M1,M2);
- // M=GaborFR::getMagnitude(M1,M2);
- // M=GaborFR::getPhase(outR,outI);
- // M=GaborFR::getMagnitude(outR,outI);
- // M=GaborFR::getMagnitude(outR,outI);
- // MatTemp2=GaborFR::getPhase(outR,outI);
- // M=outR;
- M=M1;
- // resize(M,M,Size(100,100));
- normalize(M,M,0,255,CV_MINMAX,CV_8U);
- showM.push_back(M);
- line=Mat::ones(4,M.cols,M.type())*255;
- showM.push_back(line);
- }
- showM=showM.t();
- line=Mat::ones(4,showM.cols,showM.type())*255;
- showMM.push_back(showM);
- showMM.push_back(line);
- }
- showMM=showMM.t();
- // bool flag=imwrite("H:\\out.bmp",showMM);
- imshow("saveMM",showMM);waitKey(0);
- return 0;
- }//endof main()
一下圖片可能和程式實際執行結果有點不同,圖片只是示意圖,程式碼暫時沒問題。需要考慮的是iSize大小問題,首先iSize要用奇數,然後大部分文獻iSize都比較大,好像是100左右,但沒看到他們描述過卷積核的大小。
相關文章
- opencv + SVM 程式碼OpenCV
- Gabor濾波器學習
- Opencv及常用方法示例程式碼OpenCV
- OpenCv 中Snake程式的例子OpenCV
- OPENCV版本的單目標定示例程式碼(張正友)OpenCV
- opencv中svm原始碼OpenCV原始碼
- OpenCV特徵提取與影像檢索實現(附程式碼)OpenCV特徵
- CMake生成OpenCV解決方案&&編譯OpenCV原始碼OpenCV編譯原始碼
- OpenCV計算機視覺程式設計攻略(第2版)程式碼OpenCV計算機視覺程式設計
- OpenCV 編碼樣式指南OpenCV
- 【Python】【OpenCV】定位二維碼PythonOpenCV
- 手把手教你使用OpenCV庫(附例項、Python程式碼解析)OpenCVPython
- 【OpenCV教程】OpenCV中的資料型別OpenCV資料型別
- 【OpenCV教程】OpenCV中對矩陣的常用操作OpenCV矩陣
- OpenCV 機器視覺入門精選 100 題(附 Python 程式碼)OpenCV視覺Python
- opencv SVM的使用OpenCV
- OpenCV的SVM用法OpenCV
- Opencv2.4.9原始碼分析——HoughCirclesOpenCV原始碼
- 【OpenCV】OpenCV中GPU模組使用OpenCVGPU
- opencvOpenCV
- OpenCV()OpenCV
- OpenCV進階之路:一個簡化的視訊摘要程式OpenCV
- OpenCV入門 2_1中使用【總結】的程式碼載入影像、顯示影像報錯OpenCV
- 圖片打碼(系統自帶 VS openCV)OpenCV
- 使用OpenCV+Keras輕鬆破解驗證碼OpenCVKeras
- 基於C++和OpenCv的SIFT_影象區域性特徵檢測演算法程式碼的實現C++OpenCV特徵演算法
- opencv 影像的入門OpenCV
- 嵌入式程式除錯與opencv影像庫除錯OpenCV
- 用OpenCV和Python識別二維碼和條形碼OpenCVPython
- 【C++】【OpenCV-4.9.0】影片寫入(VideoWriter,藉助samples中的程式碼示例來進行學習)C++OpenCVIDE
- delphi opencvOpenCV
- opencv CvMLData的簡單使用OpenCVLDA
- OpenCV中的神器Image WatchOpenCV
- 整潔的程式碼VS卓越的程式碼
- 【opencv五】利用opencv給讀入的視訊新增拖動滑塊OpenCV
- python+opencv檢測圖片中二維碼PythonOpenCV
- 最新《精通 OpenCV 4》第三版開源!附電子版 pdf 和隨書程式碼OpenCV
- 最快的程式碼,是不執行的程式碼