【影象特徵提取13】SIFT原理之KD樹+BBF演算法解析
本文轉載自:http://blog.csdn.NET/luoshixian099/article/details/47606159
繼上一篇中已經介紹了,最後得到了一系列特徵點,每個特徵點對應一個128維向量。假如現在有兩副圖片都已經提取到特徵點,現在要做的就是匹配上相似的特徵點。
相似性查詢有兩種基本方式:1.範圍查詢:即給點查詢點和查詢閾值,從資料集中找出所有與查詢點距離小於閾值的點。
2.K近鄰查詢:給點查詢點及正整數K,從資料集中找到與查詢點最近的K個數據,當K=1時,就是最近鄰查詢。
特徵匹配運算元可以分為兩類:1.窮舉法:即將資料集中的點與查詢點逐一計算距離,如果圖1提取到N1個特徵點,圖2中提取到N2個特徵點,用窮舉法匹配,要做N1×N2運算,這種方法顯然效率低下。
2.建立資料索引:對資料進行分析,對搜尋資料空間進行劃分,按劃分時是否有重疊,分為KD樹和R樹。KD樹是對空間劃分時沒有重疊的一種。
一個三維k-d樹。第一次劃分(紅色)把根節點(白色)劃分成兩個節點,然後它們分別再次被劃分(綠色)為兩個子節點。最後這四個子節點的每一個都被劃分(藍色)為兩個子節點。因為沒有更進一步的劃分,最後得到的八個節點稱為葉子節點。
KD樹的構建:KD樹是一個二叉樹,對資料空間空間進行劃分,每一個結點對應一個空間範圍。如上圖所示,三維空間的劃分方式。首先確定在資料集上對應方差最大的維度ki,並找到在ki維度上的資料集的中值kv(並作為根節點),即第一步把空間劃分成兩部分,在第ki維上小於kv的為一部分稱為左子節點,大於kv的為另外一部分對應右子節點,,然後再利用同樣的方法,對左子結點和右子節點繼續構建二叉樹,直所剩資料集為空。
舉個例子:有5個數據,每個資料都是5維,建立KD樹,A<7,5,7,3,8>;B<3,4,1,2,7>;C<5,2,6,6,9>;D<9,3,2,4,1>,E<2,1,5,1,4>,首先在計算在5個維度上的方差為6.56;2;5.36;2.96;8.56;可見在第5維度上方差最大,繼續在第5個維度上找到中值為7,即B點,在第5維度上值小於7的作為左子樹資料(A,C),大於7的作為右子樹(D,E),然後繼續在A,C,兩點上計算方差最大的維度,繼續劃分。D,E也是如此。如下圖,ki表示維度,kv表示該維度上的值。
KD樹的查詢:從根節點開始沿二叉樹搜尋,直到葉子結點為止,此時該葉節點並不一定是最近的點,但是一定是葉子結點附近的點。所以一定要有回溯的過程,回溯到根節點為止。例如:查詢與M<5,4,1,3,6>點的最近鄰點,查詢路徑為B,A,C,計算完MC的距離後,逆序向上,查詢A及A的右子樹,再次回溯B及B左子樹,最後得到最近的距離,MB點最近。
假如資料集是維數是D,一般來說要求資料的規模N需要滿足N>>2^D條件,才能達到高效的搜尋,一般來說用標準的KD樹時資料集的維數不超過20,但是像SIFT特徵描述子128為,SURF描述子為64維,所以要對現有的KD樹進行改進。
BBF:上述回溯的過程,完全是按照查詢時路徑決定的,沒有考慮查詢路徑上的資料性質,BBF(Best-Bin-First)查詢機制能確保優先包含最近鄰點的空間,即BBF維護了一個優先佇列,每一次查詢到左子樹或右子樹的過程中,同時計算查詢點在該維度的中值的距離差儲存在優先佇列裡,同時另一個孩子節點地址也存入佇列裡,回溯的過程即從優先佇列按(差值)從小到大的順序依次回溯。如上一個例子,首先把B儲存在優先佇列裡,然後開始從優先佇列裡取資料,取出B,發現要到左孩子A節點裡繼續查詢,這時,要把右孩子節點D儲存在優先佇列裡,同時加上距離屬性ki=5,kv=7,所以d=7-6=1,這時優先佇列裡簡記為D(1);同理,如果A有右孩子,也要存入優先佇列,加上屬性ki=2,kv=5,d=5-4=1;(例子不太恰當,o(╯□╰)o),回溯的過程是按照優先佇列的距離逐個回溯,直到優先佇列為空,或者超時,停止;BBF設定了超時機制,為了在高維資料上,滿足檢索速度的需要以精度換取時間,獲得快速查詢。這樣可知,BBF機制找到的最近鄰是近似的,並非是最近的,只能說是離最近點比較近而已。超時機制在演算法的實現上,限定了從優先佇列中提取資料的次數。
下面從演算法上解析:
構建KD樹:
[cpp] view plain copy print?- struct kd_node* kdtree_build( struct feature* features, int n )//features為特徵帶你,n為個數
- {
- struct kd_node* kd_root;
- if( ! features || n <= 0 )
- {
- fprintf( stderr, "Warning: kdtree_build(): no features, %s, line %d\n",
- __FILE__, __LINE__ );
- return NULL;
- }
- kd_root = kd_node_init( features, n ); //建立根節點,每次建立一個節點存入一個特徵點
- expand_kd_node_subtree( kd_root );//以根節點開始擴充套件KD樹
- return kd_root;
- }
- staticstruct kd_node* kd_node_init( struct feature* features, int n )
- {
- struct kd_node* kd_node;
- kd_node = malloc( sizeof( struct kd_node ) );
- memset( kd_node, 0, sizeof( struct kd_node ) );
- kd_node->ki = -1; //屬性ki初始化為1
- kd_node->features = features;//指向特徵點
- kd_node->n = n; //節點屬性n儲存以kd_node為根的樹上總節點數
- return kd_node;
- }
- staticvoid expand_kd_node_subtree( struct kd_node* kd_node ) //遞迴法建立KD樹
- {
- /* base case: leaf node */
- if( kd_node->n == 1 || kd_node->n == 0 ) //如果剩下一個節點,成為葉子節點
- {
- kd_node->leaf = 1;
- return;
- }
- assign_part_key( kd_node ); //計算最大方差的對應的維數,ki和kv
- partition_features( kd_node );//按第ki維的資料大小分成左子樹資料和右子樹的資料
- if( kd_node->kd_left ) //繼續構建左子樹
- expand_kd_node_subtree( kd_node->kd_left );
- if( kd_node->kd_right )//繼續構建右子樹
- expand_kd_node_subtree( kd_node->kd_right );
- }
[cpp] view plain copy print?
- staticvoid assign_part_key( struct kd_node* kd_node ) //計算節點資料的最大方差對應的維數ki,和中值kv
- {
- struct feature* features;
- double kv, x, mean, var, var_max = 0;
- double* tmp;
- int d, n, i, j, ki = 0;
- features = kd_node->features;
- n = kd_node->n;
- d = features[0].d;
- /* partition key index is that along which descriptors have most variance */
- for( j = 0; j < d; j++ ) //計算d維資料上,所有維數上的方差。
- {
- mean = var = 0;
- for( i = 0; i < n; i++ )
- mean += features[i].descr[j];
- mean /= n;
- for( i = 0; i < n; i++ )
- {
- x = features[i].descr[j] - mean;
- var += x * x;
- }
- var /= n; //計算第j維的資料的方差
- if( var > var_max )
- {
- ki = j;
- var_max = var;
- }
- }
- /* partition key value is median of descriptor values at ki */
- tmp = calloc( n, sizeof( double ) );
- for( i = 0; i < n; i++ ) //取得所有資料上第ki維上的資料
- tmp[i] = features[i].descr[ki];
- kv = median_select( tmp, n ); //找到第ki維度上中間的值,這裡採用了最壞情況執行時間O(n)的選擇演算法
- free( tmp );
- kd_node->ki = ki; //維度
- kd_node->kv = kv; //中間值
- }
[cpp] view plain
相關推薦
【影象特徵提取13】SIFT原理之KD樹+BBF演算法解析
本文轉載自:http://blog.csdn.NET/luoshixian099/article/details/47606159 繼上一篇中已經介紹了,最後得到了一系列特徵點,每個特徵點對應一個128維向量。假如現在有兩副圖片都已經提取到特徵點,現在要做
【影象特徵提取2】區域性二值模式LBP----從原理到實踐
(一)區域性二值模式LBP的簡介 LBP(Local Binary Pattern,區域性二值模式)是一種描述影象區域性紋理的特徵運算元,該運算元是由T.Ojala等人於1994年
【影象特徵提取7】SURF特徵提取演算法的
本文大量參考了:http://blog.csdn.net/cxp2205455256/article/details/41311013;並且在此部落格的基礎之上,增加了一些新的內容。 一、SURF演算法的概述 SURF,英文的全稱為Speed Up Ro
【影象特徵提取3】區域性二值模式LBP特徵描述符C++程式碼的實現
/******************************************************************************************************** 檔案說明: 經典LBP特徵的C++程式碼實現
【特徵匹配】SIFT原理與C原始碼剖析
SIFT的原理已經有很多大牛的部落格上做了解析,本文重點將以Rob Hess等人用C實現的程式碼做解析,結合程式碼SIFT原理會更容易理解。一些難理解點的用了☆標註。 歡迎大家批評指正! 轉載請註明出處:http://blog.csdn.net/l
經典演算法研究系列 九 影象特徵提取與匹配之SIFT演算法
經典演算法研究系列:九、SIFT演算法研究作者:July、二零一一年二月十五日。推薦閱讀:David G. Lowe, "Distinctive image features from scale-invariant keypoints," Internationa
影象特徵提取(七)——ORB特徵原理
ORB演算法的論文來自"ORB: an efficient alternative to SIFT or SURF",作者是OpenCV維護和開發的公司willowgarage的,論文名字起的很牛氣,摘要裡說,ORB演算法比sift演算法效率高
利用RobHess原始碼實現SIFT演算法及RANSAC去錯的影象特徵提取匹配及去除錯匹配
本文是在VS2010+Opencv2.4.9環境下實現! 首先下載RobHess利用opencv實現SIFT演算法原始碼,在配置好opencv環境的vs2010中實現SIFT特徵提取、匹配,在利用K-D樹、BBF和RANSAC去除錯誤匹配,實驗結果如圖: 去
影象金字塔(pyramid)與 SIFT 影象特徵提取(feature extractor)
0. 影象金字塔變換(matlab) matlab 對影象金字塔變換介面的支援(impyramid),十分簡單好用。 其支援在reduce和expand兩種方式的變換,分別是成比例的縮小和放大。
經典演算法研究系列:九、影象特徵提取與匹配之SIFT演算法
經典演算法研究系列:九、SIFT演算法研究作者:July、二零一一年二月十五日。推薦閱讀:David G. Lowe, "Distinctive image features from scale-invariant keypoints," Internation
影象特徵提取與匹配之SIFT演算法
推薦閱讀:David G. Lowe, "Distinctive image features from scale-invariant keypoints," International Journal of Computer Vision, 60, 2 (2004),
影象特徵檢測描述(一):SIFT、SURF、ORB、HOG、LBP特徵的原理概述及OpenCV程式碼實現
什麼叫特徵檢測?就是檢測影象中目標的特徵唄,所謂特徵,不管你怎麼旋轉目標,離目標遠近,它的特徵都應不變才對,這兩個特性稱為叫旋轉不變性和尺度不變性。當然還有其它特徵,如光照不一樣,也不應該變化嘛,只是旋轉不變性和尺度不變性是最基本的兩個要求。 對特徵的描述有很多種方法和運算
解析京東大資料下高效影象特徵提取方案
本文主要分享英特爾和京東在基於Spark和BigDL的深度學習技術在搭建大規模圖片特徵提取框架上的實戰經驗。 背景 影象特徵提取被廣泛地應用於相似圖片檢索,去重等。在使用BigDL框架(下文即將提到)之前,我們嘗試過在多機多GPU卡、GPU叢集上分別開發並部署特徵抽取應用。但以上框架
影象特徵提取 by OpenCV
SITF特徵提取和描述 影象的區域性特徵,對旋轉、尺度縮放、亮度變化保持不變,對視角變化、仿射變換、噪聲也保持一定程度的穩定性。 獨特性好,資訊量豐富,適用於海量特徵庫進行快速、準確的匹配。 多量性,即使是很少幾個物體也可以產生大量的SIFT特徵 高速性,經優化的SIFT
【機器學習筆記13】聚類(高斯混合聚類)
【參考資料】 【1】《統計學習方法》 【2】《概率論與數理統計》 【3】小象學院 EM演算法 高斯分佈 定義: 如果隨機變數X的概率密度為f(x)=12πσe−(x−u)22σ2f(x)= \dfrac{1}{\sqrt{2\pi}\sigma}e^{-\df
Matlab 影象特徵提取
在影象處理過程中,尤其是影象相似度的匹配,在圖片量比較小的情況下,深度學習的效果往往達不到期望,所以需要利用傳統影象處理的方法,對影象特徵進行提取,常用的方法有lbp,hog,sift,surf。 lbp演算法主要是對圖片紋理特徵進行提取,一旦圖片旋轉,平移或者縮放,所提取
初識OpenCV 練習筆記整理--學習六。【影象的算術運算】
""" 學習內容: 影象的算術運算 目標: 學習影象上的算術運算,加法,減法,位運算等。 學習的函式有:cv2.add(), cv2.addWeighted() """ # 第一小節 影象的加法,使用函式cv2
初識OpenCv 練習筆記整理--學習五。【影象的基礎操作】
""" 核心操作 影象的基礎操作 目標: 獲取畫素值並修改 獲取影象的屬性(資訊) 影象的ROI() 影象通道的拆分以及合併 """ # 第一小節 獲取並修改畫素值 2018/10/25 13:46 import cv2 i
影象特徵提取:HOG特徵
方向梯度直方圖(Histogram of Oriented Gradient, HOG)特徵是用於影象檢測的特徵描述子。它通過計算和統計區域性區域的梯度方向直方圖來構成特徵。特徵地,HOG在行人檢測方向取得巨大成功。 演算法實現過程: (1)標準化gamma空間和顏色空間
影象特徵提取三大法寶:HOG特徵,LBP特徵,Haar特徵
(一)HOG特徵 1、HOG特徵: 方向梯度直方圖(Histogram of Oriented Gradient, HOG)特徵是一種在計算機視覺和影象處理中用來進行物體檢測的特徵描述子。它通過計算和統計影象區域性區域的梯度方向直方圖來構成特徵。Hog特徵結合SVM分