【发布时间】:2014-02-13 20:48:21
【问题描述】:
我从 1024x1024 显微镜图像的 z 堆栈中识别出许多轮廓对象。每个 z 步包含大约 10000-40000 个轮廓。轮廓平均为 4 像素。
我要做的是确定多个 z 平面上存在哪些轮廓(当图像重叠时它们相互接触)以及它们的 3 维区域是什么。我可以(大约)完成此操作,但代码非常慢且内存非常重(我正在使用 32GB RAM 的计算机)。
我目前的做法如下:
将每个轮廓的所有内部点转储到一个庞大的列表中,并制作一个索引列表与之相伴。
-
对 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 重新索引原始列表以确定哪些点在 Z 步中匹配。
确定音量。
我主要对第 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