1. 程式人生 > >基於Gabor濾波器的紋理分割

基於Gabor濾波器的紋理分割

Gabor變換是一種短時傅立葉變換方法,其實質是在傅立葉變換中加入一個窗函式,通過窗函式來實現訊號的時頻分析。當選取高斯函式作為窗函式時,短時傅立葉變換稱為Gabor變換。在一維情況中,Gabor變換代表著時頻分析的最優方法,二維情況中則是空間頻域分析的方法。對於影象來說,窗函式決定了它在空域的區域性性,所以可以通過移動視窗的中心來獲得不同位置的空間域資訊。由於髙斯函式在經過傅立葉變換以後仍然是高斯函式,這就使得Gabor變換在頻域上仍然是區域性的。簡直完美!

與傳統的傅立葉變換相比,Gabor小波變換具有良好的時頻區域性化特性。即非常容易地調整Gabor濾波器的方向、基頻頻寬及中心頻率從而能夠最好的兼顧訊號在時空域和頻域中的分辨能力;Gabor小波變換具有多解析度特性即變焦能力;採用多通道濾波技術,將一組具有不同時頻域特性的Gabor小波應用於影象變換,每個通道都能夠得到輸入影象的某種區域性特性,這樣可以根據需要在不同粗細粒度上分析影象。

Gabor濾波器紋理分析方法是一種重要的基於變換的紋理特徵提取方法,通過選用某一特定的Gabor函式,設計Gabor濾波器,來實現影象的多尺度、多方向的特徵提取。

gabor濾波器的引數很多,看著就讓人頭暈,搞清楚各個引數的物理含義及相互之間的關係後,公式就好理解了。後面使用的話設好引數就可以直接用。


標準差σx、σy分別為高斯函式沿 x 軸和 y 軸的標方差, 控制高斯視窗作用的範圍,σx、σy越大,高斯窗作用的範圍也越大。變換σx、σy可以使gabor濾波器匹配影象中不同空間尺度的結構。通常取σx=σy。

這裡的縱橫比y/x=1。關於縱橫比說一下,縱橫比控制高斯函式橫截面的橢圓形狀,為1時截面就是圓。

(U,V)是中心頻率,其頻率調製的方向角φ=arctan(V/U)。

對高斯基本函式g(x,y)進行尺度變換和旋轉變換得到一簇自相似函式,即Gabor小波,這樣gabor濾波器就可以在不同尺度、方向上分析紋理,粗糙的紋理用低解析度分析,細緻的紋理用高解析度去分析。其中尺度變換和旋轉函式如下


θ 表示空域座標繞x軸逆時針旋轉θ 角,對θ 離散化, 令θ=n*π /N ,n= 0,1, N-1,N 為整數.則可用n定義濾波器的方向。改變θ,濾波器就可以在不同方向上檢測紋理。a為伸縮因子,a>1,一般取a=1.414,m 定義濾波器的尺度,m=1,2,...M-1

通常情況下,取Gabor函式中高斯函式部分的方向θ

與複數調製部分函式的輻角φ相等,即令θ=φ。


則gabor函式可化簡為


定義波長(λ):λ是COS調製因子的波長,它的值以畫素為單位指定,通常大於等於2.但不能大於輸入影象尺寸的五分之一。 λ和F有如下關係:

                                                           λ=2*π/F

要實現多尺度檢測的話,要麼改變波長,要麼改變中心頻率,濾波器的中心頻率越小(即波長越長),提取的紋理特徵的尺度越大。當濾波器紋理與影象作用時,濾波器覆蓋下的區域性紋理頻率與濾波器的頻率越接近響應就越大,反之越小。

φ是cos調製因子的相位偏移值,φ決定了Gabor函式的對稱性,比如在φ=0,π的時候,Gabor函式是中心(對於(U,V)來說)對稱的,而當 φ=-π/2,π/2的時候,Gabor函式是中心反對稱的,並且所有其他情況都是這兩種情況的組合。

gabor函式可以表示為一個橢圓高斯函式與一個複平面函式的乘積形式。複數形式的二維 gabor函式包含兩個正交投影: 實數的偶對稱餘弦部分和虛數的奇對稱正弦部分。一般根據需要提取實數部分或虛數部分或複數幅值。

#ifndef __GABOR__
#define __GABOR__


class gabor
{
//#define PI 3.1415926
	typedef unsigned char BYTE;
	const double phase=0;//相位The phase offset φ in the 
	//argument of the cosine factor of the Gabor function is specified in degrees
	//const double gama=1.8;//縱橫比
	const double OriBandwidth = PI / 6;//Orientation Bandwidth of a Gabor filter
	const double FreBandwidth = 1;
	//const int kernel_size = 21;
	const double bandwidth = 1;
	const int theta_bins = 8;const int img_size = 256;
private:
	//void resize256();//如果最長邊大於256,則將影象按比例縮放到256*,為了減小運算量
	void get_kernel(double*&kernel,const double theta,const double lamda,int &kernel_w,int&kernel_h);
	//void low_pass_filter();
	//double calculateSigma(double waveLength, double bandwidth);
	void filter2D(double*kernel, const int kernel_w, const int kernel_h, 
		BYTE*img,const int img_w,const int img_h,double**&out,int cnt);
public:
	gabor();
	~gabor();
	void apply_filter(BYTE*grey_img,const int imgH,const int imgW,double**&output);

};

#endif

#include "stdafx.h"
#include "gabor.h"
#include<cmath>

gabor::gabor()
{
}

gabor::~gabor()
{
	
}

//double gabor::gabor_func(BYTE*Image, const int imgH, const int imgW, const double oriBand,
//	const double theta, const double lambda, const double phi, const double freBand)
//{
//	//determine Sx and Sy by Oritation Frequency and Bandwidth Bandwidth
//	double Sx = lambda / PI*sqrt(log(2) / 2)*((pow(freBand,2) + 1) / (pow(freBand,2) - 1));
//	double Sy = lambda / PI* sqrt(log(2) / 2) / tan(oriBand / 2);
//
//}


void gabor::apply_filter(BYTE*grey_img, const int imgH, const int imgW, double**&output)
{
	int lamda_n = (log(img_size / 8.0) + 0.01) / log(2.0);
	double*lamda=new double[lamda_n];//The wavelength of the cosine factor of the Gabor filter
	for (int i = 0; i < lamda_n; i++)
	{
		lamda[i] = 2 * pow(sqrt(2.0), double(i));
		printf("%lf    ", lamda[i]);
	}
	double*kernel = NULL;
	double*theta = new double[theta_bins];//The orientation of Gabor filter
	for (int i = 0; i < theta_bins; i++)
		theta[i] = double(i) / theta_bins*PI;
	
	output = new double*[imgH * imgW];
	for (int i = 0; i < imgH*imgW; i++)
		{
			output[i] = new double[theta_bins * lamda_n];
		}
	for (int i = 0; i < lamda_n; i++)
		for (int j = 0; j < theta_bins; j++)
		{
			int kernel_w=0, kernel_h=0;
			get_kernel(kernel,theta[j], lamda[i], kernel_w, kernel_h);
			filter2D(kernel, kernel_w, kernel_h, grey_img, img_size, img_size, output, i * 6 + j);
			delete[]kernel;
			kernel = NULL;
		}
	delete[]lamda,theta;
}


void gabor::get_kernel(double*&kernel, const double theta, const double lamda, int &kernel_w, int&kernel_h)
{
	double Sx = lamda / PI*sqrt(log(2) / 2)*((pow(2, FreBandwidth) + 1) / (pow(2 ,FreBandwidth) - 1));
	double Sy = lamda / PI* sqrt(log(2) / 2) / tan(OriBandwidth / 2);

	double Sigma_max = Sx; if (Sy>Sx)Sigma_max=Sy;

	//Gabor Mask Size
	kernel_w = ceil(Sigma_max * 3) * 2 + 1;
	kernel_h = ceil(Sigma_max * 3) * 2 + 1;

	if (kernel)
		delete[]kernel;
	kernel = new double[kernel_w*kernel_w];

	for (int m = 0; m < kernel_h;m++)
		for (int n = 0; n < kernel_w; n++)
		{
			int x = m - ceil(kernel_w / 2);
			int y = n - ceil(kernel_h / 2);
			double xPrime = x * cos(theta) + y * sin(theta);
			double yPrime = y * cos(theta) - x * sin(theta);
			kernel[m*kernel_w + n] = 1 / (2 * PI*Sx*Sy)*exp(-0.5*(pow(xPrime / Sx, 2.0) 
				+ (yPrime / Sy)*(yPrime / Sy)))*cos(2 * PI*xPrime / lamda + phase);
			//printf("%lf    ", kernel[m*kernel_w + n]);
		}
	//printf("\n");
}

void gabor::filter2D(double*kernel, const int kernel_w, const int kernel_h, BYTE*img,
	const int img_w, const int img_h, double**&out, int chanel)
{
	BYTE*img_data = new BYTE[img_h*img_w];

	for (int i = 0; i < img_h; i++)
		for (int j = 0; j < img_w; j++)
		{
			double temp = 0;
			int cnt = 0;
			for (int m = -kernel_h/2; m <= kernel_h/2; m++)
				for (int n = -kernel_w/2; n <= kernel_w/2; n++)
				{
					double img_value = (i + m >= 0 && i + m < img_h
						&&j + n >= 0 && j + n < img_w) ? img[(i + m)*img_w + j + n] : 0;
					temp += img_value*kernel[cnt++];
				}
			out[i*img_w + j][chanel] = abs(temp);
			img_data[i*img_w + j] = abs(50*temp);
		}
	
	/*save_gray("11.bmp", img_data, img_h, img_w);
	CxImage cx;
	cx.Load("11.bmp", CXIMAGE_FORMAT_BMP);
	int templates[25] = { 1, 4, 7, 4, 1,
		4, 16, 26, 16, 4,
		7, 26, 41, 26, 7,
		4, 16, 26, 16, 4,
		1, 4, 7, 4, 1 };
	cx.Filter(templates, 25, 273, 0);*/
	delete[]img_data;
	return ;
}


opencv裡的gabor核函式生成程式碼

/*
 Gabor filters and such. To be greatly extended to have full texture analysis.
 For the formulas and the explanation of the parameters see:
 http://en.wikipedia.org/wiki/Gabor_filter
*/

cv::Mat cv::getGaborKernel( Size ksize, double sigma, double theta,
                            double lambd, double gamma, double psi, int ktype )
{
    double sigma_x = sigma;
    double sigma_y = sigma/gamma;
    int nstds = 3;
    int xmin, xmax, ymin, ymax;
    double c = cos(theta), s = sin(theta);

    if( ksize.width > 0 )
        xmax = ksize.width/2;
    else
        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 );

    Mat kernel(ymax - ymin + 1, xmax - xmin + 1, ktype);
    double scale = 1;
    double ex = -0.5/(sigma_x*sigma_x);
    double ey = -0.5/(sigma_y*sigma_y);
    double cscale = CV_PI*2/lambd;

    for( int y = ymin; y <= ymax; y++ )
        for( int x = xmin; x <= xmax; x++ )
        {
            double xr = x*c + y*s;
            double yr = -x*s + y*c;

            double v = scale*exp(ex*xr*xr + ey*yr*yr)*cos(cscale*xr + psi);
            if( ktype == CV_32F )
                kernel.at<float>(ymax - y, xmax - x) = (float)v;
            else
                kernel.at<double>(ymax - y, xmax - x) = v;
        }

    return kernel;
}


        

分割步驟

對待分割影象F(m,n)進行多尺度、多方向的Gabor變換。

對得到的各子帶採用非線性變換函式進行變換,並通過低通濾波來降低相同紋理區域內特徵的變換,增加不同區域的區別。

將上述處理得的各子帶對應的畫素組成向量

採用分類演算法對特徵向量進行分類,實現紋理影象的分割。

Log Gabor

相關推薦

基於Gabor濾波器紋理分割

Gabor變換是一種短時傅立葉變換方法,其實質是在傅立葉變換中加入一個窗函式,通過窗函式來實現訊號的時頻分析。當選取高斯函式作為窗函式時,短時傅立葉變換稱為Gabor變換。在一維情況中,Gabor變換代表著時頻分析的最優方法,二維情況中則是空間頻域分析的方法。對於影象來說,

python實現gabor濾波器提取紋理特征 提取指靜脈紋理特征 指靜脈切割代碼

thumb 存儲 傳遞 AI axis mit 適應性 float end 參考博客:https://blog.csdn.net/xue_wenyuan/article/details/51533953      https://blog.csdn.net/jinsheng

基於Gabor紋理特徵的影象檢索

一、 Gabor 紋理 在影象檢索中不同影象的紋理在不同的粗糙度以及方向性等方面有很大的差別。Gabor濾波器帶彈性以及方向性選擇了使用單個濾波器無法同時滿足不同型別紋理分析的需要。Gabor紋理特徵通過在不同的尺度、不同的方向上分別進行Gabor濾波,然後對濾波的結果進行

紋理分割(四)Snakes相關知識備份

這裡主要是備份一些演算法,和基礎知識點,基本都是有關蛇模型/主動輪廓模型。 1. 梯度下降法 有關基礎知識,這裡不贅述了,有關程式碼轉過來,備份一下。 原作地址: http://www.tuicool.com/articles/e6VzIz steepest

如何理解Gabor濾波器

轉載自:(https://blog.csdn.net/xue_wenyuan/article/details/51533953). 介紹 我們已經知道,傅立葉變換是一種訊號處理中的有力工具,可以幫助我們將影象從空域轉換到頻域,並提取到空域上不易提取的特徵。但是經過傅立葉變換後,影象在

matlab中實現Gabor濾波器

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

基於圖的影象分割(Effective graph-based image segmentation)python實現

基於圖的影象分割Effective graph-based image segmentation 前言 簡介 程式碼實現與解讀 圖的構建 影象分割 問題 前言 最近在學習區域卷積神經網路(RCN

基於OpenCV 的影象分割

1、影象閾值化 原始碼: #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace std; using

影象分割基於圖的影象分割(Graph-BasedImageSegmentation)

影象分割—基於圖的影象分割(Graph-Based Image Segmentation) Reference: Efficient Graph-Based Image Segmentation,IJCV 2004,MIT Code Graph-Based Se

opencv學習筆記五十七:基於分水嶺的影象分割

#include<opencv2\opencv.hpp> using namespace cv; using namespace std; int main(int arc, char** argv) { Mat src = imread("1.jpg");

Gabor濾波器圖片

主要任務就是做出以下這樣一張Gabor濾波器的圖片。 這裡用到的公式如下: 程式部分實現的是公式內的實數部分。 函式檔案 function gb = gaborfilter_2d( lambda, theta, phrase, gamma, bw

Log-Gabor濾波器構造,opencv實現

參照連結:https://github.com/carandraug/PeterKovesiImage/blob/master/PhaseCongruency/gaborconvolve.m點選開啟連結 畢設要用Log-Gabor濾波器來實現視網膜血管增強,這東西真是折騰了

生成二維gabor濾波器的matlab程式碼

function hp=gbfilter2(sigmax,mu,mv) % 函式功能:生成二維離散gabor函式模板hp。可能主要用於影象的紋理分析; %輸入引數:sigmax——x方向的方差; %                  mu——x方向中心頻率;mv——y

Gabor濾波器與特徵提取

一、Gabor濾波器 Gabor濾波器,最主要使用優勢體現在對物體紋理特徵的提取上。 二維Gabor基函式能夠很好地描述哺乳動物初級視覺系統中一對簡單視覺神經元的感受野特性。隨著小波變換和神經生理學

OpenCV 基於超畫素分割的影象區域選取方法及原始碼

摳取影象區域的一個小demo,藉助影象超畫素分割的方法,將影象成子分塊,再利用種子填充演算法,選取子塊區域。 超畫素分割方法,採用論文 SEEDS: Superpixels Extracted via Energy-Driven Sampling

python程式碼 Gabor濾波器

# coding:utf-8 import cv2 import numpy as np import pylab as pl from PIL import Image #構建Gabor濾波器 def build_filters(): filters = []

Gabor濾波器通俗理解

轉自:http://xuewenyuan.github.io/2016/05/27/How-To-Understand-Gabor-Filter/ 介紹 我們已經知道,傅立葉變換是一種訊號處理中的有力工具,可以幫助我們將影象從空域轉換到頻域,並提取到空域上不易提取的特

最簡單的基於FCN的語義分割任務

先上一個圖,這個圖展示的是在Weizmann horse 資料集上做的一個語義分割任務時最簡單的全卷積網路結構。其實寫這個部落格是想記錄一下自己前段時間研究FCN的內容,主要工作是在兩個資料集,一個是Weizmann horse 資料集,另一個是lfw資料集。同樣是使用的FCN網路(層數不同

什麼是Log-Gabor 濾波器,為什麼他們有效

What Are Log-Gabor Filters and Why Ate They Good? Gabor 濾波器是獲取區域性頻域資訊的一個傳統的選擇。他們提供了空間域位置和頻率域資訊的一個最好的融合。然而,他們卻有著兩個主要的限制:一方面,他的最大頻寬被限制在近似一

Gabor濾波器詳解

介紹 我們已經知道,傅立葉變換是一種訊號處理中的有力工具,可以幫助我們將影象從空域轉換到頻域,並提取到空域上不易提取的特徵。但是經過傅立葉變換後,影象在不同位置的頻度特徵往往混合在一起,但是Gabor濾波器卻可以抽取空間區域性頻度特徵,是一種有效的紋理檢測工具。  如