python實現gabor濾波器提取紋理特征 提取指靜脈紋理特征 指靜脈切割代碼
參考博客:https://blog.csdn.net/xue_wenyuan/article/details/51533953
https://blog.csdn.net/jinshengtao/article/details/17797641
傅裏葉變換是一種信號處理中的有力工具,可以幫助我們將圖像從空域轉換到頻域,並提取到空域上不易提取的特征。但是經過傅裏葉變換後,
圖像在不同位置的頻度特征往往混合在一起,但是Gabor濾波器卻可以抽取空間局部頻度特征,是一種有效的紋理檢測工具。
在圖像處理中,Gabor函數是一個用於邊緣提取的線性濾波器。Gabor濾波器的頻率和方向表達同人類視覺系統類似。研究發現,Gabor濾波器十分適合紋理表達和分離。在空間域中,一個二維Gabor濾波器是一個由正弦平面波調制的高斯核函數。
gabor核函數的表達式:
復數表達式:
可以拆解:實部:
虛部:
其中:
和
參數介紹:
方向(θ):這個參數指定了Gabor函數並行條紋的方向,它的取值為0到360度
波長(λ):它的值以像素為單位指定,通常大於等於2.但不能大於輸入圖像尺寸的五分之一。
相位偏移(φ):它的取值範圍為-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形狀越大,可見平行興奮和抑制區條紋數量越多。
好介紹完畢。
現在進入主題,我們提取紋理特征。
提取紋理特征,還有增強紋理特征,很多時候我們都是要先提取ROI感興趣區域來進行操作的。很多圖片上的其他空間其實對我們沒有什麽太大的作用,還影響程序的運行速度。則我們只拿ROI區域進行紋理提取。
先看看原來的指靜脈圖片:
這圖片區域很多,一般我們只需要中間那部分指靜脈紋理最多的ROI區域。
代碼:
#!/usr/bin/python #coding:utf-8 import numpy as np import os import cv2 def pathFile(path): return os.getcwd() + ‘/‘ + path def brightestColumn(img): w, h = img.shape r = range(h / 2, h - 1) c = range(0, w - 1) return img[c][:,r].sum(axis=0).argmax() #構建GABOR濾波器 def build_filters(): """ returns a list of kernels in several orientations """ filters = [] ksize = 31 #gaborl尺度 這裏是一個 for theta in np.arange(0, np.pi, np.pi / 4): #gaborl方向 0 45 90 135 角度尺度的不同會導致濾波後圖像不同 params = {‘ksize‘:(ksize, ksize), ‘sigma‘:3.3, ‘theta‘:theta, ‘lambd‘:18.3, ‘gamma‘:4.5, ‘psi‘:0.89, ‘ktype‘:cv2.CV_32F} #gamma越大核函數圖像越小,條紋數不變,sigma越大 條紋和圖像都越大 #psi這裏接近0度以白條紋為中心,180度時以黑條紋為中心 #theta代表條紋旋轉角度 #lambd為波長 波長越大 條紋越大 kern = cv2.getGaborKernel(**params) #創建內核 kern /= 1.5*kern.sum() filters.append((kern,params)) return filters #濾波過程 def process(img, filters): """ returns the img filtered by the filter list """ accum = np.zeros_like(img) #初始化img一樣大小的矩陣 for kern,params in filters: fimg = cv2.filter2D(img, cv2.CV_8UC3, kern) #2D濾波函數 kern為其濾波模板 np.maximum(accum, fimg, accum) #參數1與參數2逐位比較 取大者存入參數3 這裏就是將紋理特征顯化更加明顯 return accum #獲取感興趣區域的top 和 bottom值 用於切割顯示圖像 def getRoiHCut2(img, p0): h, w = img.shape maxTop = np.argmax(img[0: h / 2, 0]) #在一定區域遍歷選取指靜脈邊緣 具體高寬結合圖像 minTop = np.argmax(img[0: h / 2, w-1]) if(maxTop < 65): maxBottom = np.argmax(img[(13 * h / 16): 40*h/48 , 0]) + 3 * h / 4 minBottom = np.argmax(img[(13 * h / 16): 40*h/48, w-1]) + 3 * h / 4 else: maxBottom = np.argmax(img[(3 * h / 4): h , 0]) + 3 * h / 4 minBottom = np.argmax(img[(3 * h / 4): h, w-1]) + 3 * h / 4 maxTop = (2*maxTop + minTop) / 3 maxBottom = (maxBottom + 2*minBottom) / 3 return img[maxTop:maxBottom,:] #獲取感興趣區域範圍 def getRoi(img): height, width = img.shape heightDist = height / 4 w = img.copy() w1 = w[heightDist:3 * heightDist,width / 4:] p0 = brightestColumn(w1) + heightDist + height / 2 #將手指邊緣的高度加上四分之三原始高度 pCol = w[:,p0:p0 + 1] pColInv = pCol[::-1] clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) #構建一個有限對比適應性直方圖均衡化器 w1_2 = clahe.apply(w[:, (p0 /20):(p0 + p0 / 2)]) #截取區域寬度大概是p0高度的一點五倍 apply是獲取一個返回值 這裏是為了方便參數的傳遞 w2 = getRoiHCut2(w1_2, p0) res = cv2.resize(w2, (270, 150), interpolation=cv2.INTER_CUBIC) return clahe.apply(res) def logImg(img): return img.astype(float) / 255 #將圖像數據轉為0-1存儲 mDir=[] imgs = [] dbDir = os.getcwd() + "/db100/" people = os.listdir(dbDir) people.sort() for person in people: personDir = dbDir + person + "/" hands = os.listdir(personDir) for hand in hands: handDir = personDir + hand + "/" mDir += [handDir] mg = os.listdir(handDir) mg.sort() imgs = imgs + [handDir + s.split(".")[0] for s in mg if not s.split(".")[0] == "Thumbs"] p0Imgs = [i.replace(‘db‘, ‘gab_roi_db‘) for i in imgs] #p0Imgs是每個文件的路徑,mDir是需要創建路徑所有文件夾存放預處理後圖片 mDir = [i.replace(‘db‘, ‘gab_roi_db‘) for i in mDir] #判斷路徑是否存在 不存在就創建路徑 for path in mDir: if not os.path.exists(path): os.makedirs(path) filters = build_filters() for index, imgPath in enumerate(imgs): img = cv2.imread(imgPath + ".bmp", 0) res0 = process(getRoi(img), filters) #獲取ROI進行直方圖均衡化 切割後 在gabor濾波 cv2.imwrite(p0Imgs[index] + ".png", res0) print index cv2.waitKey(0) cv2.destroyAllWindows()
好現在看看處理後的指靜脈圖片:
看起來還不錯吧,預處理之後就可以 進行紋理特征提取放入文件進行模式匹配啊 進行指靜脈識別啊。有興趣的就期待在下之後的博客。
http://www.cnblogs.com/DOMLX/p/8989836.html 提取紋理特征
http://www.cnblogs.com/DOMLX/p/8672489.html 指靜脈細化算法
http://www.cnblogs.com/DOMLX/p/8111507.html 指靜脈切割過程
python實現gabor濾波器提取紋理特征 提取指靜脈紋理特征 指靜脈切割代碼