OpenCV / numpy:使用numpy快速比较大量轮廓对象

时间:2014-02-13 20:48:22

标签: python arrays opencv numpy

我有一些由1024 x 1024显微镜图像的z堆栈识别的轮廓对象。每个z步骤包含大约10000-40000个轮廓。轮廓平均为4像素。

我要做的是确定多个z平面上存在哪些轮廓(当图像重叠时它们彼此接触)以及它们的三维区域是什么。我可以完成这个(大约)但是代码非常慢并且内存非常重(我正在使用32GB RAM计算机)。

我目前的做法如下:

  1. 将每个轮廓的所有内部点转储到一个庞大的列表中,并制作一个索引列表。

  2. 对x和y进行二进制比较,例如:

    x_intersections=np.array(np.equal(np.matrix(z1[:,0]).T,z2[:,0]))
    y_intersections=np.array(np.equal(np.matrix(z1[:,1]).T,z2[:,1]))
    intersections=x_intersections*y_intersections
    
  3. 重新索引到原始列表,以确定哪些点在Z步骤中匹配。

  4. 确定音量。

  5. 我对第2步感到好奇,这是一种更快的方法吗?我尝试使用稀疏数组或使用np.in1d()一次运行一个轮廓,但似乎运行速度都不快。我之前尝试过内置点对比工具的OpenCVs,它看起来并不是很快。

    另外,有没有办法不必将40000x40000矩阵拉入RAM(因为需要大量的RAM)是否有合理而快速的方法来对这些列表进行分段?是否有一种聪明的方法来使用numpy来同时操作数组的某些部分而不是整个数组?有没有一种有效的方法暂时从RAM转储到磁盘上?这样我就可以在更多的计算机上同时运行它,大大减少了运行时间。

    这是一个可以从numba的AutoJIT中受益的问题吗?还是Blaze?还是pypy?是否有一个我不知道的类似工具可以在这里工作?

    更广泛地说,我在这里做些蠢事吗?我的方法是错误的方法来解决这个问题吗?

    我有时会看到20个z步,3个通道和100多个图像,所以即使每次比较花费10秒钟的代码也会最终花费每个图像一小时(我现在所处的位置)。我可以将它传播到一些服务器上以加快速度,但我真的希望尽可能地降低它。

    这是一些用于模拟大致情况的python代码:

    z1=[]
    i=0
    while i<20000:
        temp=np.array([[[1,1]],[[1,2]],[[2,1]],[[2,2]]])+np.round(np.random.rand(1,1,2)*1024)
        z1.append(temp.astype(int))
        i+=1
    z2=z1[1:10000]
    i=0
    while i<10000:
        temp=np.array([[[1,1]],[[1,2]],[[2,1]],[[2,2]]])+np.round(np.random.rand(1,1,2)*1024)
        z2.append(temp.astype(int))
        i+=1
    random.shuffle(z2)
    

    (我的轮廓不是全长4,有些更少,但这应该足够接近演示)

    然后我用大概代码将它们转储为数组:

    output=(0,0)
    index_list=(0,0)
    for itemsN,items in enumerate(z1):
        output=np.vstack([output,items.squeeze()])
        index_list=np.vstack([index_list,np.ones((len(items),1))*itemsN])
    output=np.delete(output,0,0)
    index_list=np.delete(index_list,0)
    

    然后我使用上面在步骤2中列出的代码将列表一起转换(这是一个很慢的部分,是一个巨大的内存占用,如果你运行它可能会导致内存错误)并使用索引列表找出属于一起的轮廓对。

1 个答案:

答案 0 :(得分:3)

以下是一些建议(基于我对您的问题的理解。如果这不是您想要的,请告诉我。)

  1. 要比较两个轮廓,可以在OpenCV中使用cv2.matchShapes()函数。
  2. 或者你可以计算所有轮廓的一些特征,如面积,周长,质心等。然后先比较它们。只有匹配时,才能比较整个轮廓。具有相同质心和面积的两个轮廓很可能是相同的轮廓,因此您可以将这些轮廓作为一个整体进行比较,其他您可以忽略的轮廓将为您提供一些加速。