[英]Closest point algorithm | How to improve it?
我寫了一個k-means聚類算法和一個顏色量化算法。 它們在結果方面按預期工作,但我想讓它們更快。 在兩個實現中,我需要解決一個問題:3D空間中有兩個點陣列,然后對於第一個陣列的每個點,您需要找到距離第二個陣列最近的點。 我是這樣做的:
size_t closest_cluster_index;
double x_dif, y_dif, z_dif;
double old_distance;
double new_distance;
for (auto point = points.begin(); point != points.end(); point++)
{
//FIX
//as suggested by juvian
//K = 1
if (point != points.begin())
{
auto cluster = &(clusters[closest_cluster_index]);
r_dif = cluster->r - point->r;
g_dif = cluster->g - point->g;
b_dif = cluster->b - point->b;
new_distance = r_dif * r_dif + g_dif * g_dif + b_dif * b_dif;
if (new_distance <= std::sqrt(old_distance) - ColorU8::differenceRGB(*(point - 1), *point))
{
old_distance = new_distance;
//do sth with closest_cluster_index;
continue;
}
}
//END OF FIX
old_distance = std::numeric_limits<double>::infinity();
for (auto cluster = clusters.begin(); cluster != clusters.end(); cluster++)
{
x_dif = cluster->x - point->x;
y_dif = cluster->y - point->y;
z_dif = cluster->z - point->z;
new_distance = x_dif * x_dif + y_dif * y_dif + z_dif * z_dif;
if (new_distance < old_distance)
{
old_distance = new_distance;
closest_cluster_index = cluster - clusters.begin();
}
}
//do sth with: closest_cluster_index
}
我怎樣才能改進它? (我不想讓它多線程或由GPU計算)
有效的最近鄰居查詢有多種數據結構。 對於3d, kdtree工作得很好,並且平均每個查詢的復雜度為O(log n),這將改善您當前的O(n)。
因此,使用此結構,您可以將所有點從群集添加到它,然后對於每個點的點,您可以使用該結構查詢最近的點。 對於您的特定情況,靜態kdtree就足夠了,因為您不需要更新點。
另一種方法 :
我們可以嘗試冒險在某些點上進行額外的計算,以換取其他點上的更少。 這種方法應該適用於以下假設:
我認為這些適用於您的情況,因為您的聚類很少顏色,而您的點來自真實圖像,相鄰像素之間的顏色往往相似。
對於每個點,創建一個堆。 而不是存儲最近的集群,而是在最大堆中存儲最接近的k個集群。 當您轉到下一點時,我們可以使用此信息。 讓我們稱這個點P及其第k個最近的聚類C.
現在換一個新點P2,在與所有集群比較之前,我們將檢查最接近P2的集群是否在我們的堆中。 只有當堆中的任何簇與P2之間的距離<=距離(P,C) - 距離(P,P2)時,才會出現這種情況。 當這成立時,我們只能檢查堆而不是所有簇。 當它不是真的時,我們將比較所有並重建我們的堆,P將是P2。
您需要嘗試不同的k值才能看出它是否有所改善。 對於K = 2的情況,可能值得避免增加堆的復雜性並且只使用變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.