def track(video, annot): # Create the correlation tracker - the object needs to be initialized # before it can be used tracker = dlib.correlation_tracker() win = dlib.image_window() # We will track the frames as we load them off of disk img_paths = sorted(glob.glob(os.path.join(video, "*.jpg"))) sort_nicely(img_paths) for k, f in enumerate(img_paths): print("Processing Frame {}".format(k)) img = dlib.load_rgb_image(f) # We need to initialize the tracker on the first frame if k == 0: # Start a track on the juice box. If you look at the first frame you # will see that the juice box is contained within the bounding # box (74, 67, 112, 153). with open(annot) as f: initial_box = [int(i) for i in f.readline().strip().split(',')] x, y, w, h = initial_box tracker.start_track(img, dlib.rectangle(x, y, x + w, y + h)) else: # Else we just attempt to track from the previous frame tracker.update(img) win.clear_overlay() win.set_image(img) win.add_overlay(tracker.get_position()) dlib.hit_enter_to_continue()
def show_tag(request, deviceId): # define default response response = { "err": "", "data": "" } # get device try: device = Device.objects.get(id=deviceId) # device exists # get log data list from deviceId directory path = os.path.join(RAW_LOG_ROOT, device[0].meid) # empty filelist = {} try: os.chdir(path) filelist = os.listdir(".") sort_nicely(filelist) Tagdata = '' for file in filelist: filename = os.path.join(RAW_LOG_ROOT, device[0].meid, file) Logfile = open(filename, 'r+') for line in Logfile: #Logdata = Logfile.readline() #Two ways to find with string and without string if re.search(request.POST['tagName'], line): if not request.POST.has_key('anti'): Tagdata += line else: if request.POST.has_key('anti'): Tagdata += line # render respone return render_to_response( 'device/filter.html', { 'device': device[0], 'TagName': request.POST['tagName'], 'Tagdata': Tagdata }, context_instance=RequestContext(request) ) Logfile.close() Tagfile.close() except OSError, e: if e.errno != errno.EEXIST: response['err'] = { 'no' : 'err2', 'msg': 'cannot change dir' } # device does not exist except Device.DoesNotExist: response['err'] = { 'no' : 'err1', 'msg': 'invalid device' } return json_response_from(response)
def show_tag(request, deviceId): # define default response response = {"err": "", "data": ""} # get device try: device = Device.objects.get(id=deviceId) # device exists # get log data list from deviceId directory path = os.path.join(RAW_LOG_ROOT, device[0].meid) # empty filelist = {} try: os.chdir(path) filelist = os.listdir(".") sort_nicely(filelist) Tagdata = '' for file in filelist: filename = os.path.join(RAW_LOG_ROOT, device[0].meid, file) Logfile = open(filename, 'r+') for line in Logfile: #Logdata = Logfile.readline() #Two ways to find with string and without string if re.search(request.POST['tagName'], line): if not request.POST.has_key('anti'): Tagdata += line else: if request.POST.has_key('anti'): Tagdata += line # render respone return render_to_response('device/filter.html', { 'device': device[0], 'TagName': request.POST['tagName'], 'Tagdata': Tagdata }, context_instance=RequestContext(request)) Logfile.close() Tagfile.close() except OSError, e: if e.errno != errno.EEXIST: response['err'] = {'no': 'err2', 'msg': 'cannot change dir'} # device does not exist except Device.DoesNotExist: response['err'] = {'no': 'err1', 'msg': 'invalid device'} return json_response_from(response)
def _prepare_refim_catalogue(self, use_cache, cache_dir, save_cache=True): loaded_cache = False cache_fpath = os.path.join(cache_dir, 'reference_images.hdf5') refimdir_str = self._refimdir.replace(os.sep, '|') + '|' + \ ('' if not self._maxrecur else f'maxrecur{self._maxrecur:d}_') + f'sep{self._seprep}' if not os.path.isdir(cache_dir): try: os.mkdir(cache_dir) except OSError: print( f'{self.__class__.__name__}{self._idx_str}: cannot create cache directory; not saving cache file' ) save_cache = False refimdir_mtime = os.path.getmtime(self._refimdir) if use_cache and os.path.isfile(cache_fpath): with h5.File(cache_fpath, 'r') as f: try: cached_mtime = np.array(f[f'{refimdir_str}/mtime']) if cached_mtime != refimdir_mtime: use_cache = False except KeyError: use_cache = False if use_cache: with h5.File(cache_fpath, 'r') as f: try: self._all_refimrpaths = np.array( f[f'{refimdir_str}/rpaths']).astype(str) self._all_refimids = np.array( f[f'{refimdir_str}/ids']).astype(str) loaded_cache = True except KeyError: # no cached result pass if not loaded_cache: self._all_refimrpaths = utils.sort_nicely( self._find_refims_recursively()) self._all_refimids = utils.make_unique_ids( self._all_refimrpaths, remove_extension=True, sep_replacer=self._seprep) if save_cache: with h5.File(cache_fpath, 'a') as f: if refimdir_str in f.keys(): del f[refimdir_str] f.create_dataset(f'{refimdir_str}/rpaths', data=np.array( self._all_refimrpaths).astype('S')) f.create_dataset(f'{refimdir_str}/ids', data=np.array( self._all_refimids).astype('S')) f.create_dataset(f'{refimdir_str}/mtime', data=refimdir_mtime)
def __get_pict_files(folder): """ Get all the picture files in the folder """ folder_path = os.path.abspath(folder) if not os.path.isdir(folder_path): print "Trouble reading folder path {}".format(folder_path) picture_list = [] n_files = 0 for dirname, dirnames, filenames in os.walk(folder_path): filenames = ut.sort_nicely(filenames) for filename in filenames: print "Reading file {}".format(filename) full_filepath = os.path.join(folder_path, filename) if (filename[-3:] == "bmp") or \ (filename[-3:] == "png") or \ (filename[-3:] == "jpg") : try: picture_list.append( cv2.imread(full_filepath, cv2.CV_LOAD_IMAGE_GRAYSCALE)) if picture_list[n_files] is None: picture_list.pop() print "Error loading file {}".format(filename) else: n_files += 1 except: print "Error loading file {}".format(filename) return picture_list, n_files
def __get_pict_files(folder): """ Get all the picture files in the folder """ folder_path = os.path.abspath(folder) if not os.path.isdir(folder_path): print "Trouble reading folder path {}".format(folder_path) picture_list = [] n_files = 0 for dirname, dirnames, filenames in os.walk(folder_path): filenames = ut.sort_nicely(filenames) for filename in filenames: print "Reading file {}".format(filename) full_filepath = os.path.join(folder_path, filename) if (filename[-3:] == "bmp") or \ (filename[-3:] == "png") or \ (filename[-3:] == "jpg") : try: picture_list.append(cv2.imread(full_filepath, cv2.CV_LOAD_IMAGE_GRAYSCALE)) if picture_list[n_files] is None: picture_list.pop() print "Error loading file {}".format(filename) else: n_files += 1 except: print "Error loading file {}".format(filename) return picture_list, n_files
dir = os.path.dirname(os.path.realpath(__file__)) INPUT_DIR = dir + "/detection_all_frames" OUTPUT_FILENAME = "output.mp4" OUTPUT_FILEPATH = dir + "/" + OUTPUT_FILENAME print("Cleaning output files...") if os.path.isfile(OUTPUT_FILEPATH): os.unlink(OUTPUT_FILEPATH) print("Reading images...") img_paths = [] for img_path in find_images(INPUT_DIR): img_paths.append(ntpath.basename(img_path)) sort_nicely(img_paths) print("Writing " + OUTPUT_FILENAME + "...") height, width, layers = cv2.imread(INPUT_DIR + "/" + img_paths[0]).shape size = (width, height) writer = cv2.VideoWriter(OUTPUT_FILENAME, cv2.VideoWriter_fourcc(*'MP4V'), 30, size) for img_path in img_paths: img = cv2.imread(INPUT_DIR + "/" + img_path) writer.write(img) writer.release() # height , width , layers = cv2.imread(INPUT_DIR + '/1.jpg').shape
def status(request, deviceId, statusType): user = request.user # define default response response = { "err": "", "data": "" } #check deviceId to control accesses if is_valid_device(user, deviceId): # get device try: device = Device.objects.get(id=deviceId) # device exists # get log data list from deviceId directory path = os.path.join(RAW_LOG_ROOT, device.meid) # empty filelist = {} tagName = '' if statusType == '1': tagName = 'Battery_level' #tagName = 'Battery level' elif statusType == '2': tagName = 'Location_Latitude' #tagName = 'Location: Latitude' else: tagName = 'Signal_Strength' #tagName = 'Signal Strength' try: os.chdir(path) filelist = os.listdir(".") sort_nicely(filelist) Tagdata = '' for file in filelist: filename = os.path.join(RAW_LOG_ROOT, device.meid, file) Logfile = open(filename, 'r+') for line in Logfile: #Logdata = Logfile.readline() if re.search(tagName, line): temp = line.split() Tagdata += ' [ ' + temp[0] + ' ' + temp[1] + ' ] ' if statusType == '1': Tagdata += 'Battery Level: ' + temp[7] + '\n' elif statusType == '2': Tagdata += 'GPS Latitude: ' + temp[7] + ', Longitude: ' + temp[9] + ', Accuracy: ' + temp[11] + '\n' else: Tagdata += 'Signal Strengh: ' + temp[7] + ', asu: ' + temp[9] + '\n' # render respone return render_to_response( 'device/status.html', { 'device': device, 'TagName': tagName, 'Tagdata': Tagdata }, context_instance=RequestContext(request) ) Logfile.close() Tagfile.close() except OSError, e: if e.errno != errno.EEXIST: response['err'] = { 'no' : 'err1', 'msg': 'cannot change dir' } # device does not exist except Device.DoesNotExist: response['err'] = { 'no' : 'err1', 'msg': 'invalid device' } return json_response_from(response) else: return HttpResponseRedirect('/')
def status(request, deviceId, statusType): user = request.user # define default response response = {"err": "", "data": ""} #check deviceId to control accesses if is_valid_device(user, deviceId): # get device try: device = Device.objects.get(id=deviceId) # device exists # get log data list from deviceId directory path = os.path.join(RAW_LOG_ROOT, device.meid) # empty filelist = {} tagName = '' if statusType == '1': tagName = 'Battery_level' #tagName = 'Battery level' elif statusType == '2': tagName = 'Location_Latitude' #tagName = 'Location: Latitude' else: tagName = 'Signal_Strength' #tagName = 'Signal Strength' try: os.chdir(path) filelist = os.listdir(".") sort_nicely(filelist) Tagdata = '' for file in filelist: filename = os.path.join(RAW_LOG_ROOT, device.meid, file) Logfile = open(filename, 'r+') for line in Logfile: #Logdata = Logfile.readline() if re.search(tagName, line): temp = line.split() Tagdata += ' [ ' + temp[0] + ' ' + temp[1] + ' ] ' if statusType == '1': Tagdata += 'Battery Level: ' + temp[7] + '\n' elif statusType == '2': Tagdata += 'GPS Latitude: ' + temp[ 7] + ', Longitude: ' + temp[ 9] + ', Accuracy: ' + temp[11] + '\n' else: Tagdata += 'Signal Strengh: ' + temp[ 7] + ', asu: ' + temp[9] + '\n' # render respone return render_to_response( 'device/status.html', { 'device': device, 'TagName': tagName, 'Tagdata': Tagdata }, context_instance=RequestContext(request)) Logfile.close() Tagfile.close() except OSError, e: if e.errno != errno.EEXIST: response['err'] = { 'no': 'err1', 'msg': 'cannot change dir' } # device does not exist except Device.DoesNotExist: response['err'] = {'no': 'err1', 'msg': 'invalid device'} return json_response_from(response) else: return HttpResponseRedirect('/')
def copy_nature_image(natstimdir, expdir, size=None, reformat=False, prefix='', num_mark=False): '''Adapt from attach_nature_image code''' natstimfns = utils.sort_nicely([ fn for fn in os.listdir(natstimdir) if '.bmp' in fn or '.jpg' in fn or '.png' in fn or '.jepg' in fn or '.JPEG' in fn ]) natstimnames = [fn[:fn.rfind('.')] for fn in natstimfns] nstimuli = len(natstimnames) if nstimuli == 0: raise Exception('no images found in natual stimulus directory %s' % natstimdir) if size is None: size = nstimuli else: size = int(size) # choose images to load (if nstimuli != size) toshow_args = np.arange(nstimuli) if nstimuli < size: print( 'note: number of natural images (%d) < requested (%d); repeating images' % (nstimuli, size)) toshow_args = np.repeat(toshow_args, int(np.ceil(size / float(nstimuli))))[:size] elif nstimuli > size: print( 'note: number of natural images (%d) > requested (%d); taking first %d images' % (nstimuli, size, size)) toshow_args = toshow_args[:size] natstimnames = [natstimnames[arg] for arg in toshow_args] natstimfns = [natstimfns[arg] for arg in toshow_args] # make ids natstimids = natstimnames[:] # strip off initial [], if any for i, id_ in enumerate(natstimids): if id_[0] == '[' and ']' in id_: natstimids[i] = id_[id_.find(']') + 1:] # resolve nonunique ids, if any if nstimuli < size: for i, id_ in enumerate(natstimids): icopy = 1 new_id = id_ while new_id in natstimids[:i]: new_id = '%s_copy%02d' % (id_, icopy) natstimids[i] = new_id print('showing the following %d natural stimuli loaded from %s:' % (size, natstimdir)) print(natstimids) # if no image of other format, then use copy directly; if not, use reformat to make them 'bmp' if reformat: for fn, id in zip(natstimfns, natstimids): img = imread(os.path.join(natstimdir, fn)) imwrite(os.path.join(expdir, prefix + id + '.bmp'), img) else: for fn, id in zip(natstimfns, natstimids): # copy(os.path.join(natstimdir, fn), expdir) copyfile(os.path.join(natstimdir, fn), os.path.join(expdir, prefix + id + '.bmp'))
else: isMOTformat = False success_rate_list.append( overlap_precision(ann, trk_r, threshold, isMOTformat)) mkjson(trk_name, success_rate_list) ################################################################################################# ###################################################################################################################################################################### if __name__ == '__main__': data = config.data annots = sorted(glob.glob((data['annot_folder'] + "*"))) sort_nicely(annots) dsst_r = sorted(glob.glob((data['dsst_tracked_results'] + "*"))) sort_nicely(dsst_r) ecohc_r = sorted(glob.glob((data['ecohc_tracked_results'] + "*"))) sort_nicely(ecohc_r) eco_r = sorted(glob.glob((data['eco_tracked_results'] + "*"))) sort_nicely(eco_r) re3_r = sorted(glob.glob((data['re3_tracked_results'] + "*"))) sort_nicely(re3_r) kcf_r = sorted(glob.glob((data['kcf_tracked_results'] + "*"))) sort_nicely(kcf_r) deepsort_r = sorted(glob.glob((data['deep_sort_results'] + "*"))) sort_nicely(deepsort_r) ioutrk_r = sorted(glob.glob((data['iou_traker_results'] + "*"))) sort_nicely(ioutrk_r)
def _load_natural_stimuli(self, natstimdir, size=None, natstim_catalogue_fpath=None, shuffle=False): all_natstimfns = utils.sort_nicely([ fn for fn in os.listdir(natstimdir) if '.bmp' in fn or '.jpg' in fn or '.png' in fn or '.tif' in fn or '.tiff' in fn or '.jpeg' in fn or '.JPEG' in fn ]) all_natstimnames = [fn[:fn.rfind('.')] for fn in all_natstimfns] nstimuli = len(all_natstimnames) all_natstim_times_shown = np.zeros(nstimuli, dtype=int) if nstimuli == 0: raise Exception('no images found in natual stimulus directory %s' % natstimdir) if size is None: size = nstimuli else: size = int(size) # make ids (names mapped to catalogue if any) from names (fn without extension) all_natstimids = all_natstimnames[:] # try to map filename (no extension) to short id, if catalogue given if natstim_catalogue_fpath is not None: catalogue = np.load(natstim_catalogue_fpath) name_2_id = { name: id_ for name, id_ in zip(catalogue['stimnames'], catalogue['stimids']) } for i, name in enumerate(all_natstimids): try: all_natstimids[i] = name_2_id[name] except KeyError: all_natstimids[i] = name # resolve nonunique ids, if any if nstimuli < size: for i, id_ in enumerate(all_natstimids): icopy = 1 new_id = id_ while new_id in all_natstimids[:i]: new_id = '%s_copy%02d' % (id_, icopy) all_natstimids[i] = new_id # choose images to load (if nstimuli != size) toshow_args = np.arange(nstimuli) if nstimuli < size: if shuffle: print( 'note: number of natural images (%d) < requested (%d); sampling with replacement' % (nstimuli, size)) toshow_args = self._random_generator.choice(toshow_args, size=size, replace=True) else: print( 'note: number of natural images (%d) < requested (%d); repeating images' % (nstimuli, size)) toshow_args = np.repeat(toshow_args, int(np.ceil(size / float(nstimuli))))[:size] elif nstimuli > size: if shuffle: print( 'note: number of natural images (%d) > requested (%d); sampling (no replacement)' % (nstimuli, size)) toshow_args = self._random_generator.choice(toshow_args, size=size, replace=False) else: print( 'note: number of natural images (%d) > requested (%d); taking first %d images' % (nstimuli, size, size)) toshow_args = toshow_args[:size] natstimids = [all_natstimids[arg] for arg in toshow_args] natstimfns = [all_natstimfns[arg] for arg in toshow_args] all_natstim_times_shown[toshow_args] += 1 # load images natstimuli = [] for natstimfn in natstimfns: natstimuli.append( utils.read_image(os.path.join(natstimdir, natstimfn))) print('showing the following %d natural stimuli loaded from %s:' % (size, natstimdir)) print(natstimids) # save results self._natstimdir = natstimdir self._natstimuli = natstimuli self._natstimids = natstimids self._natstimfns = natstimfns self._n_natstim_to_show = size self._all_natstimids = np.array(all_natstimids) self._all_natstimfns = np.array(all_natstimfns) self._all_natstim_times_shown = all_natstim_times_shown
def attach_natural_stimuli(self, natstimdir, size=None, natstim_catalogue_fpath=None, shuffle=False): natstimfns = sort_nicely([ fn for fn in os.listdir(natstimdir) if '.bmp' in fn or '.jpg' in fn or '.png' in fn or '.jepg' in fn or '.JPEG' in fn ]) natstimnames = [fn[:fn.rfind('.')] for fn in natstimfns] nstimuli = len(natstimnames) if nstimuli == 0: raise Exception('no images found in natual stimulus directory %s' % natstimdir) if size is None: size = nstimuli else: size = int(size) # choose images to load (if nstimuli != size) toshow_args = np.arange(nstimuli) if nstimuli < size: if shuffle: print( 'note: number of natural images (%d) < requested (%d); sampling with replacement' % (nstimuli, size)) toshow_args = np.random.choice(toshow_args, size=size, replace=True) else: print( 'note: number of natural images (%d) < requested (%d); repeating images' % (nstimuli, size)) toshow_args = np.repeat(toshow_args, int(np.ceil(size / float(nstimuli))))[:size] elif nstimuli > size: if shuffle: print( 'note: number of natural images (%d) > requested (%d); sampling (no replacement)' % (nstimuli, size)) toshow_args = np.random.choice(toshow_args, size=size, replace=False) else: print( 'note: number of natural images (%d) > requested (%d); taking first %d images' % (nstimuli, size, size)) toshow_args = toshow_args[:size] natstimnames = [natstimnames[arg] for arg in toshow_args] natstimfns = [natstimfns[arg] for arg in toshow_args] # load images natstimuli = [] for natstimfn in natstimfns: natstimuli.append(read_image(os.path.join(natstimdir, natstimfn))) # make ids natstimids = natstimnames[:] # strip off initial [], if any for i, id_ in enumerate(natstimids): if id_[0] == '[' and ']' in id_: natstimids[i] = id_[id_.find(']') + 1:] # try to map filename (no extension) to short id, if catalogue given if natstim_catalogue_fpath is not None: catalogue = np.load(natstim_catalogue_fpath) name_2_id = { name: id_ for name, id_ in zip(catalogue['stimnames'], catalogue['stimids']) } for i, name in enumerate(natstimids): try: natstimids[i] = name_2_id[name] except KeyError: natstimids[i] = name # resolve nonunique ids, if any if nstimuli < size: for i, id_ in enumerate(natstimids): icopy = 1 new_id = id_ while new_id in natstimids[:i]: new_id = '%s_copy%02d' % (id_, icopy) natstimids[i] = new_id print('showing the following %d natural stimuli loaded from %s:' % (size, natstimdir)) print(natstimids) # save results self._natstimuli = natstimuli self._natstimids = natstimids self._natstimfns = natstimfns self._natstimdir = natstimdir # self._natstimnames = natstimnames self._natstim_cumuscores = np.zeros(nstimuli, dtype='float') self._natstim_nscores = np.zeros(nstimuli, dtype='int') self._natstim_scores = np.full(nstimuli, np.nan, dtype='float')
def demo(videos, annots, trk_results, isMotformat): """ Draw multiple tracking results and annotations on video at the same time Params: videos: list of path to video directory (each directory contains video frames) annots: list of path to annotation files trk_results: list of list of path to tracking results isMotformat: True, False, or 'DET'(corresponding results are detection results) Return: None, video will be stored in output_video """ video_id = 0 for video, annot in zip(videos, annots): video_name = basename(video) if basename(annot).find(video_name) == -1: raise Exception("No corresding video and annotation!") if video_name != "person14_2": video_id += 1 continue print("Processing " + video_name) FPS = 30 # remember to modify frame width and height before testing video frame_width = 1280 frame_height = 720 video_writer = cv2.VideoWriter("output_video/"+video_name+'.avi', cv2.VideoWriter_fourcc('M','J','P','G'), FPS, (frame_width, frame_height)) image_paths = sorted(glob.glob(os.path.join(video, '*jpg'))) sort_nicely(image_paths) labels = np.loadtxt(annot, delimiter=',') preds_per_trk = [] for trk_r in trk_results: preds = np.loadtxt(trk_r[video_id], delimiter=',') preds_per_trk.append(preds) nb_lost = 0.0 for fi, image_path in enumerate(tqdm(image_paths)): image = cv2.imread(image_path) for trk_id, preds in enumerate(preds_per_trk): # Iterate over tracker results if isMotformat[trk_id] is True: # Multi-object tracking results index_list = np.argwhere(preds[:, 0] == (fi+1)) if index_list.shape[0] != 0: max_iou = 0.0 target_index = -1 for index in index_list[:, 0]: bbox = preds[index, 2:6] iou = bbox_iou(bbox, labels[fi]) if iou > max_iou: max_iou = iou target_index = index if max_iou > 0.2 and target_index != -1: target_bbox = preds[target_index, 2:6] target_bbox = xywh_to_xyxy(target_bbox) cv2.rectangle(image, (int(target_bbox[0]),int(target_bbox[1])), (int(target_bbox[2]),int(target_bbox[3])), colours[trk_id], 2) cv2.rectangle(image, (int(target_bbox[0])-2,int(target_bbox[1]-20)), (int(target_bbox[0])+20+int(preds[target_index, 1])//10 ,int(target_bbox[1])+1), colours[trk_id], -1) cv2.putText(image, str(int(preds[target_index, 1])), (int(target_bbox[0]+2), int(target_bbox[1])-3), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,0,0), 2) else: nb_lost += 1 elif isMotformat[trk_id] == 'DET': # Detection results index_list = np.argwhere(preds[:, 0] == (fi+1)) if index_list.shape[0] != 0: max_iou = 0.0 target_index = -1 for index in index_list[:, 0]: bbox = preds[index, 2:6] iou = bbox_iou(bbox, labels[fi]) if iou > max_iou: max_iou = iou target_index = index if max_iou > 0.5 and target_index != -1: target_bbox = preds[target_index, 2:6] target_bbox = xywh_to_xyxy(target_bbox) cv2.rectangle(image, (int(target_bbox[0]),int(target_bbox[1])), (int(target_bbox[2]),int(target_bbox[3])), colours[trk_id], 4) else: # Single object tracking results rect = xywh_to_xyxy(preds[fi]) cv2.rectangle(image, (int(rect[0]),int(rect[1])), (int(rect[2]),int(rect[3])), # (colours[trk_id]), 4) (255,0,0), 4) if isNAN(labels[fi]) is not True: gt_rect = xywh_to_xyxy(labels[fi]) cv2.rectangle(image, (int(gt_rect[0]),int(gt_rect[1])), (int(gt_rect[2]),int(gt_rect[3])), (0,0,255), 2) video_writer.write(image) # dir_path = 'output_video/person14_1/' # frame_name = "{0:0=3d}".format(fi) + ".jpg" # cv2.imwrite(dir_path + frame_name, image) if fi > 180: break video_id += 1 print("Lost target: {}".format(nb_lost))