总述
级联匹配中的匈牙利算法的距离计算使用的是轨迹的协方差、均值和检测目标的框坐标进行位置矩阵计算,
得到位置损失。特征损失是使用可信轨迹最后经过sample处理的特征和检测目标的特征进行距离计算得到的,
最后两个损失加权相加,得到损失矩阵。
IOU匹配是计算:此处,对轨迹的均值进行处理,得到轨迹目标的框坐标,计算轨迹框和检测目标框的坐标的IOU值,1减去其值,得到损失,进行配对。
总体上,(1)先进行目标检测算法,得到目标的检测结果(2)截取检测到的目标,进行特征提取,(3)KF预测更新,更新已有的可信轨迹的均值和协方差(4)更新,匹配,经过级联匹配和IOU匹配,找到匹配的轨迹、不可信轨迹(新检测到的目标不匹配则也转为不可信轨迹)(5)更新匹配轨迹的特征、置信度、类别和框坐标。(6)对可信轨迹坐标的特征进行处理,用于匈牙利算法中的特征矩阵计算。
python版本
加载模型、选择设备如GPU、CPU
模型推理
1.选出person的目标框、置信度
2.将检测结果的框尺寸映射到视频流的尺寸大小。
3. 从xyxy(左上右下)转为xywh(中心点宽高)
4. 分别保存坐标、置信度、类别
进入追踪阶段
- update,输入的是框、置信度、类别和源图像
- get_features,获取特征,输入的是框和源图像
(1)把xywh(中心宽高)转为xyxy(左上右下)
(2)根据图像的目标框坐标截取截取目标区域,进行特征提取,截取图像A[高区域y,宽区域x]
(3)把截取的目标送入到特征提取网络,进行特征提取,返回特征feature,如5个目标,返回的是5*512的特征矩阵 - 把xywh(中心宽高)转为tlwh(左上宽高)
- 把目标的tlwh、conf和特征逐个输入进行检测、把信息存在self中,
- tracker.predict()
(1) - tracker.update
(1) 输入检测detections(包括置信度、tlwh和feature)、类别、置信度
(2)对输入的detections进行匹配match,
(01)根据保存在self.tracks中的内容,确定可信的轨迹和不可信的轨迹
(02)进行级联匹配,输入距离矩阵、tracks、detections
(03)为计算检测到的目标框个数,用于分配轨迹id,(为检测到的目标个数),均设位置没有匹配的检测
(04)在级联深度(30)中循环,如果没有检测到的目标(没有不匹配的检测)则退出循环,如果有轨迹,则进行匈牙利算法
(05)级联匹配结束,返回匹配的a、不能匹配的轨迹a,不匹配的检测
(06)对不可信轨迹、没有匹配到的轨迹和没有匹配的检测进行IOU匹配。(输入iou代价、距离,detections、tracks、指数)
(07)iou匹配返回匹配的b、不能匹配的轨迹b,不匹配的检测
(08)返回匹配的a+b、不能匹配的轨迹a+b,不匹配的检测
(3)match结束,返回匹配的、不能匹配的轨迹,不匹配的检测
(4)更新轨迹集合。初始帧没有匹配的和不匹配的轨迹,只有不匹配的检测,添加新轨迹。
(01)初始化轨迹,输入的是检测到的框、类别、置信度
(02)把框(tlwh)转为xyah(中心点xyah),a是w/h。进行卡尔曼滤波初始化,创造轨迹
(03)卡尔曼滤波初始化结束,返回均值和协方差
(04)为该轨迹赋值,如轨迹id、类别、特征、置信度、均值和协方差、删除和置信等数值
(5)判断轨迹的状态,对轨迹进行筛选,
(01)判断轨迹是否是要删除的,保留删除后的轨迹。
(02)判断轨迹是否是可信的,如果是可信的,则更新距离矩阵(输入特征features、targets和active_targets)
7.判断是否有可信的轨迹或更新指数大于1的
(1)如有,则转化框的表达形式,转为xyxy,保存轨迹id、类别id和置信度,进行输出返回(第一帧没有可信的轨迹)
第一帧的结束。
第二帧
- yolo模型检测,经过非极大值抑制、目标类别筛选得到检测的目标框、置信度、类别
- 对框的坐标进行映射,得到视频流大小的坐标
- 从xyxy(左上右下)转为xywh(中心点宽高)
- 分别保存坐标、置信度、类别
- 进行追踪更新,update,输入的是框、置信度、类别和源图像
(1)经过外观特征模型处理,获得features,获取特征,输入的是框和源图像
(2)把xywh(中心宽高)转为tlwh(左上宽高)
(3)把目标的tlwh、conf和特征逐个输入进行检测、把信息存在self中,
(4)tracker.predict()
(01)以此对上一帧中保存的轨迹进行卡尔曼滤波预测
(001)通过输入已有轨迹的均值和协方差矩阵,返回预测的状态,获得新的均值和协方差
(002)更新参数,轨迹的age加1,time_since_update+1
(5)tracker.update,输入检测detections(包括置信度、tlwh和feature)、类别、置信度
(01)对此帧中的检测结果进行匹配match,
(001)对上一帧中保存的轨迹进行处理,筛选出可信和不可信的轨迹
(002)进行级联匹配,输入距离矩阵、tracks、detections和可信的轨迹
(003)为计算检测到的目标框个数,用于分配轨迹id,(为检测到的目标个数),均设位置没有匹配的检测
(004)在级联深度(30)中循环,如果没有检测到的目标(没有不匹配的检测)则退出循环,如果有轨迹,则进行匈牙利算法,用轨迹指数减去–匹配的指数,得到不匹配的指数
(005)级联匹配结束,返回匹配的a、不能匹配的轨迹a,不匹配的检测unmatched_detections(检测算法新检测到的目标),
(006)从不能匹配的轨迹a中刷选出iou可信的轨迹(不是可信轨迹),根据time_since_update的值,得到iou_track_candidates,剩下的依旧为不能匹配的轨迹a
(007)进行IOU匹配,输入(输入iou代价、距离,detections、tracks、iou_track_candidates,unmatched_detections)
(0001)计算代价矩阵iou_cost,输入轨迹(类别、features、等指数)、检测(包括置信度、tlwh和feature)、检测指数、轨迹指数;通过计算轨迹目标和检测目标的IOU值,返回的是轨迹行、检测列的矩阵,里边的数值是轨迹和检测,1-IOU,值越小说明越匹配。
(0002)对矩阵中的值进行处理,进行轨迹和检测的目标进行对应。
(0003)规矩对应的关系进行选择,选择出不能匹配的检测、不能匹配的轨迹;同时根据最大距离,选择出匹配的轨迹,如(0,0)(1,1)
(008)返回匹配、不能匹配的检测、不能匹配的轨迹
match结束
(02) 更新匹配的轨迹内容,如特征、框、类别置信度。根据轨迹匹配到的新检测信息,对其进行更新,还有卡尔曼滤波的均值、协方差更新,hits、轨迹状态参数值更新
(03) 更新不匹配的轨迹,如果在潜在状态和达到最大帧数(age)则更新状态为删除
(04) 对于没有匹配的检测,则进行轨迹初始化
(001)卡尔曼滤波初始化,得到均值和协方差矩阵
(002)创建新轨迹,并对其赋值,如轨迹id、类别、特征、置信度、均值和协方差、删除和置信等数值
(05) 根据轨迹状态,**进行删除轨迹,**保留剩下的进行下一步。
(06) 更新距离矩阵。
(001)判断是否是可信轨迹,得到active_targets
(002)判断是否是可信轨迹,得到features
(003)判断是否是可信轨迹,得到targets
(004)输入上面的三个数值,进行拟合
update结束
(6)判断轨迹是否是可信,如有,则转化框的表达形式,转为xyxy,保存轨迹id、类别id和置信度,进行输出返回
第三帧
- yolo模型检测,经过非极大值抑制、目标类别筛选得到检测的目标框、置信度、类别
- 对框的坐标进行映射,得到视频流大小的坐标
- 从xyxy(左上右下)转为xywh(中心点宽高)
- 分别保存坐标、置信度、类别
- 进行追踪更新,update,输入的是框、置信度、类别和源图像
(1)经过外观特征模型处理,获得features,获取特征,输入的是框和源图像
(2)把xywh(中心宽高)转为tlwh(左上宽高)
(3)把目标的tlwh、conf和特征逐个输入到detections检测、把信息存在self中,
(4)tracker.predict()
(01)以此对上一帧中保存的轨迹进行卡尔曼滤波预测
(001)通过输入已有轨迹的均值和协方差矩阵,返回预测的状态,获得新的均值和协方差
(002)更新参数,轨迹的age加1,time_since_update+1
(5)tracker.update,输入检测detections(包括置信度、tlwh和feature)、类别、置信度
(01)对此帧中的检测结果进行匹配match,
(001)对上一帧中保存的轨迹进行处理,筛选出可信和不可信的轨迹
(002)进行级联匹配,输入距离矩阵、tracks、detections和可信的轨迹
(003)为计算检测到的目标框个数,用于分配轨迹id,(为检测到的目标个数),均设位置没有匹配的检测
(004)在级联深度(30)中循环,如果没有检测到的目标(没有不匹配的检测)则退出循环,如果有轨迹(可信),则进行匈牙利算法,用轨迹指数减去–匹配的指数,得到不匹配的指数
(005)级联匹配结束,返回匹配的a、不能匹配的轨迹a,不匹配的检测unmatched_detections(检测算法新检测到的目标),
(006)从不能匹配的轨迹a中刷选出iou可信的轨迹(不是可信轨迹),根据time_since_update的值,得到iou_track_candidates,剩下的依旧为不能匹配的轨迹a
(007)进行IOU匹配,输入(输入iou代价、距离,detections、tracks、iou_track_candidates,unmatched_detections)
(0001)计算代价矩阵iou_cost,输入轨迹(类别、features、等指数)、检测(包括置信度、tlwh和feature)、检测指数、轨迹指数;通过计算轨迹目标和检测目标的IOU值,返回的是轨迹行、检测列的矩阵,里边的数值是轨迹和检测,1-IOU,值越小说明越匹配。
(0002)对矩阵中的值进行处理,进行轨迹和检测的目标进行对应。
(0003)规矩对应的关系进行选择,选择出不能匹配的检测、不能匹配的轨迹;同时根据最大距离,选择出匹配的轨迹,如(0,0)(1,1)
(008)返回匹配、不能匹配的检测、不能匹配的轨迹
match结束
(02) 更新匹配的轨迹内容,如特征、框、类别置信度。根据轨迹匹配到的新检测信息,对其进行更新,还有卡尔曼滤波的均值、协方差更新,hits、轨迹状态参数值更新
(03) 更新不匹配的轨迹,如果在潜在状态和达到最大帧数(age)则更新状态为删除
(04) 对于没有匹配的检测,则进行轨迹初始化
(001)卡尔曼滤波初始化,得到均值和协方差矩阵
(002)创建新轨迹,并对其赋值,如轨迹id、类别、特征、置信度、均值和协方差、删除和置信等数值
(05) 根据轨迹状态,**进行删除轨迹,**保留剩下的进行下一步。
(06) 更新距离矩阵。
(001)判断是否是可信轨迹,得到active_targets
(002)判断是否是可信轨迹,得到features(3n512),n是可信的轨迹个数
(003)判断是否是可信轨迹,得到targets(3*n)
(004)输入上面的三个数值,进行拟合
(0001)依次提取特征和轨迹编号,进行self.samples[target] = self.samples[target][-self.budget:]
(0002)保存可信轨迹的信息
update结束
(6)判断轨迹是否是可信,如有,则转化框的表达形式,转为xyxy,保存轨迹id、类别id和置信度,进行输出返回 - 把信息在图像上展现或保存。
第四帧
- yolo模型检测,经过非极大值抑制、目标类别筛选得到检测的目标框、置信度、类别
- 对框的坐标进行映射,得到视频流大小的坐标
- 从xyxy(左上右下)转为xywh(中心点宽高)
- 分别保存坐标、置信度、类别
- 进行追踪更新,update,输入的是框、置信度、类别和源图像
(1)经过外观特征模型处理,获得features,获取特征,输入的是框和源图像
(2)把xywh(中心宽高)转为tlwh(左上宽高)
(3)把目标的tlwh、conf和特征逐个输入到detections检测、把信息存在self中,
(4)tracker.predict()
(01)以此对上一帧中保存的轨迹进行卡尔曼滤波预测
(001)通过输入已有轨迹的均值和协方差矩阵,返回预测的状态,获得新的均值和协方差
(002)更新参数,轨迹的age加1,time_since_update+1
(5)tracker.update,输入检测detections(包括置信度、tlwh和feature)、类别、置信度
(01)对此帧中的检测结果进行匹配match,
(001)对上一帧中保存的轨迹进行处理,筛选出可信和不可信的轨迹
(002)进行级联匹配,输入距离矩阵、tracks、detections和可信的轨迹
(003)为计算检测到的目标框个数,用于分配轨迹id,(为检测到的目标个数),均设位置没有匹配的检测
(004)在级联深度(30)中循环,如果没有检测到的目标(没有不匹配的检测)则退出循环,如果有轨迹(可信),则进行匈牙利算法
(0001)输入的是距离矩阵、最大距离、轨迹、detections,当前级联level下匹配的轨迹**(更新后的均值、协方差,没有框的坐标)、不匹配的检测
(0002)min_cost_matching,计算cost_matrix矩阵,输入轨迹(类别、features、等指数)、检测(包括置信度、tlwh和feature)、检测指数、轨迹指数,计算IOU值
(00001)进行距离矩阵计算 _full_cost_metric。,得到代价矩阵
(00002)先把tracks的均值、协方差映射到测量空间,和检测的坐标框进行计算
(00003)得到位置门矩阵,大小是track*det。得到位置cost矩阵,通过和1比较大小,大于的为位置门矩阵,得到位置距离**,
(00004)计算特征之间的距离。新检测的目标有特征向量,代价矩阵大小也是trackdet。此处通过sample[ℹ]提取经过最后拟合处理的特征(对可信轨迹的特征最后会经过拟合处理,存在sample中),计算各个可信轨迹的目标特征和新检测的目标特征距离,得到特征距离
(00005)经过和匹配阈值比较,大于匹配阈值的为true,结合位置距离和特征距离,总体为1,各自占的比例不同,进行相加。
(00006)得到代价矩阵
(0003对矩阵中的值进行处理,进行轨迹和检测的目标进行对应。
(0004)规矩对应的关系进行选择,选择出不能匹配的检测、不能匹配的轨迹;同时根据最大距离,选择出匹配的轨迹,如(0,0)(1,1)
用轨迹指数减去–匹配的指数,得到不匹配的指数
(005)级联匹配结束,返回匹配的a、不能匹配的轨迹a,不匹配的检测unmatched_detections(检测算法新检测到的目标),
(006)从不能匹配的轨迹a中刷选出iou可信的轨迹(不是可信轨迹),根据time_since_update的值,得到iou_track_candidates,剩下的依旧为不能匹配的轨迹a
(007)进行IOU匹配,输入(输入iou代价、距离,detections、tracks、iou_track_candidates,unmatched_detections)
(0001)计算代价矩阵**iou_cost,**输入轨迹(类别、features、等指数)、检测(包括置信度、tlwh和feature)、检测指数、轨迹指数;通过计算轨迹目标和检测目标的IOU值,返回的是轨迹行、检测列的矩阵,里边的数值是轨迹和检测,1-IOU,值越小说明越匹配。
(0002)对矩阵中的值进行处理,进行轨迹和检测的目标进行对应。
(0003)规矩对应的关系进行选择,选择出不能匹配的检测、不能匹配的轨迹;同时根据最大距离,选择出匹配的轨迹,如(0,0)(1,1)
(008)返回匹配、不能匹配的检测、不能匹配的轨迹
match结束
(02) 更新匹配的轨迹内容,如特征、框、类别置信度。根据轨迹匹配到的新检测信息,对其进行更新,还有卡尔曼滤波的均值、协方差更新,hits、轨迹状态参数值更新
(03) 更新不匹配的轨迹,如果在潜在状态和达到最大帧数(age)则更新状态为删除
(04) 对于没有匹配的检测,则进行轨迹初始化
(001)卡尔曼滤波初始化,得到均值和协方差矩阵
(002)创建新轨迹,并对其赋值,如轨迹id、类别、特征、置信度、均值和协方差、删除和置信等数值
(05) 根据轨迹状态,**进行删除轨迹,**保留剩下的进行下一步。
(06) 更新距离矩阵。
(001)判断是否是可信轨迹,得到active_targets
(002)判断是否是可信轨迹,得到features(3n512),n是可信的轨迹个数
(003)判断是否是可信轨迹,得到targets(3n)
(004)输入上面的三个数值,进行拟合
(0001)依次提取特征和轨迹编号,进行self.samples[target] = self.samples[target][-self.budget:]
(0002)保存可信轨迹的信息
(0003)用于下一帧计算特征距离时调用
update结束
(6)判断轨迹是否是可信,如有,则转化框的表达形式,转为xyxy,保存轨迹id、类别id和置信度,进行输出返回 - 把信息在图像上展现或保存。
C++版本
Trtyolosort yosort(yolo_engine,sort_engine);
加载yolo模型
trt_engine = yolov5_trt_create(yolo_engine_path_);,
1.输入yolo的.engine模型
2. 把反序列化中用到的内容,创建到一个结构体中,如data、engine、context、inputIndex等,
3. 定义一个结构体trt_txt,并为其分配内存
4. 向结构体中的具体值分配内存,并赋值
5. 创建runtime、engine等,并分配cuda内存
6. 返回定义的结构体trt_txt。
加载外观特征模型(sort)
DS = new DeepSort(sort_engine_path_, 128, 256, 0, &gLogger);
- 在DeepSort类中,给参数进行赋值。128是批量大小,256特征维度,0GPU编号,&gLogger是tensorrt的log文件
2. 初始化
01 objTracker = new tracker(maxCosineDist, maxBudget);
02 确定余弦距离、最大余弦距离、最大IOU距离、max_age、匹配阈值、budget,samples清空
03 确定卡尔曼滤波的参数,如移动矩阵、更新矩阵、速度权重和位置权重
04 轨迹清空,id指数+1
05featureExtractor = new FeatureTensor(batchSize, imgShape, featureDim, gpuID, gLogger);
06 设置均值和标准差,对图像进行预处理,initFlag设置为false
07加载sort模型
001反序列化、内存分配,initFlag设置为true
读取图像、检测推理
读取图像
- 读取视频,转为图像,每三帧进行一次推理
- 推理,yosort.TrtDetect(frame,conf_thre,det);,输入图像、阈值和定义的容器,用于保存结果,det包含框的坐标、置信度、目标类别、追踪id*
01 对输入的图像进行预处理,尺寸重构、灰度值均值、归一化、通道转换
02 推理、非极大值抑制处理,保存检测结果,把满足要求的框、置信度和目标类别进行保存,框是左上和右下坐标
DS->sort
- 把图像、检测模型的结果det输入到sort,检测结果是框、置信度和目标类别进行保存,框是左上和右下坐标
- 定义一个DETECTIONS detections;/包含twlh,置信度、特征、to_xyah,to_tlbr/和 vector clsConf;包含 /*类别和置信度/
- 依次提取det中的box进行保存(转为xywh)和置信度到容器DETECTION_ROW(包含tlwh,置信度、特征、to_xyah,to_tlbr) d中,再把d保存到detections,把类别和分数保存到clsonf。
- 对定义的result和results容器进行清零
- 将clsConf和detections进行make_pair保存到容器DETECTIONSV2 detectionsv2中
- 传递源图像和detectionsv2到下一个sort中
01 分别提取clsonf和detections
02 把图像和detections传入bool flag = featureExtractor->getRectsFeature(frame, detections);,进行推理
001 依次提取框的信息,对目标的框进行处理(如加大x坐标的区间),再根据目标框从原图像中截取目标区域,保存到目标图像
002 mat2stream,把目标图像的像素值进行均值和协方差处理,从mat转为数值float,
003 把图像转为folat之后,输入进行doInference
004 把推理的结果传入stream2det,把输出的结果根据特征维度进行转化,保存到DETECTION_ROW容器中的feature,作为特征,在det中进行传递。
005返回flag是ture
03 如果flag是真,则进行:
001 objTracker->predict();
0001 卡尔曼滤波,生成均值和协方差,
0002 更新参数age+1、time_since_update+1
002 objTracker->update(detectionsv2),
0001 输入类别、置信度容器,再定义一个TRACHER_MATCHD res;是轨迹匹配的三种状态
0002 把定义的容器ret和detections输入match,进入匹配环节
00001 区分出可信轨迹和不可信轨迹的编号
00002 进行级联匹配输入距离矩阵、tracks、detections和可信的轨迹
000001 对检测结果进行编号,向不匹配检测容器中填充编号
000002 容器中匹配的轨迹清空
000003 在级联深度中,在级联深度(30)中循环,如果没有检测到的目标(没有不匹配的检测)则退出循环,如果有轨迹(可信),则进行匈牙利算法
(0000001)**min_cost_matching,输入的是距离矩阵、距离矩阵函数、最大距离、轨迹、detections,当前级联level下匹配的轨迹编号、不匹配的检测编号
(0000002)先判断可信轨迹编号和不可匹配检测中是否为空(尺寸大小为0),若是,则清空容器中的匹配轨迹,可信轨迹变为不匹配轨迹,不匹配检测还是不匹配检测。
(0000003)计算cost_matrix矩阵,输入轨迹(类别、features、等指数)、检测(包括置信度、tlwh和feature)、检测指数、轨迹指数,计算IOU值
(0000004)对矩阵中的值进行处理,进行轨迹和检测的目标进行对应。
(0000005)根据对应的关系进行选择,选择出不能匹配的检测、不能匹配的轨迹;同时根据最大距离,选择出匹配的轨迹,如(0,0)(1,1),返回定义的ret,包含匹配的,不匹配的轨迹,不匹别的检测,其中保存匹配的容器是键值对容器,另外两个是int
000004 扩充不匹配的检测,匹配的轨迹和不匹配的轨迹进行保存返回,返回ret(疑问???????)
级联匹配结束
00003 在不可信的轨迹中根据time_since_update值生成iou轨迹
00004 进行IOU匹配输入的是(输入iou代价、距离,tracks、detections、iou_track_candidates,unmatched_detections)
(000001)计算代价矩阵iou_cost,输入轨迹(类别、features、等指数)、检测(包括置信度、tlwh和feature)、检测指数、轨迹指数;通过计算轨迹目标和检测目标的IOU值,返回的是轨迹行、检测列的矩阵,里边的数值是轨迹和检测,1-IOU,值越小说明越匹配。
(000002)对矩阵中的值进行处理,进行轨迹和检测的目标进行对应。
(000003)规矩对应的关系进行选择,选择出不能匹配的检测、不能匹配的轨迹;同时根据最大距离,选择出匹配的轨迹,如(0,0)(1,1)
00004 结合级联匹配和IOU匹配的结果,得到最终的不匹配的检测、轨迹和匹配的轨迹。
match结束
0003 更新匹配的轨迹参数,如特征、框、类别置信度。根据轨迹匹配到的新检测信息,对其进行更新,
还有卡尔曼滤波的均值、协方差更新,hits、轨迹状态参数值更新,也会更新轨迹的可信状态time_since_update更新为0
0004 对于没有匹配的检测,则进行轨迹初始化
(00001)卡尔曼滤波初始化,得到均值和协方差矩阵
(00002)创建新轨迹,并对其赋值,如轨迹id、类别、特征、置信度、均值和协方差、删除和置信等数值
0005 根据轨迹的状态,进行删除
0005 更新距离矩阵。
(00001)判断是否是可信轨迹,可信轨迹的id得到active_targets
(00002)判断是否是可信轨迹,得到features(3n512),n是可信的轨迹个数
(00004)输入上面的两个数值,进行拟合
(000001)依次提取特征和轨迹编号,进行self.samples[target] = self.samples[target][-self.budget:]
(000002)保存可信轨迹的信息????????????????**问题
003 保存可信轨迹的目标信息result、results,框(tlwh)、置信度、类别、轨迹id - Sort中重载的sort结束,
01 分别提取result和results中的信息保存到det中
DS->sort结束
返回det内容
展示结果
- 根据det中的内容,把结果展示在图像上