1. 程式人生 > >影象區域性特徵提取

影象區域性特徵提取

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

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

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

對於區域性特徵的檢測,通常使用區域性影象描述子來進行。

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

斑點檢測原理與舉例

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}{2\sigma^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角點檢測(一