python - UDP视频流延迟 - OPENCV python
问题描述
我有流媒体视频 UDP,但数据包延迟且无序。这是我从 opencv 网站获取的参考代码。
但是当我让 Socket.Stream 使用 TCP 连接时,它可以正常传输并且帧是连续的。
服务器.py
import socket
import numpy
import time
import cv2
UDP_IP = "127.0.0.1"
UDP_PORT = 999
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
s=b''
while True:
data, addr = sock.recvfrom(46080)
s += data
if len(s) == (46080*20):
frame = numpy.fromstring (s,dtype=numpy.uint8)
frame = frame.reshape (480,640,3)
cv2.imshow('frame',frame)
s=b''
if cv2.waitKey(1) & 0xFF == ord ('q'):
break
客户端.py
import socket
import numpy as np
import cv2
UDP_IP = '127.0.0.1'
UDP_PORT = 999
cap = cv2.VideoCapture(0)
#cap.set(cv2.CAP_PROP_FRAME_WIDTH,320)
#cap.set(cv2.CAP_PROP_FRAME_HEIGHT,240)
def xrange(x):
return iter(range(x))
while (True):
ret, frame = cap.read()
cv2.imshow('frame', frame)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
d = frame.flatten()
s = d.tostring()
for i in xrange(20):
sock.sendto(s[i * 46080:(i + 1) * 46080], (UDP_IP, UDP_PORT))
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
解决方案
看起来脚本发送 UDP 帧的速度(比将它们拼凑在一起client.py
的速度要快得多) 。server.py
我不确定为什么会这样。也许在每次迭代后增加字节大小s
后,Python 需要找到一个新的存储位置s
,这会导致它丢失从client.py
. 但是,同步它们的一种方法是在确认收到帧client.py
后告诉发送。server.py
在下面的代码中,server.py
将通过b'eframe'
. server.py
将连续回复client.py
以b'n'
提示发送下一帧。client.py
将通过发送通知图像结束b'eframe'
服务器.py
import socket
import numpy
import time
import cv2
UDP_IP = "127.0.0.1"
UDP_PORT = 999
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
s=b''
while True:
data, addr = sock.recvfrom(6) # b'eframe' is 6 byte long
if data == b'sframe':
while True:
sock.sendto(b'n', addr)
data, addr = sock.recvfrom(46080)
if data == b'eframe':
break
s += data
if len(s) == (46080*20):
frame = numpy.fromstring (s,dtype=numpy.uint8)
frame = frame.reshape (480,640,3)
cv2.imshow('frame',frame)
s=b''
if cv2.waitKey(1) & 0xFF == ord ('q'):
break
客户端.py
import socket
import numpy as np
import cv2
UDP_IP = '127.0.0.1'
UDP_PORT = 999
cap = cv2.VideoCapture(0)
#cap.set(cv2.CAP_PROP_FRAME_WIDTH,320)
#cap.set(cv2.CAP_PROP_FRAME_HEIGHT,240)
def xrange(x):
return iter(range(x))
while (True):
ret, frame = cap.read()
cv2.imshow('frame', frame)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
d = frame.flatten()
s = d.tostring()
sock.sendto(b'sframe', (UDP_IP, UDP_PORT))
for i in xrange(20):
data, addr = sock.recvfrom(1) # b'n' is 1 byte long
if data == b'n':
sock.sendto(s[i * 46080:(i + 1) * 46080], (UDP_IP, UDP_PORT))
data, addr = sock.recvfrom(1)
sock.sendto(b'eframe', (UDP_IP, UDP_PORT))
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
推荐阅读
- java - 编译测试代码时找不到与JUnit相关的包
- python - AttributeError:模块 'utils' 没有属性 'init logging'
- java - 如何创建指数双精度值?
- java - 同一设备的两个版本中的相同应用程序
- javascript - Google Apps javascript 遍历多个数组
- git - AWK - 从 git status 命令解析第二列
- google-chrome - 几天以来,我无法在我的 SVG(谷歌浏览器)上选择或单击 html 标签
- javascript - highCharts 图例单击事件不适用于类型列
- prolog - 在序言中创建两个数字范围内的列表
- javascript - 将 websocket 连接到 mysql 数据库