单链路聚类

时间:2011-10-20 04:04:53

标签: python opencv cluster-analysis

我正在寻找一种与OpenCV进行单链路聚类的方法。我的情景:

  • 数百个(可能是数千个)特征向量(向量维度最多可达~800个特征)。
  • 未知数量的聚类(可能远低于向量数量)。
  • 固定相似度阈值E - 如果两个向量之间的l1范数小于E,则向量应位于同一群集中。
  • 我不需要群集紧凑。也就是说,我不需要集群中的所有向量都在彼此的E之内。这可能导致长链“而不是簇”,但我对此很好。

我尝试使用K-means,但因为我不知道群集的数量,所以这里并不适用。我可以做迭代的K-means并寻找最好的K,但听起来效率低下。我可以在这里使用OpenCV中实现更合适的聚类算法吗?

理想情况下,我需要类似于SLINK algorithm的内容,因为这是我目前正在尝试实施的文章中引用的内容。我的选择是直接实现SLINK(一些任务,因为调试和测试)或寻找一个类似的现有算法。

有什么建议吗?

2 个答案:

答案 0 :(得分:2)

我建议按相似度阈值构建图表并找到connected components。构建图形后,查找连接的组件将非常简单有效。如果您希望NetworkX已有连接的组件function

答案 1 :(得分:0)

我最终自己做了一个实现:

import cv
def main():
    import sys
    x = cv.Load(sys.argv[1])
    epsilon = float(sys.argv[2])
    y = cv.CloneImage(x)
    labels = range(x.height)
    tmp = cv.CreateImage((x.width, 1), x.depth, x.nChannels)
    for i in range(x.height):
        cv.SetImageROI(x, (0, i, x.width, 1))
        for j in range(i+1, x.height):
            cv.SetImageROI(y, (0, j, x.width, 1))
            cv.AbsDiff(x, y, tmp)
            dist, _, _, _ = cv.Avg(tmp)
            if dist < epsilon:
                for k, lbl in enumerate(labels):
                    if lbl == j:
                        labels[k] = i

    for i, lbl in enumerate(labels):
        print i, lbl

if __name__ == '__main__':
    main()

x是包含N x M个向量的N矩阵。向量的维数为M。它基本上使用L1范数比较每对向量,并且如果它们的差异小于epsilon则认为一对是相同的。这个算法很慢--- O(N^3),但现在对我来说已经足够了。