使用Flask和OpenCV 实现树莓派与客户端的视频流传输与显示

使用 Python 和 OpenCV 实现树莓派与客户端的视频流传输与显示

在计算机视觉和物联网领域,经常需要将树莓派作为视频流服务器,通过网络将摄像头画面传输到客户端进行处理和显示。本文将详细介绍如何利用picamera2库、Flask 框架以及 OpenCV 库,实现树莓派端的视频流推送和客户端的视频流接收与显示。

一、前期准备

硬件准备

树莓派(建议树莓派 3 及以上版本),确保已安装操作系统(如 Raspbian)。

树莓派摄像头模块,正确连接到树莓派的 CSI 接口。我这里使用的是Zero 2W和Camera Module 3

客户端电脑,操作系统可以是 Windows、MacOS 或 Linux。

软件准备

在树莓派上:

确保系统已更新到最新版本,在终端执行sudo apt updatesudo apt upgrade -y

安装picamera2库,执行pip install picamera2

安装 Flask 框架,执行pip install flask

安装Pillow库(用于图像格式转换),执行pip install pillow

在客户端电脑上:

安装 Python 环境,建议使用 Python 3.x 版本。

安装OpenCV库,对于不同操作系统安装方式略有不同:

在 Windows 上,打开命令提示符,执行pip install opencv - python

在 MacOS 上,打开终端,执行pip install opencv - python

在 Linux 上,根据不同发行版,可能需要使用sudo apt - get install python3 - opencv等命令安装。

二、树莓派端操作

树莓派服务器端代码(使用 picamera2 库和 Flask 框架)

树莓派作为视频流服务器,利用picamera2库获取摄像头画面,并通过 Flask 框架将视频流以 HTTP 的形式提供给客户端。

复制代码
import io
from flask import Flask, Response
from picamera2 import Picamera2

app = Flask(__name__)


def generate_frames():
    picam2 = Picamera2()
    # 将格式改为RGB888,后续再转换为JPEG
    picam2.configure(picam2.create_preview_configuration(main={"format": "RGB888", "size": (640, 480)}))
    picam2.start()

    while True:
        stream = io.BytesIO()
        buffer = picam2.capture_array()
        from PIL import Image
        img = Image.fromarray(buffer)
        img.save(stream, format='JPEG')
        stream.seek(0)
        yield b'--frame\r\nContent-Type: image/jpeg\r\n\r\n' + stream.read() + b'\r\n'
        stream.close()


@app.route('/video_feed')
def video_feed():
    return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, threaded=True)

代码说明:

导入库 :导入ioFlaskResponsePicamera2等必要的库。io用于处理字节流,FlaskResponse用于构建 Web 服务器,Picamera2用于控制树莓派摄像头。

摄像头配置与初始化 :使用Picamera2创建摄像头对象picam2,配置其输出格式为RGB888,分辨率为(640, 480),并启动摄像头。

生成视频帧 :在generate_frames函数中,通过picam2.capture_array获取摄像头的图像数组,使用PIL库将数组转换为图像对象并保存为 JPEG 格式到字节流stream中,然后将字节流数据以特定格式作为视频帧输出。

定义路由 :使用@app.route装饰器定义/video_feed路由,返回由generate_frames函数生成的视频流响应。

启动 Flask 应用 :在if __name__ == '__main__':条件下,启动 Flask 应用,监听所有 IP 地址(host='0.0.0.0),端口为5000

操作步骤

打开树莓派的终端。

使用文本编辑器(如nano)创建一个新的 Python 文件,例如video_server.py,命令为nano ``video_server.py

将上述代码逐行复制粘贴到video_server.py文件中。

按下Ctrl + X,然后按Y,再按Enter保存并退出文件。

在终端中执行python3 ``video_server.py运行该程序。此时树莓派开始通过摄像头采集视频流,并通过 Flask 应用将其提供在http://0.0.0.0:5000/video_feed地址上。注意记录树莓派的 IP 地址,可在终端执行hostname -I查看。

三、电脑端操作

客户端代码(使用 OpenCV 和 urllib 库)

客户端电脑通过 Python 的cv2(OpenCV)库和urllib.request库从树莓派服务器获取视频流并进行显示。

python 复制代码
import cv2
import urllib.request
import numpy as np

# 视频流的URL,即树莓派的IP地址
url = 'http://192.168.3.90:5000/video_feed'

# 打开URL
stream = urllib.request.urlopen(url)

# 用于存储视频流数据的字节数组
bytes_data = bytearray()

while True:
    # 读取视频流数据
    bytes_data += stream.read(1024)
    # 查找帧的起始位置
    a = bytes_data.find(b'\xff\xd8')
    b = bytes_data.find(b'\xff\xd9')
    if a != -1 and b != -1:
        # 提取一帧图像数据
        frame_data = bytes_data[a:b+2]
        # 从字节数据中删除已处理的部分
        bytes_data = bytes_data[b+2:]
        # 将字节数据转换为numpy数组
        frame = np.asarray(bytearray(frame_data), dtype=np.uint8)
        # 解码图像帧
        frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
        # 显示图像帧
        cv2.imshow('Video Stream', frame)
        # 等待按键事件,25毫秒
        if cv2.waitKey(25) & 0xFF == ord('q'):
            break

# 关闭窗口
cv2.destroyAllWindows()

代码说明:

导入库 :导入cv2urllib.requestnumpy库。cv2用于图像和视频处理,urllib.request用于网络请求,numpy用于处理数组数据。

设置视频流 URL :将url变量设置为树莓派服务器提供的视频流 URL。需将http://192.168.3.90:5000/video_feed中的 IP 地址替换为树莓派实际的 IP 地址。

打开 URL :使用urllib.request.urlopen打开 URL,获取视频流数据的流对象stream

读取和处理视频流数据 :循环读取stream中的数据并添加到bytes_data中,查找 JPEG 图像帧的起始和结束标记(\xff\xd8\xff\xd9),提取一帧图像数据,转换为numpy数组并使用cv2.imdecode解码为 OpenCV 可处理的格式。

显示视频帧 :使用cv2.imshow显示解码后的图像帧,并通过cv2.waitKey等待按键事件,按下q键时退出循环。

关闭窗口 :循环结束后,使用cv2.destroyAllWindows关闭所有 OpenCV 窗口。

操作步骤

  1. 通过 Python 代码接收视频流

打开客户端电脑的命令行终端(Windows 下为命令提示符或 PowerShell,MacOS 和 Linux 下为终端)。

使用文本编辑器(如 Windows 的 Notepad++、MacOS 的 TextEdit 需设置为纯文本模式、Linux 的gedit等)创建一个新的 Python 文件,例如video_client.py

将上述代码逐行复制粘贴到video_client.py文件中,特别注意将url变量中的 IP 地址替换为树莓派的实际 IP 地址。

保存video_client.py文件。

在终端中切换到保存video_client.py文件的目录,执行python ``video_client.py(如果使用的是 Python 3,可能需要执行python3 ``video_client.py)。此时客户端电脑将从树莓派服务器获取视频流,并在 OpenCV 窗口中显示树莓派摄像头捕捉到的画面。按q键可关闭视频显示窗口。

  1. 通过浏览器查看视频流

打开客户端电脑上的任意浏览器,如 Chrome、Firefox 等。

在浏览器地址栏中输入树莓派的视频流地址,格式为http://树莓派IP地址:5000/video_feed。例如,如果树莓派的 IP 地址是192.168.1.100,则输入http://192.168.1.100:5000/video_feed

按下回车键,浏览器将尝试加载树莓派摄像头的视频流画面。如果网络连接正常且树莓派服务器运行正常,应该能看到实时的视频画面。

部分浏览器可能会对视频流显示有兼容性问题。如果遇到无法正常显示的情况,可以尝试更换浏览器,或者检查浏览器是否阻止了某些内容加载。另外,确保树莓派服务器的防火墙设置允许外部访问端口5000。如果树莓派开启了防火墙,可能需要执行sudo ufw allow 5000命令(适用于使用ufw防火墙的情况)来允许外部访问该端口。

在实际应用中,确保树莓派和客户端电脑处于同一网络环境,并且客户端电脑能够访问树莓派的 IP 地址。通过上述代码及操作步骤,即可实现树莓派到客户端的视频流传输与显示功能。

相关推荐
月亮月亮要去太阳14 分钟前
python画图文字显示不全+VScode新建jupyter文件
开发语言·python
YoloMari14 分钟前
Leetcode刷题-枚举右,维护左
python·算法·leetcode
邪恶的贝利亚38 分钟前
prompt工程起步
开发语言·python·prompt
山居秋暝LS1 小时前
目标跟踪之DeepSort算法(4)
pytorch·python
Mountain and sea2 小时前
焊接机器人与线激光视觉系统搭配的详细教程
人工智能·opencv·机器人
灏瀚星空2 小时前
高效图像处理工具:从需求分析到落地实现
图像处理·人工智能·经验分享·python·学习方法
安冬的码畜日常2 小时前
【AI 加持下的 Python 编程实战 2_02】第一章:利用 GitHub Copilot 叩开 AI 辅助编程的大门
人工智能·python·ai·copilot·ai助手·ai应用·ai辅助编程
java_python源码2 小时前
【2025】基于python+django的慢性病健康管理系统(源码、万字文档、图文修改、调试答疑)
数据库·python·django
abckingaa2 小时前
python开发订单查询功能(flask+orm bee)
python·orm·bee
Terrence Shen2 小时前
跟着AI复习一下pytorch原理和操作
人工智能·pytorch·python·深度学习·算法·机器学习