原文地址,taotao1233
本文的目的是用C实现生成Gabor模版,并对图像卷积。并简单提一下,Gabor滤波器在纹理特征提取上的应用。
一、什么是Gabor函数(以下内容含部分翻译自维基百科)
在图像处理中,Gabor函数是一个用于边缘提取的线性滤波器。Gabor滤波器的频率和方向表达同人类视觉系统类似。研究发现,Gabor滤波器十分适合纹理表达和分离。在空间域中,一个二维Gabor滤波器是一个由正弦平面波调制的高斯核函数。
还有,生物学实验发现,Gabor滤波器可以很好地近似单细胞的感受野函数(光强刺激下的传递函数),什么视皮层内的超柱,bla...bla,总之是这方面仿生的数学模型。
另外,网上有一种说法,gabor分为实部和虚部,用实部进行滤波后图像会平滑;虚部滤波后用来检测边缘。【来自百度知道某个大神的回答】,我查了文献, 发现的确有人用Gabor的奇函数部分做边缘提取(《基于Gabor滤波器的边缘检测算法》 无线电工程 2000年第3卷第30期)。另外,从我的实验结果也有类似的发现。暂且认为这个对的吧。
Gabor滤波器的脉冲响应,可以定义为一个正弦波(对于二维Gabor滤波器是正弦平面波)乘以高斯函数。由于乘法卷积性质,Gabor滤波器的脉冲响 应的傅立叶变换是其调和函数的傅立叶变换和高斯函数傅立叶变换的卷积。该滤波器由实部和虚部组成,二者相互正交。一组不同频率不同方向的Gabor函数数 组对于图像特征提取非常有用。
下面给出二维Gabor函数的数学表达:
复数表达:
![](//img-blog.csdn.net/20140103194509703)
实数部分:
![](//img-blog.csdn.net/20140103194541375)
虚数部分:
![](//img-blog.csdn.net/20140103194618453)
其中:
和
下面介绍公式中各个参数的含义,及参数如何配置问题【都从老外那翻译来的】:
波长(λ):它的值以像素为单位指定,通常大于等于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![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)
function gabor_k = compute(x,y,f0,theta)
r = 1; g = 1;
x1 = x*cos(theta) + y*sin(theta);
y1 = -x*sin(theta) + y*cos(theta);
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![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)
%绘制一个Gabor滤波器的空域和频域函数图
clear;
x = 0;
theta = 0;
f0 = 0.2;
for i = linspace(-15,15,50)
x = x + 1;
y = 0;
for j = linspace(-15,15,50)
y = y + 1;
z(y,x)=compute(i,j,f0,theta);
end
end
x = linspace(-15,15,50);
y = linspace(-15,15,50);
surf(x,y,real(z))
title('Gabor filter:real component');
xlabel('x');
ylabel('y');
zlabel('z');
figure(2);
surf(x,y,imag(z))
title('Gabor filter:imaginary component');
xlabel('x');
ylabel('y');
zlabel('z');
Z = fft2(z);
u = linspace(-0.5,0.5,50);
v = linspace(-0.5,0.5,50);
figure(3);
surf(u,v,abs(fftshift(Z)))
title('Gabor filter:frequency component');
xlabel('u');
ylabel('v');
zlabel('Z');
运行结果:
[plain] view plaincopy![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)
%4个方向的Gabo滤波器通过图像显示
clear;
x = 0;
theta = pi*3/4;%用弧度0,pi/4,pi/2,pi*3/4
f0 = 0.2;
for i = linspace(-15,15,50)
x = x + 1;
y = 0;
for j = linspace(-15,15,50)
y = y + 1;
z(y,x)=compute(i,j,f0,theta);
end
end
z_real = real(z);
m = min(z_real(:));
z_real = z_real+abs(m);
M = max(z_real(:));
imshow(1/M*z_real);
figure(2)
z_imag = imag(z);
z_imag = z_imag+abs(m);
M =
m = min(z_imag(:));
max(z_imag(:));
imshow(1/M*z_imag);
运行效果:
实数部分:
![](//img-blog.csdn.net/20140103210537484)
虚数部分:
![](//img-blog.csdn.net/20140103210613968)
[plain] view plaincopy![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)
%4个方向的Gabor滤波器对lena进行滤波
clear;
I = imread('.\pic\lena.bmp');
f0 = 0.2;
count = 0;
for theta = [0,pi/4,pi/2,pi*3/4];%用弧度0,pi/4,pi/2,pi*3/4
count = count + 1;
x = 0;
for i = linspace(-8,8,11)
x = x + 1;
y = 0;
for j = linspace(-8,8,11)
y = y + 1;
z(y,x)=compute(i,j,f0,theta);
end
end
figure(count);
filtered = filter2(z,I,'valid');
f = abs(filtered);
imshow(f/max(f(:)))
end
运行效果:
![](//img-blog.csdn.net/20140103210842843) ![](//img-blog.csdn.net/20140103210855828) ![](//img-blog.csdn.net/20140103210906343)
好吧,不管他了。大概感受一下吧。由于我没看明白他的gabor函数怎么定义的,参数设置也不一样,实验结果很不相同,我希望我是对的,天地良心呐!!我只能按照维基百科给出的函数,编写了以下C代码:
[cpp] view plaincopy![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)
// my_gabor.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
#include
#include
#include "math.h"
#define PI 3.1415926
#define N 4
using namespace std;
using namespace cv;
void m_filer(double *src,int height,int width,double *mask_rel,double *mask_img,int mW,int mH,int k)
{
IplImage *tmp;
double a,b,c;
char res[20]; //保存的图像名称
tmp = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);
for (int i = 0;i widthStep+j]=(unsigned char)src->imageData[i*src->widthStep+j];
//printf("%f\n",src_data[i*src->widthStep+j]);
}
}
//构造gabor函数
for (int k = 0;k |