在边缘计算领域,NVIDIA Jetson Orin Nano是一个强大的设备,它能够处理复杂的计算机视觉任务,如实时视频流分析。通过使用Roboflow的推理管道,可以将深度学习模型部署到这个设备上,实现高效的实时推理。这种部署方式不仅能够减少延迟,还能在不牺牲性能的前提下,处理大量的视频数据。
首先,确保Jetson设备已经安装了Jetpack 5.1.1。可以通过下载Jetson Orin Nano开发者套件的SD卡镜像,并按照NVIDIA的指导将镜像写入microSD卡来完成这一步骤。启动设备后,可以通过运行一个简单的脚本来验证Jetpack是否正确安装。此外,为了充分利用NVIDIA GPU的能力,还需要安装正确的库和运行时环境。
#!/bin/bash
# 卸载已安装的onnxruntime
pip3 uninstall --yes onnxruntime
# 下载onnxruntime的wheel文件
wget https://nvidia.box.com/shared/static/v59xkrnvederwewo2f1jtv6yurl92xso.whl -O onnxruntime_gpu-1.12.1-cp38-cp38-linux_aarch64.whl
# 安装onnxruntime_gpu和opencv-python
pip3 install onnxruntime_gpu-1.12.1-cp38-cp38-linux_aarch64.whl "opencv-python<4.3"
# 清理下载的wheel文件和pip缓存
rm -f onnxruntime_gpu-1.12.1-cp38-cp38-linux_aarch64.whl
rm -rf ~/.cache/pip
# 安装pandas库
pip3 install pandas
使用Roboflow的推理管道,可以轻松地将COCO模型部署到RTSP视频流上。这个管道内置了FPS监控功能,可以跟踪推理的延迟和吞吐量。通过使用Roboflow提供的特殊模型ID,可以方便地获取模型并进行推理。下面是一个使用InferencePipeline的示例代码,它展示了如何将模型部署到RTSP视频流上。
from inference.core.interfaces.stream.inference_pipeline import InferencePipeline
from inference.core.interfaces.stream.sinks import render_boxes
import supervision as sv
# 创建FPS监控实例
fps_monitor = sv.FPSMonitor()
# 定义模型别名
REGISTERED_ALIASES = {
"yolov8n-640": "coco/3",
"yolov8n-1280": "coco/9",
"yolov8m-640": "coco/8"
}
# 示例别名
alias = "yolov8n-640"
# 函数:解析模型别名为实际模型ID
def resolve_roboflow_model_alias(model_id: str) -> str:
return REGISTERED_ALIASES.get(model_id, model_id)
# 解析别名获取实际模型ID
model_name = resolve_roboflow_model_alias(alias)
# 修改render_boxes函数以显示统计信息
def on_prediction(predictions, video_frame):
render_boxes(
predictions=predictions,
video_frame=video_frame,
fps_monitor=fps_monitor,
display_statistics=True,
)
# 初始化推理管道
pipeline = InferencePipeline.init(
model_id=model_name,
video_reference="RTSP_URL",
on_prediction=on_prediction,
api_key='API_KEY',
confidence=0.5,
)
# 启动推理管道
pipeline.start()
pipeline.join()
Supervision库提供了强大的功能,可以用于监控特定区域内的对象。例如,可以使用PolygonZone和Bytetrack来测量对象在特定区域内的停留时间。此外,还可以将对象的类别、时间戳以及在区域内的停留时间保存到CSV文件中,以便后续加载到数据库中。
# ByteTrack & Supervision
tracker = sv.ByteTrack()
annotator = sv.BoxAnnotator()
frame_count = defaultdict(int)
colors = sv.ColorPalette.default()
# 定义感兴趣的多边形区域
polygons = [
np.array([
[390, 543], [1162, 503], [1510, 711], [410, 819], [298, 551], [394, 543]
])
]
# 创建区域、区域注释器和框注释器
zones = [
sv.PolygonZone(
polygon=polygon,
frame_resolution_wh=[1440, 2560],
)
for polygon in polygons
]
zone_annotators = [
sv.PolygonZoneAnnotator(
zone=zone,
color=colors.by_idx(index),
thickness=4,
text_thickness=8,
text_scale=4
)
for index, zone in enumerate(zones)
]
box_annotators = [
sv.BoxAnnotator(
color=colors.by_idx(index),
thickness=4,
text_thickness=4,
text_scale=2
)
for index in range(len(polygons))
]
# CSV输出的列
columns = ['trackerID', 'class_id', 'frame_count', 'entry_timestamp', 'exit_timestamp', 'time_in_zone']
frame_count_df = pd.DataFrame(columns=columns)
# 定义一个字典来存储每个tracker_id的第一个检测时间戳
first_detection_timestamps = {}
last_detection_timestamps = {}
def render(predictions: dict, video_frame) -> None:
detections = sv.Detections.from_roboflow(predictions)
detections = tracker.update_with_detections(detections)
for zone, zone_annotator, box_annotator in zip(zones, zone_annotators, box_annotators):
mask = zone.trigger(detections=detections)
detections_filtered = detections[mask]
image = box_annotator.annotate(scene=video_frame.image, detections=detections, skip_label=False)
image = zone_annotator.annotate(scene=image)
for tracker_id, class_id in zip(detections_filtered.tracker_id, detections_filtered.class_id):
frame_count[tracker_id] += 1
# 检查tracker_id是否不在first_detection_timestamps中,如果不在,则添加时间戳
if tracker_id not in first_detection_timestamps:
first_detection_timestamps[tracker_id] = time.time()
last_detection_timestamps[tracker_id] = time.time()
time_difference = last_detection_timestamps[tracker_id] - first_detection_timestamps[tracker_id]
# 将数据添加到DataFrame中
frame_count_df.loc[tracker_id] = [tracker_id, class_id, frame_count[tracker_id], first_detection_timestamps[tracker_id], last_detection_timestamps[tracker_id], time_difference]
frame_count_df.to_csv('demo.csv', index=False)
cv2.imshow("Prediction", image)
cv2.waitKey(1)
在上面的代码中,定义了一个特定的多边形区域,用于计算区域内对象的数量。多边形的坐标将根据用例而有所不同。要找到适合用例的多边形坐标,可以使用PolygonZone的web助手工具。通过这个工具,可以上传视频的一帧并绘制所需的坐标。注意,必须上传视频的一帧,而不是屏幕截图,因为这个过程对图像分辨率很敏感。可以通过使用OpenCV或Pillow从InferencePipeline中保存一帧来实现这一点。
在NVIDIA Jetson Orin Nano这样的边缘设备上运行RTSP视频流可以扩展实时推理用例,而不会牺牲延迟。在本指南中,介绍了如何使用Roboflow推理服务器在NVIDIA Jetson Orin Nano上运行推理。使用Roboflow推理部署了模型,然后使用Supervision添加了跟踪视频中的车辆并计算交叉口车辆数量的逻辑。