published on in Python

影像处理・网络摄像头

返回教程主页

上篇 影像处理・调用摄像头

了解到如何使用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,如果不出意外,你将看到浏览器中正在显示你电脑摄像头所拍摄的影像。如果你的手机与你的电脑在同一个局域网下「例如都连接家里的路由器」,那么你可以尝试用手机浏览器进行访问。

下篇 影像处理・目标检测