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)

在这里插入图片描述


在这里插入图片描述

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • sql prompt linux,SQL PROMPT的设置[通俗易懂]

    sql prompt linux,SQL PROMPT的设置[通俗易懂]–10g中一般的SQLPROMPT都是’>’,为了让我们的提示符显示的更有意义,以便我们在做一些操作时可以明确我们所处的位置,采用以下方法,更改我们的SQLPROMPT。SQL>DEFINEDEFINE_DATE=”12-3月-09″(CHAR)DEFINE_CONNECT_IDENTIFIER=”orcl”(CHAR)DEFINE_USE…

    2022年7月26日
    7
  • ios分屏_【iOS越狱】越狱源+插件整理更新

    ios分屏_【iOS越狱】越狱源+插件整理更新UN 官网 https unc0ver dev UN 开源 https github com pwn20wndstuf Undecimus releases 插件查询作者源 https www ios repo updates com 插件兼容性查询 https jlippold github io tweakCompati 自制 cydia 商店源 https www

    2025年9月29日
    4
  • pytest skipif_pytest失败重跑

    pytest skipif_pytest失败重跑前言pytest.mark.skip可以标记无法在某些平台上运行的测试功能,或者您希望失败的测试功能Skip和xfail:处理那些不会成功的测试用例你可以对那些在某些特定平台上不能运行的测试用

    2022年7月31日
    8
  • Nginx学习——Nginx简单介绍和Linux环境下的安装

    Nginx 是一个俄罗斯的哥们开发的,并将其进行了开源。Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝

    2022年2月26日
    297
  • Java 手写签字去除背景 背景透明「建议收藏」

    Java 手写签字去除背景 背景透明「建议收藏」Java 手写签字去除背景 背景透明/** * 白底照片去除白底 形成透明底图片 * @param file 需要去除背景的图片 * @param Path 去除背景后保存图片的路径 * @return true 则去除成功 ,false 则失败 */public static boolean localImgToAlpha(File file, String Path) { try { BufferedImage bi = ImageIO.read(new F

    2022年8月19日
    8
  • Netty权威指南_ck2威望代码

    Netty权威指南_ck2威望代码学习《netty权威指南时》发现有的代码有误,我都更正了一下,可运行的代码可以访问我的github:https://github.com/wangdecheng/mycodes/tree/master/src/main/java/netty

    2022年9月27日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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