您不能仅将每个接收到的 1-1024 字节缓冲区显示为图像;您必须将它们连接起来,并且仅在缓冲区完成时才显示图像。
如果您在带外知道您的图像将是固定数量的字节,您可以执行以下操作:
IMAGE_SIZE = 320*240*3
def handle(self):
stream_bytes = b''
try:
stream_bytes += self.rfile.read(1024)
while len(stream_bytes) >= IMAGE_SIZE:
image = np.frombuffer(stream_bytes[:IMAGE_SIZE], dtype="B")
stream_bytes = stream_bytes[IMAGE_SIZE:]
print(image.shape)
cv2.imshow('F', image)
cv2.waitKey(0)
finally:
cv2.destroyAllWindows()
sys.exit()
如果您不知道这一点,则必须添加某种帧协议,例如在每个帧之前以 uint32 形式发送帧大小,以便服务器可以知道每个帧要接收多少字节。
接下来,如果您只是发送原始字节,没有任何数据类型或形状或顺序信息,则需要将数据类型和形状信息嵌入到服务器中。如果您知道它应该是特定形状的 C 顺序字节,您可以手动执行此操作:
image = np.frombuffer(stream_bytes, dtype="B").reshape(320, 240, 3)
…但如果没有,您也必须将该信息作为帧协议的一部分发送。
或者,您可以发送pickle.dumps
缓冲区和pickle.loads
它在另一边,或者np.save
to a BytesIO
and np.load
结果。无论哪种方式,都包括数据类型、形状、顺序和步幅信息以及原始字节,因此您不必担心它。
下一个问题是,一旦显示一张图像,您就会退出。这真的是你想要的吗?如果不是……就不要这样做。
但这又引发了另一个问题。你真的想用它来阻止整个服务器吗cv.waitKey
?您的客户正在捕获图像并尽快发送它们;当然,您要么想让服务器在它们到达时立即显示它们,要么更改设计,以便客户端仅根据需要发送帧。否则,您只会得到一堆几乎相同的帧,然后在客户端被阻塞等待您耗尽缓冲区时出现一段长达数秒的间隙,然后重复。