numpy.astype(np.uint8) 如何转换浮点数组? -1.2997805 变成了 255
how does numpy.astype(np.uint8) convert a float array? -1.2997805 became 255
这是在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?
ADD :根据下面的评论(谢谢),我是这样测试的。看起来 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)
您转换为 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
根据 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 位无符号整数不同,它至少在我测试的平台(godbolt 的 x86-64 gcc)上给出 0。
这种事情 very confusing 甚至可能依赖于平台(可能取决于 OS、numpy 版本、FP 硬件决定做什么或者处理器是否使用 2s 补码等),所以在不知道你将 运行 代码放在哪个平台的情况下,永远不要依赖这种行为,无论如何,这是一种糟糕的编码实践。令人惊讶的是,我找不到关于 numpy 的转换规则究竟如何工作的参考。
其他答案已经解决并说明了问题。但是,我可以建议一个可能实际有用的替代方案:
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)
这是在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?
ADD :根据下面的评论(谢谢),我是这样测试的。看起来 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)
您转换为 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
根据 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 位无符号整数不同,它至少在我测试的平台(godbolt 的 x86-64 gcc)上给出 0。
这种事情 very confusing 甚至可能依赖于平台(可能取决于 OS、numpy 版本、FP 硬件决定做什么或者处理器是否使用 2s 补码等),所以在不知道你将 运行 代码放在哪个平台的情况下,永远不要依赖这种行为,无论如何,这是一种糟糕的编码实践。令人惊讶的是,我找不到关于 numpy 的转换规则究竟如何工作的参考。
其他答案已经解决并说明了问题。但是,我可以建议一个可能实际有用的替代方案:
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)