八叉樹及K D樹的應用和實現

2021-06-19 08:46:42 字數 2599 閱讀 5865

1. 八叉樹、k-d樹的原理

2. 八叉樹、k-d樹的應用、優缺點

3. 八叉樹、k-d樹的實現

八叉樹和k-d樹都經常用來處理三維空間資料,k-d樹的使用範圍更寬泛些,適用於k維空間的資料,在sift演算法中,k-d樹被用於在k維的空間內搜尋鄰近特徵點。

1. 八叉樹、k-d樹的原理

wiki或百科上面都有詳細的介紹。

八叉樹,乙個立方體等分為八份,並可以持續的細分下去,雖然每個節點都能分出八個叉,但形象,且等分空間,簡單容易理解。我曾經應用八叉樹來離散化乙個三角片表示的曲面,離散曲面。

單看下面的k-d樹的圖示,就讓人眼暈了,雖然k-d樹只有兩個叉。眼暈的主要原因就是空間不等分。所以,只要理解k-d樹劃分空間的依據,剩下的細節都與八叉樹類似了。其實k-d樹葉可以有均分的模式,只要讓劃分依據變為node的中心點就行了,只不過這樣做k-d的效率就不高了。

從下圖看,其k-d每個節點劃分的依據是 挑選乙個維度,在這個維度上 找到 本節點內所有點的中值點,然後,進行劃分。

k-d樹的其他劃分依據: 

取本節點內所有點的重心。

均分法。

使用這些方法時,要注意建樹時的終止條件,避免陷入無限的迴圈(或遞迴)中。

2. 八叉樹、k-d樹的應用、優缺點

八叉樹一般都用於三維空間,若二維空間,可以用四叉樹,原理是一模一樣的。八叉樹,常用於離散化空間,資料劃分儲存,資料查詢等。

k-d樹雖然是二叉樹,卻適用於k維的空間,而且在k鄰域查詢時,比較有優勢。k-d也長用於資料劃分儲存,鄰域查詢等。

二者特性的比較:

八叉樹演算法的演算法實現簡單,但大資料量點雲資料下,其使用比較困難的是最小粒度(葉節點)的確定,粒度較大時,有的節點資料量可能仍比較大,後續查詢效率仍比較低,反之,粒度較小,八叉樹的深度增加,需要的記憶體空間也比較大(每個非葉子節點需要八個指標),效率也降低。而等分的劃分依據,使得在資料重心有偏斜的情況下,受劃分深度限制,其效率不是太高。

k-d在鄰域查詢上比較有優勢,但在大資料量的情況下,若劃分粒度較小時,建樹的開銷也較大,但比八叉樹靈活些。在小資料量的情況下,其搜尋效率比較高,但在資料量增大的情況下,其效率會有一定的下降,一般是線性上公升的規律。

也有將八叉樹和k-d樹結合起來的應用,應用八叉樹進行大粒度的劃分和查詢,而後使用k-d樹進行細分,效率會有一定的提公升,但其搜尋效率變化也與資料量的變化有乙個線性關係。

3. 八叉樹、k-d樹的實現

採用遞迴的方式,**比較簡單,邏輯明了,前提是對遞迴不要太陌生。

網上有很多octree的實現和庫。如

opencv中的也有octree的實現

octree建樹的邏輯:

自定義哪些資料型別? 

tree型別,node型別;

每個節點應該包含哪些資料? 

8個子節點指標,本節點的中心(劃分與搜尋的依據)和半徑,點的個數,和子節點儲存資料的容器

常用的手法是非葉子節點的點的個數為0,容器內無資料

如何劃分資料?如何建立索引?

每個節點都會儲存自己的中心座標和半徑,子節點儲存資料,非子節點一般不儲存資料,有了中心半徑和本節點內的資料,就能劃分建樹,或者搜尋

buildtree(資料集, 資料個數, 中心,半徑,當前深度)         // 遞迴建樹函式

確定遞迴停止條件和動作,count < num_threshold 或 遞迴深度達到最大 時,為子節點

並儲存子節點資料和個數

若無中心和半徑,計算資料集的最小包圍盒半徑和中心

依據中心和半徑,將資料劃分為八份,計算八個子節點的中心和半徑

進行新的八次遞迴建樹 child[i]->buildtree(新的資料集,新的資料個數,新的中心、半徑,深度+1).

刪除臨時資料容器,釋放記憶體

search(point)

確定遞迴停止條件:子節點的個數為小於閾值,或遞迴深度達到最大

搜遍本節點內的資料,查詢給定的點,若找到,返回true,找不到,返回false

取本節點的中心和半徑,計算出應該在下一層那個子節點進行搜尋,如k

子節點遞迴搜尋,child[k]->search(point);

k-d樹的邏輯:

自定義資料型別?

tree: 提供建樹和搜尋的介面

node節點,node節點裡包含中心,半徑,劃分的維度,兩個子節點指標,資料容器(子節點專用)

如何劃分資料?

每個node計算資料的包圍盒,每個維度的寬度,最大寬度的維度用於劃分,計算中心(重心法,或排序中值法),然後子節點繼續劃分

build()

確定遞迴停止條件,本節點資料點數小於閾值,或達到最大深度,為子節點,儲存資料。

由本節點的資料,計算包圍盒,每個維度的寬度,最大寬度的維度用於劃分計算中心(重心法,或排序中值法),然後劃分資料

子節點由劃分的資料繼續下一步的劃分建樹child[i]->build()

最鄰近點搜尋,遞迴法:

find_closest_point(point)

確認本節點是子節點,停止遞迴,計算本節點內最鄰近的點,及距離d。

若非子節點:

若距離分割面是非正數,在子節點1中搜尋。

八叉樹及K D樹的應用和實現

1.八叉樹 k d樹的原理 2.八叉樹 k d樹的應用 優缺點 3.八叉樹 k d樹的實現 八叉樹和k d樹都經常用來處理三維空間資料,k d樹的使用範圍更寬泛些,適用於k維空間的資料,在sift演算法中,k d樹被用於在k維的空間內搜尋鄰近特徵點。1.八叉樹 k d樹的原理 wiki或百科上面都有...

KD樹的C 實現

kd樹 k dimension tree 是一種對k維空間中的例項點進行儲存以便對其進行快速檢索的樹形資料結構。kd樹是是一種二叉樹,表示對k維空間的乙個劃分,構造kd樹相當於不斷地用垂直於座標軸的超平面將k維空間切分,構成一系列的k維超矩形區域。kd樹的每個結點對應於乙個k維超矩形區域。利用kd樹...

KNN的實現 KD樹

實現knn時,主要考慮的問題是如何對訓練資料進行快速近鄰搜尋.這點在特徵空間的維數大及訓練資料容量大時尤其必要.knn最簡單的實現方法是線性掃瞄 linear scan 這時要計算輸入例項與每乙個訓練例項的距離.當訓練集很大時,計算非常耗時,這種方法是不可行的.為了提高knn搜尋的效率,可以考慮使用...