我正在使用Numpy对图片文件进行一些基本操作。我想执行以下操作:
in1, in2, out # some numpy arrays of dtype uint8
out = in1 * in2 / 256
但是,由于uint8
的大小和模运算的规则,会发生溢出,结果不正确。
(例如,在C ++中不会出现同样的问题,其中中间结果可以存储在更大尺寸的临时空间中。)
另一种方法是执行两次乘法:out = in1/16 * in2/16
。但是,这会导致输出的真空值。
一个有效的解决方案是手动设置每个像素:
out = numpy.empty(in1.shape, dtype="uint8")
for i in range(out.shape[0]):
out[i] = int(in1[i])*in2[i]/256
然而,这需要您知道数组中维度的确切数量,并且通常不够优雅(并且由于显式循环,可能会更慢)。
另一种方法是将其中一个源矩阵转换为更高精度的类型,例如:
out = in1.astype("uint16")*in2/256
然而,这个可能是内存密集型的,因为它复制整个数组,而不是只保留一个带有中间结果的变量。
修改
这是一个小例子:
in1 = numpy.array([2, 4, 6], dtype="uint8")
in2 = numpy.array([128, 128, 128], dtype="uint8")
out = numpy.empty((3,), dtype="uint8")
# what I want to get: array([1, 2, 3], dtype=uint8)
out[:] = in1 * in2 / 256 # array([0, 0, 0], dtype=uint8)
所以,这是我的问题:我还有另一种方法吗?是否有一种首选的(或只是有效的)方式来做我想做的事情,或者我只需要重构我的程序?
答案 0 :(得分:1)
在numpy中,您可以使用dtype
参数在另一个dtype中计算临时数组,而无需显式复制数组:
>>> out = np.multiply(in1, in2, dtype=np.uint16) # overflow safe multiplication
>>> np.floor_divide(out, 256, out=out) # in-place division
>>> out
array([1, 2, 3], dtype=uint16)
然而,out
将是一个uint16
数组(因为人们不能用numpy连接ufunc)。但它尽可能避免使用临时数组。