我将分割图像作为唯一标签1 ... k的二维矩阵。例如:
img =
[1 1 2 2 2 2 2 3 3]
[1 1 1 2 2 2 2 3 3]
[1 1 2 2 2 2 3 3 3]
[1 4 4 4 2 2 2 2 3]
[4 4 4 5 5 5 2 3 3]
[4 4 4 5 5 6 6 6 6]
[4 4 5 5 5 5 6 6 6]
我正在尝试确定区域质心。也就是说,每个标签,质心的X,Y坐标是多少?例如,标签1的质心是(1.25,0.625)。只需将行号((0 + 0 + 1 + 1 + 1 + 2 + 2 + 3) / 8 = 1.25
)和列号((0 + 0 + 0 + 0 + 1 + 1 + 1 + 2) / 8 = 0.625
)
我知道如何做到这一点的唯一方法是使用1到k的for循环(或者在我的例子中,1到6),找到每个标签的点的索引,并平均它们的坐标通过索引图像的网格网格。
但是,我希望以针对GPU计算优化的方式执行此操作。因此,for循环的使用不太理想(对于几百个标签,在一个漂亮的GPU上每个图像大约需要1秒)。我正在使用PyTorch,但实际上任何numpy解决方案都应该足够了。
是否有针对此任务的GPU高效解决方案?
答案 0 :(得分:1)
这个计算需要积累,我不知道GPU上的效率如何。这是伪代码中的顺序算法:
int n[k] = 0
int sx[k] = 0
int sy[k] = 0
loop over y:
loop over x:
i = img[x,y]
++n[i]
sx[i] += x
sy[i] += y
for i = 1 to k
sx[i] /= n[i]
sy[i] /= n[i]
当然,(sx[i],sy[i])
是对象i
的质心。
在CPU上运行速度非常快,为此将数据发送到GPU是不值得的,除非它已经存在。
答案 1 :(得分:1)
考虑使用scikit-image或重复使用code(基于numpy / scipy)。
这是一个演示:
import numpy as np
from skimage import measure
from time import perf_counter as pc
img = np.array([[1, 1, 2, 2, 2, 2, 2, 3, 3],
[1, 1, 1, 2, 2, 2, 2, 3, 3],
[1, 1, 2, 2, 2, 2, 3, 3, 3],
[1, 4, 4, 4, 2, 2, 2, 2, 3],
[4, 4, 4, 5, 5, 5, 2, 3, 3],
[4, 4, 4, 5, 5, 6, 6, 6, 6],
[4, 4, 5, 5, 5, 5, 6, 6, 6]])
# assuming already labels of 1, 2, ... n
times = [pc()]
props = measure.regionprops(img)
times.append(pc())
for i in range(np.unique(img).shape[0]):
print(props[i].centroid)
times.append(pc())
print(np.diff(times))
输出:
(1.25, 0.625)
(1.5555555555555556, 4.4444444444444446)
(1.8999999999999999, 7.4000000000000004)
(4.3636363636363633, 1.1818181818181819)
(5.1111111111111107, 3.6666666666666665)
(5.4285714285714288, 6.7142857142857144)
[ 9.05569615e-05 8.51235438e-04 2.48126075e-04 2.59294767e-04
2.42692657e-04 2.00734598e-04 2.34542530e-04]
答案 2 :(得分:1)
一个想法是使用bincount
来累积每个区域的行和列索引,使用输入数组中的数字作为bin,因此有一个矢量化解决方案,如下所示 -
m,n = a.shape
r,c = np.mgrid[:m,:n]
count = np.bincount(a.ravel())
centroid_row = np.bincount(a.ravel(),r.ravel())/count
centroid_col = np.bincount(a.ravel(),c.ravel())/count
示例运行 -
In [77]: a
Out[77]:
array([[1, 1, 2, 2, 2, 2, 2, 3, 3],
[1, 1, 1, 2, 2, 2, 2, 3, 3],
[1, 1, 2, 2, 2, 2, 3, 3, 3],
[1, 4, 4, 4, 2, 2, 2, 2, 3],
[4, 4, 4, 5, 5, 5, 2, 3, 3],
[4, 4, 4, 5, 5, 6, 6, 6, 6],
[4, 4, 5, 5, 5, 5, 6, 6, 6]])
In [78]: np.c_[centroid_row, centroid_col]
Out[78]:
array([[ nan, nan],
[ 1.25, 0.62], # centroid for region-1
[ 1.56, 4.44], # centroid for region-2
[ 1.9 , 7.4 ], # centroid for region-3 and so on.
[ 4.36, 1.18],
[ 5.11, 3.67],
[ 5.43, 6.71]])