numpy中tobytes()的相反功能函数是什么?如何将bytes转回numpy数组
字节转NumPy数组实现方案(Socket传帧场景)
针对大体积视频帧传输场景,完全不需要依赖Pickle,直接用NumPy原生接口实现序列化/反序列化,内存开销极低,传输效率远高于通用序列化方案。核心逻辑是传输时除了数组的字节数据,额外附带数组的形状、数据类型两个小体积元数据,接收端根据元数据即可把bytes直接还原为数组。
核心转换函数(接收端用,bytes转numpy数组)
import numpy as np def bytes_to_numpy(arr_bytes: bytes, dtype: np.dtype, shape: tuple) -> np.ndarray: """ 将bytes数据转换为指定格式的NumPy数组 参数: arr_bytes: 输入的字节数据 dtype: 原NumPy数组的数据类型,比如np.uint8(视频帧常用类型) shape: 原NumPy数组的形状,比如(1080, 1920, 3)代表1080P RGB帧 返回: 还原后的NumPy数组 """ return np.frombuffer(arr_bytes, dtype=dtype).reshape(shape)
Socket传输完整实现示例
客户端(发送帧)
import socket import numpy as np import struct # 配置参数 HOST = '127.0.0.1' PORT = 9999 # 示例帧,实际场景替换为你采集的视频帧 frame = np.random.randint(0, 256, size=(1080, 1920, 3), dtype=np.uint8) # 建立socket连接 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) # 先打包元数据头:用struct把 dtype长度、dtype内容、shape维度、各维度值打包成固定格式头 # 注:视频帧固定用np.uint8的话可以省略dtype传输,进一步简化 dtype_str = frame.dtype.str dtype_len = len(dtype_str) shape = frame.shape shape_dim = len(shape) # 头结构:dtype长度(1字节) + dtype内容 + shape维度(1字节) + 各维度值(每个4字节整数) header = struct.pack('B', dtype_len) + dtype_str.encode() + struct.pack('B', shape_dim) + struct.pack(f'{shape_dim}I', *shape) # 先发送头长度(4字节整数,方便接收端先读头长度) header_len = len(header) s.sendall(struct.pack('I', header_len)) # 发送头 s.sendall(header) # 发送帧的字节数据 s.sendall(frame.tobytes()) s.close()
服务端(接收帧,调用转换函数)
import socket import numpy as np import struct HOST = '0.0.0.0' PORT = 9999 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() with conn: # 先读4字节的头长度 header_len = struct.unpack('I', conn.recv(4))[0] # 读完整的头 header = conn.recv(header_len) # 解析头 offset = 0 dtype_len = struct.unpack('B', header[offset:offset+1])[0] offset += 1 dtype = np.dtype(header[offset:offset+dtype_len].decode()) offset += dtype_len shape_dim = struct.unpack('B', header[offset:offset+1])[0] offset += 1 shape = struct.unpack(f'{shape_dim}I', header[offset:offset+shape_dim*4]) # 计算帧数据总长度 frame_size = dtype.itemsize for dim in shape: frame_size *= dim # 接收完整帧字节 frame_bytes = b'' while len(frame_bytes) < frame_size: chunk = conn.recv(frame_size - len(frame_bytes)) if not chunk: break frame_bytes += chunk # 调用转换函数还原数组 frame = bytes_to_numpy(frame_bytes, dtype, shape) # 这里frame就是还原后的原数组,可直接后续处理 print(f"还原成功,数组形状:{frame.shape}, 数据类型:{frame.dtype}")
方案优势
- 完全不依赖Pickle,没有序列化大小限制,也不存在安全风险
- 内存开销极低,
np.frombuffer默认直接共享字节内存,不需要额外拷贝 - 传输效率高,额外传输的头数据通常只有十几字节,几乎不占用带宽
- 兼容性好,支持所有NumPy支持的数据类型和数组形状
内容的提问来源于stack exchange,提问作者ella
相关产品推荐
相关产品推荐

