python-opencv图像处理之SIFT尺度不变特征变换
在這一章當中,我們將學習SIFT算法的概念,找到SIFT關鍵點和描述算符。
一、概念
在前面,我們看到了一些像Harris這樣的拐角檢測器。它們是旋轉不變的,這意味著即使圖像旋轉了,我們也可以找到相同的角。很明顯,因為轉角在旋轉的圖像中也仍然是轉角。但是縮放呢?如果縮放圖像,則拐角可能不是角。例如,檢查下面的簡單圖像。在同一窗口中放大小窗口中小圖像中的拐角時,該角是平坦的。因此,Harris拐角不是尺度不變的。
以下是SIFT算法四個步驟
1、尺度空間極值檢測
從上圖可以明顯看出,我們不能使用相同的窗口來檢測具有不同比例的關鍵點。即便小拐角可以。但是要檢測更大的拐角,我們將需要更大的窗口。為此,使用了***比例空間濾波***。在其中,找到具有各種σσσ值的圖像的高斯拉普拉斯算子。LoG用作斑點檢測器,可檢測由于σσσ的變化而導致的各種大小的斑點。簡而言之,σσσ用作縮放參數。例如,在上圖中,低σσσ的高斯核對于較小的拐角給出較高的值,而高σσσ的高斯核對于較大的拐角而言非常合適。因此,我們可以找到整個尺度和空間上的局部最大值,這給了我們(x,y,σ)(x,y,σ)(x,y,σ)值的列表,這意味著在(x,y)(x,y)(x,y)在σσσ尺度上有一個潛在的關鍵點。
但是這種LoG代價昂貴,因此SIFT算法使用的是高斯差值,它是LoG的近似值。高斯差是作為具有兩個不同σσσ的圖像的高斯模糊差而獲得的,設為σσσ和kσkσkσ。此過程是針對高斯金字塔中圖像的不同八度完成的。如下圖所示:
一旦找到該DoG,便會在圖像上搜索比例和空間上的局部極值。例如,將圖像中的一個像素與其8個相鄰像素以及下一個比例的9個像素和前一個比例的9個像素進行比較。如果是局部極值,則可能是關鍵點。從根本上說,關鍵點是最好的代表。如下圖所示:
對于不同的參數,本文給出了一些經驗數據,可以概括為:octaves=4,縮放尺度=5,初始σ=1.6σ=1.6σ=1.6,k=2k=\sqrt{2}k=2?等作為最佳值。
2. 關鍵點定位
一旦找到潛在的關鍵點位置,就必須對其進行優化以獲取更準確的結果。他們使用了標度空間的泰勒級數展開來獲得更精確的極值位置,如果該極值處的強度小于閾值(根據論文為0.03),則將其拒絕。在OpenCV DoG中,此閾值稱為ContrastThreshold,它對邊緣的響應較高,因此也需要刪除邊緣。
為此,使用類似于哈里斯拐角檢測器的概念。他們使用2x2的Hessian矩陣(H)計算主曲率。從哈里斯拐角檢測器我們知道,對于邊緣,一個特征值大于另一個特征值。因此,這里他們使用了一個簡單的函數。
如果該比率大于一個閾值(在OpenCV中稱為edgeThreshold),則該關鍵點將被丟棄。論文上寫的值為10。
因此,它消除了任何低對比度的關鍵點和邊緣關鍵點,剩下的就是很可能的目標點。
3. 方向分配
現在,將方向分配給每個關鍵點,以實現圖像旋轉的不變性。根據比例在關鍵點位置附近采取鄰域,并在該區域中計算梯度大小和方向。創建了一個具有36個覆蓋360度的bin的方向直方圖(通過梯度幅度和σσσ等于關鍵點比例的1.5的高斯加權圓窗加權)。提取直方圖中的最高峰,并且將其超過80%的任何峰也視為計算方向。它創建的位置和比例相同但方向不同的關鍵點。它有助于匹配的穩定性。
4. 關鍵點描述
現在創建了關鍵點描述符。在關鍵點周圍采用了16x16的鄰域。它分為16個4x4大小的子塊。對于每個子塊,創建8 bin方向直方圖。因此共有128個bin值可用。它被表示為形成關鍵點描述符的向量。除此之外,還采取了幾種措施來實現針對照明變化,旋轉等的魯棒性。
5. 關鍵點匹配
通過識別兩個圖像的最近鄰,可以匹配兩個圖像之間的關鍵點。但是在某些情況下,第二個最接近的匹配可能非常接近第一個。它可能是由于噪音或其他原因而發生的。在那種情況下,采用最接近距離與第二最接近距離之比。如果大于0.8,將被拒絕。根據論文,它可以消除大約90%的錯誤匹配,而僅丟棄5%的正確匹配。 因此,這是SIFT算法的總結。有關更多詳細信息和理解,強烈建議閱讀原始論文。記住一件事,該算法已申請專利。所以這個算法包含在opencv contrib repo中
二、OpenCV中的SIFT
現在,讓我們來看一下OpenCV中可用的SIFT功能。讓我們從關鍵點檢測開始并進行繪制。首先,我們必須構造一個SIFT對象。我們可以將不同的參數傳遞給它,這些參數是可選的,它們在docs中已得到很好的解釋。
import numpy as np import cv2 as cv img = cv.imread('home.jpg') gray= cv.cvtColor(img,cv.COLOR_BGR2GRAY) sift = cv.xfeatures2d.SIFT_create() kp = sift.detect(gray,None) img=cv.drawKeypoints(gray,kp,img) cv.imwrite('sift_keypoints.jpg',img)sift.detect()函數在圖像中找到關鍵點。如果只想搜索圖像的一部分,則可以通過掩碼。每個關鍵點是一個特殊的結構,具有許多屬性,例如其(x,y)坐標,有意義的鄰域的大小,指定其方向的角度,指定關鍵點強度的響應等。
OpenCV還提供cv.drawKeyPoints()函數,該函數在關鍵點的位置繪制小圓圈。 如果將標志cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS傳遞給它,它將繪制一個具有關鍵點大小的圓,甚至會顯示其方向。 請參見以下示例。
img=cv.drawKeypoints(gray,kp,img,flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) cv.imwrite('sift_keypoints.jpg',img)查看結果:
現在要計算描述符,OpenCV提供了兩種方法。
我們將看到第二種方法:
sift = cv.xfeatures2d.SIFT_create() kp, des = sift.detectAndCompute(gray,None)這里的kp將是一個關鍵點列表,而des是一個形狀為NumberofKeypoints×128Number_of_Keypoints×128Numbero?fK?eypoints×128的數字數組。
這樣我們得到了關鍵點,描述符等。現在我們想看看如何在不同圖像中匹配關鍵點。我們將在接下來的章節中學習。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的python-opencv图像处理之SIFT尺度不变特征变换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: /root/.bashrc与/etc/p
- 下一篇: 2019最新python面试题详解(应届