我将两个图像加载到两个numpy数组中。我想得到它们的区别,并删除小于50的值,并将其其余部分设置为255,最终得到黑白图像的结果。
def count(base, image):
x, y, z = base.shape
sheet = np.zeros(base.shape)
for i in range(x):
for j in range(y):
temp = 0
for k in range(z):
if base[i, j, k] > image[i, j, k]:
t = base[i, j, k] - image[i, j, k]
if t > 50:
temp = 255
else:
t = image[i, j, k] - base[i, j, k]
if t > 50:
temp = 255
sheet[i, j] = [temp, temp, temp]
array = sheet[:, :, 0]
此代码执行了我需要执行的操作。但是如您所见,我为此功能使用了最简单的for循环,并且图像的大小为2000 * 2000,因此处理时间很长。我需要一种以更快的方式重写它的方法。
谢谢
答案 0 :(得分:3)
向量化代码看起来很简单,除了一个陷阱:您的数据似乎是无符号的整数(从外观上看uint8
),这需要额外的注意,因为它们经常下溢而产生意想不到的结果。例如,明显的np.abs(image-base)>50
不能检测大于50的差异,实际上np.abs
是对未签名数据的否定。仔细的翻译看起来更像
sheet = np.array([[0,0,0],[255,255,255]], 'u1')[((np.maximum(base, image)-np.minimum(base, image))>50).any(2).view('u1')]
或
sheet = np.array([[0,0,0],[255,255,255]], 'u1')[(np.abs(np.subtract(image, base, dtype='i2'))>50).any(2).view('u1')]
此
正确计算子像素的差异,
第一个版本模仿您的if / else子句
第二个强制差异值的签名结果类型为'i2'
或int16
检测到大于50的那些
用至少一个这样的子像素(any(2)
)标记像素,
将生成的布尔掩码转换为索引(.view('u1')
)0和1
,并使用这些索引到模板数组中。
答案 1 :(得分:1)
大多数操作的工作方式与在相同大小的NumPy数组的标量上的工作方式相同。我将函数重新编写为
def count_new(base, image, thresh=50):
# these are the pixel absolute value differences
differences = np.abs(base - image)
# whether the difference exceeds the threshold
big_difference = differences > thresh
# whether each pixel has at least one big difference
big_difference = big_difference.any(axis=2)
# return 255 where big differences, and 0 everywhere else
return 255 * big_difference.astype(int)
希望注释使每一行的意图清楚。还检查了它是否与先前的输出相同
x = np.random.randint(256, size=(10, 11, 3))
y = np.random.randint(256, size=(10, 11, 3))
assert((count(x,y) == count_new(x,y)).all())
表明确实如此。