numpy.astype(np.uint8) 如何转换浮点数组? -1.2997805 变为 255
Posted
技术标签:
【中文标题】numpy.astype(np.uint8) 如何转换浮点数组? -1.2997805 变为 255【英文标题】:how does numpy.astype(np.uint8) convert a float array? -1.2997805 became 255 【发布时间】:2021-01-26 14:13:13 【问题描述】:这是 ipython3 中的一个执行
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?
添加:来自下面的 cmets(谢谢),我是这样测试的。看起来float被转换为int,并且模255(将其读取为unsigned int8)完成。
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)
【问题讨论】:
这能回答你的问题吗? Integer overflow in numpy arrays @MykolaZotko 没有回答这个与 numpy 如何进行不安全强制转换有关的具体案例uint8
类型涵盖从 0 到 255 的范围。超出此范围的负值变为 255。
在 C 中尝试一下,看看它是否做同样的事情。我的猜测是,它首先转换为有符号整数为 -1,然后无符号为 255。
@MykolaZotko 没有解释为什么 -2 是 254。
【参考方案1】:
您已转换为 unsigned int 8,其中 -1 对应于 255,-2 对应于 254 等。 如果你想得到 -1、-2,你必须使用 np.int8 将其转换为有符号的 int8:
>>> np.float32(-2.0358603).astype(np.uint8)
254
>>> np.float32(-2.0358603).astype(np.int8)
-2
【讨论】:
【参考方案2】:根据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 的转换规则究竟如何工作的参考资料。
【讨论】:
【参考方案3】:其他答案已经解决并解释了问题。但是,我可以建议一个可能实际有用的替代方案:
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)
【讨论】:
以上是关于numpy.astype(np.uint8) 如何转换浮点数组? -1.2997805 变为 255的主要内容,如果未能解决你的问题,请参考以下文章