我正在尝试通过套接字通信以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()
提前谢谢!
答案 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()