Gabor的OpenCV代码

article/2025/9/15 16:19:24

    唯一持续维护地址:http://52coding.com/opencv-gabor

      最近弄人脸识别,用到Gabor卷积核,但网上的代码似乎没有和我心意的,于是参考了自己写了下!参考了Zhou Mian以及matlab的Gabor实现代码的代码。虽然OpenCV的imporc下面有个gabor.cpp,但那个是一般形式的公式,不是用来做人脸识别的,可以参考文献A review on Gabor wavelets for face recognition,又说到。上代码和链接地址!下载地址~

   目前代码未经过更多的测试,不少功能为加入,但可以满足许多人的使用和参考了吧,很多人肯定非常非常需要,先开源下,欢迎指出错误之处。

//GaborFR.h
#pragma once
#include "opencv2\opencv.hpp"
#include <vector>
using namespace std;
using namespace cv;
class GaborFR
{
public:GaborFR();static Mat	getImagGaborKernel(Size ksize, double sigma, double theta, double nu,double gamma=1, int ktype= CV_32F);static Mat	getRealGaborKernel( Size ksize, double sigma, double theta, double nu,double gamma=1, int ktype= CV_32F);static Mat	getPhase(Mat &real,Mat &imag);static Mat	getMagnitude(Mat &real,Mat &imag);static void getFilterRealImagPart(Mat& src,Mat& real,Mat& imag,Mat &outReal,Mat &outImag);static Mat	getFilterRealPart(Mat& src,Mat& real);static Mat	getFilterImagPart(Mat& src,Mat& imag);void		Init(Size ksize=Size(19,19), double sigma=2*CV_PI,double gamma=1, int ktype=CV_32FC1);
private:vector<Mat> gaborRealKernels;vector<Mat> gaborImagKernels;bool isInited;
};

#include "stdafx.h"
#include "GaborFR.h"
GaborFR::GaborFR()
{isInited = false;
}
void GaborFR::Init(Size ksize, double sigma,double gamma, int ktype)
{gaborRealKernels.clear();gaborImagKernels.clear();double mu[8]={0,1,2,3,4,5,6,7};double nu[5]={0,1,2,3,4};int i,j;for(i=0;i<5;i++){for(j=0;j<8;j++){gaborRealKernels.push_back(getRealGaborKernel(ksize,sigma,mu[j]*CV_PI/8,nu[i],gamma,ktype));gaborImagKernels.push_back(getImagGaborKernel(ksize,sigma,mu[j]*CV_PI/8,nu[i],gamma,ktype));}}isInited = true;
}
Mat GaborFR::getImagGaborKernel(Size ksize, double sigma, double theta, double nu,double gamma, int ktype)
{double	sigma_x		= sigma;double	sigma_y		= sigma/gamma;int		nstds		= 3;double	kmax		= CV_PI/2;double	f			= cv::sqrt(2.0);int xmin, xmax, ymin, ymax;double c = cos(theta), s = sin(theta);if( ksize.width > 0 ){xmax = ksize.width/2;}else//这个和matlab中的结果一样,默认都是19 !{xmax = cvRound(std::max(fabs(nstds*sigma_x*c), fabs(nstds*sigma_y*s)));}if( ksize.height > 0 ){ymax = ksize.height/2;}else{ymax = cvRound(std::max(fabs(nstds*sigma_x*s), fabs(nstds*sigma_y*c)));}xmin = -xmax;ymin = -ymax;CV_Assert( ktype == CV_32F || ktype == CV_64F );float*	pFloat;double*	pDouble;Mat kernel(ymax - ymin + 1, xmax - xmin + 1, ktype);double k		=	kmax/pow(f,nu);double scaleReal=	k*k/sigma_x/sigma_y;for( int y = ymin; y <= ymax; y++ ){if( ktype == CV_32F ){pFloat = kernel.ptr<float>(ymax-y);}else{pDouble = kernel.ptr<double>(ymax-y);}for( int x = xmin; x <= xmax; x++ ){double xr = x*c + y*s;double v = scaleReal*exp(-(x*x+y*y)*scaleReal/2);double temp=sin(k*xr);v	=  temp*v;if( ktype == CV_32F ){pFloat[xmax - x]= (float)v;}else{pDouble[xmax - x] = v;}}}return kernel;
}
//sigma一般为2*pi
Mat GaborFR::getRealGaborKernel( Size ksize, double sigma, double theta, double nu,double gamma, int ktype)
{double	sigma_x		= sigma;double	sigma_y		= sigma/gamma;int		nstds		= 3;double	kmax		= CV_PI/2;double	f			= cv::sqrt(2.0);int xmin, xmax, ymin, ymax;double c = cos(theta), s = sin(theta);if( ksize.width > 0 ){xmax = ksize.width/2;}else//这个和matlab中的结果一样,默认都是19 !{xmax = cvRound(std::max(fabs(nstds*sigma_x*c), fabs(nstds*sigma_y*s)));}if( ksize.height > 0 )ymax = ksize.height/2;elseymax = cvRound(std::max(fabs(nstds*sigma_x*s), fabs(nstds*sigma_y*c)));xmin = -xmax;ymin = -ymax;CV_Assert( ktype == CV_32F || ktype == CV_64F );float*	pFloat;double*	pDouble;Mat kernel(ymax - ymin + 1, xmax - xmin + 1, ktype);double k		=	kmax/pow(f,nu);double exy		=	sigma_x*sigma_y/2;double scaleReal=	k*k/sigma_x/sigma_y;int	   x,y;for( y = ymin; y <= ymax; y++ ){if( ktype == CV_32F ){pFloat = kernel.ptr<float>(ymax-y);}else{pDouble = kernel.ptr<double>(ymax-y);}for( x = xmin; x <= xmax; x++ ){double xr = x*c + y*s;double v = scaleReal*exp(-(x*x+y*y)*scaleReal/2);double temp=cos(k*xr) - exp(-exy);v	=	temp*v;if( ktype == CV_32F ){pFloat[xmax - x]= (float)v;}else{pDouble[xmax - x] = v;}}}return kernel;
}
Mat GaborFR::getMagnitude(Mat &real,Mat &imag)
{CV_Assert(real.type()==imag.type());CV_Assert(real.size()==imag.size());int ktype=real.type();int row = real.rows,col = real.cols;int i,j;float*	pFloat,*pFloatR,*pFloatI;double*	pDouble,*pDoubleR,*pDoubleI;Mat		kernel(row, col, real.type());for(i=0;i<row;i++){if( ktype == CV_32FC1 ){pFloat = kernel.ptr<float>(i);pFloatR= real.ptr<float>(i);pFloatI= imag.ptr<float>(i);}else{pDouble = kernel.ptr<double>(i);pDoubleR= real.ptr<double>(i);pDoubleI= imag.ptr<double>(i);}for(j=0;j<col;j++){if( ktype == CV_32FC1 ){pFloat[j]= sqrt(pFloatI[j]*pFloatI[j]+pFloatR[j]*pFloatR[j]);}else{pDouble[j] = sqrt(pDoubleI[j]*pDoubleI[j]+pDoubleR[j]*pDoubleR[j]);}}}return kernel;
}
Mat GaborFR::getPhase(Mat &real,Mat &imag)
{CV_Assert(real.type()==imag.type());CV_Assert(real.size()==imag.size());int ktype=real.type();int row = real.rows,col = real.cols;int i,j;float*	pFloat,*pFloatR,*pFloatI;double*	pDouble,*pDoubleR,*pDoubleI;Mat		kernel(row, col, real.type());for(i=0;i<row;i++){if( ktype == CV_32FC1 ){pFloat = kernel.ptr<float>(i);pFloatR= real.ptr<float>(i);pFloatI= imag.ptr<float>(i);}else{pDouble = kernel.ptr<double>(i);pDoubleR= real.ptr<double>(i);pDoubleI= imag.ptr<double>(i);}for(j=0;j<col;j++){if( ktype == CV_32FC1 ){
// 				if(pFloatI[j]/(pFloatR[j]+pFloatI[j]) > 0.99)
// 				{
// 					pFloat[j]=CV_PI/2;
// 				}
// 				else
// 				{
//					pFloat[j] = atan(pFloatI[j]/pFloatR[j]);pFloat[j] = asin(pFloatI[j]/sqrt(pFloatR[j]*pFloatR[j]+pFloatI[j]*pFloatI[j]));
/*				}*/
//				pFloat[j] = atan2(pFloatI[j],pFloatR[j]);}//CV_32Felse{if(pDoubleI[j]/(pDoubleR[j]+pDoubleI[j]) > 0.99){pDouble[j]=CV_PI/2;}else{pDouble[j] = atan(pDoubleI[j]/pDoubleR[j]);}
//				pDouble[j]=atan2(pDoubleI[j],pDoubleR[j]);}//CV_64F}}return kernel;
}
Mat GaborFR::getFilterRealPart(Mat& src,Mat& real)
{CV_Assert(real.type()==src.type());Mat dst;Mat kernel;flip(real,kernel,-1);//中心镜面
//	filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_CONSTANT);filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_REPLICATE);return dst;
}
Mat GaborFR::getFilterImagPart(Mat& src,Mat& imag)
{CV_Assert(imag.type()==src.type());Mat dst;Mat kernel;flip(imag,kernel,-1);//中心镜面
//	filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_CONSTANT);filter2D(src,dst,CV_32F,kernel,Point(-1,-1),0,BORDER_REPLICATE);return dst;
}
void GaborFR::getFilterRealImagPart(Mat& src,Mat& real,Mat& imag,Mat &outReal,Mat &outImag)
{outReal=getFilterRealPart(src,real);outImag=getFilterImagPart(src,imag);
}

main

// Win32TestPure.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <vector>
#include <deque>
#include <iomanip>
#include <stdexcept>
#include <string>
#include <iostream>
#include <fstream>
#include <direct.h>//_mkdir()
#include "opencv2\opencv.hpp"
#include "GaborFR.h"
using namespace std;
using namespace cv;
int main()
{ //Mat M = getGaborKernel(Size(9,9),2*CV_PI,u*CV_PI/8, 2*CV_PI/pow(2,CV_PI*(v+2)/2),1,0);Mat saveM;//s8-4//s1-5//s1中年男人Mat I=imread("H:\\pic\\s1-5.bmp",-1);normalize(I,I,1,0,CV_MINMAX,CV_32F);Mat showM,showMM;Mat M,MatTemp1,MatTemp2;Mat line;int iSize=50;//如果数值比较大,比如50则接近论文中所述的情况了!估计大小和处理的源图像一样!for(int i=0;i<8;i++){showM.release();for(int j=0;j<5;j++){Mat M1= GaborFR::getRealGaborKernel(Size(iSize,iSize),2*CV_PI,i*CV_PI/8+CV_PI/2, j,1);Mat M2 = GaborFR::getImagGaborKernel(Size(iSize,iSize),2*CV_PI,i*CV_PI/8+CV_PI/2, j,1);//加了CV_PI/2才和大部分文献的图形一样,不知道为什么!Mat outR,outI;GaborFR::getFilterRealImagPart(I,M1,M2,outR,outI);
//			M=GaborFR::getPhase(M1,M2);
//			M=GaborFR::getMagnitude(M1,M2);
//			M=GaborFR::getPhase(outR,outI);
//			M=GaborFR::getMagnitude(outR,outI);//			M=GaborFR::getMagnitude(outR,outI);
// 			MatTemp2=GaborFR::getPhase(outR,outI);
// 			M=outR;M=M1;// 		resize(M,M,Size(100,100));normalize(M,M,0,255,CV_MINMAX,CV_8U);showM.push_back(M);line=Mat::ones(4,M.cols,M.type())*255;showM.push_back(line);}showM=showM.t();line=Mat::ones(4,showM.cols,showM.type())*255;showMM.push_back(showM);showMM.push_back(line);}showMM=showMM.t();
//	bool flag=imwrite("H:\\out.bmp",showMM);imshow("saveMM",showMM);waitKey(0);return 0;
}//endof   main()

一下图片可能和程序实际运行结果有点不同,图片只是示意图,代码暂时没问题。需要考虑的是iSize大小问题,首先iSize要用奇数,然后大部分文献iSize都比较大,好像是100左右,但没看到他们描述过卷积核的大小。






http://chatgpt.dhexx.cn/article/o2JZKlh2.shtml

相关文章

2021-08-07 Gabor滤波器简介以及简单应用

Gabor滤波器&#xff08;Gabor Filter&#xff09; 文章目录 Gabor滤波器&#xff08;Gabor Filter&#xff09;简介Gabor滤波器的不同参数Gabor滤波器的简单应用&#xff08;python&#xff09; 简介 Gabor滤波器是一种线性滤波器&#xff0c;用于边缘检测、纹理分析、特征提…

Gabor Filters

Gabor Filters: Manjunath, B. S., & Ma, W. Y. (1996). Texture features for browsing and retrieval of image data. IEEE Transactions on Pattern Analysis and Machine Intelligence, 18(8), 837-842. Gabor滤波器是一种基于Gabor函数的特定频率和方向选择性滤波器。…

基于Gabor滤波器的人脸特征提取

Gabor小波变换的核函数&#xff0c;其最大的特点是其与人脑的皮层神经细胞的二维反射区具有相似的特征。基于Gabor小波变换的特征信息能够有效提取各种细节结构信息&#xff0c;因此Gabor小波变换在图像识别领域有着较为广泛的应用。根据Gabor小波变换的特点&#xff0c;基于Ga…

Gabor特征提取

Gabor小波与人类视觉系统中简单细胞的视觉刺激响应非常相似。它在提取目标的局部空间和频率域信息方面具有良好的特性。虽然Gabor小波本身并不能构成正交基&#xff0c;但在特定参数下可构成紧框架。Gabor小波对于图像的边缘敏感&#xff0c;能够提供良好的方向选择和尺度选择特…

Gabor 卷积神经网络

与不涉及学习过程的 hand-crafted 滤波器不同&#xff0c;DCNNs-based feature extraction 是一种 data-driven 技术&#xff0c;可以直接从数据中学习具有鲁棒性的特征表示。然而&#xff0c;它有非常大的训练成本和复杂的模型参数。 DCNNs 有限的几何变换建模能力主要来自于…

如何理解Gabor滤波器

转载自如何理解Gabor滤波器 介绍 我们已经知道&#xff0c;傅里叶变换是一种信号处理中的有力工具&#xff0c;可以帮助我们将图像从空域转换到频域&#xff0c;并提取到空域上不易提取的特征。但是经过傅里叶变换后&#xff0c;图像在不同位置的频度特征往往混合在一起&…

基于python的图像Gabor变换及特征提取

基于python的图像Gabor变换及特征提取 1.前言2. “Gabor帮主”简介3.“Gabor帮主”大招之图像变换3.“Gabor帮主”大招之图像特征提取 深圳中兴网信科技有限公司&#xff1a;廖海斌 1.前言 在深度学习出来之前&#xff0c;图像识别领域北有“Gabor帮主”&#xff0c;南有“SIF…

Gabor滤波器详解

转载自如何理解Gabor滤波器 介绍 我们已经知道&#xff0c;傅里叶变换是一种信号处理中的有力工具&#xff0c;可以帮助我们将图像从空域转换到频域&#xff0c;并提取到空域上不易提取的特征。但是经过傅里叶变换后&#xff0c;图像在不同位置的频度特征往往混合在一起&…

Gabor 变换

http://blog.sina.com.cn/s/blog_48a242d601000a3j.html Gabor变换属于加窗傅立叶变换&#xff0c;Gabor函数可以在频域不同尺度、不同方向上提取相关的特征。另外Gabor函数与人眼的生物作用相仿&#xff0c;所以经常用作纹理识别上&#xff0c;并取得了较好的效果。 Gabor变换…

图像处理:Gabor滤波器简介以及python实现

在图像处理中&#xff0c;以Dennis Gabor命名的Gabor滤波器是一种用于纹理分析的线性滤波器&#xff0c;本质上是指在分析点或分析区域周围的局部区域内&#xff0c;分析图像中是否存在特定方向的特定频率内容。Gabor滤波器的频率和方向表示被许多当代视觉科学家认为与人类视觉…

Gabor滤波器学习

本文的目的是用C实现生成Gabor模版&#xff0c;并对图像卷积。并简单提一下&#xff0c;Gabor滤波器在纹理特征提取上的应用。 一、什么是Gabor函数&#xff08;以下内容含部分翻译自维基百科&#xff09; 在图像处理中&#xff0c;Gabor函数是一个用于边缘提取的线性滤波器。…

Gabor变换

2009-12-13 00:51:08| 分类&#xff1a; 图像处理|字号 订阅 转自 http://blog.sina.com.cn/s/blog_48a242d601000a3j.html~typev5_one&labelrela_prevarticle Gabor变换属于加窗傅立叶变换&#xff0c;Gabor函数可以在频域不同尺度、不同方向上提取相关的特征。另外Gabo…

Gabor滤波器

Gabor是一个用于边缘提取的线性滤波器&#xff0c;其频率和方向表达与人类视觉系统类似&#xff0c;能够提供良好的方向选择和尺度选择特性&#xff0c;而且对光照变换不敏感&#xff0c;因此十分适合纹理分析。 一、Gabor滤波器 在图像处理中&#xff0c;Gabor函数是一个用于…

Gabor 特征

一.Gabor 特征的简介 Gabor 特征是一种可以用来描述图像纹理信息的特征&#xff0c;Gabor 滤波器的频率和方向与人类的视觉系统类似&#xff0c;特别适合于纹理表示与判别。Gabor 特征主要依靠 Gabor 核在频率域上对信号进行加窗&#xff0c;从而能描述信号的局部频率信息。 …

Gabor滤波器特征提取原理讲解及c++实现

文章目录 Gabor滤波器复正弦载波高斯滤波 参数解释gabor滤波核实现效果&#xff1a; Gabor滤波器 1946年,Dennis Gabor于在“Theory of communication”一文中提出了著名的“窗口”傅里叶变换&#xff08;也叫短时Fourier变换&#xff0c;STFT&#xff09;&#xff0c;即Gabor…

FCN学习

简介 FCN(Fully Convolutional Networks for Semantic Segmentation)是首个端对端的针对像素级别预测的全卷积网络&#xff0c;发表在2015CVPR。全卷积的意思是全连接层全部替换成了卷积层。 上面这句话的重点是全卷积&#xff0c;但是端到端end to end这个词也同样重要。end…

卷积神经网络CNN(3)—— FCN(Fully Convolutional Networks)要点解释

前言 参考FCN论文&#xff1a;Fully Convolutional Networks for Semantic Segmentation FCN作为图像语义分割的先河&#xff0c;实现像素级别的分类&#xff08;即end to end&#xff0c;pixel-wise&#xff09;&#xff0c;为后续使用CNN作为基础的图像语义分割模型提供重要…

语义分割——FCN模型pytorch实现

FCN网络简介 全卷积网络&#xff08;Fully Convolutional Networks&#xff0c;FCN&#xff09;是Jonathan Long等人于2015年在Fully Convolutional Networks for Semantic Segmentation一文中提出的用于图像语义分割的一种框架&#xff0c;是首个端对端的针对像素级预测的全卷…

全卷积网络 FCN 详解

原文链接&#xff1a;全卷积网络 FCN 详解 FCN是深度学习应用在图像分割的代表作, 是一种端到端(end to end)的图像分割方法, 让网络做像素级别的预测直接得出label map, 下面我们来看看FCN是如何做到像素级别的分类的 论文 : Fully Convolutional Networks for Semantic Segme…

图像分割-FCN全卷积神经网络(完整代码详解)

目录 FCN全卷积神经网络 实现过程 全卷积 反卷积 FCN的三点创新 code FCN全卷积神经网络 FCN为深度学习在语义分割领域的开山之作&#xff0c;提出使用卷积层代替CNN中的全连接操作&#xff0c;生成热力图heat map而不是类别。 实现过程 图1 FCN网络结构 包括全卷积过程…