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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

图像特征匹配方法——SIFT算法原理及实现

發布時間:2023/12/19 综合教程 49 生活家
生活随笔 收集整理的這篇文章主要介紹了 图像特征匹配方法——SIFT算法原理及实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳統圖像處理中圖像特征匹配有三個基本步驟:特征提取、特征描述和特征匹配。特征提取就是從圖像中提取出關鍵點(或特征點、角點)等。特征描述就是用一組數學向量對特征點進行描述,其主要保證不同的向量和不同的特征點之間是一種對應的關系,同時相似的關鍵點之間的差異盡可能小。特征匹配其實就是特征向量之間的距離計算,常用的距離有歐氏距離、漢明距離、余弦距離等。

SIFT算法又叫尺度不變特征變換匹配算法, SIFT特征對于旋轉和尺度均具有不變性,并且對于噪聲、視角變化和光照變化具有良好的魯棒性,所以我們今天來學習一下SIFT算法。

一、SIFT簡介

二、SIFT算法原理

1.檢測尺度空間極值

2.關鍵點的精確定位

3.關鍵點主方向分配

4.關鍵點的特征描述

三、關鍵點匹配

四、實現

1.檢測感興趣點

2.描述子匹配

3.地理標記圖像匹配

五、注意事項

1.vlfeat安裝

2.Graphviz安裝教程

3.關于圖像

一、SIFT簡介

SIFT(Scale Invariant Feature Transform,尺度不變特征變換匹配算法)是由David G. Lowe教授在1999年(《Object Recognition from Local Scale-Invariant Features》)提出的高效區域檢測算法,在2004年(《Distinctive Image Features from Scale-Invariant Keypoints》)得以完善。

SIFT可以應用到物體辨識、機器人地圖感知與導航、影像縫合、3D模型建立、手勢辨識、影像追蹤和動作比對等方向。

SIFT算法的特點:

  1. 穩定性
  2. 獨特性
  3. 多量性
  4. 高速性
  5. 可擴展性

SIFT算法可以的解決問題:

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

二、SIFT算法原理

1.檢測尺度空間極值

檢測尺度空間極值就是搜索所有尺度上的圖像位置,通過高斯微分函數來識別對于尺度和旋轉不變的興趣點。其主要步驟可以分為建立高斯金字塔、生成DOG高斯差分金字塔和DOG局部極值點檢測。為了讓大家更清楚,我先簡單介紹一下尺度空間,再介紹主要步驟。

(1)尺度空間

一個圖像的尺度空間,定義為一個變化尺度的高斯函數與原圖像的卷積。即:

其中,*表示卷積計算。

其中,m、n表示高斯模版的維度,(x,y)代表圖像像素的位置。為尺度空間因子,值越小表示圖像被平滑的越少,相應的尺度就越小。小尺度對應于圖像的細節特征,大尺度對應于圖像的概貌特征,效果如下圖所示,尺度從左到右,從上到下,一次增大。

(2)建立高斯金字塔

尺度空間在實現時,使用高斯金字塔表示,高斯金字塔的構建分為兩部分:

1.對圖像做不同尺度的高斯模糊

2.對圖像做降采樣(隔點采樣)

圖像的金字塔模型是指,將原始圖像不斷降階采樣,得到一系列大小不一的圖像,由大到小,從下到上構成的塔狀模型。原圖像為金子塔的第一層,每次降采樣所得到的新圖像為金字塔的上一層(每層一張圖像),每個金字塔共n層。金字塔的層數根據圖像的原始大小和塔頂圖像的大小共同決定。

為了讓尺度體現其連續性,高斯金字塔在簡單降采樣的基礎上加上了高斯濾波。如上圖所示,將圖像金字塔每層的一張圖像使用不同參數做高斯模糊,使得金字塔的每層含有多張高斯模糊圖像,將金字塔每層多張圖像合稱為一組(Octave),金字塔每層只有一組圖像,組數和金字塔層數相等,每組含有多層Interval圖像。

高斯圖像金字塔共o組、s層, 則有:

其中,σ表示尺度空間坐標,s表示sub-level層坐標,表示初始尺度,S表示每組層數(一般為3~5)

(3)建立DOG高斯差分金字塔

為了有效提取穩定的關鍵點,利用不同尺度的高斯差分核與卷積生成。

DOG函數:

DOG在計算上只需相鄰高斯平滑后圖像相減,因此簡化了計算!

可以通過高斯差分圖像看出圖像上的像素值變化情況。(如果沒有變化,也就沒有特征。特征必須是變化盡可能多的點。)DOG圖像描繪的是目標的輪廓。

(4)DOG局部極值檢測

特征點是由DOG空間的局部極值點組成的。為了尋找DOG函數的極值點,每一個像素點要和它所有的相鄰點比較,看其是否比它的圖像域和尺度域 的相鄰點大或者小。

中間的檢測點和它同尺度的8個相鄰點和上下相鄰尺度對應的9×2個 點共26個點比較,以確保在尺度空間和二維圖像空間都檢測到極值點。

2.關鍵點的精確定位

以上方法檢測到的極值點是離散空間的極值點,以下通過擬合三維二次函數來精確確定關鍵點的位置和尺度,同時去除低對比度的關鍵點和不穩定的邊緣響應點(因為DOG算子會產生較強的邊緣響應),以增強匹配穩定性、提高抗噪聲能力。

(1)關鍵點的精確定位

利用已知的離散空間點插值得到的連續空間極值點的方法叫做子像素插值(Sub-pixel Interpolation)。

為了提高關鍵點的穩定性,需要對尺度空間DOG函數進行曲線擬合。利用DOG函數在尺度空間的Taylor展開式(擬合函數)為:

其中,。求導并讓方程等于零,可以得到極值點的偏移量為:

對應極值點,方程的值為:

其中, 代表相對插值中心的偏移量,當它在任一維度上的偏移量大于0.5時(即x或y或),意味著插值中心已經偏移到它的鄰近點上,所以必須改變當前關鍵點的位置。同時在新的位置上反復插值直到收斂;也有可能超出所設定的迭代次數或者超出圖像邊界的范圍,此時這樣的點應該刪除,在Lowe中進行了5次迭代。另外,過小的點易受噪聲的干擾而變得不穩定,所以將小于某個經驗值(Lowe論文中使用0.03,RobHess等人實現時使用0.04/S)的極值點刪除。同時,在此過程中獲取特征點的精確位置(原位置加上擬合的偏移量)以及尺度()。

(2)去除邊緣響應

由于DOG函數在圖像邊緣有較強的邊緣響應,因此需要排除邊緣響應DOG函數的峰值點在邊緣方向有較大的主曲率,而在垂直邊緣的方向有較小的主曲率。主曲率可以通過計算在該點位置尺度的2×2的Hessian矩陣得到,導數由采樣點相鄰差來估計:

表示DOG金字塔中某一尺度的圖像x方向求導兩次。

D的主曲率和H的特征值成正比。令 α ,β為特征值,則

該值在兩特征值相等時達最小。Lowe論文中建議閾值T為1.2,即時保留關鍵點,反之剔除。

在Lowe的論文中,取r=10。下圖右側為消除邊緣響應后的關鍵點分布圖。

3.關鍵點主方向分配

關鍵點主方向分配就是基于圖像局部的梯度方向,分配給每個關鍵點位置一個或多個方向。所有后面的對圖像數據的操作都相對于關鍵點的方向、尺度和位置進行變換,使得描述符具有旋轉不變性。

對于在DOG金字塔中檢測出的關鍵點,采集其所在高斯金字塔圖像3σ鄰域窗口內像素的梯度和方向分布特征。梯度的模值和方向如下:

L為關鍵點所在的尺度空間值,按Lowe的建議,梯度的模值m(x,y)按的高斯分布加成,按尺度采樣的3σ原則,鄰域窗口半徑為。

在完成關鍵點的梯度計算后,使用直方圖統計鄰域內像素的梯度和方向。梯度直方圖將0~360度的方向范圍分為36個柱(bins),其中每柱10度。如下圖所示,直方圖的峰值方向代表了關鍵點的主方向,(為簡化,圖中只畫了八個方向的直方圖)。

方向直方圖的峰值代表了該特征點處鄰域梯度的方向,以直方圖中最大值作為該關鍵點的主方向。為了增強匹配的魯棒性,只保留峰值大于主方向峰值80%的方向作為該關鍵點的輔方向。Lowe的論文指出大概有15%關鍵點具有多方向,但這些點對匹配的穩定性至為關鍵。檢測結果如下圖:

至此,將檢測出的含有位置、尺度和方向的關鍵點即是該圖像的SIFT特征點。

4.關鍵點的特征描述

通過以上步驟,對于每一個關鍵點,擁有三個信息:位置、尺度以及方向。接下來就是為每個關鍵點建立一個描述符,用一組向量將這個關鍵點描述出來,使其不隨各種變化而改變,比如光照變化、視角變化等。這個描述子不但包括關鍵點,也包含關鍵點周圍對其有貢獻的像素點,并且描述符應該有較高的獨特性,以便于提高特征點正確匹配的概率。

SIFT描述子是關鍵點鄰域高斯圖像梯度統計結果的一種表示。通過對關鍵點周圍圖像區域分塊,計算塊內梯度直方圖,生成具有獨特性的向量,這個向量是該區域圖像信息的一種抽象,具有唯一性。

Lowe建議描述子使用在關鍵點尺度空間內4*4的窗口中計算的8個方向的梯度信息,共4*4*8=128維向量表征。表示步驟如下:

(1)計算描述子所需的圖像區域

特征描述子與特征點所在的尺度有關,因此,對梯度的求取應在特征點對應的高斯圖像上進行。將關鍵點附近的鄰域劃分為d*d(Lowe建議d=4)個子區域,每個子區域做為一個種子點,每個種子點有8個方向。每個子區域的大小與關鍵點方向分配時相同,即每個區域有個子像素,為每個子區域分配邊長為的矩形區域進行采樣(個子像素實際用邊長為矩形區域進行采樣,考慮到實際計算時,需要采用雙線性插值,所需圖像窗口邊長為。在考慮到旋轉因素(方便下一步將坐標軸旋轉到關鍵點的方向),如下圖6.1所示,實際計算所需的圖像區域半徑為:

計算結果四舍五入取整。

2)將坐標軸旋轉為關鍵點的方向

將坐標軸旋轉為關鍵點的方向是為了確保旋轉不變性,如下圖所示:

旋轉后鄰域內采樣點的新坐標為:

(3)將鄰域內的采樣點分配到對應的子區域內

將子區域內的梯度值分配到8個方向上,計算其權值。旋轉后的采樣點坐標在半徑為radius的圓內被分配到的子區域,計算影響子區域的采樣點的梯度和方向,分配到8個方向上。

旋轉后的采樣點落在子區域的下標為

(6-3)

Lowe建議子區域的像素的梯度大小按的高斯加權計算,即

(6-4)

其中a,b為關鍵點在高斯金字塔圖像中的位置坐標。

(4)插值計算每個種子八個方向的梯度。

如上圖所示,將所得采樣點在子區域中的下標(x”,y”)(圖中藍色窗口內紅色點)線性插值,計算其對每個種子點的貢獻。如圖中的紅色點,落在第0 行和第1 行之間,對這兩行都有貢獻。對第0 行第3 列種子點的貢獻因子為dr,對第1 行第3 列的貢獻因子為1-dr,同理,對鄰近兩列的貢獻因子為dc 和1-dc,對鄰近兩個方向的貢獻因子為do 和1-do。則最終累加在每個方向上的梯度大小為:

其中,k,m,n為0或為1.

(5)描述符向量元素門限化

即把方向直方圖每個方向上梯度幅值限制在一定門限值一下(門限一般取0.2)

(6)描述符向量元素歸一化

特征向量形成后,為了去除光照變化的影響,需要對它們進行歸一化處理,對于圖像灰度值整體漂移,圖像各點的梯度是鄰域像素相減得到,所以也能去除。

得到的描述子向量:

歸一化后的特征向量:

三、關鍵點匹配

分別對模板圖(參考圖,reference image)和實時圖(觀測圖, observation image)建立關鍵點描述子集合。目標的識別是通過兩點 集內關鍵點描述子的比對來完成。具有128維的關鍵點描述子的相似 性度量采用歐式距離。

模板圖中關鍵點描述子:

實時圖中關鍵點描述子:

任意兩描述子相似性度量:

要得到配對的關鍵點描述子, 需滿足

關鍵點的匹配可以采用窮舉法來完成,但是這樣耗費的時間太多,一 般都采用kd樹的數據結構來完成搜索。搜索的內容是以目標圖像的關鍵點為基準,搜索與目標圖像的特征點最鄰近的原圖像特征點和次鄰近的原圖像特征點。

四、實現

1.檢測感興趣點

為了計算圖像的SIFT特征,我們用開源工具包VLFeat。用Python重新實現SIFT特征提取的全過程不會很高效,而且也超出了本書的范圍。VLFeat可以在www.vlfeat.org上下載,它的二進制文件可以用于一些主要的平臺。這個庫是用C寫的,不過我們可以利用它的命令行接口。此外,它還有Matlab接口。

# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *
from PCV.localdescriptors import sift
from PCV.localdescriptors import harris

# 添加中文字體支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)

imname = 'D:/test/111.jpg'
im = array(Image.open(imname).convert('L'))
sift.process_image(imname, '111.sift')
l1, d1 = sift.read_features_from_file('111.sift')

figure()
gray()
subplot(131)
sift.plot_features(im, l1, circle=False)
title(u'SIFT特征',fontproperties=font)
subplot(132)
sift.plot_features(im, l1, circle=True)
title(u'用圓圈表示SIFT特征尺度',fontproperties=font)

# 檢測harris角點
harrisim = harris.compute_harris_response(im)

subplot(133)
filtered_coords = harris.get_harris_points(harrisim, 6, 0.1)
imshow(im)
plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')
axis('off')
title(u'Harris角點',fontproperties=font)

show()

為了將sift和Harris角點進行比較,將Harris角點檢測的顯示在了圖像的最后側。正如你所看到的,這兩種算法選擇了不同的坐標。由圖可以看出,與Harris角點檢測相比,sift提取出來的特征點信息更多,而且更加精準,這是因為sift的特征點提取步驟比Harris的步驟復雜的多,它需要建立高斯圖像金字塔和高斯差分金字塔之后再檢測極值,而Harris角點只是對原圖進行角點檢測和變化。

2.描述子匹配

from PIL import Image
from pylab import *
import sys
from PCV.localdescriptors import sift
from PIL import Image
from pylab import *
from numpy import *
import os

if len(sys.argv) >= 3:
  im1f, im2f = sys.argv[1], sys.argv[2]
else:
  im1f = 'D:/test/111.jpg'
  im2f = 'D:/test/222.jpg'

  #im1f = 'D:/test/change/21.jpg'
  #im2f = 'D:/test/change/22.jpg'
#  im1f = '../data/crans_1_small.jpg'
#  im2f = '../data/crans_2_small.jpg'
#  im1f = '../data/climbing_1_small.jpg'
#  im2f = '../data/climbing_2_small.jpg'
im1 = array(Image.open(im1f))
im2 = array(Image.open(im2f))

sift.process_image(im1f, 'out_sift_3.txt')
l1, d1 = sift.read_features_from_file('out_sift_3.txt')
figure()
gray()
subplot(121)
sift.plot_features(im1, l1, circle=False)

sift.process_image(im2f, 'out_sift_4.txt')
l2, d2 = sift.read_features_from_file('out_sift_4.txt')
subplot(122)
sift.plot_features(im2, l2, circle=False)

#matches = sift.match(d1, d2)
matches = sift.match_twosided(d1, d2)
print '{} matches'.format(len(matches.nonzero()[0]))

figure()
gray()
sift.plot_matches(im1, im2, l1, l2, matches, show_below=True)
show()

下圖為SIFT檢測兩張圖片的感興趣點的結果圖:

由圖可以看出,SIFT可以檢測出較多的特征點。

下圖左側為SIFT算法匹配結果,右側為Harris角點匹配結果:

由上面兩張圖對比可知,SIFT算法匹配出的特征點更多,這是因為SIFT算法具有尺度和旋轉不變性,即使兩張圖大小不一樣、角度不一致也不會影響匹配結果,而Harris角點對尺度變化非常敏感,當遇到尺度變化較大時,很多正確特征點無法檢測出來。

3.地理標記圖像匹配

我們可以對上面匹配后的圖像進行連接可視化,要做到這樣,我們需要在一個圖中用邊線表示它們之間是相連的。我們采用pydot工具包,它提供了GraphViz graphing庫的Python接口。不要擔心,它們安裝起來很容易。

# -*- coding: utf-8 -*-
from pylab import *
from PIL import Image
from PCV.localdescriptors import sift
from PCV.tools import imtools
import pydot
""" This is the example graph illustration of matching images from Figure 2-10.
To download the images, see ch2_download_panoramio.py."""
#download_path = "panoimages"  # set this to the path where you downloaded the panoramio images
#path = "/FULLPATH/panoimages/"  # path to save thumbnails (pydot needs the full system path)
#download_path = "F:\\dropbox\\Dropbox\\translation\\pcv-notebook\\data\\panoimages"  # set this to the path where you downloaded the panoramio images
#path = "F:\\dropbox\\Dropbox\\translation\\pcv-notebook\\data\\panoimages\\"  # path to save thumbnails (pydot needs the full system path)
download_path = "D:/test/change"
path = "D:/test/change/"
# list of downloaded filenames
imlist = imtools.get_imlist(download_path)
nbr_images = len(imlist)
# extract features
featlist = [imname[:-3] + 'sift' for imname in imlist]
for i, imname in enumerate(imlist):
sift.process_image(imname, featlist[i])
matchscores = zeros((nbr_images, nbr_images))
for i in range(nbr_images):
for j in range(i, nbr_images):  # only compute upper triangle
print 'comparing ', imlist[i], imlist[j]
l1, d1 = sift.read_features_from_file(featlist[i])
l2, d2 = sift.read_features_from_file(featlist[j])
matches = sift.match_twosided(d1, d2)
nbr_matches = sum(matches > 0)
print 'number of matches = ', nbr_matches
matchscores[i, j] = nbr_matches
print "The match scores is: %d", matchscores
#np.savetxt(("../data/panoimages/panoramio_matches.txt",matchscores)
# copy values
for i in range(nbr_images):
for j in range(i + 1, nbr_images):  # no need to copy diagonal
matchscores[j, i] = matchscores[i, j]
threshold = 2  # min number of matches needed to create link
g = pydot.Dot(graph_type='graph')  # don't want the default directed graph
for i in range(nbr_images):
for j in range(i + 1, nbr_images):
if matchscores[i, j] > threshold:
# first image in pair
im = Image.open(imlist[i])
im.thumbnail((100, 100))
filename = path + str(i) + '.png'
im.save(filename)  # need temporary files of the right size
g.add_node(pydot.Node(str(i), fontcolor='transparent', shape='rectangle', image=filename))
# second image in pair
im = Image.open(imlist[j])
im.thumbnail((100, 100))
filename = path + str(j) + '.png'
im.save(filename)  # need temporary files of the right size
g.add_node(pydot.Node(str(j), fontcolor='transparent', shape='rectangle', image=filename))
g.add_edge(pydot.Edge(str(i), str(j)))
g.write_png('change3.png')

正如上圖所示,我們可以看到三組圖像,分別是我們我們學校不同地點的景色。上面這個例子只是一個利用局部描述子進行匹配的很簡單的例子。

五、注意事項

1.vlfeat安裝

參考教程詳見:http://yongyuan.name/pcvwithpython/installation.html

注意:

(1)sift.exe文件后有空格,有空格,有空格,重要的事情說三遍,博主因為這個空格折騰了一個下午加一個晚上,心態相當崩,血的教訓!!!

(2)vlfeat 現在更新到0.9.21版本,部分x64電腦這個版本不能使用(博主不幸躺槍),請更換之前版本,我更換的是vlfeat 0.9.20版本,下載地址http://www.vlfeat.org/download/

2.Graphviz安裝教程

下載地址:https://graphviz.gitlab.io/_pages/Download/Download_windows.html

(1)選擇grahviz-2.38.msi進行下載安裝

(2)配置環境變量

找到PATH變量并進行編輯

點擊新建,將grahiviz2.38的bin文件夾添加到PATH變量中

(3)安裝pydot

進入windows命令行界面,輸入pip install pydot。

(4)驗證是否安裝并配置成功

進入windows命令行界面,輸入dot -version,然后按回車,如果顯示graphviz的相關版本信息,則安裝配置成功。如圖

注意安裝順序,一定要先安裝grahiviz2.38,在pip install pydot

3.關于圖像

因為SIFT計算復雜度很高,所以我將圖像尺寸修改至255X255,如果按原圖匹配,特別是進行地理標記圖像匹配,電腦會死機,親測有效,歡迎嘗試,測試電腦性能絕佳之選。

參考:

https://blog.csdn.net/zddblog/article/details/7521424

https://blog.csdn.net/cxp2205455256/article/details/41747325

https://blog.csdn.net/zhuxiaoyang2000/article/details/53930610

http://yongyuan.name/pcvwithpython/chapter2.html

https://www.cnblogs.com/shuodehaoa/p/8667045.html?tdsourcetag=s_pcqq_aiomsg

總結

以上是生活随笔為你收集整理的图像特征匹配方法——SIFT算法原理及实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。