python udp发送数据(http视频传输)

一、前言最近想写一个实时的视频传输程序,然后上网找了很久没有找到合适的我想用OpenCV进行图像采集,然后用pygame将视频信号转化为可通过UDP网络传输的字符流,然后到达终端后再通过pygame对字符流进行解析,进而将图像显示出来之所以使用UDP传输而不是TCP传输,是因为UDP在视频传输方面拥有快速、无需连接等优点,适合密集传送大量信息的场合但UDP传输有一个问题,…

大家好,又见面了,我是你们的朋友全栈君。

一、前言

最近想写一个实时的视频传输程序,然后上网找了很久没有找到合适的

我想用OpenCV 进行图像采集,然后用pygame 将视频信号转化为可通过UDP 网络传输的字符流,然后到达终端后再通过pygame 对字符流进行解析,进而将图像显示出来

之所以使用UDP 传输而不是TCP 传输,是因为UDP 在视频传输方面拥有快速、无需连接等优点,适合密集传送大量信息的场合
但UDP 传输有一个问题,就是一次传输量有限,这就直接导致后续传输的视频信号需要进行一定压缩

所以我就开始自己捣鼓了 ?

本文内容若有不懂可查阅如下教程:
Windows 安装pygame 模块
树莓派 与 Xbox360手柄 基于pygame 的一次邂逅
树莓派Camera 的使用
【手把手教学—超简单】树莓派安装OpenCV 3
Python + OpenCV 学习笔记(二)>>> 加载视频流
Python >>> UDP 网络编程

我是用树莓派作为视频采集端,然后笔记本作为信号接收端的


注意:PC端需关闭防火墙后方可成功接收数据!

在这里插入图片描述

二、开始

1)整体思路

  1. 在发送端使用OpenCV 打开摄像头采集视频帧信号;
  2. 将视频帧信号输出为jpg 图片文件;
  3. pygame 模块将该jpg 图片转化为字符流;
  4. 将该字符流通过UDP 传输到接收端;
  5. 接收端同样使用pygame 对字符流进行解析,最终即可获得图像信息。

2)摄像头采集视频帧

import cv2 as cv

capture = cv.VideoCapture(0)
while True:
	# 获得图像帧
	ret, frame = capture.read()
	# 图像翻转
	frame = cv.flip(frame, -1)
	# 将图像尺寸缩小,便于传输
	frame = cv.resize(frame, (160, 120))

3)将图像帧输出为图片

cv.imwrite("test.jpg", frame)

4)将图片转化为字符流

# 加载图片
Img = pygame.image.load('/home/pi/test.jpg')
# 图片转化字符串
string = pygame.image.tostring(Img, "RGB")

5)通过UDP 传输字符流

我创建了一个进程用于传输数据:

def mythread(sock, data, addr):
        sock.sendto(data, addr)
        print("已发送 " + str(len(data)) + " bytes")
        sock.close()

# socket.SOCK_DGRAM 代表是使用UDP协议
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
t = threading.Thread(target=mythread, args=(sock, string, ('192.168.0.196', 9999)))
t.start()

注意:当发送密集数据时,如图像数据等。需要控制图像大小(例如160*120),不然发不出去。

6)接收端接收数据并解析

# 创建连接
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定端口
s.bind(('192.168.0.196', 9999))
# 接收数据
data, addr = s.recvfrom(60000)

# 字符串再转化为图片
img = pygame.image.frombuffer(data, (180, 160), "RGB")

7)将图像显示出来

# 窗口内设置白色底色和图片,并更新显示
gameDisplay.fill(WHITE)
gameDisplay.blit(img, (0, 0))
pygame.display.update()

三、完整程序

1)发送端

#coding:utf-8
import pygame
import cv2 as cv
from picamera import PiCamera
import time
import threading
import socket

pygame.init()

# 传输视频信号的UDP 连接进程
def mythread(sock, data, addr):
        sock.sendto(data, addr)
        print("已发送 " + str(len(data)) + " bytes")
        sock.close()

def main():
        print("begin")
        start = time.clock()
        capture = cv.VideoCapture(0)
        while True:
                ret, frame = capture.read()
                frame = cv.flip(frame, -1)
                frame = cv.resize(frame, (160, 120))
                cv.imwrite("test.jpg", frame)
                # 加载图片
                Img = pygame.image.load('/home/pi/test.jpg')
                # 图片转化字符串
                string = pygame.image.tostring(Img, "RGB")
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                t = threading.Thread(target=mythread, args=(sock, string, ('192.168.0.196', 9999)))
                t.start()
                if cv.waitKey(10) & 0xff == ord('q'):
                        break

main()
cv.destroyAllWindows()

2)接收端

#coding=utf-8
import socket
import time
import threading
import pygame

# 颜色
WHITE = (255,255,255)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 128)
BLACK = ( 0, 0, 0)

# 创建连接
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定端口
s.bind(('192.168.0.196', 9999))

print('Waiting for connection...')

pygame.init()

# 设置标题
pygame.display.set_caption('UDP 视频传输')

# 开启窗口
display_width = 300
display_height = 200
gameDisplay = pygame.display.set_mode((display_width,display_height))

# 判断是否结束pygame
gamefinish = False
# 帧率
frame_rate = 0

# 通过字体文件获得字体对象
fontObj = pygame.font.Font('C:/Windows/Fonts/comici.ttf', 20)
# 配置要显示的文字
textSurfaceObj = fontObj.render('FPS', True, BLACK, WHITE)
# 获得要显示的对象的rect
textRectObj = textSurfaceObj.get_rect()
# 设置显示对象的坐标
textRectObj.center = (200, 10)

# 用于视频显示delay
clock = pygame.time.Clock()
# 用于帧率计算
start = time.perf_counter()

while not gamefinish:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gamefinish = True
            print(event)

    # 无数据接收则线程挂起,等待数据
    data, addr = s.recvfrom(60000)
    frame_rate = frame_rate + 1
    if time.perf_counter() - start > 1:
        start = time.perf_counter()
        # 配置要显示的文字
        textSurfaceObj = fontObj.render(("FPS: " + str(frame_rate)), True, BLACK, WHITE)
        frame_rate = 0

    print('Received from %s:%s.' % addr)

    # 字符串再转化为图片
    img = pygame.image.frombuffer(data, (160, 120), "RGB")

    # 窗口内设置白色底色和图片,并更新显示
    gameDisplay.fill(WHITE)
    gameDisplay.blit(img, (0, 0))
    gameDisplay.blit(textSurfaceObj, textRectObj)
    pygame.display.update()
    clock.tick(60)

pygame.quit()

四、结果

在实际测试中,我发现160*120的分辨率对网络要求较高,而当分辨率降为80*60时则效果好一点(帧率基本在30左右):
当然,这样的话视频窗口显得很小。

在这里插入图片描述
我们可以在接收端对图像进行放大:
(成像质量下降)

# 指定size 放大
img = pygame.transform.scale(img, (160, 120))
# 直接放大两倍
img = pygame.transform.scale2x(img)

在这里插入图片描述


在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/128978.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 校花网爬取校花照片

    校花网爬取校花照片"""今天我们开始尝试,第一次学习爬虫的第一个案例,去校花网上爬取一些校花的照片"""fromrequests_htmlimportH

  • Werkzeug框架

    Werkzeug框架在我们使用Flask以及Werkzeug框架的过程中,经常会遇到如下三个概念:Local、LocalStack和LocalProxy。尤其在学习Flask的RequestContext和AppContext的过程中,这几个概念出现的更加频繁,另外很多Flask插件都会使用这三个概念对应的技术。那么这三个东西到底是什么?我们为什么需要它们?以及如何使用呢?本篇文章主要就是来解答这些问题。…

  • linux chmod 755

    linux chmod 755chmod是Linux下设置文件权限的命令,后面的数字表示不同用户或用户组的权限。一般是三个数字:第一个数字表示文件所有者的权限第二个数字表示与文件所有者同属一个用户组的其他用户的权限第三个数字表示其它用户组的权限。权限分为三种:读(r=4),写(w=2),执行(x=1)。综合起来还有可读可执行(rx=5=4+1)、可读可写(rw=6=4+2)、可读可写可执行(rwx=7=4+2+1)。所以,ch…

  • Raid0、Raid1、Raid5及Raid10的区别

    Raid0、Raid1、Raid5及Raid10的区别一、概况Raid(RedundantArrayofIndepentDisk独立冗余磁盘阵列)技术是加州大学伯克利分校1987年提出,最初是为了组合小的廉价磁盘来代替大的昂贵磁盘,同时希望磁盘失效时不会对数据的访问造成影响而开发的数据保护技。raid就是由多块磁盘构成的冗余阵列,在操作系统下是作为一个独立的大型存储设备出现的。它可以充分发挥出多块硬盘的优势,可以提升硬盘的读写速度,提高硬盘的利用率,日工容错功能确保数据的安全性,易于管理等优点。在任何一块硬盘出现问题的情况下都可以继续工作,不受损

  • LaTeX 插入图片失败[通俗易懂]

    LaTeX 插入图片失败[通俗易懂]LaTeX插入图片失败(引擎pdflatex)\includegraphics使用figure环境本身可正常编译,只使用\centering时\caption可正常插入。增加\includegraphics[width=10cm]{..}插入png图片时,报错100行,第101行报“Toomanyerrors.TeXstopped.”(已\usepackage{graphicx},不是旧包graphics的问题)几种报错语句重复出现,可能是循环错。“Missinge

  • update Google play services_apfs for windows

    update Google play services_apfs for windows原文首发:http://mobileside.cn/post/2010/02/10/GoogleBuzzForWindowsPhone.aspx  昨天晚上,google推出了他们的Buzz产品。什么是Buzz,简单点说,他就是把微博服务和他的地图以及邮件结合到了一起,其实这是一个很典型的LBS。下载地址为:http://www.google.com/gmm/Google

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号