我正在用Octave和Python读取带有信号样本的二进制文件。
问题是,我想为两个代码获得相同的值,但事实并非如此。
二进制文件基本上是复杂格式的信号I,Q记录为16位Int。
所以,基于Octave代码:
[data, cnt_data] = fread(fid, 2 * secondOfData * fs, 'int16');
然后:
data = data(1:2:end) + 1i * data(2:2:end);
看起来很简单,只需将二进制数据读取为16位整数。然后创建最终的复数数组。
因此我假设在Python中我需要做如下:
rel=int(f.read(2).encode("hex"),16)
img=int(f.read(2).encode("hex"),16)
in_clean.append(complex(rel,img))
好吧,我遇到的主要问题是实部和虚部的值都不相同。
例如,在Octave中,第一个值是: -20390 - 10053i
在Python中(应用上面的代码),值为:(23216 + 48088j)
由于标志不同,我首先想到的可能是记录文件的计算机的字节顺序以及我用来阅读文件的字节顺序是不同的。所以我转向解包函数,因为它允许你强制使用endian类型。
我无法找到" int16"在解压缩文档中: https://docs.python.org/2/library/struct.html
因此我选择了#34; i"选项添加" x" (填充字节),以满足" struct"中表格的32位要求。文档。
所以:
struct.unpack("i","xx"+f.read(2))[0]
结果是(-1336248200-658802568j)使用
struct.unpack("<i","xx"+f.read(2))[0]
提供相同的结果。
使用:
struct.unpack(">i","xx"+f.read(2))[0]
值为:(2021153456 + 2021178328j)
使用:
struct.unpack(">i",f.read(2)+"xx")[0]
值为:(1521514616-1143441288j)
使用:
struct.unpack("<i",f.read(2)+"xx")[0]
值为:(2021175386 + 2021185723j)
我也试过numpy和#34; frombuffer&#34;:
np.frombuffer(f.read(1).encode("hex"),dtype=np.int16)
提供:(24885 + 12386j)
那么,关于我做错了什么的任何想法?我想获得与Octave相同的价值。
在Python中读取和解释值的正确方法是什么,因此我可以通过使用&#39; int16&#39;来获取与Octave相同的值?
我一直在互联网上搜索此答案,但我找不到提供相同值的方法
非常感谢 最好的问候
答案 0 :(得分:2)
您的问题中的二进制数据似乎是5ab0bbd8
。要使用struct.unpack
解压缩带符号的16位整数,请使用'h'
格式字符。从(23216+48088j)
输出,似乎数据被编码为little-endian,因此我们需要使用<
作为格式字符串中的第一项。
from struct import unpack
data = b'\x5a\xb0\xbb\xd8'
# The wrong way
rel=int(data[:2].encode("hex"),16)
img=int(data[2:].encode("hex"),16)
c = complex(rel, img)
print c
# The right way
rel, img = unpack('<hh', data)
c = complex(rel, img)
print c
<强>输出强>
(23216+48088j)
(-20390-10053j)
请注意,rel, img = unpack('<hh', data)
也可以在Python 3上正常运行。
FWIW,在Python 3中,可以将2个字节解码为有符号整数,如下所示:
def int16_bytes_to_int(b):
n = int.from_bytes(b, 'little')
if n > 0x7fff:
n -= 0x10000
return n
Python 2中的粗略等价物是:
def int16_bytes_to_int(b):
lo, hi = b
n = (ord(hi) << 8) + ord(lo)
if n > 0x7fff:
n -= 0x10000
return n
但是必须进行减法来处理带符号的数字很烦人,使用struct.unpack
肯定会更有效率。