网络上的信息比较老,很多都是把树莓派作为服务器端,而且新系统,树莓派需要构建虚拟环境。
1 树莓派构建虚拟环境
1、下载python虚拟环境的支持包
运行命令
sudo apt-get install python3-venv
2、创建虚拟环境
后面的myenv是虚拟环境的名字,可以自己命名
python3 -m venv myenv
3、激活虚拟环境
按照路径打开bin,找到activate,复制绝对路径,再运行命令
source /home/Pi/yolo/bin/activate
此时激活了虚拟环境,就可以使用pip来安装了,注意pip也需要换源
直接一行命令永久换源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
4、安装客户端依赖:
pip install opencv-python
pip install Flask-SocketIO
pip install requests
pip install websocket-client
客户端代码如下:
import cv2
import socketio
import numpy as np
import base64
import time
sio = socketio.Client(reconnection=True, reconnection_attempts=5, reconnection_delay=1)
@sio.event
def connect():
print('连接到服务器')
@sio.event
def disconnect():
print('断开连接')
def send_frame(frame):
_, buffer = cv2.imencode('.jpg', frame, [int(cv2.IMWRITE_JPEG_QUALITY), 90])
if _:
jpg_as_text = base64.b64encode(buffer).decode('utf-8')
sio.emit('video_frame', jpg_as_text)
else:
print("JPEG编码失败")
def main():
cap = cv2.VideoCapture(0) # 使用USB摄像头
#cap.set(6,cv2.VideoWriter.fourcc('M','J','P','G'))
cap.set(3,640)
cap.set(4,480)
#cap.set(5,15)
server_url = 'server IP +: port'
while True:
try:
sio.connect(server_url)
print('连接成功')
while True:
ret, frame = cap.read()
if ret:
send_frame(frame)
else:
print("摄像头读取失败")
break
except socketio.exceptions.ConnectionError as e:
print(f'连接错误: {e}')
except Exception as e:
print(f'发生异常: {e}')
finally:
sio.disconnect()
cap.release()
print('正在尝试重新连接...')
time.sleep(1) # 等待5秒后重连
cap = cv2.VideoCapture(0) # 重新初始化摄像头
if __name__ == '__main__':
main()
服务器端:依赖同客户端,不需要python-opencv
代码如下:
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, cors_allowed_origins="*")
@socketio.on('video_frame')
def handle_video_frame(data):
emit('video_frame', data, broadcast=True)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
socketio.run(app, host='ip -server', port= "your port")
按照flask 要求,服务器端项目目录下,建立templates 目录,建立index.html模版:
<!DOCTYPE html>
<html>
<head>
<title>实时视频</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
<script type="text/javascript" charset="utf-8">
var socket = io(IPserver: port'); // 推荐使用不带connect的写法
socket.on('video_frame', function (data) {
var img = document.getElementById('video');
img.src = 'data:image/jpeg;base64,' + data;
});
</script>
</head>
<body>
<h1>实时视频</h1>
<img id="video" src="" width="1290" height="720"/>
</body>
分别运行client,server 在http: iP+ 端口中即可用浏览器看到视频
视频对带宽要求不高,在网络条件下不错,可以客户端设置jpg压缩质量,目前是90,可以降低,基本没有滞后,该代码比网上很多把树莓派作为服务器端的效率好很多。