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