Cv2: проблема с получением полных данных из сокета - PullRequest
1 голос
/ 10 апреля 2020

Я пытаюсь отправить кадры через сокет, и после кодирования они обычно составляют 50 000 - 80 000 байтов, поэтому я получаю данные по l oop, но, поскольку клиент отправляет кадры, всегда l oop в приведенном ниже коде не будет перерыв, поэтому, когда я бегу, ничего не происходит, и получающий l oop продолжает работать

Клиент

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)

Помогите plss

1 Ответ

0 голосов
/ 11 апреля 2020

Я предлагаю вам сначала отправить длину, а затем данные.
Когда сервер получает длину "полезной нагрузки", он знает, сколько байтов данных ожидает.

Клиент:

  • отправить len(f) как 8 байт
  • отправить данные f

Сервер:

  • получить 8 байтов для получения len_f.
  • для получения len_f байтов данных.
    Нет необходимости получать данные в виде блоков по 1024 байта.

В моем примере len_f кодируется в формате base64.
Количество байтов для отправки len_f всегда составляет 8 байтов (из-за заполнения base64 c padding) ,

Вы также можете закодировать 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...