本文参考:https://new.qq.com/omn/20180715/20180715G0KDIG.html
https://www.jianshu.com/p/f1d9f2482191
https://www.cnblogs.com/walccott/p/4956856.html
-
Gabor变换
Gabor变换是一种短时傅里叶变换方法,其实质是在傅里叶变换中加入一个窗函数,通过窗函数来实现信号的时频分析。当选取高斯函数作为窗函数时,短时傅里叶变换称为Gabor变换。在一维情况中,Gabor变换代表着时频分析的最优方法,二维情况中则是空间频域分析的方法。对于图像来说,窗函数决定了它在空域的局部性,所以可以通过移动窗口的中心來获得不同位置的空间域信息。由于髙斯函数在经过傅里叶变换以后仍然是高斯函数,这就使得Gabor变换在频域上仍然是局部的。
与传统的傅立叶变换相比,Gabor变换具有良好的时频局部化特性。即非常容易地调整Gabor滤波器的方向、基频带宽及中心频率从而能够最好的兼顾信号在时空域和频域中的分辨能力;Gabor小波变换具有多分辨率特性即变焦能力;采用多通道滤波技术,将一组具有不同时频域特性的Gabor小波应用于图像变换,每个通道都能够得到输入图像的某种局部特性,这样可以根据需要在不同粗细粒度上分析图像。
-
Gabor滤波器
Gabor滤波器纹理分析方法是一种重要的基于变换的纹理特征提取方法,通过选用某一特定的Gabor函数,设计Gabor滤波器,来实现图像的多尺度、多方向的特征提取。在二维空间中,使用一个三角函数(如正弦函数)与一个高斯函数叠加,我们就得到了一个 Gabor 滤波器。如下图所示:
二维 Gabor 函数的数学表达如下:
其中是复数正弦波部分,是高斯核函数。
,
因此:
进一步简化为空间域二维Gabor Filter为:
实数部分为:
虚数部分为:
其中:
参数介绍:
1、σx、σy分别为高斯函数沿 x 轴和 y 轴的标准差, 控制高斯窗口作用的范围,σx、σy越大,高斯窗作用的范围也越大。变换σx、σy可以使gabor滤波器匹配图像中不同空间尺度的结构。通常取σx=σy。
2、γ为空间纵横比,决定了 Gabor 函数形状的椭圆率。当 γ=1 时,形状是圆的;当 γ<1 时,形状随着平行条纹方向而拉长。通常该值为0.5。
3、λ表示 Gabor 核函数中余弦函数的波长参数,以像素为单位,通常大于等于2,但不能大于输入图像尺寸的五分之一。
4、θ表示 Gabor 滤波核中平行条带的方向。有效值为从0到360度的实数。
5、φ表示 Gabor 核函数中余弦函数的相位参数。它的取值范围为-180度到180度。其中,0度和180度对应的方程与原点对称,-90度和90度的方程分别于原点成中心对称。
-
Opencv实例
效果图:
原图
结果图
代码:
//
//opencv4.1.0
//
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main() {
Mat img = imread("4.png");
Mat img_f;
img.convertTo(img_f, CV_32F);
//参数初始化
int kernel_size = 3;
double sigma = 1.0, lambd = CV_PI / 8, gamma = 0.5, psi = 0;
vector<Mat>destArray;
double theta[4];
Mat temp;
//theta法线方向
theta[0] = 0;
theta[1] = CV_PI/4;
theta[2] = CV_PI / 2;
theta[3] = CV_PI-CV_PI / 4;
//这里lambd只取一个值,所以4个filter
for (size_t i = 0; i < 4; i++){
Mat kernell;
Mat dest;
kernell = cv::getGaborKernel(Size(kernel_size, kernel_size), sigma, theta[i], lambd, gamma, psi, CV_32F);
filter2D(img_f, dest, CV_32F, kernell);
destArray.push_back(dest);
}
Mat dst1, dst2, dst3, dst4;
convertScaleAbs(destArray[0], dst1);
convertScaleAbs(destArray[1], dst2);
convertScaleAbs(destArray[2], dst3);
convertScaleAbs(destArray[3], dst4);
//合并结果
add(destArray[0], destArray[1], destArray[0]);
add(destArray[2], destArray[3], destArray[2]);
add(destArray[0], destArray[2], destArray[0]);
Mat dst;
convertScaleAbs(destArray[0], dst,0.2,0);
//二值化显示
Mat gray, binary;
cvtColor(dst, gray, COLOR_BGR2GRAY);
threshold(gray, binary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
imshow("src", img);
imshow("result", dst);
imshow("result1", dst1);
imshow("result2", dst2);
imshow("result3", dst3);
imshow("result4", dst4);
imshow("binary", binary);
waitKey(0);
return 0;
}