Канал камеры, отправленный через сокет TCP, иногда застревает

#python #sockets #tcp #raspberry-pi

#python #сокеты #tcp #raspberry-pi

Вопрос:

Я получаю канал камеры с камеры на Raspberry PI на компьютер, используя сокет TCP, чтобы использовать его для OpenCV. Это работает хорошо с минимальной задержкой. Однако иногда кадр застревает (замораживается), и через некоторое время канал возвращается или окно OpenCV выходит из строя. Я искал везде и пробовал множество вещей, но я просто не знаю, что является причиной этого.

Сервер (ПК):

 import socket
import struct
import numpy as np
import cv2

host = "192.168.0.12"
portCar = 8010

# Camera socket
camS = socket.socket()
camS.bind((host, portCar))

camS.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

# Listen for camera
camS.listen(0)
print("Waiting for camera connection...")

camCon = camS.accept()[0]
camFile = camCon.makefile("rb")
print("Connection made with camera")

camS.settimeout(0.00001)

numOfBytes = struct.calcsize("<L")

try:
    while(True):
        camS.setblocking(False)

        imageLength = struct.unpack("<L", camFile.read(numOfBytes))[0]    

        if imageLength == 0:
            break

        nparr = np.frombuffer(camFile.read(imageLength), np.uint8)
        frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

        cv2.imshow('RC Car Video stream', frame)

        if cv2.waitKey(1) amp; 0xFF == ord('q'):
            break

finally:
    camFile.close()
    camS.close()
    cv2.destroyAllWindows()
    print("Server - Camera connection closed")
  

Клиент (PI):

 import io
import socket
import struct
import time
import picamera

client_socket = socket.socket()
client_socket.connect(('192.168.0.12', 8010))

client_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

connection = client_socket.makefile('wb')

class SplitFrames(object):
    def __init__(self, connection):
        self.connection = connection
        self.stream = io.BytesIO()

    def write(self, buf):
        if buf.startswith(b'xffxd8'):
            size = self.stream.tell()
            if size > 0:
                self.connection.write(struct.pack('<L', size))
                self.connection.flush()
                self.stream.seek(0)
                self.connection.write(self.stream.read(size))
                self.stream.seek(0)

        self.stream.write(buf)


try:
    output = SplitFrames(connection)
    with picamera.PiCamera(resolution='VGA', framerate=30) as camera:
        time.sleep(2)
        camera.rotation = 180
        camera.start_recording(output, format='mjpeg')
        camera.wait_recording(2000)
        camera.stop_recording()
        # Write the terminating 0-length to the connection to let the
        # server know we're done
        connection.write(struct.pack('<L', 0))
finally:
    connection.close()
    client_socket.close()
    print("Client - Connection closed")
  

Любая помощь будет высоко оценена.

Комментарии:

1. Linux не является операционной системой реального времени, и работа с SD-карты, скорее всего, вызовет задержки — так что, возможно, Pi просто не может плавно передавать видео без дополнительной буферизации — возможно, потребуется какая-то диагностика — пробовали ли вы в своем коде использовать фиктивный источник данных вместо камеры, пробовали ли вы добавить буферизацию?

2. @barny Нет, я не добавил буферизацию, я попробую это.