可参考:http://blog.csdn.net/jinshengtao/article/details/17797641
http://www.cnblogs.com/emouse/p/3611256.html
http://blog.csdn.net/yutianzuijin/article/details/10823985
基于Gabor+PCA+SVM的性别识别(1): http://www.cnblogs.com/xiaoming123abc/p/5078411.html
基于Gabor+PCA+SVM的性别识别(3): http://www.cnblogs.com/xiaoming123abc/p/5079116.html
这里只简单说一下自己的理解:
一维Gabor小波的实质是一个带通滤波器,具有频率选择性。
对于二维Gabor小波,它不仅具有频率选择性,还有频率方向的选择性;这时,可以理解Gabor是个空域的模板,匹配与模板频率大小和频率方向相同的成分。也就是说,图像中的频率大小和频率方向与该Gabor的频率大小和频率方向相同,则经过Gabor滤波后,响应会比较大,这样就把特征提取出来了。
二维Gabor小波是由二维Gabor滤波器函数 G(ω,θ)(Gabor滤波器有很多参数,为了方便理解,这里只写了两个)通过尺度伸缩和旋转生成的一组滤波器,其参数的选择通常在频率空间进行考虑。为了对一幅图像的整个频域进行采样,可以采用具有多个中心频率和方向的Gabor滤波器组来描述图像。参数 ω,θ的不同选择分别体现了二维Gabor小波在频率和方向空间的采样方式。
整个频率空间可以是0到无穷大的任意值,由于一幅图像实际的频率分布是有限的范围,所以,对于图像的局部特征来说,参数 ω只能在一个很小的范围内选取。由于图像的纹理是随机分布的, θ的取值范围为0到2*pi ,考虑到Gabor滤波器的对称性, 的实际取值范围为0到pi 。本文采用5个中心频率和8个方向组成40个Gabor滤波器。
ROI= imread(ImgName,0);//读取图片
if(ROI.data ==0)
{
printf("[error] 没有图片\n");
return -5;
}
//Gabor变换提取特征*************************
for(int i=0;i<8;i++)
{
for(int j=0;j<5;j++)
{
Mat outR,outI,M_Magnitude;
GaborFR::getFilterRealImagPart(ROI,GaborReal[i*5+j],GaborImag[i*5+j],outR,outI);
M_Magnitude=GaborFR::getMagnitude(outR,outI);
//cartToPolar( outR, outI, M_Magnitude, Angle, false ); //计算幅值和相角
normalize(M_Magnitude,M_Magnitude,0,1,CV_MINMAX,CV_32F);
Mat line= M_Magnitude.reshape(0,1);
Gabor_feature.push_back(line);
}
}
//PCA降维************************************************************
PCA pca(Gabor_feature, cv::Mat(), CV_PCA_DATA_AS_ROW,5);
Mat dst=pca.project(Gabor_feature) ;
Mat line =dst.reshape(0,1);
//处理第一个样本时初始化特征向量矩阵和类别矩阵,因为只有知道了特征向量的维数才能初始化特征向量矩阵
if( 0 == num )
{
//初始化所有训练样本的特征向量组成的矩阵,行数等于所有样本的个数,列数等于Gabor降维后描述子维数sampleFeatureMat
sampleFeatureMat = Mat::zeros(manNO+womanNO, DescriptorDim, CV_32FC1);
//初始化训练样本的类别向量,行数等于所有样本的个数,列数等于1;1表示有人,0表示无人
sampleLabelMat = Mat::zeros(manNO+womanNO, 1, CV_32FC1);
}
//将计算好的Gabor降维后描述子复制到样本特征矩阵sampleFeatureMat
for(int i=0; i
sampleLabelMat.at
}
//依次读取woman样本图片,生成Gabor描述子并降维
for(int num=0; num
cout<<"处理:"<
ROI= imread(ImgName,0);//读取图片
if(ROI.data ==0)
{
printf("[error] 没有图片\n");
return -5;
}
//Gabor变换提取特征*************************
for(int i=0;i<8;i++)
{
for(int j=0;j<5;j++)
{
Mat outR,outI,M_Magnitude;
GaborFR::getFilterRealImagPart(ROI,GaborReal[i*5+j],GaborImag[i*5+j],outR,outI);
M_Magnitude=GaborFR::getMagnitude(outR,outI);
//cartToPolar( outR, outI, M_Magnitude, Angle, false ); //计算幅值和相角
normalize(M_Magnitude,M_Magnitude,0,1,CV_MINMAX,CV_32F);
Mat line= M_Magnitude.reshape(0,1);
Gabor_feature.push_back(line);
}
}
//PCA降维************************************************************
PCA pca( Gabor_feature, cv::Mat(), CV_PCA_DATA_AS_ROW,5);
Mat dst=pca.project(Gabor_feature) ;
Mat line =dst.reshape(0,1);
for(int i=0; i
sampleLabelMat.at
}
//训练SVM分类器
//迭代终止条件,当迭代满1000次或误差小于FLT_EPSILON时停止迭代
CvSVM svm; //SVM分类器
CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000, FLT_EPSILON);
//SVM参数:SVM类型为C_SVC;线性核函数;松弛因子C=0.01
CvSVMParams param(CvSVM::C_SVC, CvSVM::LINEAR, 0, 1, 0, 0.01, 0, 0, 0, criteria);
cout<<"开始训练SVM分类器"<
cout<<"训练完成"<
waitKey();//注意:imshow之后必须加waitKey,否则无法显示图像
system("pause");
}
GarborFR.hpp
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
class GaborFR
{
public:
GaborFR();
static MatgetImagGaborKernel(Size ksize, double sigma, double theta,
double nu,double gamma=1, int ktype= CV_32F);
static MatgetRealGaborKernel( Size ksize, double sigma, double theta,
double nu,double gamma=1, int ktype= CV_32F);
static MatgetPhase(Mat &real,Mat &imag);
static MatgetMagnitude(Mat &real,Mat &imag);
static void getFilterRealImagPart(Mat& src,Mat& real,Mat& imag,Mat &outReal,Mat &outImag);
static MatgetFilterRealPart(Mat& src,Mat& real);
static MatgetFilterImagPart(Mat& src,Mat& imag);
/*
voidInit(Size ksize=Size(19,19), double sigma=2*CV_PI,
double gamma=1, int ktype=CV_32FC1);
*/
private:
//vectorgaborRealKernels;
//vectorgaborImagKernels;
bool isInited;
};
Gabor.cpp
//#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)
{
doublesigma_x= sigma;
doublesigma_y= sigma/gamma;
intnstds= 3;
doublekmax= CV_PI/2;
doublef= 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); //初始化gabor的尺寸
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(ymax-y);
}
else
{
pDouble = kernel.ptr(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)
{
doublesigma_x= sigma;
doublesigma_y= sigma/gamma;
intnstds= 3;
doublekmax= CV_PI/2;
doublef= 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(ymax-y);
}
else
{
pDouble = kernel.ptr(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;
Matkernel(row, col, real.type());
for(i=0;i{
if( ktype == CV_32FC1 )
{
pFloat = kernel.ptr(i);
pFloatR= real.ptr(i);
pFloatI= imag.ptr(i);
}
else
{
pDouble = kernel.ptr(i);
pDoubleR= real.ptr(i);
pDoubleI= imag.ptr(i);
}
for(j=0;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;
Matkernel(row, col, real.type());
for(i=0;i{
if( ktype == CV_32FC1 )
{
pFloat = kernel.ptr(i);
pFloatR= real.ptr(i);
pFloatI= imag.ptr(i);
}
else
{
pDouble = kernel.ptr(i);
pDoubleR= real.ptr(i);
pDoubleI= imag.ptr(i);
}
for(j=0;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);
}
本人能力有限,错误在所难免。敬请赐教
程序下载:http://download.csdn.net/detail/u012507022/9378491
(VS2010+opencv2.4.11)