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)
blank

相关推荐

  • MySQL使用AUTO_INCREMENT列的表注意事项之update自增列篇

    MySQL使用AUTO_INCREMENT列的表注意事项之update自增列篇

  • ORACLE备份恢复

    ORACLE备份恢复目录一、关于备份与恢复 二、逻辑备份(expdp和impdp) 三、物理备份 四、数据库日常备份计划及脚本参考一、关于备份与恢复1、备份定义备份就是把数据库复制到转储设备的过程。其中,转储设备是指用于放置数据库副本的磁带或磁盘。通常也将存放于转储设备中的数据库的副本称为原数据库的备份或转储。备份是一份数据副本2、备份分类从物理与逻辑的角度来分类:从物理与逻辑的,备份可以分为物理备份和逻辑备份。物理备份:对数据库操作系统的物理文件(数据文件,控制文件和日志文件)的备份。物…

  • android expandablelistview横向,expandableListView 总结[通俗易懂]

    android expandablelistview横向,expandableListView 总结[通俗易懂]实现效果图:expandableListViewgroupIndicator图片默认是在左边,而且比较难看,而我要的是实现groupIndicator在右边自定义图片,换图片最简单的就是直接copy系统@android:drawable/expander_group?android:attr/expandableListPreferredItemIndicatorLeft?android…

  • vue文件夹上传_vue上传文件前端完整实例

    vue文件夹上传_vue上传文件前端完整实例在项目中我们使用input标签设置type属性为file,上传文件后需要清空选中的文件,<inputtype=”file”ref=”clearFile”name=”file”id=”file”><button@click=”clearFile”></button><script>methods:{clearFile(){ this.$refs.clearFile.value=”;//清空file文件}}&

  • 互联网医疗行业PEST分析实践「建议收藏」

    互联网医疗行业PEST分析实践「建议收藏」Python微信订餐小程序课程视频https://edu.csdn.net/course/detail/36074Python实战量化交易理财系统https://edu.csdn.net/course/detail/35475前言今年开始逐步切入产品与数据工作,完全脱离了原来的舒适区,确实有一些挑战。开始以为只做数仓建设的事情,就仓促的学习了一些数仓相关的知识,但没搞多久,还要负责公司BI的工作,又开始补习数分相关的知识。BI其实比数仓建设更有挑战性,数仓建设已经有非常成熟的体系了,市面上有很多

  • pycharm中安装第三方库出现错误_pycharm常用第三方库

    pycharm中安装第三方库出现错误_pycharm常用第三方库我在命令行窗口用pipinstall库名的时候,ModuleNotFoundError:Nomodulenamed‘pip._internal.cli.main’这是在pycharm里报的错Traceback(mostrecentcalllast):File“f:\python\lib\runpy.py”,line193,in_run_module_as_main“main”,mod_spec)File“f:\python\lib\ru

发表回复

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

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