在许多应用场景中,不仅需要对静态图片进行分析,还希望能够实时地从摄像头获取的图像流中获取预测结果。本文将介绍如何使用Python和连接到电脑的USB摄像头,将摄像头数据传输到Roboflow训练的模型中,进行实时推理。
首先,需要在Roboflow上训练一个自定义模型。按照的步骤进行操作。完成模型训练后,确保已经获取了API密钥和模型ID。
确保系统中安装了Python3.7或更高版本。然后,安装以下依赖库:
pip3 install opencv-python numpy requests
创建一个名为infer.py的文件,并初始化Roboflow模型信息(训练模型并获取API密钥),以及刚刚安装的包。
ROBOFLOW_API_KEY = "填写API密钥"
ROBOFLOW_MODEL = "填写模型ID" # 例如:xx-xxxx--#
ROBOFLOW_SIZE = 416
import cv2
import base64
import numpy as np
import requests
接下来,将构建模型的API端点URL。这个示例使用了Hosted Inference API,也可以使用设备部署,只需将https://detect.roboflow.com/替换为其IP地址(例如http://127.0.0.1:9001):
upload_url = "".join([
"https://detect.roboflow.com/",
ROBOFLOW_MODEL,
"?access_token=",
ROBOFLOW_API_KEY,
"&format=image",
"&stroke=5"
])
使用OpenCV打开摄像头连接,并定义一个名为infer的函数,它将是程序的核心逻辑。每次调用它时,它执行以下操作:
# 通过Roboflow Infer API进行推理并返回结果
def infer():
# 从摄像头获取当前图像
ret, img = video.read()
# 调整大小(同时保持纵横比)以提高速度并节省带宽
height, width, channels = img.shape
scale = ROBOFLOW_SIZE / max(height, width)
img = cv2.resize(img, (round(scale * width), round(scale * height)))
# 将图像编码为base64字符串
retval, buffer = cv2.imencode('.jpg', img)
img_str = base64.b64encode(buffer)
# 从Roboflow Infer API获取预测
resp = requests.post(upload_url, data=img_str, headers={
"Content-Type": "application/x-www-form-urlencoded"
}, stream=True).raw
# 解析结果图像
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
return image
在主循环中调用此函数,并显示当前预测图像,直到检测到键盘上的“q”键被按下。
# 主循环;顺序推理,直到按下“q”键
while 1:
# 在“q”键按下时退出
if(cv2.waitKey(1) == ord('q')):
break
# 从Roboflow Infer API同步获取预测
image = infer()
# 并显示推理结果
cv2.imshow('image', image)
最后,当循环被“q”键中断后,将释放摄像头资源并清理可视化资源。
# 完成后释放资源
video.release()
cv2.destroyAllWindows()
就是这样!如果运行infer.py,将看到模型的预测结果显示在屏幕上,覆盖在来自摄像头的图像上。可以下载这个简单的同步摄像头推理示例的代码。
这个实现相当简单;它顺序地从模型中获取预测,这意味着它等待接收前一个图像的结果后才发送下一个图像。
它将进行推理的确切速度取决于模型和网络连接,但可以预期在Hosted API上大约每秒4帧,在本地网络上运行的NVIDIA Jetson Xavier NX上大约每秒8帧。
可以通过并行化请求来显著提高速度。在内存中保持图像缓冲区会增加一点延迟,但可以提高显示帧的一致性。有一个示例异步摄像头推理脚本,展示了这种方法。