今天一个同事用Python做了一个关于机器视觉的处理,他希望处理的视频结果能够在H5页面上实时呈现出来,方便客户通过浏览器查看。折腾了一天终于搞定,现总结方法如下:
需求
Python读视频流进行处理,处理结果呈现在H5网页上,要求延时不能大于0.5秒。
分析
Python处理每一帧的图片,处理好以后发送到前端呈现,所以前端最好使用canvas或img标签呈现图片,通过实时更改canvas或img的图片可以达到视频呈现的效果。通过分析,我们决定使用图片的base64编码作为发送的图片数据,所以最终选择了img标签实现视频呈现。
实时显示图片使用轮询效率太低,我们选择使用node.js搭建WebSocket服务器,Python和JS与WebSocket服务器进行通信实现功能。
步骤
WebSocket服务器
使用node.js实现,需要安装ws(此处有坑,可以看看网上关于node.js中ws的安装方法)。
server.js内容如下:
let WebSocketServer = require('ws').Server,
wss = new WebSocketServer({ port: 8188 });
wss.on('connection', function (ws) {
console.log('客户端已连接');
ws.on('message', function (message) {
wss.clients.forEach(function each(client) {
client.send(message);
});
console.log(message.length);
});
});
需要注意的是:
wss.clients.forEach(function each(client) {
client.send(message);
});
这里需要添加一个广播,网上很多代码都没有写广播,有了广播Python端和JS端就可以监听当前socket服务器中的新消息了。
python端代码
python端代码如下:
import asyncio
import websockets
import base64
from cv2 import cv2
import numpy as np
capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
if not capture.isOpened():
print('quit')
quit()
ret, frame = capture.read()
encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),95]
# 向服务器端实时发送视频截图
async def send_msg(websocket):
global ret,frame
while ret:
#time.sleep(2)
result, imgencode = cv2.imencode('.jpg', frame, encode_param)
data = np.array(imgencode)
img = data.tostring()
# base64编码传输
img = base64.b64encode(img).decode()
await websocket.send("img=sq=data:image/jpeg;base64,"+img)
await websocket.send("a1=sq="+repr(np.random.randn(7).tolist()))
ret, frame = capture.read()
# 客户端主逻辑
async def main_logic():
async with websockets.connect('ws://127.0.0.1:8188') as websocket:
await send_msg(websocket)
asyncio.get_event_loop().run_until_complete(main_logic())
通过上面的代码我们可以实现实时视频数据往socket服务器推送。
H5网页代码
H5页面中代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<img id="resImg" src="" />
</div>
<script src="js/jquery-3.3.1.min.js" ></script>
<script>
let ws = new WebSocket("ws://127.0.0.1:8188/");
ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};
ws.onmessage = function(evt) {
$("#resImg").attr("src",evt.data);
console.log( "Received Message: " + evt.data);
// ws.close();
};
ws.onclose = function(evt) {
console.log("Connection closed.");
};
</script>
</body>
</html>
最后我们通过node.js启动server.js
node server.js
打开h5页面就可以查看python推送过来的视频流了,非常流畅。从目前效果看无论是延时还是帧频都完全可以满足要求。
版权声明:本文为zhuzheqing原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。