2016-11-27 100 views
1

我目前使用OpenCV来读取视频帧。发送视频帧到客户端

在服务器端序列化使用cPickle.dumps()帧:

flag, frame = cap.read() 
frame = cPickle.dumps(frame) 
client_socket.sendall(frame) 

在客户端序列化使用cPickle.loads()帧:

data = sock.recv(4000) 
frame = cPickle.loads(data) # ValueError: insecure string pickle 
self.ImageLabel.configure(image=frame) # Want to show the frame in Tkinter 
self.ImageLabel.image = frame 
self.ImageLabel.grid(row=4, columnspan=40) 

cPickle的。加载(数据)导致ValueError:不安全的字符串pickle。我究竟做错了什么?我想读取客户端的框架并在tkinter窗口中显示它。我查了9个多小时,但找不到解决方案。

编辑1:

我也尝试这样的:

服务器侧

flag, frame = cap.read() 
if flag: 
    size = sys.getsizeof(frame) 
    client_socket.send(str(size)) 
    client_socket.sendall(cPickle.dumps(frame.tolist())) 

客户端

size = sock.recv(4000) 
data = sock.recv(int(size)) 
frame = cPickle.loads(data) # Causes EOFError 

编辑2: 服务器侧

flag, frame = cap.read() 
if flag: 
    frame = cPickle.dumps(frame) 
    size = len(frame) 
    p = struct.pack("I", size) 
    client_socket.send(p) 
    client_socket.sendall(frame) 

客户端

sizep = sock.recv(struct.calcsize("I")) 
data_size = struct.unpack("I",sizep) 
print type (data_size) # tuple - has (11026730,) 
data = sock.recv(int(data_size[0])) 
frame = cPickle.loads(data) # ValueError: insecure string pickle 
+0

@让FrançoisFabrecap.read( )是OpenCV的一项功能。它给一个对象 –

+0

@ Jean-FrançoisFabrecPickle.dumps(frame.tolist())在尝试cPickle.load(data)时会导致EOFError。 我不确定self.ImageLabel.configure(image = frame)是否接受一个ndarray。 –

+0

你可以在发送之前打印'frame'吗?似乎这里有东西是腐败的...... –

回答

1

您收到最多4000个字节的数据具有以下

data = sock.recv(4000) 

但该消息比大。您必须完整阅读该消息或将其截断,这就解释了泡菜错误。例如这样做:

packets = [] 
while True: 
    b = sock.recv(4096) 
    if b: 
     packets.append(b) 
    else: 
     break 

data = "".join(packets) 

将读取插槽,直至没有什么再阅读。我把每个数据包放在一个列表中,所以我可以使用str.join(比字符串连接更快)。

现在data可以装入泡菜。

注意:它当然不能解决self.ImageLabel.configure(image=frame)。确保将期望的数组类型传递给此方法。

编辑:现在你已经编辑了你的问题,你有更多的问题。

  • 首先你之前序列化,咸菜,这是不正确的计算对象的大小,你应该使用len(picked object)
  • 那么你正在阅读使用recv(4000)大小:你刚才所消耗的一部分通过这样做你的缓冲区,你不知道整数的大小作为字符串,所以尺寸问题没有解决。如果您需要首先发送大小,则需要使用struct.pack对其进行编码,并使用struct.unpack在客户端对其进行解码。
  • 当你有正确的大小,你可以阅读你的数据。

这里是我的建议(你需要导入struct):

服务器端:

flag, frame = cap.read() 
if flag: 
    data = cPickle.dumps(frame) # serialize 
    data_size = len(data)  # nb of bytes of serialized data 
    p = struct.pack("I",data_size) # encode size 
    client_socket.send(p) # send encoded size 
    client_socket.sendall(data) # send serialized data 

客户端:

sizep = sock.recv(struct.calcsize("I")) # first thing: recieved encoded size 
data_size = struct.unpack("I",sizep) # decode size 
data = sock.recv(data_size)   # read data size 
frame = cPickle.loads(data)   # unserialize 
+0

请参阅我的编辑。服务器将发送很多帧。所以我在发送实际帧之前首先发送了帧的大小,但仍然会导致错误。如果消息的大小是一个问题,这难道不能解决这个问题吗? –

+0

我试过使用struct的解决方案。它仍然给ValueError:不安全的字符串pickle。请参阅编辑2. –

+0

您可以在排放之前和之后打印尺寸吗? –

相关问题