圖像局部特徵提取

  • 2019 年 10 月 3 日
  • 筆記

圖像特徵可以包括顏色特徵、紋理特徵、形狀特徵以及局部特徵點等。其中局部特點具有很好的穩定性,不容易受外界環境的干擾。圖像特徵提取是圖像分析與圖像識別的前提,它是將高維的圖像數據進行簡化表達最有效的方式,從一幅圖像的的數據矩陣中,我們看不出任何信息,所以我們必須根據這些數據提取出圖像中的關鍵信息,一些基本元件以及它們的關係。

圖像局部特徵描述的核心問題是不變性(魯棒性)和可區分性。由於使用局部圖像特徵描述子的時候,通常是為了魯棒地處理各種圖像變換的情況。因此,在構建/設計特徵描述子的時候,不變性問題就是首先需要考慮的問題。在寬基線匹配中,需要考慮特徵描述子對於視角變化的不變性、對尺度變化的不變性、對旋轉變化的不變性等;在形狀識別和物體檢索中,需要考慮特徵描述子對形狀的不變性。

局部特徵點是圖像特徵的局部表達,它只能反應圖像上具有的局部特殊性,所以它只適合於對圖像進行匹配,檢索等應用。對於圖像理解則不太適合。而後者更關心一些全局特徵,如顏色分佈,紋理特徵,主要物體的形狀等。全局特徵容易受到環境的干擾,光照,旋轉,噪聲等不利因素都會影響全局特徵。相比而言,局部特徵點,往往對應着圖像中的一些線條交叉,明暗變化的結構中,受到的干擾也少。

對於局部特徵的檢測,通常使用局部圖像描述子來進行。

斑點角點是兩類局部特徵點。斑點通常是指與周圍有着顏色和灰度差別的區域,如草原上的一棵樹或一棟房子。它是一個區域,所以它比角點的抗噪能力要強,穩定性要好。而角點則是圖像中物體的拐角或者線條之間的交叉部分。

斑點檢測原理與舉例

LoG與DoH

斑點檢測的方法主要包括利用高斯拉普拉斯算子檢測的方法(LOG),以及利用像素點Hessian矩陣(二階微分)及其行列式值的方法(DOH)。

DoH方法就是利用圖像點二階微分Hessian矩陣, Hessian矩陣行列式的值,同樣也反映了圖像局部的結構信息。與LoG相比,DoH對圖像中的細長結構的斑點有較好的抑制作用。

無論是LoG還是DoH,它們對圖像中的斑點進行檢測,其步驟都可以分為以下兩步:

  1. 使用不同的生成或模板,並對圖像進行卷積運算;
  2. 在圖像的位置空間與尺度空間中搜索LoG與DoH響應的峰值。

SIFT(尺度不變特徵變換)

尺度不變特徵轉換(Scale-invariant feature transform或SIFT)是一種電腦視覺的算法用來偵測與描述影像中的局部性特徵,它在空間尺度中尋找極值點,並提取出其位置、尺度、旋轉不變量。該描述子具有非常強的穩健性。

SIFT算法詳細介紹

SIFT算法步驟

  1. 構建DOG尺度空間

    模擬圖像數據的多尺度特徵,大尺度抓住概貌特徵,小尺度注重細節特徵。通過構建高斯金字塔(每一層用不同的參數(sigma)做高斯模糊(加權)),保證圖像在任何尺度都能有對應的特徵點,即保證尺度不變性

  2. 關鍵點搜索和定位:

    確定是否為關鍵點,需要將該點與同尺度空間不同(sigma)值的圖像中的相鄰點比較,如果該點為max或min,則為一個特徵點。找到所有特徵點後,要去除低對比度和不穩定的邊緣效應的點,留下具有代表性的關鍵點(比如,正方形旋轉後變為菱形,如果用邊緣做識別,4條邊就完全不一樣,就會錯誤;如果用角點識別,則穩定一些)。去除這些點的好處是增強匹配的抗噪能力和穩定性。最後,對離散的點做曲線擬合,得到精確的關鍵點的位置和尺度信息。

  3. 方向賦值

    為了實現旋轉不變性,需要根據檢測到的關鍵點的局部圖像結構為特徵點賦值。具體做法是用梯度方向直方圖。在計算直方圖時,每個加入直方圖的採樣點都使用圓形高斯函數進行加權處理,也就是進行高斯平滑。這主要是因為SIFT算法只考慮了尺度和旋轉不變形,沒有考慮仿射不變性。通過高斯平滑,可以使關鍵點附近的梯度幅值有較大權重,從而部分彌補沒考慮仿射不變形產生的特徵點不穩定。注意,一個關鍵點可能具有多個關鍵方向,這有利於增強圖像匹配的魯棒性

  4. 關鍵點描述子生成

    關鍵點描述子不但包括關鍵點,還包括關鍵點周圍對其有貢獻的像素點。這樣可使關鍵點有更多的不變特性,提高目標匹配效率。在描述子採樣區域時,需要考慮旋轉後進行雙線性插值,防止因旋轉圖像出現白點。同時,為了保證旋轉不變性,要以特徵點為中心,在附近領域內旋轉(theta)角,然後計算採樣區域的梯度直方圖,形成n維SIFT特徵矢量(如128-SIFT)。最後,為了去除光照變化的影響,需要對特徵矢量進行歸一化處理。

SIFT特徵提取的優點

  1. SIFT特徵是圖像的局部特徵,其對旋轉、尺度縮放、亮度變化保持不變性,對視角變化、仿射變換、噪聲也保持一定程度的穩定性;
  2. 獨特性(Distinctiveness)好,信息量豐富,適用於在海量特徵數據庫中進行快速、準確的匹配;
  3. 多量性,即使少數的幾個物體也可以產生大量的SIFT特徵向量;
  4. 高速性,經優化的SIFT匹配算法甚至可以達到實時的要求;
  5. 可擴展性,可以很方便的與其他形式的特徵向量進行聯合;
  6. 需要較少的經驗主義知識,易於開發。

SIFT特徵提取的缺點

  1. 實時性不高,因為要不斷地進行下採樣和插值等操作;
  2. 有時特徵點較少(比如模糊圖像);
  3. 對邊緣光滑的目標無法準確提取特徵(比如邊緣平滑的圖像,檢測出的特徵點過少,對圓更是無能為力)。

SIFT特徵提取可以解決的問題

目標的自身狀態、場景所處的環境和成像器材的成像特性等因素影響圖像配准/目標識別跟蹤的性能。而SIFT算法在一定程度上可解決:

  1. 目標的旋轉、縮放、平移(RST)
  2. 圖像仿射/投影變換(視點viewpoint)
  3. 光照影響(illumination)
  4. 目標遮擋(occlusion)
  5. 雜物場景(clutter)
  6. 噪聲

角點檢測的原理與舉例

角點檢測的方法也是極多的,其中具有代表性的算法是Harris算法與FAST算法。
算法原理詳解:Harris特徵點檢測FAST特徵檢測

Harris角點特徵提取

Harris角點檢測是一種基於圖像灰度的一階導數矩陣檢測方法。檢測器的主要思想是局部自相似性/自相關性,即在某個局部窗口內圖像塊與在各個方向微小移動後的窗口內圖像塊的相似性。該算法認為像素周圍顯示存在多餘一個方向的邊,便認為該點為興趣點,即稱為角點。

Harris算法步驟

  1. 利用水平、豎直差分算子對圖像每個像素進行濾波以求得(I_x, I_y),進而求得圖像域中點(x)上的對稱半正定矩陣(M_I = M_I(x))
    [ M_I=nabla I nabla I^T=left[ begin{array}{c} I_x \ I_y end{array} right] left[ begin{array}{c} I_x & I_y end{array}right] = left[ begin{array}{cc} I_x^2 & I_x I_y \ I_x I_y & I_y^2 end{array} right] ]
  2. 選擇權重矩陣(W)(通常為高斯濾波器(G))對(M)進行濾波
    [ W = exp(- frac{x^2+y^2}{2sigma^2}) ]
    [ M_I = W * M_I ]
  3. 利用(M)計算對應於每個像素的角點量(cim)(R):
    [ cim = frac{I_x^2*I_y^2-(I_xI_y)^2}{I_x^2+I_y^2} ]
  4. 在矩陣 (cim) 中,同時滿足 (cim) 大於一闕值 (thresh)(cim) 是某領域內的局部極大值,這兩個條件的點被認為是角點。

    提高闕值,則提取的角點數目變少,降低闕值,則提取的角點數目變多
    另外求局部極大值的領域大小也會影響提取角點的數目和容忍度

Harris角點性質

  1. 該算法算子對亮度和對比度的變化不敏感。

    這是因為在進行Harris角點檢測時,使用了微分算子對圖像進行微分運算,而微分運算對圖像密度的拉升或收縮和對亮度的抬高或下降不敏感。換言之,對亮度和對比度的仿射變換並不改變Harris響應的極值點出現的位置,但是,由於閾值的選擇,可能會影響角點檢測的數量。

  2. 算子具有旋轉不變性。

    Harris角點檢測算子使用的是角點附近的區域灰度二階矩矩陣。而二階矩矩陣可以表示成一個橢圓,橢圓的長短軸正是二階矩矩陣特徵值平方根的倒數。當特徵橢圓轉動時,特徵值並不發生變化,所以判斷角點響應值也不發生變化,由此說明Harris角點檢測算子具有旋轉不變性。

  3. 算子不具有尺度不變性。

Harris算法實現

import numpy as np  import matplotlib.pyplot as plt  from PIL import Image  from scipy.ndimage import filters      class Harris:      def __init__(self, img_path):          self.img_path = img_path          self.grayImg = None          self.Ix = None          self.Iy = None          self.Ix_mul_Ix = None          self.Ix_mul_Iy = None          self.Iy_mul_Iy = None          self.cim = None          self.filtered_coords = None        def _rgb2gray(self):          self.grayImg = Image.open(self.img_path).convert('L')          self.grayImg = np.array(self.grayImg)        def _cal_ix_iy(self, sigma=3):          # 計算導數          self.Ix = np.zeros(self.grayImg.shape)          filters.gaussian_filter(self.grayImg, (sigma, sigma), (0, 1), self.Ix)          self.Iy = np.zeros(self.grayImg.shape)          filters.gaussian_filter(self.grayImg, (sigma, sigma), (1, 0), self.Iy)        def _cal_para(self):          # 計算Ix^2,Iy^2和Ix*Iy並加入高斯濾波          self.Ix_mul_Ix = filters.gaussian_filter(self.Ix*self.Ix, 3)          self.Iy_mul_Iy = filters.gaussian_filter(self.Iy*self.Iy, 3)          self.Ix_mul_Iy = filters.gaussian_filter(self.Ix*self.Iy, 3)        def _cal_cim(self):          self.cim = (self.Ix_mul_Ix*self.Iy_mul_Iy - 2*self.Ix_mul_Iy) / (self.Ix_mul_Ix + self.Iy_mul_Iy)        def cal_harris(self, min_dist=10, threshold=0.1):          self._rgb2gray()          self._cal_ix_iy()          self._cal_para()          self._cal_cim()          conner_threshold = self.cim.max()*threshold          self.cim = (self.cim > conner_threshold) * 1          coords = np.array(self.cim.nonzero()).T          candidate_values = [self.cim[c[0], c[1]] for c in coords]          index = np.argsort(candidate_values)          allowed_locations = np.zeros(self.cim.shape)          allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = 1          self.filtered_coords = []          for i in index:              if allowed_locations[coords[i, 0], coords[i, 1]] == 1:                  self.filtered_coords.append(coords[i])                  allowed_locations[(coords[i, 0] - min_dist):(coords[i, 0] + min_dist),                  (coords[i, 1] - min_dist):(coords[i, 1] + min_dist)] = 0  # 此處保證min_dist*min_dist只有一個harris特徵點          return self.filtered_coords        def plot_harris_point(self):          plt.figure()          plt.gray()          plt.imshow(Image.open(self.img_path).convert('L'))          plt.plot([p[1] for p in self.filtered_coords], [p[0] for p in self.filtered_coords], '*')          plt.axis('off')          plt.show()      if __name__ == '__main__':      img_path = "./imgs/3.jpg"      harris = Harris(img_path)      harris.cal_harris()      harris.plot_harris_point()

結果演示

參考文獻

python計算機視覺編程第2章
圖像處理之特徵提取
python計算機視覺編程之局部圖像描述子
圖像局部特徵點檢測算法綜述
斑點檢測
SIFT定位算法關鍵步驟的說明
SIFT算法詳解
sift特徵提取算法
Harris特徵點檢測
FAST特徵檢測
特徵點提取之Harris角點提取法
Harris角點檢測(一)