首页 > 解决方案 > 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()

在此处输入图像描述

标签: pythonsocketsopencvudp

解决方案


看起来脚本发送 UDP 帧的速度(比将它们拼凑在一起client.py的速度要快得多) 。server.py我不确定为什么会这样。也许在每次迭代后增加字节大小s后,Python 需要找到一个新的存储位置s,这会导致它丢失从client.py. 但是,同步它们的一种方法是在确认收到帧client.py后告诉发送。server.py

在下面的代码中,server.py将通过b'eframe'. server.py将连续回复client.pyb'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()

推荐阅读