【问题标题】:Cv2:problem recieving full data from socketCv2:从套接字接收完整数据的问题
【发布时间】:2020-07-23 15:35:35
【问题描述】:

我试图通过套接字发送帧,编码后它们通常是 50 000 - 80 000 字节,所以我通过循环接收数据,但由于客户端总是发送帧,所以下面代码中的循环不会中断,所以当我什么都不运行时发生并且接收循环继续进行

客户

import socket
import cv2
import time
s = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
s.connect(("127.0.0.1",60124))
camera = cv2.VideoCapture(0)
while True :
    r , f = camera.read()
    f = cv2.imencode(".jpg",f)[1].tostring()
    s.sendall(f)

服务器

import socket
import numpy as np
import cv2
s = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
s.bind(("127.0.0.1",60124))
s.listen(5)
c , a = s.accept()

while True :
    data = ""
    while True:
        f = c.recv(1024)
        if not f :
            break
        data += f
    x = np.fromstring(data , np.uint8)
    var = cv2.imdecode(x , cv2.IMREAD_COLOR)
    cv2.imshow("Camera" , var)
    cv2.waitKey(1)

请帮忙

【问题讨论】:

    标签: python python-3.x sockets opencv tcp


    【解决方案1】:

    我建议你先发送长度,然后发送数据。
    当服务器接收到“有效负载”长度时,它知道需要多少数据字节。

    客户:

    • 8字节发送len(f)
    • 发送数据f

    服务器:

    • 接收8 字节以获取len_f
    • 接收len_f 的数据字节。
      无需以 1024 字节块的形式接收数据。

    在我的示例中,len_f 被编码为base64 格式。
    发送len_f 的字节数始终为 8 个字节(由于 base64 自动填充)。

    您也可以将data 编码为base64
    如果您通过 HTTP 发送数据,这一点很重要。
    我将图像数据的base64 编码/解码放在评论中。
    只有长度被编码为base64(您也可以将长度作为文本格式发送)。


    客户:

    import socket
    import numpy as np
    import cv2
    import base64
    
    s = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
    s.connect(("127.0.0.1", 60124))
    
    width, height, n_frames = 640, 480, 100  # 100 frames, resolution 640x480
    
    for i in range(n_frames):
        # Generate synthetic image:
        img = np.full((height, width, 3), 60, np.uint8)
        cv2.putText(img, str(i+1), (width//2-100*len(str(i+1)), height//2+100), cv2.FONT_HERSHEY_DUPLEX, 10, (30, 255, 30), 20)  # Green number
    
        # JPEG Encode img into f
        _, f = cv2.imencode('.JPEG', img)
    
        # Encode jpeg_img to base64 format
        #f = base64.b64encode(f)
        # Get length of f and encode to base64
        #f_len = base64.b64encode((len(f)).to_bytes(4, byteorder='little'))
    
        f_len = base64.b64encode((len(f)).to_bytes(4, byteorder='little'))
    
        # Send the length first - so the server knows how many bytes to expect.
        s.sendall(f_len) # Send 8 bytes (assumption: b64encode of 4 bytes will be 8 bytes due to the automatic padding feature).
    
        s.sendall(f)
    
    s.close()
    

    服务器:

    import socket
    import numpy as np
    import cv2
    import base64
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(("127.0.0.1", 60124))
    s.listen(5)
    c, a = s.accept()
    
    while True:
        # Read 8 bytes that tells the length of encoded image to be expected.
        data = c.recv(8)
    
        if len(data) != 8:
            break
    
        # Decode f_len from base64
        f_len = base64.decodebytes(data)
    
        # Convet from array of 4 bytes to integer value.
        f_len = int.from_bytes(f_len, byteorder='little')
    
        #f = c.recv(1024)
        # Receive the encoded image.
        data = c.recv(f_len)
    
        if len(data) != f_len:
            break
    
        #x = base64.decodebytes(data)  # Decode base64
        #x = np.fromstring(x , np.uint8)
        x = np.fromstring(data, np.uint8)
        var = cv2.imdecode(x, cv2.IMREAD_COLOR)
    
        if var is None:
            print('Invalid image')
        else:
            cv2.imshow("Camera" , var)
            cv2.waitKey(100)
    
    s.close()
    cv2.destroyAllWindows()
    

    【讨论】:

    • 我已经通过使用 struct 和 pickle 解决了这个问题,但非常感谢你的回答,我会接受
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    • 2019-05-08
    • 1970-01-01
    相关资源
    最近更新 更多