numpy.astype(np.uint8)如何转换浮点数组?-1.2997805变成255

pkmbmrz7  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(155)

这是一个在ipython 3执行

In [81]: r2
Out[81]: 
array([-1.2997805, -1.4251276, -1.3047135, ..., -2.0358603, -1.9741256,
       -1.6412157], dtype=float32)

In [82]: r2.astype(np.uint8)
Out[82]: array([255, 255, 255, ..., 254, 255, 255], dtype=uint8)

-1.2997805如何转换为255?
补充:从下面的评论(谢谢),我这样测试。看起来像浮点数被转换为int,模255(将其读取为无符号int 8)完成。

is first convereted to int. and the it is cut using modulo(%).  
In [98]: b
Out[98]: array([-1.,  0.,  1.])

In [99]: b.astype(np.uint8)
Out[99]: array([255,   0,   1], dtype=uint8)
weylhg0b

weylhg0b1#

你转换为unsigned int 8,其中-1对应于255,-2对应于254等。如果你想得到-1,-2,你必须使用np.int8将其转换为有符号的int 8:

>>> np.float32(-2.0358603).astype(np.uint8)
254                                        
>>> np.float32(-2.0358603).astype(np.int8) 
-2
fbcarpbf

fbcarpbf2#

根据astype上的numpy文档,这是一个“不安全的转换”,意味着“任何数据转换都可以完成”。他们没有说铸造是如何完成的,我没有找到它在一个快速搜索的文档,所以它可能是实现依赖。
我的猜测如下:首先,将32位浮点数转换为8位有符号整数,其默认为向零截断,例如,-1.3变成了-1.然后从无符号8位整数转换为8位无符号整数,得到值255。事

float x = -1.2997805;  # Assume float is 32-bit
(uint8_t)(int8_t)x;

这与直接使用(uint8_t)x转换为8位无符号int不同,至少在我测试的平台上(godbolt的x86-64 gcc),它给出0。
这种事情是very confusing,甚至可能是平台相关的(可能取决于什么操作系统,numpy版本,FP硬件决定做什么,或者处理器是否使用2s补码等),所以在不知道你将在什么平台上运行代码的情况下,不要依赖这种行为,无论如何,这是糟糕的编码实践。令人惊讶的是,我找不到numpy的选角规则是如何运作的。

xvw2m8pv

xvw2m8pv3#

其他的答案已经解决和解释了这个问题。不过,我可以提出一个实际上可能有用的替代方案:

np.uint8(np.clip(x, 0, 255))

其中x是浮点型数组。
此方法确保负数变为0,而巨大的正数(> 255)变为255。
例如

>>> x = [223.2, 888.2, -32, 255.3, 255]
>>> np.uint8(np.clip(x, 0, 255))
array([223, 255,   0, 255, 255], dtype=uint8)

相关问题