发送cv2视频流用于人脸识别时遇resize错误求助
解决OpenCV视频流传输中resize函数的Bad argument错误
错误根源
- 数据未正确反序列化:客户端用
pickle.dumps()把帧序列化成字节流,但服务器直接把接收的字节转成np.array(),完全没做反序列化,导致frame根本不是有效的OpenCV图像矩阵,数据类型不匹配才触发resize的参数错误。 - 数据接收逻辑错误:客户端发送的是「8字节的长度前缀 + 序列化后的帧数据」,但服务器每次只固定接收4096字节,没有按前缀指定的长度完整接收所有数据,就算加了反序列化也会因为数据不完整失败。
- 客户端冗余操作:外层
while True循环里每次都会重新创建VideoCapture对象,反复打开摄像头,不仅浪费资源还可能导致帧读取异常。
修正后的服务器代码
import pickle import struct import cv2 import numpy as np # 假设前面已完成socket绑定、监听、accept得到client_socket if client_socket: while True: # 先接收8字节的长度前缀 length_data = client_socket.recv(8) if not length_data: break frame_length = struct.unpack("Q", length_data)[0] # 按长度完整接收序列化的帧数据 packet = b'' while len(packet) < frame_length: chunk = client_socket.recv(min(frame_length - len(packet), 4096)) if not chunk: break packet += chunk # 反序列化得到原始帧 frame = pickle.loads(packet) # 正常处理帧 small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) rgb_small_frame = small_frame[:, :, ::-1]
修正后的客户端代码
import cv2 import imutils import pickle import struct import time import socket # 假设前面已完成socket连接得到client_socket # 把VideoCapture创建放到外层,避免重复打开摄像头 vid = cv2.VideoCapture(0) while vid.isOpened(): time.sleep(0.5) ret, frame = vid.read() if not ret: break # 读取失败就退出 # imutils.resize第二个参数是宽度,改成合理值比如640,避免帧过大 frame = imutils.resize(frame, width=640) a = pickle.dumps(frame) message = struct.pack("Q", len(a)) + a try: client_socket.sendall(message) except Exception as e: print(e) break vid.release() # 最后释放摄像头资源
额外说明
- 客户端原代码里
imutils.resize(frame, 4 * 1024)的写法不合理,4096像素的宽度会让帧体积过大,传输效率极低,建议改成640、800这类常用分辨率。 - 传输过程中要做好连接中断、丢包的异常处理,避免程序直接崩溃。
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

