def loadVOT(self): self.net = SiamRPNvot() self.net.load_state_dict(torch.load('VOT/SiamRPNVOT.model')) self.net = self.net.to(self.device)
class GN(): def __init__(self, seq_index, begin, end, a, cuda=True): ''' Evaluating with the MotMetrics :param seq_index: the number of the sequence :param tt: train_test :param length: the number of frames which is used for training :param cuda: True - GPU, False - CPU ''' self.bbx_counter = 0 self.seq_index = seq_index self.hungarian = Munkres() self.device = torch.device("cuda" if cuda else "cpu") self.begin = begin self.end = end self.alpha = a self.missingCounter = 0 self.sideConnection = 0 print ' Loading the model...' self.loadAModel() self.loadMModel() self.loadVOT() if train_set_num == 4: # self.out_dir = t_dir + 'motmetrics_%s_4_%.1f%s_%.2f%s%s_tau_tdir1.0/'%(type, # self.alpha, # decay_dir, decay, # recover_dir, u_dir) # 1.9 - decay_tag > 0, 1.1~1.8 - decay_tag > 1 self.out_dir = t_dir + 'motmetrics_%s_4_%.1f%s_%.2f%s%s_vc_%.2f/' % ( type, self.alpha, decay_dir, decay, recover_dir, u_dir, vot_conf_score) # self.out_dir = t_dir + 'motmetrics_%s_4_%.1f%s_%.2f%s%s_vc_%.2f_exp/'%(type, # self.alpha, # decay_dir, decay, # recover_dir, u_dir, vot_conf_score) else: self.out_dir = t_dir + 'motmetrics_%s_4_%.1f%s_%.2f%s%s_vc_%.2f_dseq_new/' % ( type, self.alpha, decay_dir, decay, recover_dir, u_dir, vot_conf_score) print ' ', self.out_dir if not os.path.exists(self.out_dir): os.mkdir(self.out_dir) else: deleteDir(self.out_dir) os.mkdir(self.out_dir) self.initOut() def initOut(self): print ' Loading Data...' self.a_train_set = ADatasetFromFolder( sequence_dir, '../MOT/MOT16/train/MOT16-%02d' % self.seq_index, tau_conf_score) self.m_train_set = MDatasetFromFolder( sequence_dir, '../MOT/MOT16/train/MOT16-%02d' % self.seq_index, tau_conf_score) gt_training = self.out_dir + 'gt_training.txt' # the gt of the training data self.copyLines(self.seq_index, self.begin, gt_training, self.end) detection_dir = self.out_dir + 'res_training_det.txt' res_training = self.out_dir + 'res_training.txt' # the result of the training data self.createTxt(detection_dir) self.createTxt(res_training) self.copyLines(self.seq_index, self.begin, detection_dir, self.end, 1) self.out = open(res_training, 'w') self.evaluation(self.begin, self.end, detection_dir) self.out.close() def getSeqL(self, info): # get the length of the sequence f = open(info, 'r') f.readline() for line in f.readlines(): line = line.strip().split('=') if line[0] == 'seqLength': seqL = int(line[1]) f.close() return seqL def copyLines(self, seq, head, gt_seq, tail=-1, tag=0): ''' Copy the groun truth within [head, head+num] :param seq: the number of the sequence :param head: the head frame number :param tail: the number the clipped sequence :param gt_seq: the dir of the output file :return: None ''' if tt_tag: basic_dir = '../MOT/MOT%d/test/MOT%d-%02d-%s/' % (year, year, seq, type) else: basic_dir = '../MOT/MOT%d/train/MOT%d-%02d-%s/' % (year, year, seq, type) print ' Testing on', basic_dir, 'Length:', self.end - self.begin + 1 seqL = tail if tail != -1 else self.getSeqL(basic_dir + 'seqinfo.ini') det_dir = 'gt/gt_det.txt' if test_gt_det else 'det/det.txt' seq_dir = basic_dir + ('gt/gt.txt' if tag == 0 else det_dir) inStream = open(seq_dir, 'r') outStream = open(gt_seq, 'w') for line in inStream.readlines(): line = line.strip() attrs = line.split(',') f_num = int(attrs[0]) if f_num >= head and f_num <= seqL: print >> outStream, line outStream.close() inStream.close() return seqL def createTxt(self, out_file): f = open(out_file, 'w') f.close() def swapFC(self): self.cur = self.cur ^ self.nxt self.nxt = self.cur ^ self.nxt self.cur = self.cur ^ self.nxt def loadAModel(self): from mot_model import uphi, ephi, vphi name = '%s_%d' % (app_dir, train_set_num) if edge_initial == 0: model_dir = 'App2_bb' i_name = 'IoU' elif edge_initial == 1: model_dir = 'App2_bb' i_name = 'Random' tail = 10 if train_set_num == 4 else 13 self.AUphi = torch.load('../%s/Results/MOT16/%s/%s/uphi_%02d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.AVphi = torch.load('../%s/Results/MOT16/%s/%s/vphi_%02d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.AEphi1 = torch.load('../%s/Results/MOT16/%s/%s/ephi1_%02d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.AEphi2 = torch.load('../%s/Results/MOT16/%s/%s/ephi2_%02d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.Au = torch.load('../%s/Results/MOT16/%s/%s/u_%02d.pth' % (model_dir, i_name, name, tail)) self.Au = self.Au.to(self.device) def loadMModel(self): from m_mot_model import uphi, ephi name = 'all_%d' % train_set_num if edge_initial == 0: model_dir = 'Motion1_bb' i_name = 'IoU' elif edge_initial == 1: model_dir = 'Motion1_bb' i_name = 'Random' tail = 10 if train_set_num == 4 else 13 self.MUphi = torch.load('../%s/Results/MOT16/%s/%s/uphi_%d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.MEphi = torch.load('../%s/Results/MOT16/%s/%s/ephi_%d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.Mu = torch.load('../%s/Results/MOT16/%s/%s/u_%d.pth' % (model_dir, i_name, name, tail)) self.Mu = self.Mu.to(self.device) def loadVOT(self): self.net = SiamRPNvot() self.net.load_state_dict(torch.load('VOT/SiamRPNVOT.model')) self.net = self.net.to(self.device) def outputLine(self, attr, src): """ Output the tracking result into text file :param attr: The tracked detection :param src: The source code which call this function :return: None """ if attr[1] == '-1': print src, '-', attr line = '' for attr in attr[:-1]: line += attr + ',' if show_recovering: if src[0] == 'd': line += '1' elif src[0] == 'R': line += '2' else: line += '0' else: line = line[:-1] self.bbx_counter += 1 print >> self.out, line def linearModel(self, attr1, attr2, src): # print 'I got you! *.*' # print attr1, attr2 frame, frame2 = int(attr1[0]), int(attr2[0]) t = frame2 - frame if t > 1: self.sideConnection += 1 if t > f_gap: self.outputLine(attr2, src + 'LinearModel1') return x1, y1, w1, h1 = float(attr1[2]), float(attr1[3]), float( attr1[4]), float(attr1[5]) x2, y2, w2, h2 = float(attr2[2]), float(attr2[3]), float( attr2[4]), float(attr2[5]) x_delta = (x2 - x1) / t y_delta = (y2 - y1) / t w_delta = (w2 - w1) / t h_delta = (h2 - h1) / t for i in xrange(1, t + 1): frame += 1 x1 += x_delta y1 += y_delta w1 += w_delta h1 += h_delta attr1[0] = str(frame) attr1[2] = str(x1) attr1[3] = str(y1) attr1[4] = str(w1) attr1[5] = str(h1) if i == 1 or i == t: self.outputLine(attr1, src + 'LinearModel2') else: self.outputLine(attr1, 'Recovering') self.missingCounter += t - 1 def vot(self, bbx): """ Tracking with VOT (DaSiamRPN) :param bbx: The initial bounding box :return: The prediction and the confidence score """ x, y, w, h, frame = bbx [cx, cy, w, h] = [x + w / 2, y + h / 2, w, h] # tracker init target_pos, target_sz = np.array([cx, cy]), np.array([w, h]) cur_img = cv2.imread(self.a_train_set.img_dir + '%06d.jpg' % frame) state = SiamRPN_init(cur_img, target_pos, target_sz, self.net) state = SiamRPN_track(state, self.img) # track res = cxy_wh_2_rect(state['target_pos'], state['target_sz']) score = state['score'] bbx = [int(l) for l in res] return bbx, score def tracking_vot(self, gap, index): frame = self.a_train_set.f_step - self.a_train_set.gap self.img = cv2.imread(self.a_train_set.img_dir + '%06d.jpg' % (frame + gap)) bbx = self.a_train_set.bbx[frame][index] pred, score = self.vot(bbx) if score >= vot_conf_score: return pred return None def transfer(self, line, pred, frame): attr = [] attr.append(str(frame)) attr.append(line[1]) for p in pred: attr.append(str(p)) for p in line[6:]: attr.append(p) attr[-1] = 1 return attr def doTracking(self, a_t_gap, index): # @We first do tracking with DaSiamRPN. frame = self.a_train_set.f_step - a_t_gap for gap in xrange(1, a_t_gap): # print '\n Container:' # print self.line_con[self.cur] # print self.line_con[self.nxt] pred = self.tracking_vot(gap, index) if pred is not None: attr1 = self.line_con[self.cur][index] # print ' Attr1:', attr1 attr2 = self.transfer(attr1, pred, frame + gap) self.linearModel(attr1, attr2, 'doTracking1') # print 'Frame:', frame+gap # print ' Attr2:', attr2 # print ' Attr1_after:', attr1 self.line_con[self.cur][index] = attr2 # print self.line_con[self.cur][index] # raw_input('Continue?') pred = self.tracking_vot(a_t_gap, index) if pred is not None: attr1 = self.line_con[self.cur][index] # print ' Attr1:', attr1 attr2 = self.transfer(attr1, pred, frame + a_t_gap) self.linearModel(attr1, attr2, 'doTracking2') # print ' Attr2:', attr2 # print ' Attr1_after:', attr1 # self.a_train_set.addApp(pred) # self.m_train_set.addMotion(pred) self.a_train_set.moveApp(index) self.m_train_set.moveMotion(index) self.line_con[self.nxt].append(attr2) self.id_con[self.nxt].append(self.id_con[self.cur][index]) return True return False def evaluation(self, head, tail, gtFile): ''' Evaluation on dets :param head: the head frame number :param tail: the tail frame number :param gtFile: the ground truth file name :param outFile: the name of output file :return: None ''' gtIn = open(gtFile, 'r') self.cur, self.nxt = 0, 1 self.img = None self.line_con = [[], []] self.id_con = [[], []] self.id_step = 1 a_step = head + self.a_train_set.setBuffer(head) m_step = head + self.m_train_set.setBuffer(head) print 'Starting from the frame:', a_step if a_step != m_step: print 'Something is wrong!' print 'a_step =', a_step, ', m_step =', m_step raw_input('Continue?') while a_step <= tail: # print '*********************************' a_t_gap = self.a_train_set.loadNext() m_t_gap = self.m_train_set.loadNext() if a_t_gap != m_t_gap: print 'Something is wrong!' print 'a_t_gap =', a_t_gap, ', m_t_gap =', m_t_gap raw_input('Continue?') a_step += a_t_gap m_step += m_step print a_step, if a_step % 1000 == 0: print if a_step > tail: break self.loadCur(self.a_train_set.m, gtIn) # print head+step, 'F', a_m, m_m = self.a_train_set.m, self.m_train_set.m a_n, m_n = self.a_train_set.n, self.m_train_set.n if a_m != m_m or a_n != m_n: print 'Something is wrong!' print 'a_m = %d, m_m = %d' % ( a_m, m_m), ', a_n = %d, m_n = %d' % (a_n, m_n) raw_input('Continue?') self.loadNxt(gtIn, a_n) self.a_train_set.loadPre() self.m_train_set.loadPre() m_u_ = self.MUphi(self.m_train_set.E, self.m_train_set.V, self.Mu) # update the edges # print 'T', candidates = [] E_CON, V_CON = [], [] for edge in self.a_train_set.candidates: e, vs_index, vr_index = edge e = e.view(1, -1).to(self.device) vs = self.a_train_set.getApp(1, vs_index) vr = self.a_train_set.getApp(0, vr_index) e1 = self.AEphi1(e, vs, vr, self.Au) vr1 = self.AVphi(e1, vs, vr, self.Au) candidates.append((e1, vs, vr1, vs_index, vr_index)) E_CON.append(e1) V_CON.append(vs) V_CON.append(vr1) E = self.a_train_set.aggregate(E_CON).view(1, -1) V = self.a_train_set.aggregate(V_CON).view(1, -1) u1 = self.AUphi(E, V, self.Au) ret = self.a_train_set.getRet() decay_tag = [0 for i in xrange(a_m)] for i in xrange(a_m): for j in xrange(a_n): if ret[i][j] == 0: decay_tag[i] += 1 for i in xrange(len(self.a_train_set.candidates)): e1, vs, vr1, a_vs_index, a_vr_index = candidates[i] m_e, m_vs_index, m_vr_index = self.m_train_set.candidates[i] if a_vs_index != m_vs_index or a_vr_index != m_vr_index: print 'Something is wrong!' print 'a_vs_index = %d, m_vs_index = %d' % (a_vs_index, m_vs_index) print 'a_vr_index = %d, m_vr_index = %d' % (a_vr_index, m_vr_index) raw_input('Continue?') if ret[a_vs_index][a_vr_index] == tau_threshold: continue e2 = self.AEphi2(e1, vs, vr1, u1) self.a_train_set.edges[a_vs_index][a_vr_index] = e1.data.view( -1) a_tmp = F.softmax(e2) a_tmp = a_tmp.cpu().data.numpy()[0] m_e = m_e.to(self.device).view(1, -1) m_v1 = self.m_train_set.getMotion(1, m_vs_index) m_v2 = self.m_train_set.getMotion(0, m_vr_index, m_vs_index) m_e_ = self.MEphi(m_e, m_v1, m_v2, m_u_) self.m_train_set.edges[m_vs_index][ m_vr_index] = m_e_.data.view(-1) m_tmp = F.softmax(m_e_) m_tmp = m_tmp.cpu().data.numpy()[0] t = self.line_con[self.cur][a_vs_index][-1] # A = float(a_tmp[0]) * pow(decay, t-1) # M = float(m_tmp[0]) * pow(decay, t-1) if decay_tag[a_vs_index] > 0: try: # A = min(float(a_tmp[0]) * pow(decay, t + a_t_gap -2), 0.999999999999) # M = min(float(m_tmp[0]) * pow(decay, t + a_t_gap -2), 0.999999999999) A = min( float(a_tmp[0]) * pow(decay, t + a_t_gap - 2), 1.0) M = min( float(m_tmp[0]) * pow(decay, t + a_t_gap - 2), 1.0) except OverflowError: print 'OverflowError!' A = float(a_tmp[0]) M = float(m_tmp[0]) else: A = float(a_tmp[0]) M = float(m_tmp[0]) ret[a_vs_index][a_vr_index] = A * self.alpha + M * (1 - self.alpha) self.tracking(ret, a_m, a_n, m_u_, u1, a_t_gap) self.line_con[self.cur] = [] self.id_con[self.cur] = [] # print head+step, results self.a_train_set.swapFC() self.m_train_set.swapFC() self.swapFC() gtIn.close() print ' The results:', self.id_step, self.bbx_counter # tra_tst = 'training sets' if head == 1 else 'validation sets' # out = open(outFile, 'a') # print >> out, tra_tst # out.close() def loadCur(self, a_m, gtIn): if self.id_step == 1: i = 0 while i < a_m: attrs = gtIn.readline().strip().split(',') if float(attrs[6]) >= tau_conf_score: attrs.append(1) attrs[1] = str(self.id_step) self.outputLine(attrs, 'LoadCur') self.line_con[self.cur].append(attrs) self.id_con[self.cur].append(self.id_step) self.id_step += 1 i += 1 def loadNxt(self, gtIn, a_n): i = 0 while i < a_n: attrs = gtIn.readline().strip().split(',') if float(attrs[6]) >= tau_conf_score: attrs.append(1) self.line_con[self.nxt].append(attrs) self.id_con[self.nxt].append(-1) i += 1 def tracking(self, ret, a_m, a_n, m_u_, u1, a_t_gap): results = self.hungarian.compute(ret) # if self.a_train_set.f_step > 532: # print '\nCur:' # for i in xrange(len(self.line_con[self.cur])): # print ' Index:', i, '- ID:', self.id_con[self.cur][i], '- line:', self.line_con[self.cur][i] # print 'Ret:' # for i in xrange(len(ret)): # print " Index:", i, '- D:', ret[i] # print 'Nxt:' # for i in xrange(len(self.line_con[self.nxt])): # print ' Index:', i, '- ID:', self.id_con[self.nxt][i], '- line:', self.line_con[self.nxt][i] # print 'Association:' # for (i, j) in results: # print ' Index:', i, '- ID:', self.id_con[self.cur][i], '- line:', self.line_con[self.cur][i] # print ' Index:', j, '- line:', self.line_con[self.nxt][j] # print '' # raw_input('Continue?') keeper = set(i for i in xrange(a_m)) look_up = set(j for j in xrange(a_n)) nxt = self.a_train_set.nxt for (i, j) in results: # print (i,j) if ret[i][j] >= tau_threshold: continue e1 = self.a_train_set.edges[i][j].view(1, -1).to(self.device) vs = self.a_train_set.getApp(1, i) vr = self.a_train_set.getApp(0, j) vr1 = self.AVphi(e1, vs, vr, self.Au) self.a_train_set.detections[nxt][j][0] = vr1.data keeper.remove(i) look_up.remove(j) self.m_train_set.updateVelocity(i, j, False) id = self.id_con[self.cur][i] self.id_con[self.nxt][j] = id attr1 = self.line_con[self.cur][i] attr2 = self.line_con[self.nxt][j] # print attrs attr2[1] = str(id) if attr2[1] == '-1': print 'In main process:', attr2[1], self.id_con[self.cur][i] self.linearModel(attr1, attr2, 'Main') if u_update: # m_u_ = torch.clamp(m_u_, max=1.0, min=-1.0) # make sure that the global variable not that big # u1 = torch.clamp(u1, max=1.0, min=-1.0) self.Mu = m_u_.data self.Au = u1.data remainer = set() for i in keeper: if self.doTracking(a_t_gap, i) == False: remainer.add(i) for j in look_up: self.m_train_set.updateVelocity(-1, j, tag=False) self.output(a_n) self.miss_occlu(a_t_gap, remainer) # self.miss_occlu(a_t_gap, keeper) def output(self, a_n): for i in xrange(a_n): if self.id_con[self.nxt][i] == -1: self.id_con[self.nxt][i] = self.id_step attrs = self.line_con[self.nxt][i] attrs[1] = str(self.id_step) self.outputLine(attrs, 'Output') self.id_step += 1 def miss_occlu(self, a_t_gap, remainer): # For missing & Occlusion for index in remainer: attrs = self.line_con[self.cur][index] # print '*', attrs, '*' if attrs[-1] + a_t_gap <= gap: attrs[-1] += a_t_gap self.line_con[self.nxt].append(attrs) self.id_con[self.nxt].append(self.id_con[self.cur][index]) self.a_train_set.moveApp(index) self.m_train_set.moveMotion(index)
class GN(): def __init__(self, seq_index, begin, end, a, cuda=True): ''' Evaluating with the MotMetrics :param seq_index: the number of the sequence :param tt: train_test :param length: the number of frames which is used for training :param cuda: True - GPU, False - CPU ''' self.bbx_counter = 0 self.seq_index = seq_index self.hungarian = Munkres() self.device = torch.device("cuda" if cuda else "cpu") self.begin = begin self.end = end self.alpha = a self.missingCounter = 0 self.sideConnection = 0 print ' Loading the model...' self.loadAModel() self.loadMModel() self.loadFasterRCNN() self.loadVOT() if train_set_num == 4: self.out_dir = t_dir + 'motmetrics_%s_4_cf_%.1f_iou_%.1f_vc_%.2f_%s/' % ( type, cf, iou, vot_conf_score, recover_dir) else: self.out_dir = t_dir + 'motmetrics_%s_4_cf_%.1f_iou_%.1f_vc_%.2f_%s_fgap_%d_dseq_new/' % ( type, cf, iou, vot_conf_score, recover_dir, f_gap) print ' ', self.out_dir if not os.path.exists(self.out_dir): os.mkdir(self.out_dir) else: deleteDir(self.out_dir) os.mkdir(self.out_dir) self.initOut() def initOut(self): print ' Loading Data...' self.a_train_set = ADatasetFromFolder( sequence_dir, '../MOT/MOT16/train/MOT16-%02d' % self.seq_index, tau_conf_score) self.m_train_set = MDatasetFromFolder( sequence_dir, '../MOT/MOT16/train/MOT16-%02d' % self.seq_index, tau_conf_score) gt_training = self.out_dir + 'gt_training.txt' # the gt of the training data self.copyLines(self.seq_index, self.begin, gt_training, self.end) detection_dir = self.out_dir + 'res_training_det.txt' res_training = self.out_dir + 'res_training.txt' # the result of the training data self.createTxt(detection_dir) self.createTxt(res_training) self.copyLines(self.seq_index, self.begin, detection_dir, self.end, 1) self.out = open(res_training, 'w') self.evaluation(self.begin, self.end, detection_dir) self.out.close() def getSeqL(self, info): # get the length of the sequence f = open(info, 'r') f.readline() for line in f.readlines(): line = line.strip().split('=') if line[0] == 'seqLength': seqL = int(line[1]) f.close() return seqL def copyLines(self, seq, head, gt_seq, tail=-1, tag=0): ''' Copy the groun truth within [head, head+num] :param seq: the number of the sequence :param head: the head frame number :param tail: the number the clipped sequence :param gt_seq: the dir of the output file :return: None ''' if tt_tag: basic_dir = '../MOT/MOT%d/test/MOT%d-%02d-%s/' % (year, year, seq, type) else: basic_dir = '../MOT/MOT%d/train/MOT%d-%02d-%s/' % (year, year, seq, type) print ' Testing on', basic_dir, 'Length:', self.end - self.begin + 1 seqL = tail if tail != -1 else self.getSeqL(basic_dir + 'seqinfo.ini') det_dir = 'gt/gt_det.txt' if test_gt_det else 'det/det.txt' seq_dir = basic_dir + ('gt/gt.txt' if tag == 0 else det_dir) inStream = open(seq_dir, 'r') outStream = open(gt_seq, 'w') for line in inStream.readlines(): line = line.strip() attrs = line.split(',') f_num = int(attrs[0]) if f_num >= head and f_num <= seqL: print >> outStream, line outStream.close() inStream.close() return seqL def createTxt(self, out_file): f = open(out_file, 'w') f.close() def swapFC(self): self.cur = self.cur ^ self.nxt self.nxt = self.cur ^ self.nxt self.cur = self.cur ^ self.nxt def loadAModel(self): from mot_model import uphi, ephi, vphi name = '%s_%d' % (app_dir, train_set_num) if edge_initial == 0: model_dir = 'App2_bb' i_name = 'IoU' elif edge_initial == 1: model_dir = 'App2_bb' i_name = 'Random' tail = 10 if train_set_num == 4 else 13 self.AUphi = torch.load('../%s/Results/MOT16/%s/%s/uphi_%02d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.AVphi = torch.load('../%s/Results/MOT16/%s/%s/vphi_%02d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.AEphi1 = torch.load('../%s/Results/MOT16/%s/%s/ephi1_%02d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.AEphi2 = torch.load('../%s/Results/MOT16/%s/%s/ephi2_%02d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.Au = torch.load('../%s/Results/MOT16/%s/%s/u_%02d.pth' % (model_dir, i_name, name, tail)) self.Au = self.Au.to(self.device) def loadMModel(self): from m_mot_model import uphi, ephi name = 'all_%d' % train_set_num if edge_initial == 0: model_dir = 'Motion1_bb' i_name = 'IoU' elif edge_initial == 1: model_dir = 'Motion1_bb' i_name = 'Random' tail = 10 if train_set_num == 4 else 13 self.MUphi = torch.load('../%s/Results/MOT16/%s/%s/uphi_%d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.MEphi = torch.load('../%s/Results/MOT16/%s/%s/ephi_%d.pth' % (model_dir, i_name, name, tail)).to( self.device) self.Mu = torch.load('../%s/Results/MOT16/%s/%s/u_%d.pth' % (model_dir, i_name, name, tail)) self.Mu = self.Mu.to(self.device) def loadFasterRCNN(self): pprint.pprint(cfg) np.random.seed(cfg.RNG_SEED) load_name = 'data/pretrained_model/faster_rcnn_1_7_10021.pth' self.pascal_classes = np.asarray([ '__background__', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor' ]) self.fasterRCNN = resnet(self.pascal_classes, 101, pretrained=True) self.fasterRCNN.create_architecture() checkpoint = torch.load(load_name) self.fasterRCNN.load_state_dict(checkpoint['model']) self.fasterRCNN = self.fasterRCNN.to(self.device) self.fasterRCNN.eval() def detect(self, bbx): with torch.no_grad(): vis = False thresh = 0.05 im_data = torch.FloatTensor(1).to(self.device) im_info = torch.FloatTensor(1).to(self.device) num_boxes = torch.LongTensor(1).to(self.device) gt_boxes = torch.FloatTensor(1).to(self.device) # total_tic = time.time() x, y, w, h = [int(p) for p in bbx] x = max(x, 0) y = max(y, 0) im = self.img[y:(y + h), x:(x + w)] # print ' (x=%d, y=%d), %d * %d, (%d, %d) - cropsize: %d * %d' % (x, y, w, h, x+w, y+h, im.shape[1], im.shape[0]) w, h = im.shape[1], im.shape[0] refine_bbx = [0, 0, w, h] if w * h == 0: print 'What? %d * %d' % (w, h) # raw_input('Continue?') return False blobs, im_scales = _get_image_blob(im) assert len(im_scales) == 1, "Only single-image batch implemented" im_blob = blobs im_info_np = np.array( [[im_blob.shape[1], im_blob.shape[2], im_scales[0]]], dtype=np.float32) im_data_pt = torch.from_numpy(im_blob) im_data_pt = im_data_pt.permute(0, 3, 1, 2) im_info_pt = torch.from_numpy(im_info_np) im_data.data.resize_(im_data_pt.size()).copy_(im_data_pt) im_info.data.resize_(im_info_pt.size()).copy_(im_info_pt) gt_boxes.data.resize_(1, 1, 5).zero_() num_boxes.data.resize_(1).zero_() # pdb.set_trace() # det_tic = time.time() rois, cls_prob, bbox_pred, \ rpn_loss_cls, rpn_loss_box, \ RCNN_loss_cls, RCNN_loss_bbox, \ rois_label = self.fasterRCNN(im_data, im_info, gt_boxes, num_boxes) scores = cls_prob.data boxes = rois.data[:, :, 1:5] if cfg.TEST.BBOX_REG: # Apply bounding-box regression deltas box_deltas = bbox_pred.data if cfg.TRAIN.BBOX_NORMALIZE_TARGETS_PRECOMPUTED: # Optionally normalize targets by a precomputed mean and stdev box_deltas = box_deltas.view(-1, 4) * torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS).cuda() \ + torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_MEANS).to(self.device) box_deltas = box_deltas.view(1, -1, 4 * len(self.pascal_classes)) pred_boxes = bbox_transform_inv(boxes, box_deltas, 1) pred_boxes = clip_boxes(pred_boxes, im_info.data, 1) else: # Simply repeat the boxes, once for each class _ = torch.from_numpy(np.tile(boxes, (1, scores.shape[1]))) pred_boxes = _.to(self.device) pred_boxes /= im_scales[0] scores = scores.squeeze() pred_boxes = pred_boxes.squeeze() # det_toc = time.time() # detect_time = det_toc - det_tic # misc_tic = time.time() if vis: im2show = np.copy(im) j = 15 inds = torch.nonzero(scores[:, j] > thresh).view(-1) # if there is det step = 0 if inds.numel() > 0: cls_scores = scores[:, j][inds] _, order = torch.sort(cls_scores, 0, True) cls_boxes = pred_boxes[inds][:, j * 4:(j + 1) * 4] cls_dets = torch.cat((cls_boxes, cls_scores.unsqueeze(1)), 1) # cls_dets = torch.cat((cls_boxes, cls_scores), 1) cls_dets = cls_dets[order] keep = nms(cls_dets, cfg.TEST.NMS, force_cpu=not cfg.USE_GPU_NMS) cls_dets = cls_dets[keep.view(-1).long()] dets = cls_dets.cpu().numpy() for i in range(dets.shape[0]): if dets[i, -1] > cf: x1, y1, w1, h1 = dets[i][:4] det = [x1, y1, w1 - x1, h1 - y1] ratio = self.a_train_set.IOU(det, refine_bbx) if ratio[0] > iou: # IOU between prediction and detection should not be limited step += 1 if vis: print cls_dets dets = cls_dets.cpu().numpy() # for i in range(dets.shape[0]): # bbox = tuple(int(np.round(x)) for x in dets[i, :4]) # score = dets[i, -1] # if score > thresh: # crop = im[bbox[1]:bbox[3], bbox[0]:bbox[2]] # cv2.imwrite('in_place/%02d.jpg'%step, crop) # step += 1 im2show = vis_detections(im2show, self.pascal_classes[j], dets) # misc_toc = time.time() # nms_time = misc_toc - misc_tic if vis: cv2.imshow('test', im2show) cv2.waitKey(0) # result_path = os.path.join('results', imglist[num_images][:-4] + "_det.jpg") # cv2.imwrite(result_path, im2show) if step: return True return False def loadVOT(self): self.net = SiamRPNvot() self.net.load_state_dict(torch.load('VOT/SiamRPNVOT.model')) self.net = self.net.to(self.device) def outputLine(self, attr, src): """ Output the tracking result into text file :param attr: The tracked detection :param src: The source code which call this function :return: None """ if attr[1] == '-1': print src, '-', attr line = '' for attr in attr[:-1]: line += attr + ',' if show_recovering: if src[0] == 'd': line += '1' elif src[0] == 'R': line += '2' else: line += '0' else: line = line[:-1] self.bbx_counter += 1 print >> self.out, line def linearModel(self, attr1, attr2, src): # print 'I got you! *.*' # print attr1, attr2 frame, frame2 = int(attr1[0]), int(attr2[0]) t = frame2 - frame if t > 1: self.sideConnection += 1 if t > f_gap: self.outputLine(attr2, src + 'LinearModel1') return x1, y1, w1, h1 = float(attr1[2]), float(attr1[3]), float( attr1[4]), float(attr1[5]) x2, y2, w2, h2 = float(attr2[2]), float(attr2[3]), float( attr2[4]), float(attr2[5]) x_delta = (x2 - x1) / t y_delta = (y2 - y1) / t w_delta = (w2 - w1) / t h_delta = (h2 - h1) / t for i in xrange(1, t + 1): frame += 1 x1 += x_delta y1 += y_delta w1 += w_delta h1 += h_delta attr1[0] = str(frame) attr1[2] = str(x1) attr1[3] = str(y1) attr1[4] = str(w1) attr1[5] = str(h1) if i == 1 or i == t: self.outputLine(attr1, src + 'LinearModel2') else: self.outputLine(attr1, 'Recovering') self.missingCounter += t - 1 def vot(self, bbx): """ Tracking with VOT (DaSiamRPN) :param bbx: The initial bounding box :return: The prediction and the confidence score """ x, y, w, h, frame = bbx [cx, cy, w, h] = [x + w / 2, y + h / 2, w, h] # tracker init target_pos, target_sz = np.array([cx, cy]), np.array([w, h]) cur_img = cv2.imread(self.a_train_set.img_dir + '%06d.jpg' % frame) state = SiamRPN_init(cur_img, target_pos, target_sz, self.net) state = SiamRPN_track(state, self.img) # track res = cxy_wh_2_rect(state['target_pos'], state['target_sz']) score = state['score'] bbx = [int(l) for l in res] return bbx, score def tracking_vot(self, gap, index): frame = self.a_train_set.f_step - self.a_train_set.gap self.img = cv2.imread(self.a_train_set.img_dir + '%06d.jpg' % (frame + gap)) bbx = self.a_train_set.bbx[frame][index] pred, score = self.vot(bbx) if score >= vot_conf_score and self.detect(pred): return pred return None def transfer(self, line, pred, frame): attr = [] attr.append(str(frame)) attr.append(line[1]) for p in pred: attr.append(str(p)) for p in line[6:]: attr.append(p) attr[-1] = 1 return attr def doTracking(self, a_t_gap, index): # @We first do tracking with DaSiamRPN. frame = self.a_train_set.f_step - a_t_gap for gap in xrange(1, a_t_gap): # print '\n Container:' # print self.line_con[self.cur] # print self.line_con[self.nxt] pred = self.tracking_vot(gap, index) if pred is not None: attr1 = self.line_con[self.cur][index] # print ' Attr1:', attr1 attr2 = self.transfer(attr1, pred, frame + gap) self.linearModel(attr1, attr2, 'doTracking1') # print 'Frame:', frame+gap # print ' Attr2:', attr2 # print ' Attr1_after:', attr1 self.line_con[self.cur][index] = attr2 # print self.line_con[self.cur][index] # raw_input('Continue?') pred = self.tracking_vot(a_t_gap, index) if pred is not None: attr1 = self.line_con[self.cur][index] # print ' Attr1:', attr1 attr2 = self.transfer(attr1, pred, frame + a_t_gap) self.linearModel(attr1, attr2, 'doTracking2') # print ' Attr2:', attr2 # print ' Attr1_after:', attr1 # self.a_train_set.addApp(pred) # self.m_train_set.addMotion(pred) self.a_train_set.moveApp(index) self.m_train_set.moveMotion(index) self.line_con[self.nxt].append(attr2) self.id_con[self.nxt].append(self.id_con[self.cur][index]) return True return False def evaluation(self, head, tail, gtFile): ''' Evaluation on dets :param head: the head frame number :param tail: the tail frame number :param gtFile: the ground truth file name :param outFile: the name of output file :return: None ''' gtIn = open(gtFile, 'r') self.cur, self.nxt = 0, 1 self.img = None self.line_con = [[], []] self.id_con = [[], []] self.id_step = 1 a_step = head + self.a_train_set.setBuffer(head) m_step = head + self.m_train_set.setBuffer(head) print 'Starting from the frame:', a_step if a_step != m_step: print 'Something is wrong!' print 'a_step =', a_step, ', m_step =', m_step raw_input('Continue?') while a_step <= tail: # print '*********************************' a_t_gap = self.a_train_set.loadNext() m_t_gap = self.m_train_set.loadNext() if a_t_gap != m_t_gap: print 'Something is wrong!' print 'a_t_gap =', a_t_gap, ', m_t_gap =', m_t_gap raw_input('Continue?') a_step += a_t_gap m_step += m_step print a_step, if a_step % 1000 == 0: print if a_step > tail: break self.loadCur(self.a_train_set.m, gtIn) # print head+step, 'F', a_m, m_m = self.a_train_set.m, self.m_train_set.m a_n, m_n = self.a_train_set.n, self.m_train_set.n if a_m != m_m or a_n != m_n: print 'Something is wrong!' print 'a_m = %d, m_m = %d' % ( a_m, m_m), ', a_n = %d, m_n = %d' % (a_n, m_n) raw_input('Continue?') self.loadNxt(gtIn, a_n) self.a_train_set.loadPre() self.m_train_set.loadPre() m_u_ = self.MUphi(self.m_train_set.E, self.m_train_set.V, self.Mu) # update the edges # print 'T', candidates = [] E_CON, V_CON = [], [] for edge in self.a_train_set.candidates: e, vs_index, vr_index = edge e = e.view(1, -1).to(self.device) vs = self.a_train_set.getApp(1, vs_index) vr = self.a_train_set.getApp(0, vr_index) e1 = self.AEphi1(e, vs, vr, self.Au) vr1 = self.AVphi(e1, vs, vr, self.Au) candidates.append((e1, vs, vr1, vs_index, vr_index)) E_CON.append(e1) V_CON.append(vs) V_CON.append(vr1) E = self.a_train_set.aggregate(E_CON).view(1, -1) V = self.a_train_set.aggregate(V_CON).view(1, -1) u1 = self.AUphi(E, V, self.Au) ret = self.a_train_set.getRet() decay_tag = [0 for i in xrange(a_m)] for i in xrange(a_m): for j in xrange(a_n): if ret[i][j] == 0: decay_tag[i] += 1 for i in xrange(len(self.a_train_set.candidates)): e1, vs, vr1, a_vs_index, a_vr_index = candidates[i] m_e, m_vs_index, m_vr_index = self.m_train_set.candidates[i] if a_vs_index != m_vs_index or a_vr_index != m_vr_index: print 'Something is wrong!' print 'a_vs_index = %d, m_vs_index = %d' % (a_vs_index, m_vs_index) print 'a_vr_index = %d, m_vr_index = %d' % (a_vr_index, m_vr_index) raw_input('Continue?') if ret[a_vs_index][a_vr_index] == tau_threshold: continue e2 = self.AEphi2(e1, vs, vr1, u1) self.a_train_set.edges[a_vs_index][a_vr_index] = e1.data.view( -1) a_tmp = F.softmax(e2) a_tmp = a_tmp.cpu().data.numpy()[0] m_e = m_e.to(self.device).view(1, -1) m_v1 = self.m_train_set.getMotion(1, m_vs_index) m_v2 = self.m_train_set.getMotion(0, m_vr_index, m_vs_index) m_e_ = self.MEphi(m_e, m_v1, m_v2, m_u_) self.m_train_set.edges[m_vs_index][ m_vr_index] = m_e_.data.view(-1) m_tmp = F.softmax(m_e_) m_tmp = m_tmp.cpu().data.numpy()[0] t = self.line_con[self.cur][a_vs_index][-1] # A = float(a_tmp[0]) * pow(decay, t-1) # M = float(m_tmp[0]) * pow(decay, t-1) if decay_tag[a_vs_index] > 0: try: # A = min(float(a_tmp[0]) * pow(decay, t + a_t_gap -2), 0.999999999999) # M = min(float(m_tmp[0]) * pow(decay, t + a_t_gap -2), 0.999999999999) A = min( float(a_tmp[0]) * pow(decay, t + a_t_gap - 2), 1.0) M = min( float(m_tmp[0]) * pow(decay, t + a_t_gap - 2), 1.0) except OverflowError: print 'OverflowError!' A = float(a_tmp[0]) M = float(m_tmp[0]) else: A = float(a_tmp[0]) M = float(m_tmp[0]) ret[a_vs_index][a_vr_index] = A * self.alpha + M * (1 - self.alpha) self.tracking(ret, a_m, a_n, m_u_, u1, a_t_gap) self.line_con[self.cur] = [] self.id_con[self.cur] = [] # print head+step, results self.a_train_set.swapFC() self.m_train_set.swapFC() self.swapFC() gtIn.close() print ' The results:', self.id_step, self.bbx_counter # tra_tst = 'training sets' if head == 1 else 'validation sets' # out = open(outFile, 'a') # print >> out, tra_tst # out.close() def loadCur(self, a_m, gtIn): if self.id_step == 1: i = 0 while i < a_m: attrs = gtIn.readline().strip().split(',') if float(attrs[6]) >= tau_conf_score: attrs.append(1) attrs[1] = str(self.id_step) self.outputLine(attrs, 'LoadCur') self.line_con[self.cur].append(attrs) self.id_con[self.cur].append(self.id_step) self.id_step += 1 i += 1 def loadNxt(self, gtIn, a_n): i = 0 while i < a_n: attrs = gtIn.readline().strip().split(',') if float(attrs[6]) >= tau_conf_score: attrs.append(1) self.line_con[self.nxt].append(attrs) self.id_con[self.nxt].append(-1) i += 1 def tracking(self, ret, a_m, a_n, m_u_, u1, a_t_gap): results = self.hungarian.compute(ret) # if self.a_train_set.f_step > 532: # print '\nCur:' # for i in xrange(len(self.line_con[self.cur])): # print ' Index:', i, '- ID:', self.id_con[self.cur][i], '- line:', self.line_con[self.cur][i] # print 'Ret:' # for i in xrange(len(ret)): # print " Index:", i, '- D:', ret[i] # print 'Nxt:' # for i in xrange(len(self.line_con[self.nxt])): # print ' Index:', i, '- ID:', self.id_con[self.nxt][i], '- line:', self.line_con[self.nxt][i] # print 'Association:' # for (i, j) in results: # print ' Index:', i, '- ID:', self.id_con[self.cur][i], '- line:', self.line_con[self.cur][i] # print ' Index:', j, '- line:', self.line_con[self.nxt][j] # print '' # raw_input('Continue?') keeper = set(i for i in xrange(a_m)) look_up = set(j for j in xrange(a_n)) nxt = self.a_train_set.nxt for (i, j) in results: # print (i,j) if ret[i][j] >= tau_threshold: continue e1 = self.a_train_set.edges[i][j].view(1, -1).to(self.device) vs = self.a_train_set.getApp(1, i) vr = self.a_train_set.getApp(0, j) vr1 = self.AVphi(e1, vs, vr, self.Au) self.a_train_set.detections[nxt][j][0] = vr1.data keeper.remove(i) look_up.remove(j) self.m_train_set.updateVelocity(i, j, False) id = self.id_con[self.cur][i] self.id_con[self.nxt][j] = id attr1 = self.line_con[self.cur][i] attr2 = self.line_con[self.nxt][j] # print attrs attr2[1] = str(id) if attr2[1] == '-1': print 'In main process:', attr2[1], self.id_con[self.cur][i] self.linearModel(attr1, attr2, 'Main') if u_update: # m_u_ = torch.clamp(m_u_, max=1.0, min=-1.0) # make sure that the global variable not that big # u1 = torch.clamp(u1, max=1.0, min=-1.0) self.Mu = m_u_.data self.Au = u1.data remainer = set() for i in keeper: if self.line_con[ self.cur][i][-1] + a_t_gap <= gap and self.doTracking( a_t_gap, i) == False: # if self.doTracking(a_t_gap, i) == False: remainer.add(i) for j in look_up: self.m_train_set.updateVelocity(-1, j, tag=False) self.output(a_n) self.miss_occlu(a_t_gap, remainer) # self.miss_occlu(a_t_gap, keeper) def output(self, a_n): for i in xrange(a_n): if self.id_con[self.nxt][i] == -1: self.id_con[self.nxt][i] = self.id_step attrs = self.line_con[self.nxt][i] attrs[1] = str(self.id_step) self.outputLine(attrs, 'Output') self.id_step += 1 def miss_occlu(self, a_t_gap, remainer): # For missing & Occlusion for index in remainer: attrs = self.line_con[self.cur][index] # print '*', attrs, '*' if attrs[-1] + a_t_gap <= gap: attrs[-1] += a_t_gap self.line_con[self.nxt].append(attrs) self.id_con[self.nxt].append(self.id_con[self.cur][index]) self.a_train_set.moveApp(index) self.m_train_set.moveMotion(index)