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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

计算机视觉:特征提取与匹配

發布時間:2023/12/15 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 计算机视觉:特征提取与匹配 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

1. 特征提取和匹配

1.1 背景知識

1.2 特征匹配基本流程

1.3?局部特征描述子

2. Harris角點檢測?

2.1 角點(corner points)

2.2?HARRIS角點檢測基本思想

2.3?HARRIS檢測:數學表達

2.4 角點響應函數

2.5 編程實現

2.5.1 角點檢測代碼實現?

2.5.2 角點檢測數據測試

3.??SIFT特征匹配算法

3.1 SIFT算法實現步驟

3.2?關鍵點檢測的相關概念

3.2.1 關鍵點(特征點)

3.2.2 尺度空間

3.2.3 高斯模糊

3.2.4?高斯金字塔

3.3?檢測尺度空間極值

3.3.1 DoG(Difference of Gaussian)函數

3.3.2 DoG高斯差分金字塔

3.3.3?DOG局部極值檢測

3.4 關鍵點的精確定位

3.4.1?特征點的精確定位

3.4.2?剔除不穩定的邊緣響應點

3.5?關鍵點方向分配

3.6?關鍵點描述

3.7?關鍵點匹配

3.8 編程實現

3.8.1 檢測感興趣點

3.8.2 兩張圖像的SIFT特征匹配

3.8.3?地理標記圖像匹配

3.8.4?實驗過程中遇到的問題


1. 特征提取和匹配

1.1 背景知識

????????特征提取和匹配是許多計算機視覺應用中的一個重要任務,廣泛運用在運動結構、圖像檢索、目標檢測等領域。 特征可能是圖像中的特定結構,例如點,邊緣或對象。特征也可能是應用于圖像的一般鄰域操作或特征檢測的結果。特征點匹配,是圖像拼接、三維重建、相機標定等應用的關鍵步驟。

????????關鍵點也稱興趣點,是紋理中表達的點。關鍵點往往是物體邊界方向突然改變的點或兩個或多個邊緣段之間的交點。它在圖像空間中具有明確的位置或很好地定位。即使圖像域的局部或全局存在如光照和亮度變化等的擾動,關鍵點仍然是穩定,可以被重復可靠地計算出。除此之外它能夠提供有效的檢測。

1.2 特征匹配基本流程

  • 根據特定準則,提取圖像中的特征點 ;
  • 提取特征點周圍的圖像塊,構造特征描述符;
  • 通過特征描述符對比,實現特征匹配。

1.3?局部特征描述子

???特征點必須具有不變性,比如:

  • 幾何不變性: 位移、旋轉、尺度,......
  • 光度不變性: 光照、 曝光,......

? ?特征分類

  • 角點。Harris算子,SUSAN算子, FAST算子。
  • 梯度特征點。 SIFT、SURF、GLOH、ASIFT、PSIFT算子 等。 ? 邊緣特征(線型)。Canny算子, Marr算子。
  • 紋理特征。灰度共生矩陣,小波Gabor算子。
  • 快速特征匹配的基本策略:以圖像中穩定角點的領域訓練特 征分類器,為輸入圖像的特征分類。

2. Harris角點檢測?

????????Harris 角點檢測算法(也稱 Harris & Stephens 角點檢測器)是一個極為簡單的角點檢測算法。該算法的主要思想是,如果像素周圍顯示存在多于一個方向的邊,我們認為該點為興趣點。該點就稱為角點。

2.1 角點(corner points

  • 局部窗口沿各方向移動,均產生明顯變化的點;
  • 圖像局部曲率突變的點。

? ??

? ?好的角點檢測算法應該具有的特點

  • 檢測出圖像中“真實的”角點
  • 準確的定位性能
  • 很高的穩定性
  • 具有對噪聲的魯棒性
  • 具有較高的計算效率

2.2?HARRIS角點檢測基本思想

????????算法基本思想是使用一個固定窗口在圖像上進行任意方向上的滑動,比較滑動前與滑動后兩種情況,窗口中的像素灰度變化程度,如果存在任意方向上的滑動,都有著較大灰度變化,那么我們可以認為該窗口中存在角點。

固定窗口在圖像上進行任意方向上的滑動,有以下幾種情況:

平坦區域: 任意方向移動,無灰度變化。

平坦區域

邊緣:沿著邊緣方向移動,無灰度變化 。

邊緣上移動

角點:窗口向任意方向的移動都導致圖像灰度的明顯變化。

角點處移動

2.3?HARRIS檢測:數學表達

將圖像窗口平移??產生灰度變化? 的數學表達式如下:

其中,為窗口函數,可用1表示在窗口內部,用0表示在外面,或者用高斯拉普拉斯算子。

為灰度圖像,為平移后的圖像灰度。

延伸知識點:

一元函數泰勒展開:

?二元函數泰勒展開:

為了對求解方便,我們利用二元泰勒近似可將表達式簡化,將函數在處泰勒展開,得:

又我們可以將??表示為:

于是對于局部微小的移動量??,可以近似得到下面的表達:

其中M是 2*2 矩陣,可由圖像的導數求得:

窗口移動導致的圖像變化量:實對稱矩陣M的特征值分析

對于,??,??記的特征值為?.

通過M的兩個特征值的大小對圖像點進行分類:

  • 平臺區域:如果 和 都很小,圖像窗口在所有方向上移動都無明顯灰度變化;
  • 邊緣:如果?或?,圖像窗口在某一方向上移動有明顯灰度變化。
  • 角點:如果 和 都較大且數值相當 ~ ,圖像窗口在所有方向上移動都產生明顯灰度變化;

?

2.4 角點響應函數

????????在不需要實際計算特征值的情況下,為了把重要的情況和其他情況分開,Harris 和 Stephens 引入了指示函數。

定義:角點響應函數R

?

?

?

? ? R 只與M的特征值有關

  • 角點:R 為大數值正數
  • 邊緣:R為大數值負數
  • 平坦區:R為小數值

? ??

角點計算流程

  • 對角點響應函數R進行閾值處理:R>threshold
  • 提取R的局部最大值
  • 為了消除參數k的影響,也可采用商來計算響應:

2.5 編程實現

Harris角點檢測步驟

  • 讀入圖像轉灰度圖
  • 計算角點響應函數
  • 基于響應值選擇角點
  • 在原點中畫出檢測的角點
  • 2.5.1 角點檢測代碼實現?

    from PIL import Image from numpy import * from pylab import * from scipy.ndimage import filters# 在灰度圖像中,對每個像素計算Harris角點檢測器響應函數 def compute_harris_response(im, sigma=3):# 計算導數: 先初始化矩陣imx = zeros(im.shape)imy = zeros(im.shape)# 高斯導數: 3*3的高斯濾波filters.gaussian_filter(im, (sigma, sigma), (0, 1), imx)filters.gaussian_filter(im, (sigma, sigma), (1, 0), imy)# 計算 Harris 矩陣的分量Wxx = filters.gaussian_filter(imx * imx, sigma)Wxy = filters.gaussian_filter(imx * imy, sigma)Wyy = filters.gaussian_filter(imy * imy, sigma)# 計算特征值Wdet = Wxx * Wyy - Wxy ** 2Wtr = Wxx + Wyyreturn Wdet/Wtr # 從一幅Harris響應圖像中返回角點 def get_harris_points(harrisim, min_dist=10, threshold=0.1):# min_dist 為分割角點和圖像邊界的最少像素數目# 尋找高于閾值的候選角點corner_threshold = harrisim.max() * thresholdharrisim_t = (harrisim > corner_threshold) * 1# 得到候選點的坐標coords = array(harrisim_t.nonzero()).T# 獲取候選點的 Harris 響應值candidate_values = [harrisim[c[0], c[1]] for c in coords]# 對候選點按照 Harris 響應值進行排序index = argsort(candidate_values)# 將可行點的位置保存到數組中allowed_locations = zeros(harrisim.shape)allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = 1# 按照 min_distance 原則,選擇最佳 Harris 點filtered_coords = []for i in index:if allowed_locations[coords[i, 0], coords[i, 1]] == 1:filtered_coords.append(coords[i])allowed_locations[(coords[i, 0] - min_dist):(coords[i, 0] + min_dist),(coords[i, 1] - min_dist): (coords[i, 1] + min_dist)] = 0return filtered_coords # 繪制圖像中檢測到的角點 def plot_harris_points(image, filtered_coords):figure()gray()imshow(image)plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')axis('off')show()

    2.5.2 角點檢測數據測試

    數據一:

    數據二:

    ?數據三:

    ? 測試代碼示例:

    if __name__ == '__main__':# 讀入圖像im = array(Image.open('Images/picture1.jpg').convert('L'))# 檢測Harris角點harrisim = compute_harris_response(im)# Harris響應函數harrisim1 = 255 - harrisimfigure()gray()# 畫出Harris響應圖subplot(221)title("harrisim")imshow(harrisim1)axis('off')axis('equal')# 設置多個閾值,比較實驗結果threshold = [0.1, 0.2, 0.3]for i, thres in enumerate(threshold):filtered_coords = get_harris_points(harrisim, 6, thres)subplot(2, 2, i+2)title("threshold: "+str(threshold[i]))imshow(im)plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')axis('off')show()

    ? 運行結果:

    ? 數據一結果:?

    ??

    ? 數據二結果:

    ?數據三結果:

    ????????閾值增大,角點響應值R減小,降低角點檢測的靈性,被檢測角點數量減少;閾值減小,角點響應值R增大,增加角點檢測的靈敏性,被檢測角點的數量增加。

    3.??SIFT特征匹配算法

    ????????David Lowe 提出的 SIFT(Scale-Invariant Feature Transform,尺度不變特征變換)是過去十年中最成功的圖像局部描述子之一。SIFT 特征后來得到精煉并詳述,經受住了時間的考驗。SIFT 特征包括興趣點檢測器和描述 子。SIFT 描述子具有非常強的穩健性,這在很大程度上也是 SIFT 特征能夠成功和流行的主要原因。自從 SIFT 特征的出現,許多其他本質上使用相同描述子的方法也相繼出現。現在,SIFT 描述符經常和許多不同的興趣點檢測器相結合使用(有些 情況下是區域檢測器),有時甚至在整幅圖像上密集地使用。SIFT 特征對于尺度、旋轉和亮度都具有不變性,因此,它可以用于三維視角和噪聲的可靠匹配。

    SIFT算法可以解決的問題

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

    3.1 SIFT算法實現步驟

    實質可以歸為在不同尺度空間上查找特征點(關鍵點)的問題。

    SIFT算法實現特征匹配主要有三個流程:

  • 提取關鍵點;
  • 對關鍵點附加 詳細的信息(局部特征),即描述符;
  • 通過特征點(附帶上特征向量的關 鍵點)的兩兩比較找出相互匹配的若干對特征點,建立景物間的對應關系。
  • 3.2?關鍵點檢測的相關概念

    3.2.1 關鍵點(特征點)

    ???????? 這些點是一些十分突出的點,不會因光照、尺度、旋轉等因素的改變而消失,比如角點邊緣點暗區域的亮點以及亮區域的暗點。假定兩幅圖像中有相同的景物,那么使用某種算法分別提取各自的特征點,這些點之間會有相互對應的匹配關系。根據歸納,我們可以看出SIFT特征點希望選出具有下述不變性的點:尺度、方向、位移、光照。

    3.2.2 尺度空間

    ????????尺度空間理論最早于1962年提出,其主要思想是通過對原始圖像進行尺度變換,獲得圖像多尺度下的空間表示。從而實現邊緣、角點檢測和不同分辨率上的特征提取,以滿足特征點的尺度不變性

    ????????尺度空間中各尺度圖像的模 糊程度逐漸變大,能夠模擬人在 距離目標由近到遠時目標在視網 膜上的形成過程。 尺度越大圖像越模糊。

    ? ? ? ?

    • 尺度不變性

    ? ??

    • 旋轉不變性

    ? ??

    ?根據文獻《Scale-space theory: A basic tool for analysing structures at different scales》可知,高斯核可以產生多尺度空間的核,一個圖像的尺度空間L(x, y, σ) ,定義為原始圖像 I(x, y)與一個可變尺度的2維高斯函數G(x, y, σ) 卷積運算。

    高斯函數:

    尺度空間:

    ?其中,*表示卷積計算。

    3.2.3 高斯模糊

    ????????高斯模糊是在Adobe Photoshop等圖像處理軟件中廣泛使用的處理 效果,通常用它來減小圖像噪聲以及降低細節層次。這種模糊技術生成的圖像的視覺效果是好像經過一個半透明的屏幕觀察圖像。

    3.2.4?高斯金字塔

    ????????高斯金字塔的構建過程可分為兩步: (1)對圖像做高斯平滑; (2)對圖像做降采樣。

    ????????為了讓尺度體現其連續性,在簡單 下采樣的基礎上加上了高斯濾波。一幅圖像可以產生幾組(octave) 圖像,一組圖像包括幾層(interval)圖像。

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

    σ——尺度空間坐標;s——sub-level層坐標;σ0——初始尺度;S——每組層數(一般為3~5)。

    最后可將組內和組間尺度歸為:

    i——金字塔組數;n——每一組的層數。

    3.3?檢測尺度空間極值

    3.3.1 DoG(Difference of Gaussian)函數

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

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

    3.3.2 DoG高斯差分金字塔

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

    3.3.3?DOG局部極值檢測

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

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

    3.4 關鍵點的精確定位

    ????????以上方法檢測到的極值點是離散空間的極值點,我們可以通過擬合三維二次函數來精確定位關鍵點的位置與尺度,由于DoG函數在圖像邊緣有較強的邊緣響應,因此需要排除邊緣響應,增強穩定性和抗噪聲能力。

    3.4.1?特征點的精確定位

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

    對尺度空間DOG函數進行曲線擬合,以提高關鍵點的穩定性,減小誤差。

    利用DoG函數在尺度空間的Taylor展開式(擬合函數)為:

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

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

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

    3.4.2?剔除不穩定的邊緣響應點

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

    其中??,是候選點鄰域對應位置的差分求得的。

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

    該值在兩特征值相等時達最小。Lowe論文中建議閾值T為1.2,即:

    時保留關鍵點,反之剔除。

    3.5?關鍵點方向分配

    ????????通過尺度不變性求極值點,可以使其具有縮放不變的性質。而利用?鍵點鄰域像素的梯度方向分布特性,可以為每個關鍵點指定方向參數方向,從而使描述子對圖像旋轉具有不變性

    ????????通過求每個極值點的梯度來為極值點賦予方向。

    ????????像素點的梯度表示:

    ? ? ? ? 梯度幅值:

    ????????梯度方向:

    ????????計算得到梯度方向后,就是用直方圖統計特征點鄰域內像素對應的梯度方向和幅值。梯度方向的直方圖的橫軸是梯度方向的角度(梯度方向的范圍是 0 到 360 度,直方圖每 36 度一個柱,共 10 個柱),縱軸是梯度方向對應梯度幅值的累加,在直方圖的峰值就是特征點的主方向。

    關鍵點的主方向與輔方向:

    • 關鍵點主方向:極值點周圍區域梯度直方圖的主峰值也是特征點方向
    • 關鍵點輔方向:在梯度方向直方圖中,當存在另一個相當于主峰值 80%能量的峰值時,則將這個方向認為是該關鍵點的輔方向。

    ????????這可以增強匹配的魯棒性,Lowe的論文指出大概有15%關鍵點具有 多方向,但這些點對匹配的穩定性至為關鍵。

    3.6?關鍵點描述

    ????????下圖是一個SIFT描述子事例。其中描述子由2×2×8維向量表征,也即是 2×2個8方向的方向直方圖組成。左圖的種子點由8×8單元組成。每一個小格都代表了特征點鄰域所在的尺度空間的一個像素,箭頭方向代表了像素梯度方 向,箭頭長度代表該像素的幅值。然后在4×4的窗口內計算8個方向的梯度方向直方圖。繪制每個梯度方向的累加可形成一個種子點,如右圖所示:一個特征 點由4個種子點的信息所組成。

    ????????與求主方向不同,此時每個種子區域的梯度直方圖在0-360之間劃分為8個方向區間,每個區間為45度,即每個種子點有8個方向的梯度強度信息。在實際的計算過程中,為了增強匹配的穩健性,Lowe建議對每個關鍵點使用? 4×4共16個種子點來描述,這樣一個關鍵點就可以產生128維的SIFT特征向量。

    ????????通過對特征點周圍的像素進行分塊,計算塊內梯度直方圖,生成具有獨特性的向量,這個向量是該區域圖像信息的一種抽象,具有唯一性。

    3.7?關鍵點匹配

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

    模板圖中關鍵點描述子:

    實時圖中關鍵點描述子:

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

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

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

    3.8 編程實現

    3.8.1 檢測感興趣點

    # 檢測感興趣點 from PIL import Image from pylab import * from numpy import * import os# 處理一幅圖像,然后將結果保存在文件中 def process_image(imagename, resultname, params="--edge-thresh 10 --peak-thresh 5"):if imagename[-3:] != 'pgm':# 創建一個pgm文件im = Image.open(imagename).convert('L')im.save('tmp.pgm')imagename = 'tmp.pgm'cmmd = str("D:\python\win64vlfeat\sift.exe " + imagename + " --output=" + resultname + " " + params)os.system(cmmd)print('processed', imagename, 'to', resultname)# 讀取特征屬性值,然后將其以矩陣的形式返回 def read_features_from_file(filename):f = loadtxt(filename)return f[:, :4], f[:, 4:] # 特征位置,描述子# 將特征位置和描述子保存到文件中 def write_featrues_to_file(filename, locs, desc):savetxt(filename, hstack((locs, desc)))# 顯示帶有特征的圖像 def plot_features(im, locs, circle=False):# 輸入:im(數組圖像),locs(每個特征的行、列、尺度和朝向)def draw_circle(c, r):t = arange(0, 1.01, .01) * 2 * pix = r * cos(t) + c[0]y = r * sin(t) + c[1]plot(x, y, 'b', linewidth=2)imshow(im)if circle:for p in locs:draw_circle(p[:2], p[2])else:plot(locs[:, 0], locs[:, 1], 'ob')axis('off')

    ? 運行測試:

    imname = 'picture1.jpg' im = array(Image.open(imname).convert('L')) process_image(imname, 'picture1.sift') l1, d1 = read_features_from_file('picture1.sift')figure() gray() subplot(131) plot_features(im, l1, circle=False) title('SIFT Feature') subplot(132) plot_features(im, l1, circle=True) title('SIFT Feature Scale')# 檢測harris角點 harrisim = compute_harris_response(im)subplot(133) filtered_coords = get_harris_points(harrisim, 60, 0.1) imshow(im) plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*') axis('off') title('Harris Corner Point') show()

    ? 輸出結果:

    3.8.2 兩張圖像的SIFT特征匹配

    # SIFT特征匹配 from PIL import Image from pylab import * from numpy import * import os# 處理一幅圖像,然后將結果保存在文件中 def process_image(imagename, resultname, params="--edge-thresh 10 --peak-thresh 5"):if imagename[-3:] != 'pgm':# 創建一個pgm文件im = Image.open(imagename).convert('L')im.save('tmp.pgm')imagename = 'tmp.pgm'cmmd = str("D:\python\win64vlfeat\sift.exe " + imagename + " --output=" + resultname + " " + params)os.system(cmmd)print('processed', imagename, 'to', resultname)# 讀取特征屬性值,然后將其以矩陣的形式返回 def read_features_from_file(filename):f = loadtxt(filename)return f[:, :4], f[:, 4:] # 特征位置,描述子# 將特征位置和描述子保存到文件中 def write_featrues_to_file(filename, locs, desc):savetxt(filename, hstack((locs, desc)))# 顯示帶有特征的圖像 def plot_features(im, locs, circle=False):# 輸入:im(數組圖像),locs(每個特征的行、列、尺度和朝向)def draw_circle(c, r):t = arange(0, 1.01, .01) * 2 * pix = r * cos(t) + c[0]y = r * sin(t) + c[1]plot(x, y, 'b', linewidth=2)imshow(im)if circle:for p in locs:draw_circle(p[:2], p[2])else:plot(locs[:, 0], locs[:, 1], 'ob')axis('off')# 對于第一幅圖像中的每個描述子,選取其在第二幅圖像中的匹配 def match(desc1, desc2):# 輸入:desc1(第一幅圖像中的描述子),desc2(第二幅圖像中的描述子)desc1 = array([d / linalg.norm(d) for d in desc1])desc2 = array([d / linalg.norm(d) for d in desc2])dist_ratio = 0.6desc1_size = desc1.shapematchscores = zeros((desc1_size[0], 1), 'int')desc2t = desc2.T # 預先計算矩陣轉置for i in range(desc1_size[0]):dotprods = dot(desc1[i, :], desc2t) # 向量點乘dotprods = 0.9999 * dotprods# 反余弦和反排序,返回第二幅圖像中特征的索引indx = argsort(arccos(dotprods))# 檢查最近鄰的角度是否小于dist_ratio乘以第二近鄰的角度if arccos(dotprods)[indx[0]] < dist_ratio * arccos(dotprods)[indx[1]]:matchscores[i] = int(indx[0])return matchscores# 雙向對稱版本的match() def match_twosided(desc1, desc2):matches_12 = match(desc1, desc2)matches_21 = match(desc2, desc1)ndx_12 = matches_12.nonzero()[0]# 去除不對稱的匹配for n in ndx_12:if matches_21[int(matches_12[n])] != n:matches_12[n] = 0return matches_12# 返回將兩幅圖像并排拼接成的一幅新圖像 def appendimages(im1, im2):# 選取具有最少行數的圖像,然后填充足夠的空行rows1 = im1.shape[0]rows2 = im2.shape[0]if rows1 < rows2:im1 = concatenate((im1, zeros((rows2 - rows1, im1.shape[1]))), axis=0)elif rows1 > rows2:im2 = concatenate((im2, zeros((rows1 - rows2, im2.shape[1]))), axis=0)return concatenate((im1, im2), axis=1)# 顯示一幅帶有連接匹配之間連線的圖片 def plot_matches(im1, im2, locs1, locs2, matchscores, show_below=True):# 輸入:im1, im2(數組圖像), locs1,locs2(特征位置),matchscores(match()的輸出),# show_below(如果圖像應該顯示在匹配的下方)im3 = appendimages(im1, im2)if show_below:im3 = vstack((im3, im3))imshow(im3)cols1 = im1.shape[1]for i in range(len(matchscores)):if matchscores[i] > 0:plot([locs1[i, 0], locs2[matchscores[i, 0], 0] + cols1], [locs1[i, 1], locs2[matchscores[i, 0], 1]], 'c')axis('off')

    ? 運行測試:

    im1f = 'picture1.jpg' im2f = 'picture1.jpg' im1 = array(Image.open(im1f)) im2 = array(Image.open(im2f))process_image(im1f, 'out_sift_1.txt') l1, d1 = read_features_from_file('out_sift_1.txt') figure() gray() subplot(121) plot_features(im1, l1, circle=False)process_image(im2f, 'out_sift_2.txt') l2, d2 = read_features_from_file('out_sift_2.txt') subplot(122) plot_features(im2, l2, circle=False)matches = match_twosided(d1, d2) print('{} matches'.format(len(matches.nonzero()[0]))) figure() gray() plot_matches(im1, im2, l1, l2, matches, show_below=True) show()

    ? 輸出結果:

    3.8.3?地理標記圖像匹配

    from PIL import Image from numpy import * import os import pydot from PCV.localdescriptors import sift# 獲取圖像列表 def get_imlist(path):return [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.png')]download_path = "D:/python/workSpace/ComputerVision/Test2/Pictures" path = "D:/python/workSpace/ComputerVision/Test2/Pictures"# 獲取文件名列表 imlist = get_imlist(download_path) nbr_images = len(imlist) print(nbr_images)# 提取特征 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 triangleprint('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: \n", matchscores)# 復制值 for i in range(nbr_images):for j in range(i + 1, nbr_images): # no need tomatchscores[j, i] = matchscores[i, j]# 可視化 # min number of matches needed to craete link threshold = 2# don't want the default directed graph g = pydot.Dot(graph_type='graph')for i in range(nbr_images):for j in range(i + 1, nbr_images):if matchscores[i, j] > threshold:# 圖像對中的第一幅圖像im = Image.open(imlist[i])im.thumbnail((100, 100))filename = path + str(i) + '.png'im.save(filename) # 需要一定大小的臨時文件g.add_node(pydot.Node(str(i), fontcolor='transparent',shape='rectangle', image=filename))# 圖像對中的第二幅圖像im = Image.open(imlist[j])im.thumbnail((100, 100))filename = path + str(j) + '.png'print(filename);im.save(filename) # 需要一定大小的臨時文件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('result.png')

    ? 輸出結果:

    3.8.4?實驗過程中遇到的問題

    問題一:

    UserWarning: loadtxt: Empty input file: "out_sift.1.txt"? f = loadtxt(filename)

    IndexError: too many indices for array: array is 1-dinmensional,but 2 were indexed

    —直報錯類似的問題,還沒解決!!!

    錯誤原因:生成的sift文件為空,即特征提取為空。

    解決辦法:vlfeat0.9.20版本,下載了vcomp100.dll文件,下載鏈接https://cn.dll-files.com/vcomp100.dll.html,64位系統對應64位。

    參考博客:vlfeat0.9.21提取sift特征為空_lrwin_bian的博客-CSDN博客

    vlfeat安裝參考教程Python計算機視覺編程 - 安裝

    問題二:

    關于Graphviz安裝教程的一些問題:

    第一步:確認在Graphviz官網下載并安裝了對應操作系統(Windows,Linux,Mac)的Graphviz軟件。官網地址:https://www.graphviz.org/。安裝過程中有一個選項,建議選擇添加至所有人,如下圖:


    第二步:將軟件安裝目錄的bin文件添加到系統環境中。如我的電腦是Windows系統,Graphviz安裝在D:\Program Files\Graphviz2.38,該目錄下有bin文件,將該路徑添加到系統環境變量中,即D:\Program Files\Graphviz2.38\bin。如果第一步選擇了PATH添加至所有人,則這一步可以直接跳過!
    第三步:使用pip命令安裝以下模塊:
    ????????????????pip install pydot-ng
    ????????????????pip install graphviz
    ????????????????pip install pydot

    ????????????????注意安裝順序,一定要先安裝grahiviz,再pip install pydot!!!
    第四步:進入windows命令行界面,輸入dot -version,然后按回車,如果顯示graphviz的相關版本信息,則安裝配置成功。如圖:

    依照上述步驟基本不會有問題,若仍報錯"dot" not found in path,那么在提示目錄下(如前文報錯內容加粗目錄)找到pydot.py文件的源碼,在pydot.py中找到類Dot的定義,進行如下修改:

    保存文件,如果運行仍報錯"dot" not found in path,那就重啟電腦!!!!

    到這里,再運行就沒出問題了。

    總結

    以上是生活随笔為你收集整理的计算机视觉:特征提取与匹配的全部內容,希望文章能夠幫你解決所遇到的問題。

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