[英]how does numpy.astype(np.uint8) convert a float array? -1.2997805 became 255
this is an execution in ipython3这是在 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)
how is -1.2997805 converted to 255? -1.2997805 如何转换为 255?
ADD : from the comments below(thanks), I tested like this.添加:从下面的评论(谢谢),我是这样测试的。 looks like the float is converted to int, and the modulo 255 (to read it as unsigned int8) is done.看起来浮点数转换为 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)
You converted to unsigned int 8, where -1 correspond to 255, -2 to 254 etc. If you want to get -1, -2 you have to convert it to signed int8 using np.int8:您转换为 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
This is an "unsafe cast" according to numpy docs on astype
, meaning "any data conversions may be done".根据astype
上的 numpy 文档,这是“不安全的转换”,这意味着“可以完成任何数据转换”。 They didn't say how exactly the casting is done and I did not find it in a quick search of the docs, so it may be implementation dependent.他们没有说明转换是如何完成的,我也没有在文档的快速搜索中找到它,所以它可能取决于实现。
My guess is the following: first the 32 bit float is cast to 8 bit signed integer, which defaults to truncating towards zero, ex.我的猜测如下:首先将 32 位浮点数转换为 8 位有符号整数,默认为向零截断,例如。 -1.3 becomes -1. -1.3 变为 -1。 Then a cast from unsigned 8 bit integer to 8 bit unsigned integer, giving a value of 255. Something like然后从无符号 8 位整数转换为 8 位无符号整数,得到 255 的值。
float x = -1.2997805; # Assume float is 32-bit
(uint8_t)(int8_t)x;
This is not the same as directly converting to 8-bit unsigned int with (uint8_t)x
, which gives 0 at least on the platform I tested on (godbolt's x86-64 gcc).这与使用(uint8_t)x
直接转换为 8 位 unsigned int 不同,它至少在我测试的平台上给出 0(godbolt 的 x86-64 gcc)。
This kind of thing is very confusing and may even be platform dependent (possibly depending on what OS, numpy version, what the FP hardware decides to do or if the processor even uses 2s complement, etc) so do not ever rely on this behavior without knowing exactly what platform you will be running the code on, and it is poor coding practice anyway.这种事情非常令人困惑,甚至可能依赖于平台(可能取决于什么操作系统、numpy 版本、FP 硬件决定做什么或者处理器是否甚至使用 2s 补码等)所以不要依赖这种行为确切地知道您将在哪个平台上运行代码,无论如何这都是糟糕的编码实践。 Surprisingly, I couldn't find a reference on exactly how numpy's casting rules work.令人惊讶的是,我找不到关于 numpy 的转换规则究竟是如何工作的参考。
The other answers already solve and explain the problem.其他答案已经解决并解释了问题。 I can however suggest an alternative that may be practically useful:但是,我可以建议一个可能实际有用的替代方案:
np.uint8(np.clip(x, 0, 255))
where x is your floating-type array.其中 x 是您的浮动类型数组。
This method ensures negative numbers become 0, and huge positive numbers (> 255) become 255.此方法可确保负数变为 0,而巨大的正数 (> 255) 变为 255。
For example例如
>>> x = [223.2, 888.2, -32, 255.3, 255]
>>> np.uint8(np.clip(x, 0, 255))
array([223, 255, 0, 255, 255], dtype=uint8)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.