了解到如何使用OpenCV调用摄像头并显示视频内容后,我们可以尝试实现支持远程客户端的网络摄像头。我们将使用到OpenCV以及WebSockets。
WebSockets的安装方法记载如下:
pip install websockets
服务器程序
我们在服务器上打开摄像头,然后分享给“遥远”的客户端:
import asyncio
import websockets
import cv2 as cv
async def capture(websocket, path):
while video.isOpened():
ret, frame = video.read()
if not ret: continue
_, buf = cv.imencode('.jpeg', frame)
await websocket.send(buf.tobytes())
await asyncio.sleep(0.05)
async def main():
async with websockets.serve(capture, "0.0.0.0", 5678):
await asyncio.Future()
video = cv.VideoCapture(0)
try:
asyncio.run(main())
except KeyboardInterrupt:
if video.isOpened():
video.release()
有几个地方需要说明:
import asyncio
我们需要引入这个异步模块来帮助处理异步问题import websockets
需要的WebSocket模块def capture
定义用于处理视频发送的函数,当有客户端连接时会触发「需要使用async
做异步声明」cv.imencode
将numpy数组转换成字节数据,便于被浏览器使用websocket.send
发送视频数据,需要使用await
做等待声明asyncio.sleep
控制摄像头读取频率websockets.serve
启动一个服务,传入参数capture
,主机地址,端口号asyncio.run
运行主程序
有关WebSockets的更多内容可以去往项目文档网站进行了解: https://websockets.readthedocs.io/en/stable/index.html
客户端HTML
可以创建一个名为index.html的文本文件「注意.html是扩展名」,复制粘贴以下代码并保存:
<!DOCTYPE html>
<html>
<head>
<title>OpenCV&WebSocket</title>
</head>
<body>
<img id="img"/>
</body>
</html>
<script>
var ws = new WebSocket(`ws://${location.hostname}:5678/`);
var image = document.querySelector('#img');
ws.onmessage = function (event) {
image.src = URL.createObjectURL(event.data);
};
</script>
运行测试
首先,我们运行服务端程序,这与之前的代码的运行没有不同,因此不做具体说明。
然后,我们在HTML文件所在的目录下开启一个静态文件服务器,例如:
python3 -m http.server
这时用浏览器访问http://<你的局域网IP地址>:8000
,如果不出意外,你将看到浏览器中正在显示你电脑摄像头所拍摄的影像。如果你的手机与你的电脑在同一个局域网下「例如都连接家里的路由器」,那么你可以尝试用手机浏览器进行访问。