本次作業主要實作feature matching 共分為四大部分
介紹matching的理論及說明增加精確度的方法 : template matching、knn matching、radius matching、cross check、ratio test
Patches:主要利用FAST實作template matching
Matcher:了解feature desriptor的原理,並使用SURF和SIFT完成模擬
Binary Descriptors:了解binary desriptor的原理,主要使用ORB和BRISK完成模擬
作業環境:
Windows 11
OpenCV 4.7.0
Visual Studio 2022
以下為本次作使用的圖片。
Template Matching 的目的是在一張影像中搜尋模板影像位置的方法。原理是將模板圖滑動,類似2D convolution的移動方式,將輸入影像和模板相互比較,在OpenCV提供函式cv::matchTemplate()可以使用,此函數會返回grayscale 影像,影像中的數值表示該pixel周圍的pixel與模板的匹配程度。
計算匹配程度的方法有很多種,以下介紹三種常見的的計算方法。
最常見的是計算Sum of Squared Differences 計算公式為:
除了這個計算方式外,OpenCV還提供很多當在使用template matching可以選擇的雞算相似度的方法,舉裡來說,將Sum of Squared Differences做normalization,公式如下:
也可以計算Correlation Coefficient ,以求出相似度。
得到 cv::matchTemplate()的輸出結果後,可以用 cv::minMaxLoc()來找最大最小值,以求出matching point.
kNN (K Nearest Neighbor) 分類演算原理是找和新數據最近的K個鄰居,根據這些鄰居多數為甚麼分類,新數據則為麼樣的分類,KNN matching 應用這個原理,在圖片二找出和圖片依最匹配的K個keypoint。
實踐 KNN matching 的函式稱作 knnMatch(),若K=2每個keypoint函式會返回兩條 match-lines。
radius matching使用在計算完propensity score後,設定一個範圍(radius),接下來比較範圍內的所有數值。使用radius matching方法會比nearest neighbor matching的結果更加精準,nearest neighbor matching是將距離最小的兩個keypoint判定為match,但有可能第一張偵測到的keypoint在第二張圖中未出現,導致距離很大但仍判定為match的情況。使用radius matching會得到更小的偏差,因為不是對整張圖做matching ,而是局部的鄰近區域中做matching。
在OpenCV 中,實踐 radius matching 的函式稱作 cv::DescriptorMatcher::radiusMatch()。
Brute-Force matcher 是一個很值觀的matching方法,在OpenCV中提供的函式稱作 cv::BFMatcher。原理是拿第一張圖中每個keypoint 的 descriptor,依序對第二張圖所有keypoint做distance calculation,距離最近的兩個keypoint,則標示為match。將距離最短得定為matching point 會遇到一個問題是,有可能第一張偵測到的keypoint在第二張圖中未出現,但根據理論,演算法仍會認為距離最短的是matching,所以為了提高matching的正確度,發展出cross check。
cross check的概念是,除了拿第一張圖中每個keypoint 的 descriptor,依序對第二張圖所有keypoint做distance calculation,還需要反向再做一次,意思是拿第二張圖中每個keypoint 的 descriptor,依序對第ㄧ張圖所有keypoint做distance calculation,將兩次matching 結果取交集,只有在雙向做match且得到相同的一組keypoint時,才判定為matching point。cross check的缺點是,需要花費兩倍的運算時間,雖然運算量大,但在資料數少的時候效果很好。
Ratio test 目的是為了增加matching 結果的精確度,會將一些模稜兩可的答案去除掉。假設從影像一中取keypoint (fa) ,欲在影像二中找匹配點,會在影像二中找和影像一中的keypoint距離最短的兩個點( fb1、fb2 ),也就是最匹配的兩個keypoint,其中又以 fb1 的距離比 fb2 短,下一步帶入公式d(fa, fb1) / d(fa, fb2)計算兩點的ratio test。
若計算結果數值很小,代表fb1 的距離遠小於 fb2的距離,則fb1是良好的matching結果,相反的若計算結果很大,則有代表fb1 的距離和 fb2的距離很接近,fb1是模稜兩可的matching結果,因此將 fb1、fb2捨棄。
主要使用FAST做keypoint detect,FAST的優點是速度很快,本節將利用template matching來完成maching。以下主要說明實踐template matching的理論、程式碼說明及測試當使用不同keypoint detector所得到的效果差異。
完成keypoint detect 後,所得到的結果是單一pixel,僅單一piexl無法做matching,必須將四周的pixel都考慮進去。實踐概念是,分別求出兩張圖的keypoint,接著將圖片一中得到的keypoint,依序在圖片二中找最相近pixel,判斷兩張圖中pixel的相似程度用方法有很多種最基本的方式是,計算Sum of Squared Differences,以得到兩個patch裡的intensity values differences,最後將差異最小的兩個keypoint,則判定為match。
Sum of Squared Differences 的計算公式為:
在做matching要先求出keypoint,因此首先,先選擇要使用哪種keypoint detector,而作者選擇FAST,接著對兩張圖片做keypoint detect,然後設定patch的大小,這邊設定大小為11 x 11 。
先來看一下這部分的輸出結果,從image1找到313個keypoint,從image2找到比較少keypoint共183個。
接下來要需將image1中的patch依序找出和image2裡哪一個patch最相似。
可以看到patch是以keypoint 為中心patch大小為11x11,若所選擇到的patch超出照片直接跳下一個keypoint 做matching。
選擇兩張圖要比對的patch後,使用cv::matchTemplate() 選擇類型為計算Sum of Squared Differences,而數值最小的相似度最高。
若這次計算出的比上一次計算出的數值還小,則使用 .queryIdx 和 .trainIdx 將結果儲存進BestMatch。
因為前面的步驟會選擇最相似的keypoint做match,無論在第二張圖中是否出現相同的keypoint,都會match,所以將相似度差的mtaching結果慮掉。
先使用std::nth_element()做排序,意思是第51個點(從0開始)為第51大的數字,前50個點雖然沒做排序,但可以知道前50個點均比第51個點小,所以僅選擇相似度前50佳的點標示為matching。
最後使用cv::drawMatches() 劃出matching結果就完成了,以下為模擬結果,先看左圖,matching結果大致上還算正確,只有幾條呈現傾斜的線段matching錯誤。再看到右圖,書名"Harry Potter"的部分多數都matching到別本數,人物的部分乍看下還算正確。
將結果放大來看,matching結果幾乎都是錯的,雖然都是選到人物上,但keypoint點不多,沒辦法精準的選擇到徵確的位置上。
因為上圖的效果很不理想,所以我換了一張圖,讓相似度提高一些,確實matching得到的結果卻率很高。
接下來做另一種模擬,測試template matching的效果。
因為原先的程式碼很難選定我要做matching得區域,所以我加了右圖中的程式碼,將影像和框線直接顯示出來。
接著使用cv::matchTemplate() 找尋再image2裡和選擇區域最相近的區域,計算方式一樣使用Sum of Squared Differences。
使用cv::minMaxLoc()找出輸出結果最小的值,標示為matching,最後將模擬結果顯示出來。
左圖為我所選擇的參考區域,再第二張圖中,找到的patch視覺上差異很大,但卻判定為最相似的patch,第三張圖結果就很正確,同的的選擇到人物的臉上。
我嘗試換其他照片希望可以找到一些規律,要如何選擇選擇區域,可以讓效果清楚一些。以下結果可以發現,選擇不同區域,使用cv::matchTemplate() 模擬出來的效果不穩定,第一組圖就很正確的選擇到牆上的裝飾,但第二張圖卻選擇到視覺上差異很大的patch。我認為選擇區域選擇patch內顏色差異大的,且選定物件在兩張圖中都清晰可見的效果最好。
以下我使用不同的keypoint detector做模擬,在上一次作業中有提到,每種不同的keypoint detector被發展出來的優勢,有的是為了提高精確度,有的是為了提高速度,有的是為了解決scaleing和rotation的問題,我在程式碼中加入計算時間的涵式如下,計算從翠取出keypoint到matching結束的時間,並分析比較結果。
double time = static_cast<double>(cv::getTickCount());
time = (static_cast<double>(cv::getTickCount()) - time) / cv::getTickFrequency();
std::cout << "time = " << time << "ms" << std::endl;
首先先使用FAST來偵測keypoint,參數設定如下,和前面相同,先matching較多的點,再取前50個較好的matching結果輸出。
ptrDetector = cv::FastFeatureDetector::create(80);
cv::Ptr<cv::xfeatures2d::SURF> ptrDetector = cv::xfeatures2d::SURF::create(2000.0);
cv::Ptr<cv::SIFT> ptrDetector = cv::SIFT::create(1000);
cv::Ptr<cv::BRISK> ptrDetector = cv::BRISK::create(60, 5);
cv::Ptr<cv::ORB> ptrDetector = cv::ORB::create(1000, 1.2, 8);
依時間長短做比較,需要花費的時間長短依序為:BRISK > ORB > SIFT > SURF > FAST, 時間長短落差很大。在看matching結果,沒辦法很精確的比較,但視覺上是ORB的效果最好,像是玻璃花窗的部分結果最正確。
FAST
SURF
SIFT
BRISK
ORB
以下調整不同的patch大小,match點一樣限制為50個,並分析不同大小對結果帶來的影響。隨著patch大小變大,一次考慮更多的pixel所花的時間也變長。當 nsize = 9 有一條很明顯的斜線,nsize 增加後斜線就不見了,nsize = 11 和 nsize = 13 必較,觀察人物身上的match結果可以發現隨著patch大小變大視覺上match的結果也更精準。
nsize = 9
nsize = 11
nsize = 13
我使用不同類型,用不同的計算公式來判斷相似度
cv::matchTemplate( roi, target, result, cv::TM_SQDIFF);
原圖如右圖所示,我選擇人像的作為參考區域做偵測,模擬結果如下,以計算Sum of Squared Differences和計算Sum of Squared Differences的normalization,兩張圖的結果最正確。
cv::TM_SQDIFF
cv::TM_SQDIFF_NORMED
cv::TM_CCORR
cv::TM_CCORR_NORMED
cv::TM_CCOEFF
cv::TM_CCOEFF_NORMED
SIFT和SURF 使用feature descriptor來描述keypoint周圍的特徵,本節將了解feature desriptor的原理並利用template matching、radius match、KNN matching、ratio test來實踐matching。
SIFT 使用128 dimension來描述特徵,SURF 使用64 dimension來描述特徵。造成兩中方法的feature descriptor大小不同是因為,SIFT則利用多個空間區域的梯度方向histogram,得到一個128維的feature descriptor。SURF為了加速SIFT而作改良,使用近似 Gaussan來進行關鍵點描述,來得到一個64維的feature descriptor。
SIFT 的作法是,以keypoint 為中心,取16×16大小的pixel,再平均切為4×4的cells,每個cells計算gradient 和 orientation 形成8個bins的一個Histogram,一個keypoint有16個cells會得到16個histogram,總共16×8=128維度的資料,最後針對這些資料進行L2-Normalizing,即可得到代表該keypoint的Feature vectors。
SURF會先使用近似Gaussian來提取feature,代表接近keypoint 的pixel權重比較重,接著一樣以keypoint 為中心,取16×16大小的pixel,再平均切為4×4的cells,計算gradient 和 orientation ,和SIFT不同的是,每一個cell所得到的Histogram只有4個bin,如圖所示,分別為dx, |dx|, dy, |dy|,因此一個keypoint 總共為 16x4=64維度的資料。
求出feature descriptor 後,將第一張圖的keypoint 依序和第二張圖做比較,差異最小的則為標示為 matching。
這部分主要選擇Brute-Force matcher來做matching,並測試兩件事,第一使用SURF和SIFT作為keypoint detector的差異,第二使用使用cross check 對結果的影像。
首先,先將keypoint detector 設定為SURF使用方式如下
cv::xfeatures2d::SURF::create(hessianThreshold, nOctaves = 4, nOctaveLayers = 3, extended = false, upright = false )
我將參數設定hessianThreshold = 4000其他參數使用預設值,作者原先設定的參數數值還高,因為使用原本的數值,找到的keypoint太多,做matching後畫面很雜亂,很困難判斷出match正不正確。
使用compute 計算keypoint 和 feature decriptor
接著使用 cv::BFMatcher做matching 一共跑兩次,一次未使用crosscheck一次有使用crosscheck。
Brute-Force matcher的原理是將第一張圖的keypoint 依序和第二張圖做比較,差異最小的則為標示為 matching,而crosscheck 代表雙向均執行一遍,找共同的結果。
最後使用cv::DrawMatchesFlags標示出結果,選擇NOT_DRAW_SINGLE_POINTS 和 DRAW_RICH_KEYPOINTS 只標示有matching 的點和且標示keypoint size and orientation ,線的顏色原本是白色的但效果不明顯,所以我調整了一下顏色。
模擬結果顯示,找到364個keypoint,接下來再使用SIFT重新模擬一次,參數設定為keypoint = 364,重複以上步驟,一樣使用cv::BFMatcher做matching 一共跑兩次,一次未使用crosscheck一次有使用crosscheck。
SURF
SURF with crosscheck
這部分選擇KNN matching,並使用ratio test 來提升結果的準確度。
先使用SURF分別對兩張影像偵測出keypoint。
接著選擇 knnMatch()做matching,設定k=2,意思是在圖片一中每個keypoint函式會對應到圖片二中兩個keypoint,返回兩條 match-lines。
knnMatch( InputArray1, InputArray2, matches, k, mask = noArray(), compactResult = false )
下一步帶入公式d(fa, fb1) / d(fa, fb2)計算兩點的ratio test,若計算結果數值小於ratioMax,則判定為match,若計算結果大於ratioMax 則將 fb1、fb2捨棄。
最後使用cv::drawMatches()將結果繪製出來。
模擬結果僅得到4個matches,數量和前面相比少了許多
接下來使用radius matching
使用SURF分別對兩張影像偵測出keypoint。
接著使用radiusMatch() 做matching,匹配結果須小於等於maxDist才會被判定為match。
radiusMatch( InputArray, InputArray, matches, maxDistance, mask = noArray(), compactResult = false )
最後使用cv::drawMatches()將結果繪製出來。
模擬結果僅得到342個matches
最後測試使用SIFT的效果,我將原先放在最後的程式碼複製到最前面,使用SIFT重新測試四種不同matching 方法
使用SIFT來偵測keypoint,並使用detectAndCompute()求出keypoints 和 descriptors
我將keypoint數量設定和前面相同,限制在364個keypoint
第一,使用Brute-Force matcher,並分別測試有無加加入cross check,結果如下,可以看出使用cross check後加,將一些很明顯的錯誤都消除掉了。
cv::BFMatcher matcher(cv::NORM_L2);
cv::BFMatcher matcher(cv::NORM_L2, true);
第二,使用 match(),match是使用Nearest Neighbor Matching來計算相似度,接著排序並取距離前50短的matches
第三,選擇KNN matching,並使用ratio test 來提升結果的準確度
第四,使用radius matching。
右圖為模擬結果,我使用和前面一樣的參數數值,可以看到沒有匹配到任何點,我有嘗試過將maxDist提高我甚至加大到maxDist=100,但結果仍維持一樣的結果,代表所有的匹配結果距離都很遠相似度不高。
右圖顯示是用不同方式匹配到的matches數量,從所有的模擬結果可以大致觀察到,當匹配到的matches越少,正確度越高。
先看觀察SURF的結果,未使用cross check 的結果總共matching 到364個keypoint,畫面看起來很雜亂,很難清楚辨認match結果的正確性,視覺上看起來大多數都是不正確得,再看到有使用cross check的結果偵測到48個matching結果,視覺上玻璃花窗的部分看起最正確,其他部分正確度不高。
再將SURF和SIFT做比較,SIFT設定震測到364個keypoint,未使用cross check 的結果畫面一樣很雜亂,使用cross check後偵測到119個matching結果,比SURF偵測到的多,而正確率看起來也比SIFT還高,尤其是在玻璃花窗還有樓塔上窗戶兩部分。
SURF
SURF with crosscheck
SIFT
SIFT with crosscheck
以下測試ratio test改變不同的 ratioMax 帶來的效果,及比較在相同 ratioMax 使用不同keypoint detector 的差異。
隨著ratioMax 增大matches增加,代表fb1和fb2間的距離差異變短,被判定為match 的門檻降低。使用SIFT的matches比使用SURF所呈現的matches多,且視覺上SIFT的正確度較高,我推測是因為SIFT是使用128為的feature descriptor,而SURF使用64維,所以SIFT所能呈現的結果較精確。
ratioMax = 0.6
using SIFT & ratioMax = 0.6
ratioMax = 0.5
ratioMax = 0.7
以下測試radius match改變不同的 maxDist帶來的效果,及比較在相同 maxDist 使用不同keypoint detector 的差異。
使用SURF的matches比使用SIFT所呈現的matches多,在前面也有提到,我將參數設定 maxDist = 100 結果沒改變,我推測是我選擇這兩張圖差異過大。再看到使用SURF的三張圖,隨著 maxDist 提高matches也越多,正確率提高。
maxDist = 0.3
using SIFT & maxDist = 0.3
maxDist = 0.2
maxDist = 0.4
ORB和BRISK 使用Binary descriptor來描述keypoint周圍的特徵,Binary descriptor 和 feature descriptor的差異是,binary descriptor使用binary strings可以更佳容易計算和做特徵比較。本節將了解Binary descriptor的原理及實踐matching。
Binary descriptor 的原理是先在keypoint的周圍選擇patch的範圍,接著在patch的範圍內倆倆一組比較intensity,令其中一點為S1一點為S2,若 I(S1) > I(S2) 則編碼為1,相反的I(S1) <= I(S2) 則編碼為0。接著比較每個keypoint的binary descriptor來完成matching,比較的方式是計算Normalized Hamming Distance。先從hamming distance開始說明,hamming distance是比較兩個binary descriptor在相同位置上有幾個bit數值不同,而Normalized Hamming Distance = Hamming Distance/ length of the string,是將Hamming Distance做正規化的結果。
ORB:
binary descriptor為256 維
計算binary descriptor 的採樣方式是取 optimal sampling pairs 。希望採樣點具辨識性(discriminative ),所以Sampling Pairs 須具備uncorrelated 和 high variance 兩特性,使用Greedy search找出符合這兩個特性最佳的binary descriptor。
具有 rotation invariant,實踐的方法是做rotation compensation,計算patch的質心(centroid)及主方向(main orientation)
BRISK:
binary descriptor為512 維
計算binary descriptor 的採樣方式意圖如右圖,使用Gaussian smoothing,調整standard deviation 的大小來調節patch的大小。
為了解決rotation的問題,需計算keypoint的方向,利用 sampling pairs 之間的 gradient,帶入以下公式計算
這部分主要實作ORB並選擇Brute-Force matcher來做matching。
首先先設定要使用的keypoint detector,使用ORB的方式如下:
Ptr<ORB> cv::ORB::create( nfeatures = 500, scaleFactor = 1.2f, nlevels = 8, edgeThreshold = 31, firstLevel = 0, WTA_K = 2, scoreType = ORB::HARRIS_SCORE, patchSize = 31, fastThreshold = 20)
接著使用detectAndCompute()求出keypoints 和 descriptors,並將偵測到的keypont數量和結果顯示出來
使用 cv::BFMatcher做matching 一共跑兩次,一次未使用crosscheck一次有使用crosscheck,因為是以binary descriptor 來描述特徵,所以要選擇cv::NORM_HAMMING。
接著將結果顯示出來,因為原作者使用的方法會標示出keypoint size and orientation ,我覺得畫面有點雜亂,很難看出結果的正確性,所以我多增加另一種標示matching結果的方式,用多種顏色標示出線,且僅呈現keypoint的位置。
以下為模擬結果,兩張圖均設定偵測60個keypoint,第一張圖keypoint多出現在窗戶上第二張圖keypoint則多出現在左邊塔上及圖片右下區域。
比較是否有使用cross check的結果,使用cross check後僅17個matches,雖然濾到了一些很明顯是錯誤的線,但兩張圖的結果視覺上正確率都不高。
cv::BFMatcher matcher(cv::NORM_HAMMING);
cv::BFMatcher matcher(cv::NORM_HAMMING);
cv::BFMatcher matcher(cv::NORM_HAMMING, true);
cv::BFMatcher matcher(cv::NORM_HAMMING, true);
這部分實踐BRISK,且搭配FREAK以增加精確度。FREAK 不是從影像中去提取特徵,而是從既有的特徵中去提取具辨識性(discriminative )的Sampling Pairs,從而計算binary descriptor,因此需搭配ORB或BRISK作使用。 FREAK 計算binary descriptor的方式和ORB很像,若I(S1) > I(S2) 則編碼為1,反之則編碼為0 。
首先先設定要使用的keypoint detector,使用ORB的方式如下:
static Ptr<BRISK> cv::BRISK::create(thresh = 30, octaves = 3, patternScale = 1.0f)
我將threshold設定在120,原作者設定在80,但模擬結果會匹配到太多matches,畫面過於雜亂很難判斷結果,所以我升高threshold讓keypoint數量降低。
接著使用detectAndCompute()求出keypoints 和 descriptors,並將偵測到的keypont數量和結果顯示出來
接著設定extractor計算keypoint descriptor,FREAK的使用方式如下:
cv::xfeatures2d::FREAK::create( orientationNormalized = true, scaleNormalized = true, patternScale = 22.0f, nOctaves = 4,
const std::vector< int > & selectedPairs = std::vector<int>())
使用compute 計算keypoint 和 feature decriptor
接著使用 cv::BFMatcher做matching 一共跑兩次,一次未使用crosscheck一次有使用crosscheck。因為是以binary descriptor 來描述特徵,所以要選擇cv::NORM_HAMMING。
以下為模擬結果,第一張圖keypoint多出現在窗戶上,第二張圖keypoint則多出現在左邊塔上和樓梯扶手上。
比較是否有使用cross check的結果,使用cross check後僅18個matches,雖然慮到了一些很明顯是錯誤的線,但兩張圖的結果視覺上正確率都不高。
cv::BFMatcher matcher(cv::NORM_HAMMING);
cv::BFMatcher matcher(cv::NORM_HAMMING);
cv::BFMatcher matcher(cv::NORM_HAMMING, true);
cv::BFMatcher matcher(cv::NORM_HAMMING, true);
以下調整FREAK裡的參數,改變不同的patternScale 帶來的效果。
隨著patternScale 增加matches慢慢減少,視覺上改變不明顯,但看起來正確率有提升。
patternScale = 20.0f
patternScale = 22.0f
patternScale = 25.0f
雖然正確率有提高但整體上錯誤率仍很高,剛好在查資料的時候,有看到有人有和我相同的疑問,使用BRISK搭配FREAK來增加精確度,但模擬結果還是不理想,底下有人建議可以使用再搭配coross check 和 ratio-test 提高精確度,所以以下增加ratio-test的程式碼,再重新模擬一次比較結果。
FREAK的參數設定如下,接著使用BREAK 和 ORB個模擬一次,比較結果。
cv::xfeatures2d::FREAK::create(true, true, 22.0f, 4, std::vector< int >())
cv::Ptr<cv::Feature2D> feature = cv::BRISK::create(120);
因為上圖matching 結果仍不是很正確,所以我慢慢降低threshold值,偵測出更多的keypoint點,matching效果更好。
cv::Ptr<cv::Feature2D> feature = cv::BRISK::create(100);
cv::Ptr<cv::Feature2D> feature = cv::BRISK::create(80);
因為前面由BRISK在threshold=80時於第一張圖中偵測到988個keypoint,我將keypoint detector 改為使用 ORB設定在nfeatures =988,以觀察結果。matches變少,因為在第二張圖中右邊塔上的窗戶沒有被偵測到keypoint,所以將左邊的塔和第一張圖的窗戶匹配在一起,選擇最相接近的特徵作匹配。
cv::Ptr<cv::Feature2D> feature = cv::ORB::create(988);
這次的作業很多函式在上一次作業中就使用過,所以在解讀程式碼和做一些變化的部分沒遇到甚麼困難。在模擬的時候,我一直在測試不同的參數,以觀察其對結果的影響,希望找到一組能夠提高匹配結果準確度的參數,但特別是在模擬BRISK和ORB的部分,無論我如何調整參數,都難以達到像之前使用SURF和SIFT時那樣高精確度的匹配結果。我猜想問題可能出在我所選擇的圖片上,可能是因為圖片的顏色或旋轉角度差異太大,這使得結果都不太理想。
特徵匹配 (Template Matching) , Medium
第六章 匹配方法 , 侯天宇 , CIRG2020 , 2020-11-19
help radiusmatch , Martin Huber, University of St. Gallen. , Michael Lechner, University of St. Gallen.
Week 10: Image features, feature descriptors, and feature matching
[Machine Learning] kNN分類演算法 , 白昌永(大白), LOGDUWN
Lecture 4.2 Feature matching , Trym Vegard Haavardsholm , UNIK
How does the Lowe's ratio test work? , stackoverflow
cv::DMatch Class Reference , OpenCV 4.7.0-dev , Open Source Computer Vision
Template Matching , OpenCV 4.7.0-dev , Open Source Computer Vision
Object Detection Image Processing , OpenCV 4.7.0-dev , Open Source Computer Vision
OpenCV 找出图像中最小值最大值函数minMaxLoc的使用
cv::BFMatcher Class Reference , OpenCV 4.7.0-dev , Open Source Computer Vision
cv::DrawMatchesFlags Struct Reference , OpenCV 4.7.0-dev , Open Source Computer Vision
Speeded Up Robust Features (SURF)
圖像特徵比對(二)-特徵點描述及比對 , CH.Tseng
cv::Feature2D Class Reference , OpenCV 4.7.0-dev , Open Source Computer Vision
cv::DescriptorMatcher Class Reference , OpenCV 4.7.0-dev , Open Source Computer Vision
A tutorial on binary descriptors – part 3 – The ORB descriptor , Gil's CV blog
A tutorial on binary descriptors – part 4 – The BRISK descriptor , Gil's CV blog
Visual Features: Descriptors(SIFT, BRIEF, and ORB) , Cyrill Stachniss
ORB (Oriented FAST and Rotated BRIEF) , OpenCV 4.7.0-dev , Open Source Computer Vision
ORB Descriptor, Anchit Navelkar , Ashwani Rathee , JuliaImages , 2021
ImageFeatures BRISK , Edit on GitHub
FREAK Descriptor , JuliaImages , Edit on GitHub
cv::xfeatures2d::FREAK Class Reference , OpenCV 4.7.0-dev , Open Source Computer Vision
FREAK or BRISK neither good nor faster than SIFT/SURF when using BruteForceMatcher edit , OpenCV