Gabor滤波器的特征提取C++实现

自己项目中用到了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;
}

你可能感兴趣的:(图像处理)