opencv中特徵匹配的2NN演算法

2021-09-23 06:17:18 字數 1808 閱讀 1219

前言

在提取了影象的特徵點,並形成特徵描述子後,我們往往需要對兩張(本質上是兩個mat)進行特徵點匹配·,opencv提供的匹配方法有兩種,分別是flann以及暴力匹配。暴力匹配思路最為簡單,就是圖1的乙個特徵描述子a,與圖2的所有特徵描述子均進行一次距離計算(一般為歐氏距離),距離最小的點即為a點在圖2的匹配點。flann我沒有詳細的了解,據說是基於概率的思想,只找到乙個差不多相近的點,而不是距離最近的點。暴力匹配雖然精準,但是慢,另外,也會出現一定數量的錯誤匹配點。為盡可能地剔除錯誤匹配點,2nn演算法應運而生。

什麼是2nn?

2nn演算法全稱是 two neareast neighbour ,即兩個與目標點最相近的點。2nn演算法通過衡量最近距離,與次近(第二接近)距離的比值,來判斷該點是否為匹配點,具體公式如下

換句話說,現在不僅僅要求兩個關鍵點之間的距離最近,同時還要求最近的點與次近的點不能太相似(兩者比值越接近1,約相似嘛),滿足了這個條件,我們才說這兩個點是匹配的。

但為什麼這樣做會有效呢?

我的理解是「設定了一定的區分度」,舉例來說,特徵點a的最近特徵點為b(候選特徵點),此近特徵點為c,如果a-b的距離跟a-c的距離差不多,那麼究竟是b是特徵點,還是c是特徵點呢?在這種模稜兩可的情況下,演算法很可能就會產生了錯配。2nn演算法很好地結局兩者之間的關係,如果兩者很像,說明c也很可能是a的匹配點,那你憑什麼選擇b呢?所以就乾脆b也不選了吧!!!杜絕一切風險!!!

相關模版類

keypoint類

這是opencv中用來儲存關鍵點的乙個模版

class keypoint

dmatch類

這是opencv用來儲存匹配好一對關鍵點,原型為:

class cv_exports_w_****** dmatch

;

每乙個dmatch物件儲存的是一對匹配好的特徵點的資訊,那儲存了什麼資訊呢?

2nn的**實現

void twonn_matcher(vector& matches, mat des1, mat des2, const float min_ration)

cout << "k_matches:" << k_matches.size() << endl; //測試用的

cout << "matches:" << matches.size() << endl;

}

opencv中knnmatch()方法可以返回k個最近的特徵點,2nn中我們就設定為2,應該注意的是,匹配結果應該儲存在

std::vectork_matches;

而不是std::vector ,這也很好理解,乙個關鍵點有最近跟次近兩個點嘛。

實驗結果

直接暴力匹配

使用2nn:

可見,使用2nn能有效地消除錯誤匹配點

閾值對關鍵點數量的影響

在2nn中,我們需要乙個閾值來衡量最近距離與次近距離的關係,那這個閾值對匹配特徵數目有什麼影響嗎?

在上圖中,暴力匹配獲得的匹配特徵點為779對

在使用2nn後,我分別使用了0.6666,0.6,0.3,以及0.8

實驗結果為163、126、22、246。可見,閾值設定越接近1,找到的匹配點越多(有可能使是錯的匹配點),反之越少。

SIFT特徵檢測 最近鄰近似匹配 2NN優化

import math from matplotlib import pyplot as plt import matplotlib matplotlib inline book l cv2.imread images book l.png book r cv2.imread images book...

OpenCV2簡單的特徵匹配

特徵的匹配大致可以分為3個步驟 特徵的提取 計算特徵向量 特徵匹配 對於3個步驟,在opencv2中都進行了封裝。所有的特徵提取方法都實現featuredetector介面,descriptorextractor介面則封裝了對特徵向量 特徵描述符 的提取,而所有特徵向量的匹配都繼承了descript...

OpenCV2簡單的特徵匹配

特徵的匹配大致可以分為3個步驟 特徵的提取 計算特徵向量 特徵匹配 對於3個步驟,在opencv2中都進行了封裝。所有的特徵提取方法都實現featuredetector介面,descriptorextractor介面則封裝了對特徵向量 特徵描述符 的提取,而所有特徵向量的匹配都繼承了descript...