【问题标题】:OpenCV/numpy: Quickly comparing a large number of contour objects using numpyOpenCV/numpy:使用numpy快速比较大量轮廓对象
【发布时间】:2014-02-13 20:48:21
【问题描述】:

我从 1024x1024 显微镜图像的 z 堆栈中识别出许多轮廓对象。每个 z 步包含大约 10000-40000 个轮廓。轮廓平均为 4 像素。

我要做的是确定多个 z 平面上存在哪些轮廓(当图像重叠时它们相互接触)以及它们的 3 维区域是什么。我可以(大约)完成此操作,但代码非常慢且内存非常重(我正在使用 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. 确定音量。

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

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

这个问题会从 numba 的 AutoJIT 中受益吗?还是烈焰?还是皮皮?有没有我不知道的类似工具可以在这里工作?

更广泛地说,我在这里做了什么傻事吗?我的方法是不是解决这个问题的错误方法?

我有时有 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,有些多有些少,但这应该足够接近demo了)

然后我通过近似代码将它们转储为数组:

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 步中列出的代码将列表组合在一起(这是速度慢且占用大量内存的部分,如果运行它可能会导致内存错误)并使用索引列表找出属于一起的轮廓对。

【问题讨论】:

    标签: python arrays opencv numpy


    【解决方案1】:

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

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

    【讨论】:

    • 这项工作我比较了质心以将列表预排序为更小的子集,然后再逐像素进行比较。谢谢!
    猜你喜欢
    • 2023-04-04
    • 2022-01-23
    • 2016-08-11
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 2018-09-29
    • 1970-01-01
    • 2015-04-04
    相关资源
    最近更新 更多