Gabor Filter

What do the Gabor filter parameters mean?

Here is a parameter sweep of the 5 different Gabor filter parameters with a visualization of each corresponding Gabor filter.


Code for generating this Gabor filter parameter sweep demo

#include <stdio.h>
#include <tchar.h>
#include <limits>
 
// OpenCV
#include "cv.h"
#include "highgui.h"
 
#define _USE_MATH_DEFINES
#include <math.h>
 
 
int m_FrameNr;
 
 
 
float GaborFilterValue(int x,
                       int y,
                       float lambda,
                       float theta,
                       float phi,
                       float sigma,
                       float gamma)
{
    float xx =  x * cos(theta) + y * sin(theta);
    float yy = -x * sin(theta) + y * cos(theta);
 
    float envelopeVal = exp( - ( (xx*xx + gamma*gamma* yy*yy) / (2.0f * sigma*sigma) ) );
 
    float carrierVal = cos( 2.0f * (float)M_PI * xx / lambda + phi);
 
    float g = envelopeVal * carrierVal;
 
    return g;
}
 
 
double round(double d)
{
  return floor(d + 0.5);
}
 
 
 
void CreateGaborFilterImage(char* demoName,   float wavelength, float orientation, float phaseoffset, float gaussvar, float aspectratio)
{
    // Create an empty image
    int ImgWidth  = 725;
    int ImgHeight = 725;
    IplImage* img = cvCreateImage( cvSize(ImgWidth,ImgHeight), IPL_DEPTH_8U, 3 );
    for (int y=0; y<ImgHeight; y++)
        for (int x=0; x<ImgWidth; x++)
        {
            ((uchar *)(img->imageData + y*img->widthStep))[x*img->nChannels + 0]=0; // B
            ((uchar *)(img->imageData + y*img->widthStep))[x*img->nChannels + 1]=0; // G
            ((uchar *)(img->imageData + y*img->widthStep))[x*img->nChannels + 2]=0; // R
        }
 
 
    int winSize = 300;
    int my = ImgHeight / 2;
    int mx = ImgWidth  / 2;
 
 
    // Display gabor filter values
    float MinGaborValue = std::numeric_limits<float>::max();
    float MaxGaborValue = std::numeric_limits<float>::min();
    for (int dy=-winSize; dy<=winSize; dy++)
    {
        for (int dx=-winSize; dx<=winSize; dx++)
        {
            float val = GaborFilterValue(dx,dy, wavelength, orientation, phaseoffset, gaussvar, aspectratio);
 
            int R=0;
            int G=0;
            int B=0;
            CvScalar s;
            if (val>0.0f)
                R = (int)round(val * 255.0f);
            else
                B = (int)round(-val * 255.0f);
            s.val[0] = B;
            s.val[1] = G;
            s.val[2] = R;            
            cvSet2D(img, my+dy, mx+dx, s);
 
            if (val<MinGaborValue)
                MinGaborValue = val;
            if (val>MaxGaborValue)
                MaxGaborValue = val;
 
        }
    }
 
 
 
    // Display gabor filter parameters
    CvFont font;
    double hScale=1.0;
    double vScale=1.0;
    int    lineWidth=1;
    cvInitFont(&font,CV_FONT_HERSHEY_PLAIN, hScale,vScale,0,lineWidth);
    char txt[100];
    cvPutText (img, "Gabor filter values visualization by Juergen Mueller.",                             cvPoint(10,20), &font, cvScalar(0,255,255) );
    cvPutText (img, "variable naming conventions as used by http://en.wikipedia.org/wiki/Gabor_filter.", cvPoint(10,50), &font, cvScalar(0,255,255) );
    cvPutText (img, "Red: positive values. Blue: negative values",                                       cvPoint(10,70), &font, cvScalar(0,255,255) );
 
 
    cvPutText(img, demoName, cvPoint(10,100), &font, cvScalar(0,255,0) );     
    sprintf_s(txt, "1. wavelength  (lambda) : %.2f", wavelength);    cvPutText (img, txt, cvPoint(10,120), &font, cvScalar(0,255,255) );
    sprintf_s(txt, "2. orientation (theta)  : %.2f", orientation);   cvPutText (img, txt, cvPoint(10,140), &font, cvScalar(0,255,255) );
    sprintf_s(txt, "3. gaussvar    (sigma)  : %.2f", gaussvar);      cvPutText (img, txt, cvPoint(10,160), &font, cvScalar(0,255,255) );
    sprintf_s(txt, "4. phaseoffset (phi)    : %.2f", phaseoffset);   cvPutText (img, txt, cvPoint(10,180), &font, cvScalar(0,255,255) );
    sprintf_s(txt, "5. aspectratio (gamma)  : %.2f", aspectratio);   cvPutText (img, txt, cvPoint(10,200), &font, cvScalar(0,255,255) );
 
    sprintf_s(txt, "min gabor val : %.2f", MinGaborValue);   cvPutText (img, txt, cvPoint(10,230), &font, cvScalar(0,255,255) );
    sprintf_s(txt, "max gabor val : %.2f", MaxGaborValue);   cvPutText (img, txt, cvPoint(10,250), &font, cvScalar(0,255,255) );
 
 
 
    // Show gabor filter image
    cvShowImage( "Gaborfilter", img );
 
 
 
    // Wait for a key press 
    int key = cvWaitKey( 1 );
 
 
    // Save current image to create an animation based on the sequence of such images
    char filename[500];
    sprintf_s(filename, "D:\\tmp\\frame_%05d.png", m_FrameNr);
    cvSaveImage(filename, img);
    m_FrameNr++;
 
 
 
    cvReleaseImage( &img );
}
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    int key = 0;
    m_FrameNr = 0;
 
    // 1. Create display window
    cvNamedWindow( "Gaborfilter", CV_WINDOW_AUTOSIZE );
 
 
    // 2. Gabor parameter sweep
 
    float wavelength;
    float orientation;
    float gaussvar;
    float phaseoffset;
    float aspectratio;
 
    wavelength  = 40.0f;
    orientation = (float)M_PI/4.0f;
    gaussvar    = 20.0f;
    phaseoffset = 0.0f;
    aspectratio = 0.5f;
    for (wavelength=5.0f; wavelength<=100.0f; wavelength+=5.0f)
    {
        CreateGaborFilterImage("1. Wavelength is changed.", wavelength, orientation, phaseoffset, gaussvar, aspectratio);
    }
 
 
    wavelength  = 40.0f;
    orientation = (float)M_PI/4.0f;
    gaussvar    = 20.0f;
    phaseoffset = 0.0f;
    aspectratio = 0.5f;
    for (orientation=0.0f; orientation<=2*(float)M_PI; orientation+=2*(float)M_PI / 8.0f)
    {
       CreateGaborFilterImage("2. Orientation is changed.", wavelength, orientation, phaseoffset, gaussvar, aspectratio);
    }
 
 
    wavelength  = 40.0f;
    orientation = (float)M_PI/4.0f;
    gaussvar    = 20.0f;
    phaseoffset = 0.0f;
    aspectratio = 0.5f;
    for (gaussvar=10.0f; gaussvar<=60; gaussvar+=5)
    {
        CreateGaborFilterImage("3. Gaussvariance is changed.", wavelength, orientation, phaseoffset, gaussvar, aspectratio);
    }
 
 
 
    wavelength  = 40.0f;
    orientation = (float)M_PI/4.0f;
    gaussvar    = 20.0f;
    phaseoffset = 0.0f;
    aspectratio = 0.5f;
    for (phaseoffset = 0.0f; phaseoffset<=2*(float)M_PI; phaseoffset+=2*(float)M_PI / 16.0f)
    {
         CreateGaborFilterImage("4. Phase offset is changed.", wavelength, orientation, phaseoffset, gaussvar, aspectratio);
    }
 
 
 
    wavelength  = 40.0f;
    orientation = (float)M_PI/4.0f;
    gaussvar    = 20.0f;
    phaseoffset = 0.0f;
    aspectratio = 0.5f;
    for (aspectratio = 0.1f; aspectratio<=1.0f; aspectratio+=.05f)
    {
        CreateGaborFilterImage("5. Aspect ratio is changed.", wavelength, orientation, phaseoffset, gaussvar, aspectratio);
    }
 
 
	return 0;
}

Gabor filter response samples

Gabor filter bank used

Note:

  • blue filter result values: negative Gabor filter responses
  • red filter result values: positive Gabor filter responses

Sample image #1

Sample image #2

Sample image #3 (#2 inverted)

Responses of a bank of 15 different Gabor filters to the numbers 1-4

Input images:

You need to install a Flash Player to watch this video!

Gabor filter responses:

You need to install a Flash Player to watch this video!

Original Work

Theory

Demos

Software

How to use a Gabor filter kernel to filter an image?

Just use OpenCV's cvFilter2D() function!

Some test code

Here is some code by Dominik Lessel that allows to change some parameters using sliders:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
 
cv::Mat mkKernel(int ks, double sig, double th, double lm, double ps)
{
    int hks = (ks-1)/2;
    double theta = th*CV_PI/180;
    double psi = ps*CV_PI/180;
    double del = 2.0/(ks-1);
    double lmbd = lm;
    double sigma = sig/ks;
    double x_theta;
    double y_theta;
    cv::Mat kernel(ks,ks, CV_32F);
    for (int y=-hks; y<=hks; y++)
    {
        for (int x=-hks; x<=hks; x++)
        {
            x_theta = x*del*cos(theta)+y*del*sin(theta);
            y_theta = -x*del*sin(theta)+y*del*cos(theta);
            kernel.at<float>(hks+y,hks+x) = (float)exp(-0.5*(pow(x_theta,2)+pow(y_theta,2))/pow(sigma,2))* cos(2*CV_PI*x_theta/lmbd + psi);
        }
    }
    return kernel;
}
 
int kernel_size=21;
int pos_sigma= 5;
int pos_lm = 50;
int pos_th = 0;
int pos_psi = 90;
cv::Mat src_f;
cv::Mat dest;
 
void Process(int , void *)
{
    double sig = pos_sigma;
    double lm = 0.5+pos_lm/100.0;
    double th = pos_th;
    double ps = pos_psi;
    cv::Mat kernel = mkKernel(kernel_size, sig, th, lm, ps);
    cv::filter2D(src_f, dest, CV_32F, kernel);
    cv::imshow("Process window", dest);
    cv::Mat Lkernel(kernel_size*20, kernel_size*20, CV_32F);
    cv::resize(kernel, Lkernel, Lkernel.size());
    Lkernel /= 2.;
    Lkernel += 0.5;
    cv::imshow("Kernel", Lkernel);
    cv::Mat mag;
    cv::pow(dest, 2.0, mag);
    cv::imshow("Mag", mag);
}
 
int main(int argc, char** argv)
{
    cv::Mat image = cv::imread("W:\\01_data\\07_testimgs\\0230.png",1);
    cv::imshow("Src", image);
    cv::Mat src;
    cv::cvtColor(image, src, CV_BGR2GRAY);
    src.convertTo(src_f, CV_32F, 1.0/255, 0);
    if (!kernel_size%2)
    {
        kernel_size+=1;
    }
    cv::namedWindow("Process window", 1);
    cv::createTrackbar("Sigma", "Process window", &pos_sigma, kernel_size, Process);
    cv::createTrackbar("Lambda", "Process window", &pos_lm, 100, Process);
    cv::createTrackbar("Theta", "Process window", &pos_th, 180, Process);
    cv::createTrackbar("Psi", "Process window", &pos_psi, 360, Process);
    Process(0,0);
    cv::waitKey(0);
    return 0;
}
 
public/gabor_filter.txt · Last modified: 2012/09/04 10:00 (external edit) · []
Recent changes RSS feed Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki