我正在尝试通过Socket通信以python流式传输视频,但是失败了吗?

时间:2018-08-10 21:46:08

标签: python sockets opencv pickle

我正在尝试通过套接字通信以python流式传输视频,但是失败了吗?我究竟做错了什么?我的目标是能够使用网络摄像头捕获图像,对其进行消毒,然后通过套接字发送。问题是在接收端我得到了:

this is supposed to show the received image 这是代码:

服务器:

import socket,cv2,pickle                                     
serversocket = socket.socket(
            socket.AF_INET, socket.SOCK_STREAM) 
host = socket.gethostname()                           
port = 9999                                           
serversocket.bind((host, port))                                  
serversocket.listen(5)                                           
while True:
   clientsocket,addr = serversocket.accept()      
   print("Got a connection from %s" % str(addr))
   if clientsocket:
      vid = cv2.VideoCapture(0)
      while(vid.isOpened()):
         img, frame = vid.read()

         gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
         print(frame)
         a = pickle.dumps(frame)
         clientsocket.send(a)

         b = pickle.loads(a)
   clientsocket.close()

客户端:

import socket,cv2,pickle


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 


host = socket.gethostname()                           

port = 9999


s.connect((host, port))                               

data = []
while True:

    packet = s.recv(4096)
    if not packet: break
    data.append(packet)
    k=0
    try:
        data_arr = pickle.loads(b"".join(data))
        print(data_arr)
        if k<1:
            cv2.imshow('frame',data_arr)
        k = k + 1
        data=[]
    except:
        continue
s.close()

提前谢谢!

1 个答案:

答案 0 :(得分:0)

结构是我们的朋友!它是python标准库字符串服务的一部分。 它将字符串解释为打包的二进制数据,并在Python值和以Python字符串表示的C结构之间执行转换。这有助于处理文件,套接字网络连接和其他来源中的二进制数据。在server.py中,将帧矩阵作为变量a中的字符串进行酸洗转储,然后使用struct.pack添加参考有效负载大小(对于a中的字符串)。有效载荷大小使用+附加到a,然后.sendall发送整个帧。为了简单说明,假设我们的帧只是3x3矩阵:

frame = np.array([[1,2,3],[4,5,6],[7,8,9]]

a = pickle.dumps(frame)

框架的腌制形式如下所示:

b'\ x80 \ x03cnumpy.core.multiarray \ n_reconstruct \ nq \ x00cnumpy \ nndarray \ nq \ x01K \ x00 \ x85q \ x02C \ x01bq \ x03 \ x87q \ x04Rq \ x05(K \ x01K \ x03K \ x03 \ x86q \ x06cumpy \ ndtype \ nq \ x07X \ x02 \ x00 \ x00 \ x00i4q \ x08K \ x00K \ x01 \ x87q \ tRq \ n(K \ x03X \ x01 \ x00 \ x00 \ x00

有效载荷大小:len(a)为193,其字符串表示形式为4字节“ L”格式为b'\ xc1 \ x00 \ x00 \ x00'。 然后,message = struct.pack(“ L”,len(a))+ a

b'\ xc1 \ x00 \ x00 \ x00 \ x80 \ x03cnumpy.core.multiarray \ n_reconstruct \ nq \ x00cnumpy \ nndarray \ nq \ x01K \ x00 \ x85q \ x02C \ x01bq \ x03 \ x87q \ x04Rq \ x05(K \ x01K \ x03K \ x03 \ x86q \ x06cumpy \ ndtype \ nq \ x07X \ x02 \ x00 \ x00 \ x00i4q \ x08K \ x00K \ x01 \ x87q \ tRq \ n(K \ x03X \ x01 \ x00 \ x00 \ x00

现在,该消息还包含数据前面的有效载荷大小。 len(消息)= 197。 在client.py中,s.recv(4096)表示最多将通过阻塞调用接收到4096个字节。 数据以每个数据包4096字节的形式附加到字符串中。其余部分非常明显。 我希望这个解释会有所帮助!下面的工作server.py和client.py供您参考:

server.py

    import socket,cv2,pickle
    import struct
    serversocket = socket.socket(
                socket.AF_INET, socket.SOCK_STREAM)
    host = socket.gethostname()
    port = 9999
    serversocket.bind((host, port))
    serversocket.listen(5)

    while True:
        clientsocket,addr = serversocket.accept()

        print("Got a connection from %s" % str(addr))
        if clientsocket:
            vid = cv2.VideoCapture(0)
            while(vid.isOpened()):
                img, frame = vid.read()
                gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                print(frame)
                a = pickle.dumps(frame)
                message =struct.pack("L", len(a))+a
                clientsocket.sendall(message)
                cv2.imshow('Transmitted',frame)
                key = cv2.waitKey(1) & 0xFF
                if key == ord("q"):
                    clientsocket.close()

client.py

    import socket,cv2,pickle
    import struct
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = socket.gethostname()
    port = 9999
    s.connect((host, port))
    data = b""
    payload_size = struct.calcsize("L") 
    while True:
        while len(data) < payload_size:
            packet= s.recv(4096)
            if not packet: break
            data += packet
        packed_msg_size = data[:payload_size]
        data = data[payload_size:]
        msg_size = struct.unpack("L", packed_msg_size)[0]
        while len(data) < msg_size:
            data += s.recv(4096)
        frame_data = data[:msg_size]
        data = data[msg_size:]
        frame=pickle.loads(frame_data)
        cv2.imshow('Received',frame)
        key = cv2.waitKey(1) & 0xFF
        if key == ord("q"):
            break
    s.close()