python—sift特征提取


一、SIFT提出的目的和意義

二、SIFT的特征簡介

三、SIFT算法實現步驟簡述

四、圖像集

五、匹配地理標記圖像

 

  • 代碼
  • 結果截圖
  • 小結 

 

六、SIFT算法代碼實現

  • 代碼
  • 結果截圖
  • 小結 

七、圖像全景拼接RANSAC

八、SIFT實驗總結

九、實驗遇到的問題

 

一、SIFT提出的目的和意義

1999年David G.Lowe教授總結了基於特征不變技術的檢測方法,在圖像尺度空間基礎上,提出了對圖像縮放、旋轉保持不變性的圖像局部特征描述算子-SIFT(尺度不變特征變換),該算法在2004年被加以完善。

 
二、SIFT的特征簡介
SIFT算法可以解決的問題
  1.  目標的旋轉、縮放、平移(RST)
  2. 圖像仿射/投影變換(視點viewpoint)
  3. 弱光照影響(illumination)
  4. 部分目標遮擋(occlusion)
  5. 雜物場景(clutter)
  6. 噪聲
 
 三、SIFT算法實現步驟簡述
SIFT算法的實質可以歸為在不同尺度空間上查找特征點(關鍵點)的問題。 SIFT算法實現特征匹配主要有三個流程,1、提取關鍵點;2、對關鍵點附加 詳細的信息(局部特征),即描述符;3、通過特征點(附帶上特征向量的關 鍵點)的兩兩比較找出相互匹配的若干對特征點,建立景物間的對應關系。
 

                                                                         圖1
需要配置vfleat安裝包
使用開源工具包 VLFeat 提供的二進制文件來計算圖像的 SIFT特征 。這里附上VLFeat 工具包鏈接http://www.vlfeat.org/ 
操作步驟:
1.把vlfeat文件夾下win64中的sift.exe和vl.dll這兩個文件復制到項目的文件夾中

2.修改PCV文件夾內的(我的PCV位置為D:\Anaconda2\Lib\site-packages\PCV))文件夾里面的localdescriptors文件夾中的sift.py文件,用記事本打開,修改其中的cmmd內的路徑cmmd=str(r"D:\new\sift.exe“+imagename+” --output="+resultname+" "+params) (路徑是你項目文件夾中的sift.exe的路徑)一定要在括號里加上r。
 
 
 
四、圖像集
一共19 張圖像

                                                                                                                     圖2

 

五、匹配地理標記圖像        

 1、做此實驗我們需用pydot工具包中的GraphViz,可以點擊https://graphviz.gitlab.io/_pages/Download/Download_windows.html下載安裝包,安裝步驟如下:

      配置環境: 保存graphviz安裝時,一定要記住保存路徑,方便找到你的安裝包安裝中的gvedit.exe的位置,我的是C:\Program Files (x86)\Graphviz2.38\bin

把gvedit.exe發送到桌面快捷方式,然后去系統里點擊高級系統設置->點擊環境變量->點擊系統變量的path選擇編輯->輸入C:\Program Files (x86)\Graphviz2.38\bin,之后就確定保存。

 

 接下來是驗證環境配置是否成功,輸入dot -version命令,成功如下:

然后依次執行以下命令:

pip install graphviz

pip install pydot

 

成功如下:

 d

 2、實驗代碼:

 1 # -*- coding: utf-8 -*-
 2 from pylab import *
 3 from PIL import Image
 4 from PCV.localdescriptors import sift
 5 from PCV.tools import imtools
 6 import pydot
 7  
 8 """ This is the example graph illustration of matching images from Figure 2-10.
 9 To download the images, see ch2_download_panoramio.py."""
10  
11 #download_path = "panoimages"  # set this to the path where you downloaded the panoramio images
12 #path = "/FULLPATH/panoimages/"  # path to save thumbnails (pydot needs the full system path)
13  
14 #download_path = "F:\\dropbox\\Dropbox\\translation\\pcv-notebook\\data\\panoimages"  # set this to the path where you downloaded the panoramio images
15 #path = "F:\\dropbox\\Dropbox\\translation\\pcv-notebook\\data\\panoimages\\"  # path to save thumbnails (pydot needs the full system path)
16 download_path = "D:/new"
17 path = "D:/new"
18 # list of downloaded filenames
19 imlist = imtools.get_imlist(download_path)
20 nbr_images = len(imlist)
21  
22 # extract features
23 featlist = [imname[:-3] + 'sift' for imname in imlist]
24 for i, imname in enumerate(imlist):
25     sift.process_image(imname, featlist[i])
26  
27 matchscores = zeros((nbr_images, nbr_images))
28  
29 for i in range(nbr_images):
30     for j in range(i, nbr_images):  # only compute upper triangle
31         print 'comparing ', imlist[i], imlist[j]
32         l1, d1 = sift.read_features_from_file(featlist[i])
33         l2, d2 = sift.read_features_from_file(featlist[j])
34         matches = sift.match_twosided(d1, d2)
35         nbr_matches = sum(matches > 0)
36         print 'number of matches = ', nbr_matches
37         matchscores[i, j] = nbr_matches
38 print "The match scores is: %d", matchscores
39  
40 #np.savetxt(("../data/panoimages/panoramio_matches.txt",matchscores)
41  
42 # copy values
43 for i in range(nbr_images):
44     for j in range(i + 1, nbr_images):  # no need to copy diagonal
45         matchscores[j, i] = matchscores[i, j]
46  
47 threshold = 2  # min number of matches needed to create link
48  
49 g = pydot.Dot(graph_type='graph')  # don't want the default directed graph
50  
51 for i in range(nbr_images):
52     for j in range(i + 1, nbr_images):
53         if matchscores[i, j] > threshold:
54             # first image in pair
55             im = Image.open(imlist[i])
56             im.thumbnail((100, 100))
57             filename = path + str(i) + '.png'
58             im.save(filename)  # need temporary files of the right size
59             g.add_node(pydot.Node(str(i), fontcolor='transparent', shape='rectangle', image=filename))
60  
61             # second image in pair
62             im = Image.open(imlist[j])
63             im.thumbnail((100, 100))
64             filename = path + str(j) + '.png'
65             im.save(filename)  # need temporary files of the right size
66             g.add_node(pydot.Node(str(j), fontcolor='transparent', shape='rectangle', image=filename))
67  
68             g.add_edge(pydot.Edge(str(i), str(j)))
69 g.write_png('protect2.png')

3、結果截圖:

         

 

 實驗小結:圖像集一共有十九張圖片,運行出來只有十七張圖片,我拍攝的照片范圍過小,只選擇了六個地點拍攝,沒有顯示出來的兩張圖片是跟以上圖片沒有太多相似的特征點的。顯示出來的第一個連線的部分,是在同一個位置拍攝,只是從不同的角度,但是提取出來的特征點匹配度很高,說明了sift算法角度不變性,還有色彩影響不是很大,並且只要有一點特征點匹配度的圖片就會相連起來,第二部分和第三部分依然如此。

                                                                    

六、SIFT算法代碼實現
1、單張圖片的sift特征提取Harris角點提取、用圓圈表示SIFT特征尺度提取

代碼:

 1 # -*- coding: utf-8 -*-
 2 from PIL import Image
 3 from pylab import *
 4 from PCV.localdescriptors import sift
 5 from PCV.localdescriptors import harris
 6 
 7 # 添加中文字體支持
 8 from matplotlib.font_manager import FontProperties
 9 font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
10 
11 imname = 'siftt/24.jpg'
12 im = array(Image.open(imname).convert('L'))
13 sift.process_image(imname, '24.sift')
14 l1, d1 = sift.read_features_from_file('24.sift')
15 
16 figure()
17 gray()
18 subplot(131)
19 sift.plot_features(im, l1, circle=False)
20 title(u'SIFT特征',fontproperties=font)
21 subplot(132)
22 sift.plot_features(im, l1, circle=True)
23 title(u'用圓圈表示SIFT特征尺度',fontproperties=font)
24 
25 # 檢測harris角點
26 harrisim = harris.compute_harris_response(im)
27 
28 subplot(133)
29 filtered_coords = harris.get_harris_points(harrisim, 6, 0.1)
30 imshow(im)
31 plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')
32 axis('off')
33 title(u'Harris角點',fontproperties=font)
34 
35 show()

原圖

運行結果:

小結:由圖看出,sift算法檢測出來的特征點比harris角點算法檢測出的角點多。sift算法測出來的特征點大多數都是重合的。

 2、圖像集里的所有圖像的sift特征提取

 代碼:

 1 # -*- coding: utf-8 -*-
 2 from PIL import Image
 3 from pylab import *
 4 from PCV.localdescriptors import sift
 5 from PCV.localdescriptors import harris
 6 from PCV.tools.imtools import get_imlist # 導入原書的PCV模塊
 7 
 8 # 添加中文字體支持
 9 from matplotlib.font_manager import FontProperties
10 font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
11 
12 # 獲取project2_data文件夾下的圖片文件名(包括后綴名)
13 filelist = get_imlist('siftt/')
14 
15 for infile in filelist: # 對文件夾下的每張圖片進行如下操作
16     print(infile) # 輸出文件名
17     
18     im = array(Image.open(infile).convert('L'))
19     sift.process_image(infile, 'infile.sift')
20     l1, d1 = sift.read_features_from_file('infile.sift')
21     i=1
22     
23     figure(i)
24     i=i+1
25     gray()
26     
27     subplot(131)
28     sift.plot_features(im, l1, circle=False)
29     title(u'SIFT特征',fontproperties=font)
30     
31     subplot(132)
32     sift.plot_features(im, l1, circle=True)
33     title(u'用圓圈表示SIFT特征尺度',fontproperties=font)
34     
35     # 檢測harris角點
36     harrisim = harris.compute_harris_response(im)
37     
38     subplot(133)
39     filtered_coords = harris.get_harris_points(harrisim, 6, 0.1)
40     imshow(im)
41     plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')
42     axis('off')
43     title(u'Harris角點',fontproperties=font)
44     
45     show()

 

結果截圖:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3、兩張圖片,計算sift特征匹配結果

代碼:

  1 # -*- coding: utf-8 -*-
  2 from PIL import Image
  3 from pylab import *
  4 from numpy import *
  5 import os
  6 
  7 def process_image(imagename, resultname, params="--edge-thresh 10 --peak-thresh 5"):
  8     """ 處理一幅圖像,然后將結果保存在文件中"""
  9     if imagename[-3:] != 'pgm':
 10         #創建一個pgm文件
 11         im = Image.open(imagename).convert('L')
 12         im.save('tmp.pgm')
 13         imagename ='tmp.pgm'
 14     cmmd = str("sift "+imagename+" --output="+resultname+" "+params)
 15     os.system(cmmd)
 16     print 'processed', imagename, 'to', resultname
 17     
 18 def read_features_from_file(filename):
 19     """讀取特征屬性值,然后將其以矩陣的形式返回"""
 20     f = loadtxt(filename)
 21     return f[:,:4], f[:,4:] #特征位置,描述子
 22     
 23 def write_featrues_to_file(filename, locs, desc):
 24     """將特征位置和描述子保存到文件中"""
 25     savetxt(filename, hstack((locs,desc)))
 26     
 27 def plot_features(im, locs, circle=False):
 28     """顯示帶有特征的圖像
 29        輸入:im(數組圖像),locs(每個特征的行、列、尺度和朝向)"""
 30        
 31     def draw_circle(c,r):
 32         t = arange(0,1.01,.01)*2*pi
 33         x = r*cos(t) + c[0]
 34         y = r*sin(t) + c[1]
 35         plot(x, y, 'b', linewidth=2)
 36         
 37     imshow(im)
 38     if circle:
 39         for p in locs:
 40             draw_circle(p[:2], p[2])
 41     else:
 42         plot(locs[:,0], locs[:,1], 'ob')
 43     axis('off')
 44     
 45 def match(desc1, desc2):
 46     """對於第一幅圖像中的每個描述子,選取其在第二幅圖像中的匹配
 47     輸入:desc1(第一幅圖像中的描述子),desc2(第二幅圖像中的描述子)"""
 48     desc1 = array([d/linalg.norm(d) for d in desc1])
 49     desc2 = array([d/linalg.norm(d) for d in desc2])
 50     dist_ratio = 0.6
 51     desc1_size = desc1.shape
 52     matchscores = zeros((desc1_size[0],1),'int')
 53     desc2t = desc2.T #預先計算矩陣轉置
 54     for i in range(desc1_size[0]):
 55         dotprods = dot(desc1[i,:],desc2t) #向量點乘
 56         dotprods = 0.9999*dotprods
 57         # 反余弦和反排序,返回第二幅圖像中特征的索引
 58         indx = argsort(arccos(dotprods))
 59         #檢查最近鄰的角度是否小於dist_ratio乘以第二近鄰的角度
 60         if arccos(dotprods)[indx[0]] < dist_ratio * arccos(dotprods)[indx[1]]:
 61             matchscores[i] = int(indx[0])
 62     return matchscores
 63     
 64 def match_twosided(desc1, desc2):
 65     """雙向對稱版本的match()"""
 66     matches_12 = match(desc1, desc2)
 67     matches_21 = match(desc2, desc1)
 68     ndx_12 = matches_12.nonzero()[0]
 69     # 去除不對稱的匹配
 70     for n in ndx_12:
 71         if matches_21[int(matches_12[n])] != n:
 72             matches_12[n] = 0
 73     return matches_12
 74     
 75 def appendimages(im1, im2):
 76     """返回將兩幅圖像並排拼接成的一幅新圖像"""
 77     #選取具有最少行數的圖像,然后填充足夠的空行
 78     rows1 = im1.shape[0]
 79     rows2 = im2.shape[0]
 80     if rows1 < rows2:
 81         im1 = concatenate((im1, zeros((rows2-rows1,im1.shape[1]))),axis=0)
 82     elif rows1 >rows2:
 83         im2 = concatenate((im2, zeros((rows1-rows2,im2.shape[1]))),axis=0)
 84     return concatenate((im1,im2), axis=1)
 85     
 86 def plot_matches(im1,im2,locs1,locs2,matchscores,show_below=True):
 87     """ 顯示一幅帶有連接匹配之間連線的圖片
 88         輸入:im1, im2(數組圖像), locs1,locs2(特征位置),matchscores(match()的輸出),
 89         show_below(如果圖像應該顯示在匹配的下方)
 90     """
 91     im3=appendimages(im1, im2)
 92     if show_below:
 93         im3=vstack((im3, im3))
 94     imshow(im3)
 95     cols1 = im1.shape[1]
 96     for i in range(len(matchscores)):
 97         if matchscores[i]>0:
 98             plot([locs1[i,0],locs2[matchscores[i,0],0]+cols1], [locs1[i,1],locs2[matchscores[i,0],1]],'c')
 99     axis('off')
100     
101 im1f = 'siftt/25.jpg'
102 im2f = 'siftt/26.jpg'
103 
104 im1 = array(Image.open(im1f))
105 im2 = array(Image.open(im2f))
106 
107 process_image(im1f, 'out_sift_1.txt')
108 l1,d1 = read_features_from_file('out_sift_1.txt')
109 figure()
110 gray()
111 subplot(121)
112 plot_features(im1, l1, circle=False)
113 
114 process_image(im2f, 'out_sift_2.txt')
115 l2,d2 = read_features_from_file('out_sift_2.txt')
116 subplot(122)
117 plot_features(im2, l2, circle=False)
118 
119 matches = match_twosided(d1, d2)
120 print '{} matches'.format(len(matches.nonzero()[0]))
121 
122 figure()
123 gray()
124 plot_matches(im1, im2, l1, l2, matches, show_below=True)
125 show()

 

結果截圖:

 

 

 

 

 

 

 小結:用siftt算法提取兩張圖的特征點,然后雙向匹配兩張圖片的描述子,用線將兩幅圖相匹配的描述子相連,連的線越多,說明這兩幅圖的匹配度越高,兩幅圖越相似。

 4、給定一張圖片,輸出匹配度最高的三張圖片

代碼:

  1 # -*- coding: utf-8 -*-
  2 from PIL import Image
  3 from pylab import *
  4 from numpy import *
  5 import os
  6 from PCV.tools.imtools import get_imlist # 導入原書的PCV模塊
  7 import matplotlib.pyplot as plt # plt 用於顯示圖片
  8 import matplotlib.image as mpimg # mpimg 用於讀取圖片
  9 
 10 def process_image(imagename, resultname, params="--edge-thresh 10 --peak-thresh 5"):
 11     """ 處理一幅圖像,然后將結果保存在文件中"""
 12     if imagename[-3:] != 'pgm':
 13         #創建一個pgm文件
 14         im = Image.open(imagename).convert('L')
 15         im.save('tmp.pgm')
 16         imagename ='tmp.pgm'
 17     cmmd = str("sift "+imagename+" --output="+resultname+" "+params)
 18     os.system(cmmd)
 19     print 'processed', imagename, 'to', resultname
 20     
 21 def read_features_from_file(filename):
 22     """讀取特征屬性值,然后將其以矩陣的形式返回"""
 23     f = loadtxt(filename)
 24     return f[:,:4], f[:,4:] #特征位置,描述子
 25     
 26 def write_featrues_to_file(filename, locs, desc):
 27     """將特征位置和描述子保存到文件中"""
 28     savetxt(filename, hstack((locs,desc)))
 29     
 30 def plot_features(im, locs, circle=False):
 31     """顯示帶有特征的圖像
 32        輸入:im(數組圖像),locs(每個特征的行、列、尺度和朝向)"""
 33        
 34     def draw_circle(c,r):
 35         t = arange(0,1.01,.01)*2*pi
 36         x = r*cos(t) + c[0]
 37         y = r*sin(t) + c[1]
 38         plot(x, y, 'b', linewidth=2)
 39         
 40     imshow(im)
 41     if circle:
 42         for p in locs:
 43             draw_circle(p[:2], p[2])
 44     else:
 45         plot(locs[:,0], locs[:,1], 'ob')
 46     axis('off')
 47     
 48 def match(desc1, desc2):
 49     """對於第一幅圖像中的每個描述子,選取其在第二幅圖像中的匹配
 50     輸入:desc1(第一幅圖像中的描述子),desc2(第二幅圖像中的描述子)"""
 51     desc1 = array([d/linalg.norm(d) for d in desc1])
 52     desc2 = array([d/linalg.norm(d) for d in desc2])
 53     dist_ratio = 0.6
 54     desc1_size = desc1.shape
 55     matchscores = zeros((desc1_size[0],1),'int')
 56     desc2t = desc2.T #預先計算矩陣轉置
 57     for i in range(desc1_size[0]):
 58         dotprods = dot(desc1[i,:],desc2t) #向量點乘
 59         dotprods = 0.9999*dotprods
 60         # 反余弦和反排序,返回第二幅圖像中特征的索引
 61         indx = argsort(arccos(dotprods))
 62         #檢查最近鄰的角度是否小於dist_ratio乘以第二近鄰的角度
 63         if arccos(dotprods)[indx[0]] < dist_ratio * arccos(dotprods)[indx[1]]:
 64             matchscores[i] = int(indx[0])
 65     return matchscores
 66     
 67 def match_twosided(desc1, desc2):
 68     """雙向對稱版本的match()"""
 69     matches_12 = match(desc1, desc2)
 70     matches_21 = match(desc2, desc1)
 71     ndx_12 = matches_12.nonzero()[0]
 72     # 去除不對稱的匹配
 73     for n in ndx_12:
 74         if matches_21[int(matches_12[n])] != n:
 75             matches_12[n] = 0
 76     return matches_12
 77     
 78 def appendimages(im1, im2):
 79     """返回將兩幅圖像並排拼接成的一幅新圖像"""
 80     #選取具有最少行數的圖像,然后填充足夠的空行
 81     rows1 = im1.shape[0]
 82     rows2 = im2.shape[0]
 83     if rows1 < rows2:
 84         im1 = concatenate((im1, zeros((rows2-rows1,im1.shape[1]))),axis=0)
 85     elif rows1 >rows2:
 86         im2 = concatenate((im2, zeros((rows1-rows2,im2.shape[1]))),axis=0)
 87     return concatenate((im1,im2), axis=1)
 88     
 89 def plot_matches(im1,im2,locs1,locs2,matchscores,show_below=True):
 90     """ 顯示一幅帶有連接匹配之間連線的圖片
 91         輸入:im1, im2(數組圖像), locs1,locs2(特征位置),matchscores(match()的輸出),
 92         show_below(如果圖像應該顯示在匹配的下方)
 93     """
 94     im3=appendimages(im1, im2)
 95     if show_below:
 96         im3=vstack((im3, im3))
 97     imshow(im3)
 98     cols1 = im1.shape[1]
 99     for i in range(len(matchscores)):
100         if matchscores[i]>0:
101             plot([locs1[i,0],locs2[matchscores[i,0],0]+cols1], [locs1[i,1],locs2[matchscores[i,0],1]],'c')
102     axis('off')
103     
104 # 獲取project2_data文件夾下的圖片文件名(包括后綴名)
105 filelist = get_imlist('project2_data/')
106 
107 # 輸入的圖片
108 im1f = '23.jpg'
109 im1 = array(Image.open(im1f))
110 process_image(im1f, 'out_sift_1.txt')
111 l1, d1 = read_features_from_file('out_sift_1.txt')
112 
113 i=0
114 num = [0]*30    #存放匹配值
115 for infile in filelist: # 對文件夾下的每張圖片進行如下操作
116     im2 = array(Image.open(infile))
117     process_image(infile, 'out_sift_2.txt')
118     l2, d2 = read_features_from_file('out_sift_2.txt')
119     matches = match_twosided(d1, d2)
120     num[i] = len(matches.nonzero()[0])
121     i=i+1
122     print '{} matches'.format(num[i-1])  #輸出匹配值
123     
124 i=1
125 figure()
126 while i<4: #循環三次,輸出匹配最多的三張圖片
127     index=num.index(max(num))
128     print index, filelist[index]
129     lena = mpimg.imread(filelist[index])  # 讀取當前匹配最大值的圖片
130     # 此時 lena 就已經是一個 np.array 了,可以對它進行任意處理
131     # lena.shape  # (512, 512, 3)
132     subplot(1,3,i)
133     plt.imshow(lena)  # 顯示圖片
134     plt.axis('off')  # 不顯示坐標軸
135     num[index] = 0  #將當前最大值清零
136     i=i+1
137 show()

 

結果截圖:

給定的圖片

 

 

輸出的圖片

 

小結:通過用給定的圖匹配圖像集中的每張圖片的描述子,然后用線與圖像集中的圖片的描述子相連,匹配度最高的圖片就會被輸出。

 七、圖像全景拼接RANSAC

7.1 RANSAC算法原理

OpenCV中濾除誤匹配對采用RANSAC算法尋找一個最佳單應性矩陣H,矩陣大小為3×3。RANSAC目的是找到最優的參數矩陣使得滿足該矩陣的數據點個數最多,通常令h33=1來歸一化矩陣。由於單應性矩陣有8個未知參數,至少需要8個線性方程求解,對應到點位置信息上,一組點對可以列出兩個方程,則至少包含4組匹配點對。

                    

 

 

 RANSAC算法從匹配數據集中隨機抽出4個樣本並保證這4個樣本之間不共線,計算出單應性矩陣,然后利用這個模型測試 

                    

所有數據,並計算滿足這個模型數據點的個數與投影誤差(即代價函數),若此模型為最優模型,則對應的代價函數最小。

7.2 RANSAC算法步驟 

  1. 隨機從數據集中隨機抽出4個樣本數據 (此4個樣本之間不能共線),計算出變換矩陣H,記為模型M;

  2. 計算數據集中所有數據與模型M的投影誤差,若誤差小於閾值,加入內點集 I ;

  3. 如果當前內點集 I 元素個數大於最優內點集 I_best , 則更新 I_best = I,同時更新迭代次數k ;

  4. 如果迭代次數大於k,則退出 ; 否則迭代次數加1,並重復上述步驟;

  注:迭代次數k在不大於最大迭代次數的情況下,是在不斷更新而不是固定的;p為置信度,一般取0.995;w為"內點"的比例 ; m為計算模型所需要的最少樣本數=4;

7.3 RANSAC 基本假設

測試的數據都是由"局外點"組成的,建立模型,局外點是不能適應該模型的數據,也就是不合適該模型的局外點就是噪聲。

7.4  RANSAC 局外點產生的原因

A、噪聲的極值

B、錯誤的測量方法

C、對數據的錯誤假設

7.5實驗代碼

 

 1 from pylab import *
 2 from PIL import Image
 3 import warp
 4 import homography
 5 import sift
 6  
 7 # set paths to data folder
 8 featname = ['D:/new/jia/' + str(i + 1) + '.sift' for i in range(3)]
 9 imname = ['D:/new/jia/' + str(i + 1) + '.jpg' for i in range(3)]
10  
11 # extract features and match
12 l = {}
13 d = {}
14 for i in range(3):
15     sift.process_image(imname[i], featname[i])
16     l[i], d[i] = sift.read_features_from_file(featname[i])
17  
18 matches = {}
19 for i in range(2):
20     matches[i] = sift.match(d[i + 1], d[i])
21  
22 # visualize the matches (Figure 3-11 in the book)
23 for i in range(2):
24     im1 = array(Image.open(imname[i]))
25     im2 = array(Image.open(imname[i + 1]))
26     figure()
27     sift.plot_matches(im2, im1, l[i + 1], l[i], matches[i], show_below=True)
28  
29  
30 # function to convert the matches to hom. points
31 def convert_points(j):
32     ndx = matches[j].nonzero()[0]
33     fp = homography.make_homog(l[j + 1][ndx, :2].T)
34     ndx2 = [int(matches[j][i]) for i in ndx]
35     tp = homography.make_homog(l[j][ndx2, :2].T)
36  
37     # switch x and y - TODO this should move elsewhere
38     fp = vstack([fp[1], fp[0], fp[2]])
39     tp = vstack([tp[1], tp[0], tp[2]])
40     return fp, tp
41  
42  
43 # estimate the homographies
44 model = homography.RansacModel()
45  
46 fp,tp = convert_points(1)
47 H_12 = homography.H_from_ransac(fp,tp,model)[0] #im 1 to 2
48  
49 fp,tp = convert_points(0)
50 H_01 = homography.H_from_ransac(fp,tp,model)[0] #im 0 to 1
51  
52  
53 # warp the images
54 delta = 1000 # for padding and translation
55  
56 im1 = array(Image.open(imname[1]), "uint8")
57 im2 = array(Image.open(imname[2]), "uint8")
58 im_12 = warp.panorama(H_12,im1,im2,delta,delta)
59  
60 im1 = array(Image.open(imname[0]), "f")
61 im_02 = warp.panorama(dot(H_12,H_01),im1,im_12,delta,delta)
62  
63 figure()
64 imshow(array(im_02, "uint8"))
65 axis('off')
66 show()

7.6結果截圖

單一的環境圖片

 

分析:我拍攝的是四張圖片,環境很單一,同一個場景,不同的角度,由結果截圖看出前面一張圖片的拼接點較多,從第二張看出刪除點較為明顯,一看就可以看出來那些點被刪除了,刪除后覺得看到的連線比較清晰,連接的線條變少。

 

 

 

 

分析:這組圖片是同一個地點拍的,環境比較豐富,從不同的角度拍攝,第一張圖片跟第二張的不同點相當的明顯,第一張的連線很多,拼接的效果很成功,連線很多,看出有重復點,覆蓋匹配點,第二張的圖片相似點較少,連線也不多,說明了,相似度高的匹配程度就高,拼接效果也好,相似度低的就相反。

 

 

7.7遇到的問題

因為運行之前沒有導入包,就產生了錯誤,然后我就導入了warp包

 報錯

 1 Arrays cannot be empty 

矩陣為空,我就重新改了圖像的像素,提取sift特征

然后由報錯

 1 did not meet fit acceptance criteria 

這是因為圖片的水平落差比較大,我們得再拍一組照片。改了圖片的下高速,圖片的像素都改成一樣,不能太大也不能太小,我改成的是600*600.

 

八、SIFT實驗總結

1、sift算法提取特征點穩定,不會因為光照、旋轉、尺度等因素而改變圖像的特征點。

2、圖像的尺度越大,圖像就會越模糊。

3、sift算法可以對多張圖像進行快速的、准確的關鍵點匹配,產生大量的特征點,可以適用於生活中的很多運用。

4、sift算法提取的特征點會有重疊。

5、在用sift算法提取特征時,應該降低圖片的像素,像素過高會導致運行時間過長或失敗。

 

九、實驗遇到的問題

出現的問題:1、運行代碼時出現這樣的錯誤:

在D:\Anaconda2\Lib\site-packages目錄中找到pydot.py ,用記事本打開,把self.prog = 'dot‘改成self.prog = r'C:\Program Files (x86)\Graphviz2.38\bin\dot.exe',保存,關掉運行軟件再打開就可以了。

 2、運行代碼出現這樣的結果

 

 我用的項目的路徑,出現以上報錯,把路徑改成了圖片的路徑,圖片的后綴改成.jpg就可以了。

 3、因為圖片像素過高,運行時間會過長,結果一直出不來,還以為是代碼出來了錯誤,但是不報錯,想着可能是照片是自己拍的,像素過高了,就去降低了圖片的像素,運行速率變快,結果就出來了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM