首页 > 解决方案 > 如何用单个元素替换 2d numpy 数组中重复的连续元素

问题描述

我有一个 numpy 形状数组(1080,960)

[[0 0 255 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 255 0 0]
 ...
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 255 255 ... 0 0 0]]

我想输出一个 numpy 数组,用单个 0 和单个 255 替换 0 和 255 的重复值

numpy 数组是二进制图像的表示形式,其像素格式为 BBBWWWWWWWBBBBWWW,其中 B 为黑色,W 为白色。我想把它转换成BWBW。

示例

输入:

[[0,0,0,255,255,255,0,0,0,0],
 [255,255,255,0,0,0,255,255,255],
 [0,0,255,0,0,255,0,0,255]]

输出:

[[0,255,0],
 [255,0,255]
 [0,255,0,255,0,255]]

标签: pythonarraysnumpyreplace

解决方案


您不能输出 2D numpy 数组,因为输出行可能有不同的长度。我会满足于一个 numpy 数组的列表。所以首先让我们生成一些数据:

img = np.random.choice([0,255], size=(1080, 960))

然后遍历每一行:

out=[]
for row in img:
    idx=np.ediff1d(row, to_begin=1).nonzero()[0]
    out.append(row[idx])

通过获取差异,我们只是检测发生变化的位置,然后使用这些索引idx来选择连续条纹中的起始元素。这个解决方案比@DavidWinder 的解决方案更简单更快(30 毫秒对 150 毫秒)。

完全矢量化的解决方案可能会更快一些,但代码会有点复杂。这将涉及展平数组、分解和分解索引......并np.split在最后应用,这不是一个非常快速的操作,因为它涉及创建一个列表。所以我认为这个答案在速度/代码简单性之间已经足够好。

编辑#1

如果首选输出是一个最后用 0 填充的数组,则最好创建一个 zeros 数组并用outlist 的值填充它。首先找出哪一行有更多的元素,并创建数组:

max_elms = np.max([len(x) for x in out])
arr = np.zeros((1080, max_elms), dtype=np.int32)

然后遍历outlist 和,用list 中的arr值填充 的值:arrout

for row, data in zip(arr, out):
    row[:len(data)] = data

推荐阅读