日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

第十三节、SURF特征提取算法

發(fā)布時(shí)間:2024/9/5 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第十三节、SURF特征提取算法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上一節(jié)我們已經(jīng)介紹了SIFT算法,SIFT算法對(duì)旋轉(zhuǎn)、尺度縮放、亮度變化等保持不變性,對(duì)視角變換、仿射變化、噪聲也保持一定程度的穩(wěn)定性,是一種非常優(yōu)秀的局部特征描述算法。但是其實(shí)時(shí)性相對(duì)不高。

SURF(Speeded Up Robust Features)算法改進(jìn)了特征了提取和描述方式,用一種更為高效的方式完成特征點(diǎn)的提取和描述。

一 使用快速Hessian算法和SURF來(lái)提取和檢測(cè)特征

我們先用OpenCV庫(kù)函數(shù)演示一下快速Hessian算法和SURF來(lái)提取的效果,然后再來(lái)講述一下SURF算法的原理。

SURF特征檢測(cè)算法由Herbert Lowe于2006年發(fā)表,該算法比SIFT算法快好幾倍,它吸收了SIFT算法的思想。

SURF算法采用快速Hessian算法檢測(cè)關(guān)鍵點(diǎn),而SURF算子會(huì)通過(guò)一個(gè)特征向量來(lái)描述關(guān)鍵點(diǎn)周圍區(qū)域的情況。這和SIFT算法很像,SIFT算法分別采用DoG和SIFT算子來(lái)檢測(cè)關(guān)鍵點(diǎn)和提取關(guān)鍵點(diǎn)的描述符。下面我們來(lái)演示一個(gè)例子:

# -*- coding: utf-8 -*- """ Created on Fri Aug 24 20:09:32 2018@author: lenovo """# -*- coding: utf-8 -*- """ Created on Wed Aug 22 16:53:16 2018@author: lenovo """''' SURF算法 ''' import cv2 import numpy as npimg = cv2.imread('./image/cali.bmp') img = cv2.resize(img,dsize=(600,400)) #轉(zhuǎn)換為灰度圖像 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #創(chuàng)建一個(gè)SURF對(duì)象 surf = cv2.xfeatures2d.SURF_create(20000) #SIFT對(duì)象會(huì)使用Hessian算法檢測(cè)關(guān)鍵點(diǎn),并且對(duì)每個(gè)關(guān)鍵點(diǎn)周圍的區(qū)域計(jì)算特征向量。該函數(shù)返回關(guān)鍵點(diǎn)的信息和描述符 keypoints,descriptor = surf.detectAndCompute(gray,None) print(type(keypoints),len(keypoints),keypoints[0]) print(descriptor.shape) #在圖像上繪制關(guān)鍵點(diǎn) img = cv2.drawKeypoints(image=img,keypoints = keypoints,outImage=img,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) #顯示圖像 cv2.imshow('surf_keypoints',img) cv2.waitKey(0) cv2.destroyAllWindows()

我們把Hessian閾值設(shè)置為20000,閾值越高,能識(shí)別的特征就越少,因此可以采用試探法來(lái)得到最優(yōu)檢測(cè)。

二 SURF算法原理

1、SURF特征檢測(cè)的步驟

  • 尺度空間的極值檢測(cè):搜索所有尺度空間上的圖像,通過(guò)Hessian來(lái)識(shí)別潛在的對(duì)尺度和選擇不變的興趣點(diǎn)。
  • 特征點(diǎn)過(guò)濾并進(jìn)行精確定位。
  • 特征方向賦值:統(tǒng)計(jì)特征點(diǎn)圓形鄰域內(nèi)的Harr小波特征。即在60度扇形內(nèi),每次將60度扇形區(qū)域旋轉(zhuǎn)0.2弧度進(jìn)行統(tǒng)計(jì),將值最大的那個(gè)扇形的方向作為該特征點(diǎn)的主方向。
  • 特征點(diǎn)描述:沿著特征點(diǎn)主方向周圍的鄰域內(nèi),取$4×4$個(gè)矩形小區(qū)域,統(tǒng)計(jì)每個(gè)小區(qū)域的Haar特征,然后每個(gè)區(qū)域得到一個(gè)4維的特征向量。一個(gè)特征點(diǎn)共有64維的特征向量作為SURF特征的描述子。
  • 2、構(gòu)建Hessian(黑塞矩陣)

    構(gòu)建Hessian矩陣的目的是為了生成圖像穩(wěn)定的邊緣點(diǎn)(突變點(diǎn)),跟Canny、拉普拉斯邊緣檢測(cè)的作用類似,為特征提取做準(zhǔn)備。構(gòu)建Hessian矩陣的過(guò)程對(duì)應(yīng)著SIFT算法中的DoG過(guò)程。

    黑塞矩陣(Hessian Matrix)是由一個(gè)多元函數(shù)的二階偏導(dǎo)數(shù)構(gòu)成的方陣,描述了函數(shù)的局部曲率。由德國(guó)數(shù)學(xué)家Ludwin Otto Hessian于19世紀(jì)提出。

    對(duì)于一個(gè)圖像$I(x,y)$,其Hessian矩陣如下:

    $$H(I(x,y))=\begin{bmatrix} \frac{\partial^2I}{\partial{x^2}} & \frac{\partial^2I}{\partial{x}\partial{y}}? \\ \frac{\partial^2I}{\partial{x}\partial{y}} &?\frac{\partial^2I}{\partial{y^2}} \end{bmatrix}$$

    H矩陣的判別式是:

    $$Det(H)=\frac{\partial^2I}{\partial{x^2}}*\frac{\partial^2I}{\partial{y^2}}-\frac{\partial^2I}{\partial{x}\partial{y}} * \frac{\partial^2I}{\partial{x}\partial{y}}$$

    在構(gòu)建Hessian矩陣前需要對(duì)圖像進(jìn)行高斯濾波,經(jīng)過(guò)濾波后的Hessian矩陣表達(dá)式為:

    $$H(x,y,\sigma)=\begin{bmatrix} L_{xx}(x,y,\sigma) & L_{xy}(x,y,\sigma) \\ L_{xy}(x,y,\sigma) & L_{yy}(x,y,\sigma) \end{bmatrix}$$

    其中$(x,y)$為像素位置,$L(x,y,\sigma)=G(\sigma)*I(x,y)$,代表著圖像的高斯尺度空間,是由圖像和不同的高斯卷積得到。

    我們知道在離散數(shù)學(xué)圖像中,一階導(dǎo)數(shù)是相鄰像素的灰度差:

    $$L_x=L(x+1,y)-L(x,y)$$

    二階導(dǎo)數(shù)是對(duì)一階導(dǎo)數(shù)的再次求導(dǎo):

    $$L_{xx}=[L(x+1,y)-L(x,y)]-[L(x,y)-L(x-1,y)]$$

    $$=L(x+1,y)+L(x-1,y)-2L(x,y)$$

    反過(guò)來(lái)看Hessian矩陣的判別式,其實(shí)就是當(dāng)前點(diǎn)對(duì)水平方向二階偏導(dǎo)數(shù)乘以垂直方向二階偏導(dǎo)數(shù)再減去當(dāng)前水平、垂直二階偏導(dǎo)的二次方:

    $$Det(H)=L_{xx}*L_{yy}-L_{xy}*L_{xy}$$

    通過(guò)這種方法可以為圖像中每個(gè)像素計(jì)算出其H行列式的決定值,并用這個(gè)值來(lái)判別圖像局部特征點(diǎn)。Hession矩陣判別式中的$L(x,y)$是原始圖像的高斯卷積,由于高斯核服從正太分布,從中心點(diǎn)往外,系數(shù)越來(lái)越小,為了提高運(yùn)算速度,SURF算法使用了盒式濾波器來(lái)替代高斯濾波器$L$,所以在$L_{xy}$上乘了一個(gè)加權(quán)系數(shù)0.9,目的是為了平衡因使用盒式濾波器近似所帶來(lái)的誤差,則H矩陣判別式可表示為:

    $$Det(H)=L_{xx}*L_{yy}-(0.9*L_{xy})^2$$

    盒式濾波器和高斯濾波器的示意圖如下:

    上面兩幅圖是$9×9$高斯濾波器模板分別在圖像垂直方向上二階導(dǎo)數(shù)$L_{yy}$和$L_{xy}$對(duì)應(yīng)的值,下邊兩幅圖是使用盒式濾波器對(duì)其近似,灰色部分的像素值為0,黑色為-2,白色為1.

    那么為什么盒式濾波器可以提高運(yùn)算速度呢?這就涉及到積分圖的使用,盒式濾波器對(duì)圖像的濾波轉(zhuǎn)化成計(jì)算圖像上不同區(qū)域間像素的加減運(yùn)算問(wèn)題,這正是積分圖的強(qiáng)項(xiàng),只需要簡(jiǎn)單積分查找積分圖就可以完成。

    3、構(gòu)造尺度空間

    同SIFT算法一樣,SURF算法的尺度空間由$O$組$S$層組成,不同的是,SIFT算法下一組圖像的長(zhǎng)寬均是上一組的一半,同一組不同層圖像之間尺寸一樣,但是所使用的尺度空間因子(高斯模糊系數(shù)$\sigma$)逐漸增大;而在SURF算法中,不同組間圖像的尺寸都是一致的,不同的是不同組間使用的盒式濾波器的模板尺寸逐漸增大,同一組不同層圖像使用相同尺寸的濾波器,但是濾波器的尺度空間因子逐漸增大。如下圖所示:

    4、特征點(diǎn)過(guò)濾并進(jìn)行精確定位

    SURF特征點(diǎn)的定位過(guò)程和SIFT算法一致,將經(jīng)過(guò)Hessian矩陣處理的每個(gè)像素點(diǎn)(即獲得每個(gè)像素點(diǎn)Hessian矩陣的判別式值)與其圖像域(相同大小的圖像)和尺度域(相鄰的尺度空間)的所有相鄰點(diǎn)進(jìn)行比較,當(dāng)其大于(或者小于)所有相鄰點(diǎn)時(shí),該點(diǎn)就是極值點(diǎn)。如圖所示,中間的檢測(cè)點(diǎn)要和其所在圖像的$3×3$鄰域8個(gè)像素點(diǎn),以及其相鄰的上下兩層$3×3$鄰域18個(gè)像素點(diǎn),共26個(gè)像素點(diǎn)進(jìn)行比較。

    初步定位出特征點(diǎn)后,再經(jīng)過(guò)濾除能量比較弱的關(guān)鍵點(diǎn)以及錯(cuò)誤定位的關(guān)鍵點(diǎn),篩選出最終的穩(wěn)定的特征點(diǎn)。

    ?

    5、計(jì)算特征點(diǎn)主方向

    SIFT算法特征點(diǎn)的主方向是采用在特征點(diǎn)鄰域內(nèi)統(tǒng)計(jì)其梯度直方圖,橫軸是梯度方向的角度,縱軸是梯度方向?qū)?yīng)梯度幅值的累加,取直方圖bin最大的以及超過(guò)最大80%的那些方向作為特征點(diǎn)的主方向。

    而在SURF算法中,采用的是統(tǒng)計(jì)特征點(diǎn)圓形鄰域內(nèi)的Harr小波特征,即在特征點(diǎn)的圓形鄰域內(nèi),統(tǒng)計(jì)60度扇形內(nèi)所有點(diǎn)的水平、垂直Harr小波特征總和,然后扇形以0.2弧度大小的間隔進(jìn)行旋轉(zhuǎn)并再次統(tǒng)計(jì)該區(qū)域內(nèi)Harr小波特征值之后,最后將值最大的那個(gè)扇形的方向作為該特征點(diǎn)的主方向。該過(guò)程示意圖如下:

    Harr特征的具體內(nèi)容可以參考第九節(jié)、人臉檢測(cè)之Haar分類器。

    6、生成特征描述

    在SIFT算法中,為了保證特征矢量的旋轉(zhuǎn)不變性,先以特征點(diǎn)為中心,在附近鄰域內(nèi)將坐標(biāo)軸旋轉(zhuǎn)$\theta$(特征點(diǎn)的主方向)角度,然后提取特征點(diǎn)周圍$4×4$個(gè)區(qū)域塊,統(tǒng)計(jì)每小塊內(nèi)8個(gè)梯度方向,這樣一個(gè)關(guān)鍵點(diǎn)就可以產(chǎn)生128維的SIFT特征向量。

    SURF算法中,也是提取特征點(diǎn)周圍$4×4$個(gè)矩形區(qū)域塊,但是所取得矩形區(qū)域方向是沿著特征點(diǎn)的主方向,而不是像SIFT算法一樣,經(jīng)過(guò)旋轉(zhuǎn)$\theta$角度。每個(gè)子區(qū)域統(tǒng)計(jì)25個(gè)像素點(diǎn)水平方向和垂直方向的Haar小波特征,這里的水平和垂直方向都是相對(duì)主方向而言的。該Harr小波特征為水平方向值之和、垂直方向值之和、水平方向值絕對(duì)值之和以及垂直方向絕對(duì)之和4個(gè)方向。該過(guò)程示意圖如下:

    把這4個(gè)值作為每個(gè)子塊區(qū)域的特征向量,所以一共有$4×4×4$=64維向量作為SURF特征的描述子,比SIFT特征的描述子減少了一半。

    三 特征點(diǎn)匹配

    與SIFT特征點(diǎn)匹配類似,SURF也是通過(guò)計(jì)算兩個(gè)特征點(diǎn)間特征向量的歐氏距離來(lái)確定匹配度,歐式距離越短,代表兩個(gè)特征點(diǎn)的匹配度越好。不同的是SURF還加入了Hessian矩陣跡(矩陣特征值的和)的判斷,如果兩個(gè)特征點(diǎn)的矩陣跡正負(fù)號(hào)相同,代表著兩個(gè)特征點(diǎn)具有相同方向上的對(duì)比度變化,如果不同,說(shuō)明這兩個(gè)特征點(diǎn)的對(duì)比度方向是相反的,即使歐氏距離為0,也直接剔除。

    # -*- coding: utf-8 -*- """ Created on Fri Aug 24 20:09:32 2018@author: lenovo """# -*- coding: utf-8 -*- """ Created on Wed Aug 22 16:53:16 2018@author: lenovo """''' SURF算法 ''' import cv2 import numpy as np'''1、加載圖片''' img1 = cv2.imread('./image/cali1.bmp',cv2.IMREAD_GRAYSCALE) img1 = cv2.resize(img1,dsize=(600,400)) img2 = cv2.imread('./image/cali2.bmp',cv2.IMREAD_GRAYSCALE) img2 = cv2.resize(img2,dsize=(600,400)) image1 = img1.copy() image2 = img2.copy()'''2、提取特征點(diǎn)''' #創(chuàng)建一個(gè)SURF對(duì)象 surf = cv2.xfeatures2d.SURF_create(25000) #SIFT對(duì)象會(huì)使用Hessian算法檢測(cè)關(guān)鍵點(diǎn),并且對(duì)每個(gè)關(guān)鍵點(diǎn)周圍的區(qū)域計(jì)算特征向量。該函數(shù)返回關(guān)鍵點(diǎn)的信息和描述符 keypoints1,descriptor1 = surf.detectAndCompute(image1,None) keypoints2,descriptor2 = surf.detectAndCompute(image2,None) print('descriptor1:',descriptor1.shape,'descriptor2',descriptor2.shape) #在圖像上繪制關(guān)鍵點(diǎn) image1 = cv2.drawKeypoints(image=image1,keypoints = keypoints1,outImage=image1,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) image2 = cv2.drawKeypoints(image=image2,keypoints = keypoints2,outImage=image2,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) #顯示圖像 cv2.imshow('surf_keypoints1',image1) cv2.imshow('surf_keypoints2',image2) cv2.waitKey(20)'''3、特征點(diǎn)匹配''' matcher = cv2.FlannBasedMatcher() matchePoints = matcher.match(descriptor1,descriptor2) print(type(matchePoints),len(matchePoints),matchePoints[0])#提取強(qiáng)匹配特征點(diǎn) minMatch = 1 maxMatch = 0 for i in range(len(matchePoints)):if minMatch > matchePoints[i].distance:minMatch = matchePoints[i].distanceif maxMatch < matchePoints[i].distance:maxMatch = matchePoints[i].distance print('最佳匹配值是:',minMatch) print('最差匹配值是:',maxMatch) #獲取排雷在前邊的幾個(gè)最優(yōu)匹配結(jié)果 goodMatchePoints = [] for i in range(len(matchePoints)):if matchePoints[i].distance < minMatch + (maxMatch-minMatch)/16:goodMatchePoints.append(matchePoints[i])#繪制最優(yōu)匹配點(diǎn) outImg = None outImg = cv2.drawMatches(img1,keypoints1,img2,keypoints2,goodMatchePoints,outImg,matchColor=(0,255,0),flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT) cv2.imshow('matche',outImg) cv2.waitKey(0) cv2.destroyAllWindows()

    我們來(lái)看一看特征點(diǎn)匹配效果,可以看到好多點(diǎn)都匹配錯(cuò)誤,這主要與我選擇的圖片有關(guān),由于我選擇的圖片是用來(lái)做相機(jī)標(biāo)點(diǎn)的,而當(dāng)我們使用SURF算法提取特征點(diǎn),圖片上大部分特征點(diǎn)都具有相同的性質(zhì),特征向量也近似相等,因此在匹配時(shí)會(huì)出現(xiàn)很大的誤差。

    下面我們更換兩張圖片,再次進(jìn)行特征點(diǎn)匹配:

    我們可以看到這個(gè)匹配效果比剛才好了不少,而且我對(duì)Hessian閾值也進(jìn)行了修改,這個(gè)值需要自己不斷的調(diào)整,以達(dá)到自己的期望。但是總體上來(lái)看,我們選擇的這兩幅圖片亮度和對(duì)比度差異都是很大的,而且拍攝所使用的相機(jī)也是不同的,左側(cè)是我自己用手機(jī)拍攝到的,右側(cè)是從網(wǎng)上下載的,匹配能有這樣的效果也已經(jīng)不錯(cuò)了。但是如果我們想達(dá)到更高的匹配度,我們應(yīng)該盡量選擇兩張更為相似的圖片。下面是我稍微修改后的代碼:

    # -*- coding: utf-8 -*- """ Created on Fri Aug 24 20:09:32 2018@author: lenovo """# -*- coding: utf-8 -*- """ Created on Wed Aug 22 16:53:16 2018@author: lenovo """''' SURF算法 ''' import cv2'''1、加載圖片''' img1 = cv2.imread('./image/match1.jpg') img1 = cv2.resize(img1,dsize=(600,400)) gray1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY) img2 = cv2.imread('./image/match2.jpg') img2 = cv2.resize(img2,dsize=(600,400)) gray2 = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY) image1 = gray1.copy() image2 = gray2.copy()'''2、提取特征點(diǎn)''' #創(chuàng)建一個(gè)SURF對(duì)象 surf = cv2.xfeatures2d.SURF_create(10000) #SIFT對(duì)象會(huì)使用Hessian算法檢測(cè)關(guān)鍵點(diǎn),并且對(duì)每個(gè)關(guān)鍵點(diǎn)周圍的區(qū)域計(jì)算特征向量。該函數(shù)返回關(guān)鍵點(diǎn)的信息和描述符 keypoints1,descriptor1 = surf.detectAndCompute(image1,None) keypoints2,descriptor2 = surf.detectAndCompute(image2,None) print('descriptor1:',descriptor1.shape,'descriptor2',descriptor2.shape) #在圖像上繪制關(guān)鍵點(diǎn) image1 = cv2.drawKeypoints(image=image1,keypoints = keypoints1,outImage=image1,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) image2 = cv2.drawKeypoints(image=image2,keypoints = keypoints2,outImage=image2,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) #顯示圖像 cv2.imshow('surf_keypoints1',image1) cv2.imshow('surf_keypoints2',image2) cv2.waitKey(20)'''3、特征點(diǎn)匹配''' matcher = cv2.FlannBasedMatcher() matchePoints = matcher.match(descriptor1,descriptor2) print(type(matchePoints),len(matchePoints),matchePoints[0])#提取強(qiáng)匹配特征點(diǎn) minMatch = 1 maxMatch = 0 for i in range(len(matchePoints)):if minMatch > matchePoints[i].distance:minMatch = matchePoints[i].distanceif maxMatch < matchePoints[i].distance:maxMatch = matchePoints[i].distance print('最佳匹配值是:',minMatch) print('最差匹配值是:',maxMatch) #獲取排雷在前邊的幾個(gè)最優(yōu)匹配結(jié)果 goodMatchePoints = [] for i in range(len(matchePoints)):if matchePoints[i].distance < minMatch + (maxMatch-minMatch)/4:goodMatchePoints.append(matchePoints[i])#繪制最優(yōu)匹配點(diǎn) outImg = None outImg = cv2.drawMatches(img1,keypoints1,img2,keypoints2,goodMatchePoints,outImg,matchColor=(0,255,0),flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT) cv2.imshow('matche',outImg) cv2.waitKey(0) cv2.destroyAllWindows()

    參考文章:

    [1]圖像識(shí)別基本算法之SURF

    [2]SURF算法

    [3]SURF算法與源碼分析、上

    [4]SURF算法與源碼分析、下

    [5]SURF原理及源碼解析(C++)

    轉(zhuǎn)載于:https://www.cnblogs.com/zyly/p/9531907.html

    總結(jié)

    以上是生活随笔為你收集整理的第十三节、SURF特征提取算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。