我有一个
video
元素whos-src被设置为我的网络摄像头的提要。这是使用OpenCV(opencvjs)完成的。
使用opencv,我读取一个帧并将其渲染为
canvas
.
然后,我从画布上读取数据,并使用
socketio
一、
emit
到我的服务器应用程序,这是一个Flask应用程序,作为base64。。。
服务器端,我捕获传入的视频帧,从base64解码,做一些处理,重新编码为base64,并将其发送回客户端。
这整个base64->图像->base64是无稽之谈,效率极低。然而,这是我的第一个Flask应用程序,我已经很多年没有真正接触过web开发了,所以我在这里有点困惑。
我如何将视频从浏览器发送到服务器,进行处理,然后在不进行所有base64转换的情况下将其发送回客户端?我正在寻找一种更有效的方法来做到这一点。
这是我的代码:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="../static/jquery-3.5.1.min.js" ></script>
<script type="text/javascript" src="../static/index.js"></script>
<script type="text/javascript" src="../static/socket.io.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-8 offset-lg-2">
<h3 class="mt-5">Live Streaming</h3>
<video style="display: none;" id="videoInput"></video>
</div>
</div>
<div class="row">
<div class="col-lg-8 offset-lg-2">
<h3 class="mt-5">Edited video</h3>
<canvas class="center-block" id="canvasOutput" width=320 height=240></canvas>
</div>
</div>
<div class="row">
<div class="col-lg-8 offset-lg-2">
<h3 class="mt-5">SOCKETIO IMAGES</h3>
<img id="imagebox" src="" width="320" height="240">
</div>
</div>
</div>
<script src="../static/opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
</body>
</html>
index.js
let video = null;
let width = 320;
let height = 0;
let src = null;
let dst = null;
let streaming = false;
let stream = null;
let vc = null;
let socket = null;
function processVideo() {
vc.read(src);
cv.imshow("canvasOutput", src);
var type = "image/png"
var data = document.getElementById("canvasOutput").toDataURL(type);
data = data.replace('data:' + type + ';base64,', '');
socket.emit('image', data);
requestAnimationFrame(processVideo);
}
function stopVideoProcessing() {
if (src != null && !src.isDeleted()) src.delete();
}
function stopCamera() {
if (!streaming) return;
stopVideoProcessing();
document.getElementById("canvasOutput").getContext("2d").clearRect(0, 0, width, height);
video.pause();
video.srcObject=null;
stream.getVideoTracks()[0].stop();
streaming = false;
}
function startVideoProcessing() {
if (!streaming) { console.warn("Please startup your webcam"); return; }
stopVideoProcessing();
src = new cv.Mat(height, width, cv.CV_8UC4);
requestAnimationFrame(processVideo);
}
function startCamera() {
if (streaming) return;
navigator.mediaDevices.getUserMedia({video: true, audio: false})
.then(function(s) {
stream = s;
video.srcObject = s;
video.play();
})
.catch(function(err) {
console.log("An error occured! " + err);
});
video.addEventListener("canplay", function(ev){
if (!streaming) {
height = video.videoHeight / (video.videoWidth/width);
video.setAttribute("width", width);
video.setAttribute("height", height);
streaming = true;
vc = new cv.VideoCapture(video);
}
startVideoProcessing();
}, false);
}
function onOpenCvReady() {
console.log('OpenCV.js is readyyyyy.');
}
$( document ).ready(function() {
console.log('document ready');
video = document.getElementById("videoInput");
video.width = 640;
video.height = 480;
startCamera();
socket = io('http://localhost:8080');
socket.on('connect', function(){
console.log("Connected...!", socket.connected)
});
socket.on('response_back', function(image){
console.log('got response back!');
const image_id = document.getElementById('imagebox');
image_id.src = image;
});
});
服务器.py
#Import necessary libraries
from flask import Flask, render_template, Response, request , jsonify
import cv2
import random
import json
import numpy as np
import base64
import os , io , sys
from PIL import Image
from flask_socketio import SocketIO, emit
import imutils
#Initialize the Flask app
app = Flask(__name__)
socketio = SocketIO(app=app,logger=True)
@socketio.on('image')
def image(image):
sbuf = io.StringIO()
sbuf.write(image)
# decode and convert into image
b = io.BytesIO(base64.b64decode(image))
pimg = Image.open(b)
## converting RGB to BGR, as opencv standards
frame = cv2.cvtColor(np.array(pimg), cv2.COLOR_RGB2BGR)
# Process the image frame
# frame = imutils.resize(frame, width=700)
frame = cv2.flip(frame, 1)
imgencode = cv2.imencode('.jpg', frame)[1]
# base64 encode
stringData = base64.b64encode(imgencode).decode('utf-8')
b64_src = 'data:image/jpg;base64,'
stringData = b64_src + stringData
# emit the frame back
emit('response_back', stringData)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080, debug=False)