一、项目介绍
项目通过读取本地H264文件,Vdec解码后,通过Yolov8实现多目标检测,Deepsort实现多目标跟踪功能的整个流程;
二、代码的技术栈
项目主要使用海思的MPP VDEC,vpss,IVE,NPU,Framebuffer(LVGL),嵌入式软件开发基础!
2.1 Pipeline设计
Pipeline里面几个核心要点:
1.VDEC和VPSS Grp 为bind关系,主要参考SDK VDEC demo即可
2.VPSS 两个chn,Ch0 为640*360分辨率主要给NPU服务,CH1 为1920*1080为VO服务输出到HDMI
3.IVE CPY 主要是为了将640*360 -》640*640 给Yolo作为输入
4.Yolov8输出的图像需要Resize 每个框的图像特征值给DeepSort模块,提取特征值是用NPU,Deepsort Track用的CPU
5.Framebuffer主要是用来绘制文本方便,利用lvgl 的label直接写文本绘制,是异步实现,实现功能比较简单
2.2 DeepSort的移植
移植代码来源:https://github.com/shaoshengsong/DeepSORT
1.DeepSort代码Track部分完全用的上面链接的代码
2.DeepSort提取特征值部分用的3403 NPU来实现
3.DeepSort优势:跟踪效果好,遮挡部分后还是比较容易被跟踪到
4.DeepSort不足:每个目标框都需要提取特征值,跑NPU流程,随着目标增多,时间延长很多,平均一个目标跟踪需要差不多7ms时间(暂时没做任何优化,直接用开源模型转的om前提)
2.3 LVGL的应用
1.LVGL主要目标是实现OSD叠加功能
2.LVGL核心代码
2.1(LVGL代码到Framebuffer代码的映射)
void fbDispFlush(lv_disp_drv_t *disp, const lv_area_t *area,
lv_color_t *color_p) {
int32_t x, y;
if (area->y1 > screen_info.height || area->y2 > screen_info.height ||
area->x1 > screen_info.width || area->x2 > screen_info.width) {
return;
}
uint32_t *argb8888;
for (y = area->y1; y <= area->y2; y++) {
for (x = area->x1; x <= area->x2; x++) {
uint32_t *offset =
(uint32_t *)(stUiParam.fb_base + x * screen_info.pixel_width +
y * screen_info.line_width);
argb8888 = (uint32_t *)offset;
argb8888 = (uint32_t *)offset;
*argb8888 = ((color_p->ch.alpha) << 24) | ((color_p->ch.blue) << 16) |
((color_p->ch.green) << 8) | (color_p->ch.red);
color_p++;
}
}
lv_disp_flush_ready(disp);
}
2.2 绘制自定义文本(整个过程直接用的label标签)
int labcount = 0;
void DrawOsdInfo(stYolovDetectObjs *pOut) {
pthread_mutex_lock(&Uilock);
for (size_t i = 0; i < labcount; i++) {
lv_obj_del(stPages.label[i]);
}
labcount = 0;
for (size_t i = 0; i < pOut->id_count; i++) {
stPages.label[i] = lv_label_create(lv_scr_act());
lv_label_set_text_fmt(stPages.label[i], "ID:%d", pOut->id_objs[i].id);
lv_obj_align(stPages.label[i], LV_ALIGN_TOP_LEFT, pOut->id_objs[i].x,
pOut->id_objs[i].y);
lv_obj_set_style_text_font(stPages.label[i], &lv_font_simsun_16, 0);
lv_obj_set_style_text_color(stPages.label[i],
lv_color_make(0x00, 0xFF, 0x00), 0);
}
labcount = pOut->id_count;
pthread_mutex_unlock(&Uilock);
}
static td_void *uiprocess(td_void *args) {
prctl(PR_SET_NAME, "uiprocess", 0, 0, 0);
while (stUiParam.run) {
pthread_mutex_lock(&Uilock);
lv_task_handler();
pthread_mutex_unlock(&Uilock);
ot_usleep(50 * 1000);
}
}
特别注意这个Uilock,因为LVGL单线程特性,需要保证刷新ui数据的时候,和内部线程自动刷新不冲突,需要和lv_task_handler();互斥,否则很容易资源重入,段错误!!
三、视频效果与培训具体流程
3.海思SS928(3403)YOLOV8+DeepSort目标跟踪
四、开源代码路径
https://gitee.com/apchy_ll/ss928_yolov5s.git yolov8_deepsort 分支