主要参考链接:
https://blog.csdn.net/weixin_41869700/article/details/104263980
https://www.52pojie.cn/thread-915818-1-1.html
流程: 使用opencv采取多进程实时读取usb摄像头, 采用websocket传图片给前端
读取摄像头文件
由于博主用的环境是linux16.04 且安装了ros
ros自带的opencv只能用python2编译
所有需要先 移除 ros 中 Python 路径
如果没有安装ros
可直接用 import cv2 语句就可
编译: python3 ce.py
# ce.py
# 移除 ros 中 Python 路径
import sys
ros_path = '/opt/ros/kinetic/lib/python2.7/dist-packages'
if ros_path in sys.path:
sys.path.remove(ros_path)
import cv2
# 导入包过后重新添加回 ros 中的 Python 路径
sys.path.append('/opt/ros/kinetic/lib/python2.7/dist-packages')
import time
import multiprocessing as mp
import numpy as np
import asyncio
import websockets
frame = None
def websocket_process(img_dict):
# 服务器端主逻辑
async def main_logic(websocket, path):
await recv_msg(websocket, img_dict)
start_server = websockets.serve(main_logic, '0.0.0.0', 5678)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
async def recv_msg(websocket, img_dict): #websocket发送图片
recv_text = await websocket.recv()
if recv_text == 'begin':
while True:
frame = img_dict['img']
if isinstance(frame, np.ndarray):
enconde_data = cv2.imencode('.png', frame)[1]
enconde_str = enconde_data.tostring()
try:
await websocket.send(enconde_str)
time.sleep(0.07) #设置时延
except Exception as e:
print(e)
return True
def image_put(q, id):
cap = cv2.VideoCapture(id)
cap.set(6, cv2.VideoWriter.fourcc('M', 'J', 'P', 'G')) # 视频流格式
# cap.set(6, cv2.VideoWriter.fourcc('H', '2', '6', '4')) # 视频流格式
cap.set(3, 1280) # 帧宽
cap.set(4, 720) # 帧高 #主要调整图片大小 可设置图片帧率等
while True:
ret, frame = cap.read()
# image_path = "22.jpg" # 图片路径
# img = cv2.imread(image_path)
# q.put(img)
# q.get() if q.qsize() > 1 else time.sleep(0.01)
if ret:
frame = cv2.resize(frame, None, fx=0.7, fy=0.7) #压缩图片
q.put(frame)
q.get() if q.qsize() > 1 else time.sleep(0.01)
def image_get(q, img_dict):
while True:
frame = q.get()
if isinstance(frame, np.ndarray):
img_dict['img'] = frame
def run_single_camera(id):
mp.set_start_method(method='spawn') # init
queue = mp.Queue(maxsize=3)
m = mp.Manager()
img_dict = m.dict()
Processes = [mp.Process(target=image_put, args=(queue, id)),
mp.Process(target=image_get, args=(queue, img_dict)),
mp.Process(target=websocket_process, args=(img_dict,))]
[process.start() for process in Processes]
[process.join() for process in Processes]
def run():
run_single_camera(0) # 使用内置摄像头 即/dev/video0
if __name__ == '__main__':
run()
主要就是将后台传输的blob格式数据转换为base64编码
以图片img标签展示
<!DOCTYPE HTML>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script src="js/jquery-2.1.0.js" type="text/javascript" charset="utf-8"></script>
<title>websocket通信客户端</title>
<script type="text/javascript">
function WebSocketTest()
{
if ("WebSocket" in window)
{
// 打开一个 web socket
var ws = new WebSocket("ws://localhost:5678");
// 连接建立后的回调函数
ws.onopen = function()
{
// Web Socket 已连接上,使用 send() 方法发送数据
ws.send("begin");
};
// 接收到服务器消息后的回调函数
ws.onmessage = function (evt)
{
var received_msg = evt.data;
// alert("收到消息:"+received_msg);
// console.log("要输出的内容" + received_msg);
blobToDataURI(received_msg,function(result){ //blob格式再转换为base64格式
document.getElementById('img').src = result;
})
};
// 连接关闭后的回调函数
ws.onclose = function()
{
// 关闭 websocket
alert("连接已关闭...");
};
}
else
{
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
}
function blobToDataURI(blob, callback) {
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (e) {
callback(e.target.result);
}
}
</script>
</head>
<body onload="WebSocketTest()">
<div><img src="" id="img" alt=""></div>
</body>
</html>
延时300ms左右
肉眼感觉要更低一点
一帧图片为600kb,我时延设置差不多是一秒10帧图片
测试一帧图片最好不要超过2mb
可在这下载呀 挣一点点积分
https://download.csdn.net/download/xuan196/20907432
注意在linux下需要用python3编译
否则会报以下错误
SyntaxError: invalid syntax
需要安装opencv、websocket库
pip3 install opencv-python
pip3 install websockets
其次我在安装pip升级时出现以下问题,试了多种方法最后用以下命令解决
sys.stderr.write(f“ERROR: {exc}“)
curl -fsSL -o- https://bootstrap.pypa.io/pip/3.5/get-pip.py | python3.5