自己项目中用到了Gabor滤波器,于是自己借助Opencv图像库,实现了Gabor滤波器的特征提取,用类的形式将其封装,希望对大家有用>0<。
Gabor参数主要是5个尺度,8个方向,共40个卷积核。本人图片大小为36*48大小。下采样为10*11,故特征维数为:10*11*5*40=4400维。针对特征维数过大,可以采用PCA或LDA降维,这里就不展现了。
Gabor.h
#ifndef _GABOR_H
#define _GABOR_H
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
#define Gabor_num 40
#define U 8
#define V 5
class Gabor
{
public:
Gabor():m_kmax(CV_PI/2),m_f(sqrt(2.0)),m_sigma(CV_PI),ds_w(10),ds_h(11),ke_w(31),ke_h(31),raT(0.9){};
void MakeAllGaborKernal();
void MakeGaborKernal(int ke_h,int ke_w,int u,int v,Mat &GaborReal,Mat &GaborImg);
Mat Gabor_T_Fast1(Mat &src,int ds_h,int ds_w,Mat kel_GR[Gabor_num],Mat kel_GI[Gabor_num]);
int Gabor_T_Fast2(Mat &src,int ds_h,int ds_w,Mat kel_GR[Gabor_num],Mat kel_GI[Gabor_num],double* feature);
Mat Create_GaborF(Mat& src);
int getGaborMeanAndVarianceFeature(Mat &src,double* feature);
private:
double m_kmax;
double m_f;
double m_sigma;
int ds_w;
int ds_h;
int ke_w;
int ke_h;
double raT;
Mat GaborReal[Gabor_num];
Mat GaborImg[Gabor_num];
};
#endif
Gabor.cpp
#include "Gabor.h"
enum convtype
{
full,
same,
valid
};
/*
*@函数名: conv2
*@功能: 卷积运算
*@参数: const Mat &img 原图片
const Mat ikernel 卷积核
convtype type 卷积类型
*@返回值: Mat 矩阵卷积后的结果
*@作者: WiseClown
*@日期: 2016-1-7
*---------------------------------------
*时间 修改人 修改者
*---------------------------------------
**/
Mat conv2(const Mat &img, const Mat ikernel, convtype type)
{
Mat dest;
Mat kernel;
flip(ikernel,kernel,-1);
Mat source = img;
if(type == full)
{
source = Mat();
int additionalRows = kernel.rows-1, additionalCols = kernel.cols-1;
copyMakeBorder(img, source, (additionalRows+1)/2, additionalRows/2, (additionalCols+1)/2, additionalCols/2, BORDER_CONSTANT, Scalar(0));
}
Point anchor(kernel.cols - kernel.cols/2 - 1, kernel.rows - kernel.rows/2 - 1);
int borderMode = BORDER_CONSTANT;
filter2D(source, dest, img.depth(), kernel, anchor, 0, borderMode);
if(type == valid)
{
dest = dest.colRange((kernel.cols-1)/2, dest.cols - kernel.cols/2).rowRange((kernel.rows-1)/2, dest.rows - kernel.rows/2);
}
return dest;
}
/*
*@函数名: MakeGaborKernal
*@功能: 生成所有Gabor核
*@参数:
*@返回值: void
*@作者: WiseClown
*@日期: 2016-1-7
*---------------------------------------
*时间 修改人 修改者
*---------------------------------------
**/
void Gabor::MakeAllGaborKernal()
{
int n=0;
for(int v=0;vfor(int u=0;u8+u],GaborImg[v*8+u]);
}
}
}
/*
*@函数名: MakeGaborKernal
*@功能: 生成固定方向与固定尺度的Gabor核
*@参数: int ke_h 核函数的高度
int ke_w 核函数的宽度
int u Gabor的尺度
int v Gabor的方向
Mat &GaborReal Gabor的实部
Mat &GaborImg Gabor的虚部
*@返回值: Mat 返回的Gabor特征
*@作者: WiseClown
*@日期: 2016-1-7
*---------------------------------------
*时间 修改人 修改者
*---------------------------------------
**/
void Gabor::MakeGaborKernal(int ke_h,int ke_w,int u,int v,Mat &GaborReal,Mat &GaborImg)
{
int HarfH=ke_h/2;
int HarfW=ke_w/2;
double Qu=CV_PI*u/8;
double sqsigma=m_sigma*m_sigma;
double Kv=m_kmax/(pow(m_f,v));
double postmean=exp(-sqsigma/2);
GaborReal.create(HarfH+HarfW+1,HarfH+HarfW+1,CV_32FC1);
GaborImg.create(HarfH+HarfW+1,HarfH+HarfW+1,CV_32FC1);
float *ptr_real=NULL;
float *ptr_img=NULL;
for(int j=-HarfH;j<=HarfH;j++)
{
ptr_real=GaborReal.ptr<float>(j+HarfH);
ptr_img=GaborImg.ptr<float>(j+HarfH);
for(int i=-HarfW;i<=HarfW;i++)
{
double tmp1=exp(-(Kv*Kv*(j*j+i*i)/(2*sqsigma)));
double tmp2=cos(Kv*cos(Qu)*i+Kv*sin(Qu)*j)-postmean;
double tmp3=sin(Kv*cos(Qu)*i+Kv*sin(Qu)*j);
ptr_real[i+HarfW]=Kv*Kv*tmp1*tmp2/sqsigma;
ptr_img[i+HarfW]=Kv*Kv*tmp1*tmp3/sqsigma;
}
}
}
/*
*@函数名: Gabor_T_Fast1
*@功能: 获取固定核函数的Gabor特征
*@参数: Mat &src 原图---彩色图片
int ds_h 下采样的高度
int ds_w 下采样的宽度
Mat kel_GR[Gabor_num] 固定核函数的实部
Mat kel_GI[Gabor_num] 固定核函数的虚部
*@返回值: Mat 返回的Gabor特征
*@作者: WiseClown
*@日期: 2016-1-7
*---------------------------------------
*时间 修改人 修改者
*---------------------------------------
**/
Mat Gabor::Gabor_T_Fast1(Mat &src,int ds_h,int ds_w,Mat kel_GR[Gabor_num],Mat kel_GI[Gabor_num])
{
Mat feature;
Mat feature1;
for(int i=0;isqrt(feat_mode_part,feat_mode_part);
Mat tmp2;
Mat tmp3;
resize(feat_mode_part,tmp2,Size(ds_w,ds_h));
tmp3=tmp2.reshape(1,1);
float mean=0;
float std=0;
float sum1=0;
float sum2=0;
for(int j=0;jfloat>(0,j);
}
mean=sum1/(tmp3.cols);
for(int j=0;jpow((tmp3.at<float>(0,j)-mean),2);
}
sum2/=tmp3.cols;
std=sqrt(sum2);
subtract(tmp3,mean,tmp3);
divide(tmp3,std,tmp3);
feature.push_back(tmp3);
}
feature1=feature.reshape(1,1);
return feature1;
}
/*
*@函数名: Gabor_T_Fast2
*@功能: 获取固定核函数的Gabor均值与方差二维特征
*@参数: Mat &src 原图---彩色图片
int ds_h 下采样的高度
int ds_w 下采样的宽度
Mat kel_GR[Gabor_num] 固定核函数的实部
Mat kel_GI[Gabor_num] 固定核函数的虚部
double* feature 特征值
*@返回值: Mat 返回的Gabor特征
*@作者: WiseClown
*@日期: 2016-1-7
*---------------------------------------
*时间 修改人 修改者
*---------------------------------------
**/
int Gabor::Gabor_T_Fast2(Mat &src,int ds_h,int ds_w,Mat kel_GR[Gabor_num],Mat kel_GI[Gabor_num],double* feature)
{
vector<float> featureTmp;
for(int i=0;isqrt(feat_mode_part,feat_mode_part);
Mat tmp2;
Mat tmp3;
//使用双线性插值法,使feat_mode_part宽高调整到(ds_w,ds_h)
resize(feat_mode_part,tmp2,Size(ds_w,ds_h));
tmp3=tmp2.reshape(1,1);
//求均值mean和方差std
float mean=0;
float std=0;
float sum1=0;
float sum2=0;
for(int j=0;jfloat>(0,j);
}
mean=sum1/(tmp3.cols);
for(int j=0;jpow((tmp3.at<float>(0,j)-mean),2);
}
sum2/=tmp3.cols;
std=sqrt(sum2);
featureTmp.push_back(mean);
featureTmp.push_back(std);
}
for(size_t i=0; ireturn 0;
}
/*
*@函数名: Create_GaborF
*@功能: 获取Gabor特征
*@参数: Mat &src 原图---彩色图片
*@返回值: Mat 返回的Gabor特征
*@作者: WiseClown
*@日期: 2016-1-7
@说明:
*---------------------------------------
*时间 修改人 修改者
*---------------------------------------
**/
Mat Gabor::Create_GaborF(Mat &src)
{
MakeAllGaborKernal();
Mat feature;
double tmp1=ke_w/2;
double tmp2=ke_h/2;
int radius_w =(int)floor(tmp1);
int radius_h =(int)floor(tmp2);
int center_w = radius_w+1;
int center_h = radius_h+1;
int step=5;
Mat kel_GR[Gabor_num],kel_GI[Gabor_num];
int t1=center_h-radius_h+step;
int t2=center_h+radius_h-step;
int t3=center_w-radius_w+step;
int t4=center_w+radius_w-step;
for(int m=0;m1,t2),Range(t3-1,t4));
kel_GI[m]=GaborImg[m](Range(t1-1,t2),Range(t3-1,t4));
}
feature=Gabor_T_Fast1(src,ds_h,ds_w,kel_GR,kel_GI);
return feature;
}
/*
*@函数名: getGaborMeanAndVarianceFeature
*@功能: 获取Gabor的均值与方差二维特征
*@参数: Mat &src 原图---彩色图片
double* feature 特征
*@返回值:
0 特征获取成功
-1 特征获取失败
*@作者: WiseClown
*@日期: 2016-1-7
@说明:
*---------------------------------------
*时间 修改人 修改者
*---------------------------------------
**/
int Gabor::getGaborMeanAndVarianceFeature(Mat &src,double* feature)
{
MakeAllGaborKernal();
double tmp1=ke_w/2;
double tmp2=ke_h/2;
int radius_w =(int)floor(tmp1);
int radius_h =(int)floor(tmp2);
int center_w = radius_w+1;
int center_h = radius_h+1;
int step=5;
Mat kel_GR[Gabor_num],kel_GI[Gabor_num];
int t1=center_h-radius_h+step;
int t2=center_h+radius_h-step;
int t3=center_w-radius_w+step;
int t4=center_w+radius_w-step;
for(int m=0;m1,t2),Range(t3-1,t4));
kel_GI[m]=GaborImg[m](Range(t1-1,t2),Range(t3-1,t4));
}
Gabor_T_Fast2(src,ds_h,ds_w,kel_GR,kel_GI,feature);
return 0;
}