【问题标题】:Fast / built-in bit-manipulation in Python/numpy?Python/numpy 中的快速/内置位操作?
【发布时间】:2012-05-09 20:55:26
【问题描述】:

我正在使用一个外部库,该库输出一个数据类型为“>u2”(大端、无符号、2 字节/16 位)的 numpy 数组。就我而言,只有 10 位有效(输出来自实际输出 little-endian 的硬件设备)。例如:

65283是最大值,对应bin(65283)=0b1111111100000011作为直接python输出,或者00001111111111如果是little-endian。

我想将库输出的0-65283 范围映射到0-1023 范围,这对10 位硬件功能来说是有意义的。我该怎么做?

我尝试了以下方法:

>>>import numpy as np

>>>arr=np.array([65283, 6528, 652, 65, 6], dtype=">u2")
>>>print arr/64  # same as arr/2**6 and arr >> 6
[1020  102   10    1    0]
>>>print arr.byteswap()
[ 1023 32793 35842 16640  1536]

但这并没有给出预期的结果。我发现bin() 函数以大端格式输出(在这个 numpy 数组的情况下),但省略了填充零。例如,65283 表示所有 16 位,但 bin(6528)=0b1100110000000(中间缺少 3 个零)。

为了解决这个问题(并返回一个 10 位 little-endian 数字),我可以得到 6528 的二进制形式,在中间添加 3 个零,然后进行字节交换。但是 1)这是非常繁琐的(每个元素都完成)和 2)零填充不一致(例如 652 需要另外 6 个零)。

有没有内置的方法来做到这一点?看起来struct 模块(带有pack 和或unpack)可能会有所帮助,但它现在对我来说是希腊语。任何帮助将不胜感激!

编辑

相信我已经找到了罪魁祸首。我上面的示例(从 65238 的相机/库中获取实际值并假设半任意附加值,显然只是删除了最右边的数字)不会发生!例如6528 要求最低有效字节中的 1 (00011001**1**0000000) 永远不会发生(只有 10 位有效)。

经过进一步检查,我的代码中的一个简单的arr.byteswap()(其中arr 具有合法值)有效。例如:

>>>arr=np.array([12288, 13312, 12800, 12032, 13312, 13824, 65283, 0, 7936], dtype=">u2")
>>>arr.byteswap()
array([  48,   52,   50,   47,   52,   54, 1023,    0,   31], dtype=uint16)

我从来没有在我的代码中真正尝试过,只是在这个虚构的例子中。对困惑感到抱歉。但希望它可以帮助其他人解决这个问题(特别是如果你使用 Basler 相机!),我猜这结果是微不足道的......

【问题讨论】:

    标签: python numpy bit-manipulation


    【解决方案1】:
    import struct
    struct.pack('<H',val)
    

    或者,更好的是:

    >>> arr.byteswap().newbyteorder()
    array([65283,  6528,   652,    65,     6], dtype=uint16)
    >>> arr.byteswap().newbyteorder().tostring()
    '\x03\xff\x80\x19\x8c\x02A\x00\x06\x00'
    

    docs

    【讨论】:

    • 嗯。从arr.byteswap().newbyteorder().tostring() 返回的情况下我该怎么做才能将其转换为 10 位 uint16(或 int16)? (可能是一个愚蠢的问题;现在想弄清楚;如果我这样做会回复):) 谢谢...
    • 你到底想做什么?
    • 我需要将这个 &gt;u2 值数组 (0-65283) 映射到范围 (0-1023)。 &gt;u2 有 16 位,但在这个特定的数组中只有 10 位有效(这就是为什么它在 65283 时达到最大值,或者,00001111111111 在 little-endian 中,1111111100000011 在 big-endian 中。所以,65283将是 1023。0 将是 0。中间的东西,如 6528(&gt;u2)在 big-endian 中将是 1100110000000000,因此,0000000011001100(=204)在 little-endian 中。当然我' 宁愿不将 6528(例如)转换为二进制形式的字符串表示形式,用任何必要的 0 填充它,然后转换为 int。
    • 地图是什么意思?从包含 65284 个元素的集合到仅包含 1024 个元素的集合之间没有一对一的映射。
    • 当然不会是一对一的。存在动态范围问题。 6528 将映射到 204。但(可能)6529、6527、6526 等也会如此。您失去了分辨率,但这种分辨率一开始就从未存在于我的数据中。这有意义吗?
    猜你喜欢
    • 2015-12-01
    • 2023-03-07
    • 2011-12-20
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    相关资源
    最近更新 更多