使用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 地址。通过上述代码及操作步骤,即可实现树莓派到客户端的视频流传输与显示功能。

相关推荐
小白学大数据5 分钟前
如何避免爬虫因Cookie过期导致登录失效
开发语言·爬虫·python·scrapy
测试老哥16 分钟前
接口测试和功能测试详解
自动化测试·软件测试·python·功能测试·测试工具·测试用例·接口测试
小白学大数据1 小时前
Python自动化解决滑块验证码的最佳实践
开发语言·python·自动化
数据与后端架构提升之路1 小时前
深度解析如何将图像帧和音频片段特征高效存储到向量数据库 Milvus
数据库·opencv·音视频
Albert Edison1 小时前
Python入门基础
开发语言·python
时光旅人01号1 小时前
I-CON: A Unifying Framework for Representation Learning
python
T0uken1 小时前
【Python】Matplotlib:立体永生花绘制
开发语言·python·matplotlib
HHONGQI1231 小时前
嵌入式人工智能应用-第三章 opencv操作8 图像特征之 Haar 特征
人工智能·opencv·计算机视觉
猿饵块1 小时前
opencv--图像滤波
图像处理·opencv·计算机视觉
豌豆花下猫1 小时前
Python 3.14 t-string 要来了,它与 f-string 有何不同?
后端·python·ai