图像处理之Gabor滤波器(C++)
前言
Gabor滤波器是一个用于边缘提取的线性滤波器,其频率和方向表达与人类视觉系统类似,能够提供良好的方向选择和尺度选择特性,而且对于光照变化不敏感,十分适合纹理特征分析。
一、Gabor滤波器原理
在空间域,一个二维的Gabor滤波器是一个正弦平面波和高斯核函数的乘积。前者是调谐函数,后者是窗口函数。因此,Gabor变换又称为窗口傅里叶变换(短时傅里叶变换),帮助我们更多的关心信号局部范围内的特征。
参数解释:
- sigma(σ):高斯函数的标准差,通常取2*PI
- theta(θ):滤波器的方向,单位为弧度,取值为(0、PI/4(45°)…)。
- gamma(γ):长宽比,决定Gabor函数图像的椭圆率(滤波器形状),一般取0.5。
- psi(ψ):相位偏移量,取值范围是-180°~180°,单位也是弧度,即[-PI,PI]。
- lambda(λ):滤波器的波长,通常大于等于2。
- x、y的大小由gabor核的大小决定,一般xmax=kernel.width/2;ymax=kernel.height/2;
xmin=-xmax;ymin=-ymax;
二、代码实现
1.代码实现
代码如下(示例):
#include <iostream>
#include <opencv.hpp>
using namespace std;
/*
* @param cv::Size ksize 卷积核的大小
* @param double sigma 高斯函数标准差,一般取2*CV_PI
* @param double theta Gabor核函数的倾斜角度
* @param double lambd 波长
* @param double gamma 长宽比,决定Gabor核函数的椭圆率,一般取0.5
* @param double psi 相位偏移量[-CV_PI,CV_PI]
* @param int ktype 数据类型(CV_32F/CV_64F)
*/
cv::Mat GetGaborKernel(cv::Size ksize, double sigma, double theta, double lambd, double gamma, double psi, int ktype=CV_32F)
{
cv::Mat kernel(ksize, ktype);
double sigma_x = sigma;
double sigma_y = sigma / gamma;
double c = cos(theta), s = sin(theta);
//确定卷积核函数的变化范围
int xmax = ksize.width / 2;
int ymax = ksize.height / 2;
int xmin = -xmax;
int ymin = -ymax;
CV_Assert(ktype == CV_32F || ktype == CV_64F);
double ex = -0.5 / (sigma_x * sigma_x);
double ey = -0.5 / (sigma_y * sigma_y);
double cscale = CV_PI * 2 / lambd;
double _x=0, _y=0;
for (int y = ymin; y <= ymax; y++)
{
for (int x = xmin; x <= xmax; x++)
{
_x = x * c + y * s;
_y =-x * s + y * c;
double value = std::exp(ex * _x * _x + ey * _y * _y) * cos(cscale * _x + psi);
if (ktype == CV_32F)
kernel.at<float>(ymax - y, xmax - x) = (float)value;
else
kernel.at<double>(ymax - y, xmax - x) = value;
}
}
return kernel;
}
int main()
{
//读取图片
string filepath = "F://work_study//algorithm_demo//baby.jpg";
cv::Mat src = cv::imread(filepath, cv::IMREAD_GRAYSCALE);
if (src.empty())
{
std::cout << "imread error" << std::endl;
return -1;
}
cv::Mat dst(src.size(), src.type());
//构造Gabor卷积核
cv::Mat kernel=myGetGaborKernel(cv::Size(5, 5), CV_PI/4, 1.0, 5.0, 0.5, -CV_PI / 2);
//进行滤波
cv::filter2D(src, dst, CV_8UC1, kernel);
//保存图片
imwrite("dst.bmp", dst);
cv::waitKey(0);
return 0;
}
2.结果展示
总结
本文介绍了Gabor原理以及C++实现的Gabor的过程。