#python #sockets #opencv #python-sockets
#python #сокеты #opencv #python-сокеты
Вопрос:
Я пытаюсь отправить фреймы python-opencv через сокеты. Я собираю данные и удаляю их, но по какой-то причине они пустые или ничего не отображается.
Это мой терминал, когда я запускаю client.py
new message length: b'720 '
Он должен транслировать веб-камеру с сервера, но ничего не отображается.
Вот мой код для клиента и сервера:
client.py
import socket
import numpy as np
import cv2
import pickle
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1232))
while True:
full_msg = b''
new_msg = True
while True:
msg = s.recv(16)
if new_msg:
print(f'new message length: {msg[:HEADERSIZE]}')
msglen = int(msg[:HEADERSIZE])
new_msg = False
full_msg = msg
if len(full_msg)-HEADERSIZE == msglen:
print('full msg recvd')
print(full_msg[HEADERSIZE:])
d = pickle.loads(full_msg[HEADERSIZE:])
print(d)
cv2.namedWindow('Webcam', cv2.WINDOW_NORMAL)
cv2.imshow('Webcam', full_msg[HEADERSIZE:])
new_msg = True
full_msg = b''
print(full_msg)
server.py
import socket
import numpy as np
import cv2
import time
import pickle
from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE, SIG_DFL)
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1232))
s.listen(5)
cap = cv2.VideoCapture(0)
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
while True:
ret, frame = cap.read()
msg = pickle.dumps(frame)
print(frame)
msg = bytes(f'{len(frame):<{HEADERSIZE}}', "utf-8") msg
clientsocket.send(msg)
Я понятия не имею, почему ничего не отображается. Я даже не знаю, приходит ли что-нибудь. Связано ли это с данными numpy? Я слышал, что это может быть сложно.
Ответ №1:
Когда вы передаете кадры объемом 720 байт с сервера, вы фактически отправляете 730 байт (длина 10 байт данные 720 байт) на кадр непрерывно, один кадр за другим.
В клиенте вы читаете 16 байт на recv()
. Следовательно, ваше условие if len(full_msg)-HEADERSIZE == msglen:
никогда не будет истинным, с размером заголовка 10, поскольку 730 не делится на 16.
Итак, ваша программа бесконечно зацикливается на while True:
в клиенте.
Попробуйте приведенную ниже программу для клиента. Я тестировал с фиктивными данными.
client.py
import socket
import numpy as np
import cv2
import pickle
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1232))
while True:
msg_length=int(s.recv(HEADERSIZE))
full_msg=b''
while len(full_msg)<msg_length:
full_msg =s.recv(msg_length-len(full_msg))
print(full_msg)
d = pickle.loads(full_msg)
cv2.namedWindow('Webcam', cv2.WINDOW_NORMAL)
cv2.imshow('Webcam', full_msg)
Комментарии:
1. Это решило проблему, о которой я спрашивал изначально, но теперь у меня возникла новая проблема. На самом деле, когда вы ответили своим решением, я переделал свою программу, но вместо этого я не использовал pickle и самостоятельно преобразовал в байты. Я попал в то же место, что и ваше решение:
Traceback (most recent call last): File "client.py", line 21, in <module> cv2.imshow('Webcam', full_msg) TypeError: Expected Ptr<cv::UMat> for argument 'mat'