【OC_SORT,ByteTrack】论文+代码解读

运行OCSORT出现的BUG

  1. 在utils/args.py中将expn换成绝对路径就可以了~
ImportError: exps/example/mot/yolox_dancetrack_test.py doesn't contains class named 'Exp'

ByteTrack代码备注

class BYTETracker(object):
    def __init__(self, args, frame_rate=30):
        self.tracked_stracks = []  # type: list[STrack]
        self.lost_stracks = []  # type: list[STrack]
        self.removed_stracks = []  # type: list[STrack]

        self.frame_id = 0
        self.args = args
        #self.det_thresh = args.track_thresh
        self.det_thresh = args.track_thresh + 0.1
        self.buffer_size = int(frame_rate / 30.0 * args.track_buffer)
        self.max_time_lost = self.buffer_size
        self.kalman_filter = KalmanFilter()
        self.track_count_gen = itertools.count(start=1)


    def update(self, output_results, img_info, img_size):
        self.frame_id += 1
        # 保存当前帧处理结束之后的tracker
        activated_starcks = []  # 激活列表
        refind_stracks = []     # 重新列表 保存帧 到 之前目标丢失的轨迹
        lost_stracks = []       # 丢失列表
        removed_stracks = []    # 删除列表

        # 将objects转换为x1,y1,x2,y2,score的格式,并构建strack
        if output_results.shape[1] == 5:
            scores = output_results[:, 4]
            bboxes = output_results[:, :4]
        else:
            output_results = output_results.cpu().numpy()
            scores = output_results[:, 4] * output_results[:, 5]
            bboxes = output_results[:, :4]  # x1y1x2y2
        img_h, img_w = img_info[0], img_info[1]
        scale = min(img_size[0] / float(img_h), img_size[1] / float(img_w))
        bboxes /= scale

        '''1. 筛选当前帧的检测结果'''
        remain_inds = scores > self.args.track_thresh
        inds_low = scores > 0.1                      # 例:array([False,  True,  True,  True,  True])
        inds_high = scores < self.args.track_thresh  # 例:array([ True,  True,  True,  True, False])

        inds_second = np.logical_and(inds_low, inds_high)  # 结果例array([False,  True,  True,  True, False]),交集

        # 高分检测框以及置信度(cls_conf*obj_conf)
        dets = bboxes[remain_inds]
        scores_keep = scores[remain_inds]

        # 低分检测框以及置信度(cls_conf*obj_conf)
        dets_second = bboxes[inds_second]
        scores_second = scores[inds_second]

        if len(dets) > 0:
            '''Detections'''
            detections = [STrack(STrack.tlbr_to_tlwh(tlbr), s, self.track_count_gen) for
                          (tlbr, s) in zip(dets, scores_keep)]  # 先detection是det和scores_keep
        else:
            detections = []

        ''' Add newly detected tracklets to tracked_stracks'''

        '''区分上一帧中休眠和激活两种状态的 tracker(BYTETracker 类中的)'''
        unconfirmed = []
        tracked_stracks = []  # type: list[STrack]
        for track in self.tracked_stracks:
            if not track.is_activated:
                unconfirmed.append(track)  # 休眠状态的trackers / 新的
            else:
                tracked_stracks.append(track)  # 优先关联激活状态的(正常的)trackers

        ''' Step 2: First association, with high score detection boxes '''
        '''第一次关联,使用高分检测框'''
        # 将正常的 tracker 和 已丢失的 tracker,根据 tracker_id 放在一起
        strack_pool = joint_stracks(tracked_stracks, self.lost_stracks)
        # Predict the current location with KF 卡尔曼预测 mean,covariance
        # 例如 len(strack_pool)=17
        STrack.multi_predict(strack_pool)

        # 代价矩阵 1-iou (计算trackers和当前(高分)检测框的iou)
        # 例如 len(detections)=20, dists.shape=[17, 20]
        dists = matching.iou_distance(strack_pool, detections)
        if not self.args.mot20:
            # iou=1-dists iou 和 当前检测框的置信度相乘,先把score(20,)repeat成(17, 20)
            # 确保代价函数更可信??
            dists = matching.fuse_score(dists, detections)
        # 根据dist做数据关联,match_thresh=0.8,匈牙利&KM
        # matches.shape=[17,2], u_track:[], u_detection:[16,18,19](detection比track多3个,未匹配上的)
        matches, u_track, u_detection = matching.linear_assignment(dists, thresh=self.args.match_thresh)
        # matches(存的id),根据匹配到的检测框,更新参数
        for itracked, idet in matches:
            track = strack_pool[itracked]
            det = detections[idet]
            if track.state == TrackState.Tracked:
                # (state=1)
                # 更新 tracklet_len,frame_id,坐标,置信度,卡尔曼的均值和方差,state=1,is_activated=True,track_id 不变
                track.update(detections[idet], self.frame_id)
                activated_starcks.append(track)
            else:
                # (lost)
                # 更新 tracklet_len,frame_id,坐标,置信度,卡尔曼的均值和方差,state=1,is_activated=True,track_id 不变
                track.re_activate(det, self.frame_id, new_id=False)
                refind_stracks.append(track)

        ''' Step 3: Second association, with low score detection boxes'''
        '''3. 第二次关联,与低分数检测框'''
        # association the untrack to the low score detections
        if len(dets_second) > 0:
            '''Detections'''
            detections_second = [STrack(STrack.tlbr_to_tlwh(tlbr), s, self.track_count_gen) for
                                 (tlbr, s) in zip(dets_second, scores_second)]
        else:
            detections_second = []
        # 这里有一个tracker的种类过滤,在u_track(未匹配到的tracker的id)里,还要是正常种类
        r_tracked_stracks = [strack_pool[i] for i in u_track if strack_pool[i].state == TrackState.Tracked]
        # 以下和第一次关联相同
        dists = matching.iou_distance(r_tracked_stracks, detections_second)
        matches, u_track, u_detection_second = matching.linear_assignment(dists, thresh=0.5)
        for itracked, idet in matches:
            track = r_tracked_stracks[itracked]
            det = detections_second[idet]
            if track.state == TrackState.Tracked:
                track.update(det, self.frame_id)
                activated_starcks.append(track)
            else:  # 多余,可以不要
                track.re_activate(det, self.frame_id, new_id=False)
                refind_stracks.append(track)
        '''高低分检测没有匹配到的(上一帧的)tracker,其种类设为 丢失'''
        for it in u_track:
            track = r_tracked_stracks[it]
            if not track.state == TrackState.Lost:
                track.mark_lost()
                lost_stracks.append(track)

        '''搞定u_track,现在匹配u_detection'''
        '''Deal with unconfirmed tracks, usually tracks with only one beginning frame'''
        detections = [detections[i] for i in u_detection]
        # 与休眠(未激活,即全新tracker)状态的tracker匹配
        dists = matching.iou_distance(unconfirmed, detections)
        if not self.args.mot20:
            dists = matching.fuse_score(dists, detections)
        matches, u_unconfirmed, u_detection = matching.linear_assignment(dists, thresh=0.7)
        for itracked, idet in matches:
            # 匹配到,track的参数和状态更新,放入到激活列表中
            unconfirmed[itracked].update(detections[idet], self.frame_id)
            activated_starcks.append(unconfirmed[itracked])
        for it in u_unconfirmed:
            track = unconfirmed[it]
            track.mark_removed()
            removed_stracks.append(track)

        '''4. 对没有匹配到的检测框判断,<0.6 的过滤掉,>0.6 更新 tracker_id,均值、方差,状态,is_activate=False'''
        """ Step 4: Init new stracks"""
        for inew in u_detection:
            track = detections[inew]
            if track.score < self.det_thresh:
                continue
            track.activate(self.kalman_filter, self.frame_id)
            activated_starcks.append(track)
        """ Step 5: Update state"""
        # # lost_stracks 中记载的是丢失的traker,如果大于 30 帧,则设为删除种类
        for track in self.lost_stracks:
            if self.frame_id - track.end_frame > self.max_time_lost:
                track.mark_removed()
                removed_stracks.append(track)

        # print('Ramained match {} s'.format(t4-t3))
        # 前一帧 (正常种类)tracker,包括(上一帧)新的、正常的,tracked_stracks 中若在当前帧匹配到了,state 必会设为1(正常种类)
        self.tracked_stracks = [t for t in self.tracked_stracks if t.state == TrackState.Tracked]
        # 上一步(过滤的)tracked_stracks 和 当前的激活列表(主要是当前帧产生的新的 tracker)
        self.tracked_stracks = joint_stracks(self.tracked_stracks, activated_starcks)
        # 上一步 tracked_stracks 和 当前的重新列表(主要是丢失的又重新匹配的)
        self.tracked_stracks = joint_stracks(self.tracked_stracks, refind_stracks)

        # self.lost_stracks 里是上一帧判定为丢失的 trackers,在经过前面的处理,有可能放入了重新列表和删除列表
        # 放入了重新列表的,拿走
        self.lost_stracks = sub_stracks(self.lost_stracks, self.tracked_stracks)
        # 当前帧的新的丢失的 tracker
        self.lost_stracks.extend(lost_stracks)
        # 放入了删除列表的,拿走
        self.lost_stracks = sub_stracks(self.lost_stracks, self.removed_stracks)

        # 合并以前帧和当前帧删除类型的 tracker
        self.removed_stracks.extend(removed_stracks)

        # 筛选出 tracked_stracks 和 lost_stracks iou>0.85 的,然后比较时间跨度,时间跨度小的 tracker 去掉,去除重轨迹
        self.tracked_stracks, self.lost_stracks = remove_duplicate_stracks(self.tracked_stracks, self.lost_stracks)
        # get scores of lost tracks只输出正常激活状态的tracker
        output_stracks = [track for track in self.tracked_stracks if track.is_activated]

        return output_stracks
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于这个问题,是因为在计算V_oc时,T_amb和G都是向量,而G_stc是一个常数,所以在log(G./G_stc)时,会出现矩阵维度不一致的问题。可以将G_stc改为一个与G维度相同的向量,将其元素全部赋值为G_stc即可解决问题。 修改后的代码如下: ```matlab clear all close all % 定义常量 R = 8.314; % 气体常数,单位:J/(mol*K) T_stc = 25; % 标准测试条件温度,单位:℃ G_stc = 1000; % 标准测试条件辐射强度,单位:W/m^2 V_oc_stc = 37.5; % 标准测试条件开路电压,单位:V I_sc_stc = 8.21; % 标准测试条件短路电流,单位:A n = 1.2; % 常数,取值范围是1.0到2.0 % 定义变量 T_amb = [-10, 0, 25, 40]; % 环境温度,单位:℃ G = [200, 400, 600, 800, 1000]; % 辐射强度,单位:W/m^2 G_stc_vec = ones(size(G)) * G_stc; % 将G_stc转化为与G维度相同的向量 % 计算光伏模块参数 I_sc = I_sc_stc * (G ./ G_stc); V_oc = V_oc_stc + (R * ((T_amb + 273) - (T_stc + 273)) ./ n) .* log(G ./ G_stc_vec); I_0 = I_sc ./ exp((V_oc + (R * ((T_amb + 273) - (T_stc + 273)) ./ n)) / (n * 0.0259)); I_mp = I_sc ./ (1 + ((I_sc / I_0) - 1) .* exp(-n * V_oc / (R * ((T_amb + 273) - (T_stc + 273))))); V_mp = (R * ((T_amb + 273) - (T_stc + 273)) ./ n) .* log((I_sc - I_mp) ./ I_0) + V_oc; % 绘制出力曲线 figure hold on for i = 1:length(T_amb) P = V_mp .* I_mp; plot(G, P, 'LineWidth', 2) end legend(num2str(T_amb'), 'Location', 'NorthWest') xlabel('辐射强度(W/m^2)') ylabel('输出功率(W)') title('典型四季光伏出力曲线') grid on ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值