Gabor滤波器学习

转自:http://blog.csdn.net/jinshengtao/article/details/17797641

本文的目的是用C实现生成Gabor模版,并对图像卷积。并简单提一下,Gabor滤波器在纹理特征提取上的应用。

一、什么是Gabor函数(以下内容含部分翻译自维基百科)

在图像处理中,Gabor函数是一个用于边缘提取的线性滤波器。Gabor滤波器的频率和方向表达同人类视觉系统类似。研究发现,Gabor滤波器十分适合纹理表达和分离。在空间域中,一个二维Gabor滤波器是一个由正弦平面波调制的高斯核函数。

还有,生物学实验发现,Gabor滤波器可以很好地近似单细胞的感受野函数(光强刺激下的传递函数),什么视皮层内的超柱,bla...bla,总之是这方面仿生的数学模型。

另外,网上有一种说法,gabor分为实部和虚部,用实部进行滤波后图像会平滑;虚部滤波后用来检测边缘。【来自百度知道某个大神的回答】,我查了文献,发现的确有人用Gabor的奇函数部分做边缘提取(《基于Gabor滤波器的边缘检测算法》 无线电工程 2000年第3卷第30期)。另外,从我的实验结果也有类似的发现。暂且认为这个对的吧。

Gabor滤波器的脉冲响应,可以定义为一个正弦波(对于二维Gabor滤波器是正弦平面波)乘以高斯函数。由于乘法卷积性质,Gabor滤波器的脉冲响应的傅立叶变换是其调和函数的傅立叶变换和高斯函数傅立叶变换的卷积。该滤波器由实部和虚部组成,二者相互正交。一组不同频率不同方向的Gabor函数数组对于图像特征提取非常有用。

下面给出二维Gabor函数的数学表达:

复数表达:

实数部分:

虚数部分:

其中:

下面介绍公式中各个参数的含义,及参数如何配置问题【都从老外那翻译来的】:

波长(λ):它的值以像素为单位指定,通常大于等于2.但不能大于输入图像尺寸的五分之一。

方向(θ):这个参数指定了Gabor函数并行条纹的方向,它的取值为0到360度

相位偏移(φ):它的取值范围为-180度到180度。其中,0he180度分别对应中心对称的center-on函数和center-off函数,而-90度和90度对应反对称函数。

长宽比(γ):空间纵横比,决定了Gabor函数形状(support,我翻译为形状)的椭圆率(ellipticity)。当γ= 1时,形状是圆的。当γ< 1时,形状随着平行条纹方向而拉长。通常该值为0.5

带宽(b):Gabor滤波器的半响应空间频率带宽b和σ/ λ的比率有关,其中σ表示Gabor函数的高斯因子的标准差,如下:

σ的值不能直接设置,它仅随着带宽b变化。带宽值必须是正实数,通常为1,此时,标准差和波长的关系为:σ= 0.56 λ。带宽越小,标准差越大,Gabor形状越大,可见平行兴奋和抑制区条纹数量越多。

下面给出,不同参数配置下的Gabor核函数效果图,大小均100*100:

a.波长对比组【方向为:0,相位偏移量为:0,纵横比率为:0.5,带宽为:1,下图波长分别为5,10,15】

b.方向对比组【波长为:10,相位偏移量为:0,空间纵横比为:0.5,带宽为:1,方向分别为:0,45,90】

c.相位偏移量对比组【波长为:10,方向为:0,空间纵横比:0.5,带宽:1,相位偏移量分别为:0,180,-90,90】

d.空间纵横比对比组【波长:10,相位偏移量:0,方向:0,带宽:1,空间纵横比分别为:0.5,1】

e.带宽对比组【波长:10,方向:0,相位偏移量:0,空间纵横比:0.5,带宽分别为:0.5,1,2】

二、gabor函数实现:

matlab版本,我从pudn上找来的,但他的gabor函数,我没怎么看明白:

gabor函数:

[plain] view plaincopy

  1. function gabor_k = compute(x,y,f0,theta)
  2. r = 1; g = 1;
  3. x1 = x*cos(theta) + y*sin(theta);
  4. y1 = -x*sin(theta) + y*cos(theta);
  5. gabor_k = f0^2/(pi*r*g)*exp(-(f0^2*x1^2/r^2+f0^2*y1^2/g^2))*exp(i*2*pi*f0*x1);

[plain] view plaincopy

  1. %绘制一个Gabor滤波器的空域和频域函数图
  2. clear;
  3. x = 0;
  4. theta = 0;
  5. f0 = 0.2;
  6. for i = linspace(-15,15,50)
  7. x = x + 1;
  8. y = 0;
  9. for j = linspace(-15,15,50)
  10. y = y + 1;
  11. z(y,x)=compute(i,j,f0,theta);
  12. end
  13. end
  14. x = linspace(-15,15,50);
  15. y = linspace(-15,15,50);
  16. surf(x,y,real(z))
  17. title(‘Gabor filter:real component‘);
  18. xlabel(‘x‘);
  19. ylabel(‘y‘);
  20. zlabel(‘z‘);
  21. figure(2);
  22. surf(x,y,imag(z))
  23. title(‘Gabor filter:imaginary component‘);
  24. xlabel(‘x‘);
  25. ylabel(‘y‘);
  26. zlabel(‘z‘);
  27. Z = fft2(z);
  28. u = linspace(-0.5,0.5,50);
  29. v = linspace(-0.5,0.5,50);
  30. figure(3);
  31. surf(u,v,abs(fftshift(Z)))
  32. title(‘Gabor filter:frequency component‘);
  33. xlabel(‘u‘);
  34. ylabel(‘v‘);
  35. zlabel(‘Z‘);

运行结果:

[plain] view plaincopy

  1. %4个方向的Gabo滤波器通过图像显示
  2. clear;
  3. x = 0;
  4. theta = pi*3/4;%用弧度0,pi/4,pi/2,pi*3/4
  5. f0 = 0.2;
  6. for i = linspace(-15,15,50)
  7. x = x + 1;
  8. y = 0;
  9. for j = linspace(-15,15,50)
  10. y = y + 1;
  11. z(y,x)=compute(i,j,f0,theta);
  12. end
  13. end
  14. z_real = real(z);
  15. m = min(z_real(:));
  16. z_real = z_real+abs(m);
  17. M = max(z_real(:));
  18. imshow(1/M*z_real);
  19. figure(2)
  20. z_imag = imag(z);
  21. m = min(z_imag(:));
  22. z_imag = z_imag+abs(m);
  23. M = max(z_imag(:));
  24. imshow(1/M*z_imag);

运行效果:

实数部分:

虚数部分:

[plain] view plaincopy

  1. %4个方向的Gabor滤波器对lena进行滤波
  2. clear;
  3. I = imread(‘.\pic\lena.bmp‘);
  4. f0 = 0.2;
  5. count = 0;
  6. for theta = [0,pi/4,pi/2,pi*3/4];%用弧度0,pi/4,pi/2,pi*3/4
  7. count = count + 1;
  8. x = 0;
  9. for i = linspace(-8,8,11)
  10. x = x + 1;
  11. y = 0;
  12. for j = linspace(-8,8,11)
  13. y = y + 1;
  14. z(y,x)=compute(i,j,f0,theta);
  15. end
  16. end
  17. figure(count);
  18. filtered = filter2(z,I,‘valid‘);
  19. f = abs(filtered);
  20. imshow(f/max(f(:)))
  21. end

运行效果:

好吧,不管他了。大概感受一下吧。由于我没看明白他的gabor函数怎么定义的,参数设置也不一样,实验结果很不相同,我希望我是对的,天地良心呐!!我只能按照维基百科给出的函数,编写了以下C代码:

[cpp] view plaincopy

  1. // my_gabor.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include<iostream>
  5. #include <opencv2/core/core.hpp>
  6. #include <opencv2/highgui/highgui.hpp>
  7. #include <opencv2/imgproc/imgproc.hpp>
  8. #include "math.h"
  9. #define  PI 3.1415926
  10. #define  N 4
  11. using namespace std;
  12. using namespace cv;
  13. void m_filer(double *src,int height,int width,double *mask_rel,double *mask_img,int mW,int mH,int k)
  14. {
  15. IplImage *tmp;
  16. double a,b,c;
  17. char res[20];       //保存的图像名称
  18. tmp = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);
  19. for (int i = 0;i < height;i++)
  20. {
  21. for (int j = 0;j < width;j++)
  22. {
  23. a = 0.0;
  24. b = 0.0;
  25. c = 0.0;
  26. //去掉靠近边界的行列,无法滤波,超出范围
  27. if (i > int(mH/2) && i < height - int(mH/2) && j > int(mW) && j < width - int(mW/2))
  28. {
  29. for (int m = 0;m < mH;m++)
  30. {
  31. for(int n = 0;n < mW;n++)
  32. {
  33. //printf("%f\n",src[(i+m-int(mH/2))*width+(j+n-int(mW))]);
  34. a += src[(i+m-int(mH/2))*width+(j+n-int(mW))]*mask_rel[m*mW+n];
  35. b += src[(i+m-int(mH/2))*width+(j+n-int(mW))]*mask_img[m*mW+n];
  36. //printf("%f,%f\n",a,b);
  37. }
  38. }
  39. }
  40. c = sqrt(a*a+b*b);
  41. c /= mW*mH;
  42. tmp->imageData[i*width+j] = (unsigned char)c;
  43. }
  44. }
  45. sprintf(res,"result%d.jpg",k);
  46. cvSaveImage(res,tmp);
  47. cvReleaseImage(&tmp);
  48. }
  49. int _tmain(int argc, _TCHAR* argv[])
  50. {
  51. IplImage *src;
  52. double *rel,*img,*src_data,xtmp,ytmp,tmp1,tmp2,tmp3,re,im;
  53. double Theta,sigma,Gamma,Lambda,Phi;        //公式中的5个参数
  54. int gabor_height,gabor_width,x,y;
  55. src = cvLoadImage("test.jpg",CV_LOAD_IMAGE_GRAYSCALE);
  56. gabor_height = 10;
  57. gabor_width = 10;
  58. Gamma = 1.0;
  59. Lambda = 10.0;
  60. sigma = 100;
  61. Phi = 0;
  62. rel = (double *)malloc(sizeof(double)*gabor_width*gabor_height);//实数部分
  63. img = (double *)malloc(sizeof(double)*gabor_width*gabor_height);//虚数部分
  64. src_data = (double *)malloc(sizeof(double)*src->widthStep*src->height);   //图像数据
  65. for (int i=0;i<src->height;i++)
  66. {
  67. for (int j=0;j<src->widthStep;j++)
  68. {
  69. src_data[i*src->widthStep+j]=(unsigned char)src->imageData[i*src->widthStep+j];
  70. //printf("%f\n",src_data[i*src->widthStep+j]);
  71. }
  72. }
  73. //构造gabor函数
  74. for (int k = 0;k < N;k++)                    //定义N方向
  75. {
  76. Theta = PI*((double)k/N);
  77. for (int i = 0;i < gabor_height;i++) //定义模版大小
  78. {
  79. for (int j = 0;j < gabor_width;j++)
  80. {
  81. x = j - gabor_width/2;
  82. y = i - gabor_height/2;
  83. xtmp = (double)x*cos(Theta) + (double)y*sin(Theta);
  84. ytmp = (double)y*cos(Theta) - (double)x*sin(Theta);
  85. tmp1 = exp(-(pow(xtmp,2)+pow(ytmp*Gamma,2))/(2*pow(sigma,2)));
  86. tmp2 = cos(2*PI*xtmp/Lambda + Phi);
  87. tmp3 = sin(2*PI*xtmp/Lambda + Phi);
  88. re = tmp1*tmp2;
  89. im = tmp1*tmp3;
  90. rel[i*gabor_width+j] = re;
  91. img[i*gabor_width+j] = im;
  92. //printf("%f,%f\n",re,im);
  93. }
  94. }
  95. //用不同方向的GABOR函数对图像滤波并保存图片
  96. m_filer(src_data,src->height,src->width,rel,img,10,10,k);
  97. }
  98. free(rel);free(img);free(src_data);
  99. return 0;
  100. }

运行效果:

      

大概就这样凑活吧。我这边实数部分和虚数部分的处理是采用求模的方式。有问题的,请广大人民群众提出来啊。

三、用gabor提取纹理特征的思路【抄别人的论文】

Gabor滤波方法的主要思想是:不同纹理一般具有不同的中心频率及带宽,根据这些频率和带宽可以设计一组Gabor滤波器对纹理图像进行滤波,每个Gabor滤波器只允许与其频率相对应的纹理顺利通过,而使其他纹理的能量受到抑制,从各滤波器的输出结果中分析和提取纹理特征,用于之后的分类或分割任务。Gabor滤波器提取纹理特征主要包括两个过程:①设计滤波器(例如函数、数目、方向和间隔);②从滤波器的输出结果中提取有效纹理特征集。Gabor滤波器是带通滤波器,它的单位冲激响应函数(Gabor函数)是高斯函数与复指数函的乘积。它是达到时频测不准关系下界的函数,具有最好地兼顾信号在时频域的分辨能力。

实现步骤:

(1)将输入图像分为3×3(9块)和4×4(16块)的图像块;

(2)建立Gabor滤波器组:选择4个尺度,6个方向,这样组成了24个Gabor滤波器;

(3)Gabor滤波器组与每个图像块在空域卷积,每个图像块可以得到24个滤波器输出,这       些输出是图像块大小的图像,如果直接将其作为特征向量,特征空间的维数会很大,       所以需要“浓缩”;

(4)每个图像块经过Gabor滤波器组的24个输出,要“浓缩”(文中提到“average filter        responses within the block”我的理解是取灰度均值)为一个24×1的列向量作为该图像       块的纹理特征。查阅相关文献,发现也可以用方差。

利用一幅真实图像,按照文献原文所说,利用4scales*6orientations的Gabor滤波器组进行纹理特征提取,可以有效获得图像纹理信息。其中,单独拿出某组相同scale的结果,展示如下所示。【别人的实验结果,也没给代码,我也没去做】

时间: 2024-10-07 17:43:10

Gabor滤波器学习的相关文章

Gabor滤波器与纹理特征检索

本文目录 1 Gabor函数的空频特性 2 Gabor滤波器组设计 3 纹理特征的表示 1 Gabor函数的空频特性 先介绍一下什么是Gabor函数,以非对称的Gabor函数为例: (公式1) 它的实部是这样的: (公式2) Gabor函数的实况可以看成是一个高斯函数乘一个余弦函数,可以把高斯函数看成调制信号,把余弦函数看成载波信号,这样就容易相信gabor函数的波形了,如下: 了解了gabor函数的构造,下面我们从傅里叶变换的性质出发,了解一下gabor函数的滤波特性. (1)频移特性 我们知

Gabor滤波器的理解

2014-02-28 20:03 关于Gabor滤波器是如何提取出特征点,这个过程真是煎熬.看各种文章,结合百度.文章内部的分析才有一点点明白. Gabor滤波器究竟是什么? 很多表述说的是加窗傅里叶变换.怎么理解呢? 公式有下面几种表述:              (1)                      (2) (3) 文章中的和第三种最相似,那么我理解是:傅里叶变换的基是e^(j2πfx),那么所谓的加窗指的是加上一个高斯函数,如公式(1),和Gabor函数卷积的过程,很想再做一个

【图像处理】Gabor滤波器

Gabor的核函数参考的wiki 使用实数Real的公式计算核函数代码: Mat getGaborFilter(float lambda, float theta, float sigma2,float gamma, float psi = 0.0f){ if(abs(lambda-0.0f)<1e-6){ lambda = 1.0f; } float sigma_x = sigma2; float sigma_y = sigma2/(gamma*gamma); int nstds = 3; f

python实现gabor滤波器提取纹理特征 提取指静脉纹理特征 指静脉切割代码

参考博客:https://blog.csdn.net/xue_wenyuan/article/details/51533953 https://blog.csdn.net/jinshengtao/article/details/17797641 傅里叶变换是一种信号处理中的有力工具,可以帮助我们将图像从空域转换到频域,并提取到空域上不易提取的特征.但是经过傅里叶变换后, 图像在不同位置的频度特征往往混合在一起,但是Gabor滤波器却可以抽取空间局部频度特征,是一种有效的纹理检测工具. 在图像处理

matlab实现gabor滤波器的几种方式

转自:http://blog.csdn.net/watkinsong/article/details/7882443 方式一: [csharp] view plaincopy function result = gaborKernel2d( lambda, theta, phi, gamma, bandwidth) % GABORKERNEL2D % Version: 2012/8/17 by watkins.song % Version: 1.0 %   Fills a (2N+1)*(2N+

学习OpenCV——Gabor函数的应用

原文:http://blog.csdn.net/yao_zhuang/article/details/2532279 下载cvgabor.cpp和cvgabor.h到你的C/C++工程目录下 注:在我的资源中有改进过的cvgabor类 相关链接为:http://download.csdn.net/source/490114 特别注意:使用该类需要opencv库的支持,如何配置环境参见:http://www.opencv.org.cn/index.php/Template:Install 它有如下

Deep Learning(深度学习)学习笔记整理系列七

Deep Learning(深度学习)学习笔记整理系列 声明: 1)该Deep Learning的学习系列是整理自网上很大牛和机器学习专家所无私奉献的资料的.具体引用的资料请看参考文献.具体的版本声明也参考原文献. 2)本文仅供学术交流,非商用.所以每一部分具体的参考资料并没有详细对应.如果某部分不小心侵犯了大家的利益,还望海涵,并联系博主删除. 3)本人才疏学浅,整理总结的时候难免出错,还望各位前辈不吝指正,谢谢. 4)阅读本文需要机器学习.计算机视觉.神经网络等等基础(如果没有也没关系了,没

Deep Learning(深度学习)学习笔记整理系列之(四)——CNN

[email protected] http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0  2013-04-08 1)该Deep Learning的学习系列是整理自网上很大牛和机器学习专家所无私奉献的资料的.具体引用的资料请看参考文献.具体的版本声明也参考原文献. 2)本文仅供学术交流,非商用.所以每一部分具体的参考资料并没有详细对应.如果某部分不小心侵犯了大家的利益,还望海涵,并联系博主删除. 3)本人才疏学浅,整理总结的时候难免出错,还望各位前辈

Deep Learning(深度学习)学习笔记整理

申明:本文非笔者原创,原文转载自:http://www.sigvc.org/bbs/thread-2187-1-3.html 4.2.初级(浅层)特征表示 既然像素级的特征表示方法没有作用,那怎样的表示才有用呢? 1995 年前后,Bruno Olshausen和 David Field 两位学者任职 Cornell University,他们试图同时用生理学和计算机的手段,双管齐下,研究视觉问题. 他们收集了很多黑白风景照片,从这些照片中,提取出400个小碎片,每个照片碎片的尺寸均为 16x1