簡體   English   中英

最近點算法|怎么改進呢?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM