使用Flask和OpenCV 实现树莓派与客户端的视频流传输与显示
使用 Python 和 OpenCV 实现树莓派与客户端的视频流传输与显示
在计算机视觉和物联网领域,经常需要将树莓派作为视频流服务器,通过网络将摄像头画面传输到客户端进行处理和显示。本文将详细介绍如何利用picamera2库、Flask 框架以及 OpenCV 库,实现树莓派端的视频流推送和客户端的视频流接收与显示。
一、前期准备
硬件准备
树莓派(建议树莓派 3 及以上版本),确保已安装操作系统(如 Raspbian)。
树莓派摄像头模块,正确连接到树莓派的 CSI 接口。我这里使用的是Zero 2W和Camera Module 3

客户端电脑,操作系统可以是 Windows、MacOS 或 Linux。
软件准备
在树莓派上:
确保系统已更新到最新版本,在终端执行sudo apt update和sudo 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)
代码说明:
导入库:导入io、Flask、Response、Picamera2等必要的库。io用于处理字节流,Flask和Response用于构建 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库从树莓派服务器获取视频流并进行显示。
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()
代码说明:
导入库:导入cv2、urllib.request、numpy库。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 窗口。
操作步骤
- 通过 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键可关闭视频显示窗口。
- 通过浏览器查看视频流
打开客户端电脑上的任意浏览器,如 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 地址。通过上述代码及操作步骤,即可实现树莓派到客户端的视频流传输与显示功能。
