云计算百科
云计算领域专业知识百科平台

边缘端商品识别系统构建实战:基于YOLO系列的货架缺货检测方案从训练到部署完整记录

边缘端商品识别系统构建实战:基于YOLO系列的货架缺货检测方案从训练到部署完整记录

一、项目背景与需求定义

零售门店的货架缺货检测是库存管理中的核心痛点。传统方案依赖人工巡检,平均每店每日耗费2.5小时巡检工时,漏检率高达18%。将视觉检测能力部署至边缘设备,可在摄像头端实时判定缺货状态并上报云端,将巡检响应周期从小时级缩短至秒级。

本项目目标参数如下:

指标目标值
缺货检测准确率 ≥95%(mAP@0.5)
单帧推理延迟 ≤120ms(ARM Cortex-A72平台)
模型参数量 ≤8MB(INT8量化后)
连续运行功耗 ≤5W
日均上报频率 每15分钟一次状态快照

硬件选型为瑞芯微RK3568(4×A72@2.0GHz + NPU 0.8TOPS),配合2MP宽动态摄像头模组。NPU支持INT8卷积加速,但后处理算子需在CPU侧完成,这是后续部署调优的关键约束点。

二、数据采集与模型训练

数据集构建流程:

实际采集覆盖6家门店、42个货架位,共标注12,800帧图像。缺货样本占比约22%,在架56%,遮挡22%。数据增强策略模拟了货架灯光闪烁(亮度±30%)、顾客遮挡(随机矩形掩码)以及排列不齐(水平平移±5%)等真实场景干扰。

训练配置选用YOLOv8s(11.2M参数),输入分辨率640×640,batch=32,学习率cosine衰减从0.01至0.001,共300 epoch。验证集mAP@0.5达到0.963,测试集0.951,满足部署指标。

# 训练启动脚本关键配置
import ultralytics

model = ultralytics.YOLO("yolov8s.pt")
result = model.train(
data="shelf_empty.yaml", # 数据集描述文件
epochs=300,
imgsz=640,
batch=32,
lr0=0.01,
lrf=0.001,
augment=True,
device="0", # GPU训练
workers=8,
project="shelf_detect",
name="yolov8s_v1",
)
if result is None:
raise RuntimeError("训练过程异常终止,请检查数据集路径与GPU状态")

三、模型量化与边缘部署

ONNX模型经onnxruntime验证无误后,通过RKNN-Toolkit2完成INT8量化。量化校准数据取验证集的200帧,覆盖不同光照条件。

量化后模型体积从28.3MB压缩至7.8MB,mAP@0.5从0.951降至0.931(下降2.1%),仍在可接受范围内。板端单帧推理耗时98ms,满足≤120ms指标。

// RKNN模型加载与推理核心代码
#include "rknn_api.h"

int run_shelf_detect(const char *model_path, const uint8_t *frame_buf,
int width, int height, rknn_output *outputs)
{
rknn_context ctx = 0;
int ret = rknn_init(&ctx, model_path, NULL, 0, NULL);
if (ret != RKNN_SUCC) {
fprintf(stderr, " rknn_init 失败, 错误码: %d\\n", ret);
return -1;
}

rknn_input input = {
.index = 0,
.buf = frame_buf,
.size = width * height * 3,
.pass_through = 0,
.type = RKNN_TENSOR_UINT8,
.fmt = RKNN_TENSOR_NHWC,
};
ret = rknn_inputs_set(ctx, 1, &input);
if (ret != RKNN_SUCC) {
fprintf(stderr, " rknn_inputs_set 失败, 错误码: %d\\n", ret);
rknn_destroy(ctx);
return -2;
}

ret = rknn_run(ctx, NULL);
if (ret != RKNN_SUCC) {
fprintf(stderr, " rknn_run 失败, 错误码: %d\\n", ret);
rknn_destroy(ctx);
return -3;
}

ret = rknn_outputs_get(ctx, 3, outputs, NULL);
if (ret != RKNN_SUCC) {
fprintf(stderr, " rknn_outputs_get 失败\\n");
rknn_destroy(ctx);
return -4;
}

rknn_destroy(ctx);
return 0;
}

四、后处理优化与系统集成

NPU输出的原始检测结果需经NMS(非极大值抑制)过滤后方可用。原始NMS在A72单核耗时约15ms,通过以下优化降至4ms:

  • 预设置信度阈值0.45,直接剔除低分候选框,减少排序量
  • 采用单类NMS(货架缺货为单类检测场景),避免多类并行计算
  • 将IoU计算改为整数近似,牺牲<0.5%精度换取2倍加速
  • // 单类NMS快速实现(整数IoU近似)
    static int fast_nms(box_t *boxes, int num, float iou_thresh, box_t *out, int max_out)
    {
    if (num <= 0 || boxes == NULL || out == NULL) {
    fprintf(stderr, " fast_nms 输入参数异常\\n");
    return 0;
    }

    // 按置信度降序排序(部分排序,取前max_out个即可)
    int effective = (num < max_out) ? num : max_out;
    for (int i = 0; i < effective; i++) {
    int best = i;
    for (int j = i + 1; j < num; j++) {
    if (boxes[j].score > boxes[best].score) best = j;
    }
    box_t tmp = boxes[i]; boxes[i] = boxes[best]; boxes[best] = tmp;
    }

    int keep = 0;
    uint8_t suppressed[256] = {0}; // 标记被抑制的候选框

    for (int i = 0; i < effective; i++) {
    if (suppressed[i]) continue;
    out[keep++] = boxes[i];
    for (int j = i + 1; j < effective; j++) {
    // 整数IoU近似: (交集面积 * 256) / (并集面积)
    int inter = box_intersection_q8(boxes[i], boxes[j]);
    int union_ = box_area_q8(boxes[i]) + box_area_q8(boxes[j]) – inter;
    if (union_ == 0) continue;
    int iou_q8 = (inter << 8) / union_;
    int thresh_q8 = (int)(iou_thresh * 256);
    if (iou_q8 > thresh_q8) suppressed[j] = 1;
    }
    }
    return keep;
    }

    系统整体集成采用进程间MQ通信架构:推理进程每15分钟提取一帧,执行检测后将缺货层数写入共享内存,上报进程读取后通过MQTT发布至云端。设备端平均功耗4.2W(CPU降频至1.5GHz时),满足≤5W约束。

    五、总结

    本方案从数据标注、模型训练、INT8量化到板端部署,完整覆盖了边缘端货架缺货检测系统的构建流程。关键数据汇总:

    环节核心指标实测值
    训练 mAP@0.5 0.951
    量化 精度损失 2.1%
    模型体积 INT8后 7.8MB
    板端推理 单帧延迟 98ms
    NMS后处理 耗时 4ms
    系统功耗 日均 4.2W

    量化精度损失控制在2%以内,推理延迟优于120ms目标,说明YOLOv8s + RK3568 NPU的组合在零售货架场景具备工程可行性。后续改进方向包括:引入时序帧融合以降低遮挡误判率,以及尝试YOLOv8n进一步压缩模型体积以适配更低算力平台。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 边缘端商品识别系统构建实战:基于YOLO系列的货架缺货检测方案从训练到部署完整记录
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!