Python树莓派利用UDP传输视频帧实现远程监控

陆景行
陆景行
发布时间:2026-10-13| 6人浏览过
原创

本文详解如何在树莓派上使用Python通过UDP协议传输视频帧至PC,实现低成本远程监控。针对UDP包大小限制,采用OpenCV进行JPEG编码压缩,解决图像数据分片问题。文章提供了树莓派发送端与PC接收端的完整代码,涵盖Socket创建、图像编解码、字节流处理及异常退出机制,并分析了实际测试中的阻塞与摄像头连接问题。

UDP视频帧传输背景与目标

本文详细介绍在Python环境下,利用树莓派通过UDP协议传输视频帧的具体操作方法。

由于作者未在笔记本电脑上成功安装OpenCV-Contrib模块,无法使用人脸识别等高级功能,但树莓派已安装成功。因此,作者尝试将树莓派采集的视频帧传输至PC,旨在省去为树莓派配备显示屏的麻烦,并为未来的远程监控应用提供解决方案。

传输协议选择:UDP与TCP对比

1 选择UDP还是TCP传输协议

首先需确定传输方式。虽然TCP使用广泛,但视频帧传输对速度要求高于准确性。视频数据量大且帧间隔短,需优先保证传输速度,允许少量数据丢失。TCP需维护连接并确保数据包正确性,耗时较长;而UDP不关心连接建立及数据是否准确接收,仅关注发送,因此更适合视频传输。

从Python的socket代码可直观体现UDP特性。发送方通过server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)创建UDP套接字对象,随后执行server.connect((HOST,PORT))指定发送方地址。与TCP不同,connect函数直接返回,不等待连接成功,随后即可在套接字对象上调用send函数发送数据,整个过程未确立连接。

图像传输的编解码处理

2 图像传输中的编解码处理

使用UDP传输图像需考虑数据大小。根据UDP协议,单个包最大数据量为65507字节(不含包头)。以逻辑C270摄像头为例,单幅图像大小为480X640X3字节,远超UDP包限制,无法单次发送。解决方法有两种:一是将图像拆分为多次发送,接收端循环接收,虽能完整接收但速度受影响且需自定义规则;二是发送前对图像进行编码压缩,接收后解码,虽清晰度略降但能保持速度优势,更为合适。

OpenCV中的imencode和imdecode方法分别用于图像编码和解码。imencode根据指定标识将图像数据编码并存入缓冲区,函数原型为cv2.imencode(ext, img[, params]) → retval, buf。其中ext为文件扩展名(如'.jpg'),img为待编码图像数据,params为编码标识,形式为paramId_1, paramValue_1, paramId_2, paramValue_2, ... ,。对于jpg格式,可指定标识为CV_IMWRITE_JPEG_QUALITY,值在0到100之间,值越大压缩率越高,编码后数据量越小,但解码后图像质量越差。

imdecode从缓冲区读取图像数据,通过指定标识实现指定解码格式。其函数原型为cv2.imdecode(buf, flags) → retval,flags指定图像读取类型,即指定以多少深度多少通道读取图像。例如,CV_LOAD_IMAGE_ANYDEPTH(整数2)表示单通道、深度不变的灰度图;CV_LOAD_IMAGE_COLOR(整数1)表示3通道、8位深度的彩色图。

树莓派发送端代码实现

3 树莓派发送端程序实现

结合套接字对象和编解码函数编写发送端代码时,需注意数据格式。套接字的收发均为字节流(byte数组),发送时需以字节流格式发送,接收后需转换为合适的数据类型。

从摄像头获取的图像为480X640X3的numpy.ndarray类型,经imencode编码后得到?X1的numpy.ndarray对象,测试表明该对象可直接发送。接收端获得的byte数组直接作为imdecode参数会报错,经调试需转换为numpy.ndarray类型。树莓派作为发送端,其Python代码如下:


import cv2
import numpy
import socket
import struct
HOST='192.168.1.122'
PORT=9999
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #socket对象
server.connect((HOST,PORT))
print('now starting to send frames...')
capture=cv2.VideoCapture(0) #VideoCapture对象,可获取摄像头设备的数据
try:
  while True:
    success,frame=capture.read()
    while not success and frame is None:
      success,frame=capture.read() #获取视频帧
  result,imgencode=cv2.imencode('.jpg',frame,[cv2.IMWRITE_JPEG_QUALITY,50]) #编码
  server.sendall(struct.pack('i',imgencode.shape[0])) #发送编码后的字节长度,这个值不是固定的
  server.sendall(imgencode) #发送视频帧数据
  print('have sent one frame')
except Exception as e:
  print(e)
  server.sendall(struct.pack('c',1)) #发送关闭消息
  capture.release()
  server.close()

代码中首先发送编码后的字节长度,供接收端进行简单校验,并据此判断是否关闭程序。自定义单字节的1作为关闭消息。

PC接收端代码实现

4 PC端接收程序实现

PC作为接收端,为解码数据,需将原始字节流转为numpy.ndarray对象,具体代码如下:


import cv2
import numpy
import socket
import struct
HOST='192.168.191.122'
PORT=9999
buffSize=65535
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #创建socket对象
server.bind((HOST,PORT))
print('now waiting for frames...')
while True:
  data,address=server.recvfrom(buffSize) #先接收的是字节长度
  if len(data)==1 and data[0]==1: #如果收到关闭消息则停止程序
    server.close()
    cv2.destroyAllWindows()
    exit()
  if len(data)!=4: #进行简单的校验,长度值是int类型,占四个字节
    length=0
  else:
    length=struct.unpack('i',data)[0] #长度值
  data,address=server.recvfrom(buffSize) #接收编码图像数据
  if length!=len(data): #进行简单的校验
    continue
  data=numpy.array(bytearray(data)) #格式转换
  imgdecode=cv2.imdecode(data,1) #解码
  print('have received one frame')
  cv2.imshow('frames',imgdecode) #窗口显示
  if cv2.waitKey(1)==27: #按下“ESC”退出
    break
server.close()
cv2.destroyAllWindows()

测试过程与常见问题分析

5 测试与问题排查

由于树莓派上的OpenCV仅关联Python2,故以python2 UDP_Frame_Send.py命令启动发送程序(连接摄像头);PC端通过开始菜单输入cmd进入控制台,进入程序目录后输入python UDP_Frame_Recv.py启动接收程序。测试结果显示窗口显示较流畅,但存在两个问题:一是树莓派上程序有时无法打开摄像头,需重启几次;二是PC端recvfrom函数为阻塞式,Windows控制台无法用键盘中断强制退出,若发送端出错,接收端程序无法正常退出。对此,可通过TCP&UDP调试助手手动发送单个字节的1来终止程序。

更多关于Python相关内容可查看本站专题:《Python Socket编程技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。