123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- #!/usr/bin/env python
- from __future__ import print_function
- import os, sys, shutil
- import argparse
- import json, re
- from subprocess import check_output
- import datetime
- import matplotlib.pyplot as plt
- def load_json(path):
- f = open(path, "r")
- data = json.load(f)
- return data
- def save_json(obj, path):
- tmp_file = path + ".bak"
- f = open(tmp_file, "w")
- json.dump(obj, f, indent=2)
- f.flush()
- os.fsync(f.fileno())
- f.close()
- try:
- os.rename(tmp_file, path)
- except:
- os.remove(path)
- os.rename(tmp_file, path)
- def parse_evaluation_result(input_str, i):
- res = {}
- res['frame_number'] = i + 1
- res['error'] = {}
- regex = "([A-Za-z. \\[\\].0-9]+):[ ]*([0-9]*\.[0-9]+|[0-9]+)"
- for elem in re.findall(regex,input_str):
- if "Time" in elem[0]:
- res['time'] = float(elem[1])
- elif "Average" in elem[0]:
- res['error']['average'] = float(elem[1])
- elif "deviation" in elem[0]:
- res['error']['std'] = float(elem[1])
- else:
- res['error'][elem[0]] = float(elem[1])
- return res
- def evaluate_sequence(sequence, algorithm, dataset, executable, img_files, gt_files,
- state, state_path):
- if "eval_results" not in state[dataset][algorithm][-1].keys():
- state[dataset][algorithm][-1]["eval_results"] = {}
- elif sequence in state[dataset][algorithm][-1]["eval_results"].keys():
- return
- res = []
- for i in range(len(img_files) - 1):
- sys.stdout.write("Algorithm: %-20s Sequence: %-10s Done: [%3d/%3d]\r" %
- (algorithm, sequence, i, len(img_files) - 1)),
- sys.stdout.flush()
- res_string = check_output([executable, img_files[i], img_files[i + 1],
- algorithm, gt_files[i]])
- res.append(parse_evaluation_result(res_string, i))
- state[dataset][algorithm][-1]["eval_results"][sequence] = res
- save_json(state, state_path)
- #############################DATSET DEFINITIONS################################
- def evaluate_mpi_sintel(source_dir, algorithm, evaluation_executable, state, state_path):
- evaluation_result = {}
- img_dir = os.path.join(source_dir, 'mpi_sintel', 'training', 'final')
- gt_dir = os.path.join(source_dir, 'mpi_sintel', 'training', 'flow')
- sequences = [f for f in os.listdir(img_dir)
- if os.path.isdir(os.path.join(img_dir, f))]
- for seq in sequences:
- img_files = sorted([os.path.join(img_dir, seq, f)
- for f in os.listdir(os.path.join(img_dir, seq))
- if f.endswith(".png")])
- gt_files = sorted([os.path.join(gt_dir, seq, f)
- for f in os.listdir(os.path.join(gt_dir, seq))
- if f.endswith(".flo")])
- evaluation_result[seq] = evaluate_sequence(seq, algorithm, 'mpi_sintel',
- evaluation_executable, img_files, gt_files, state, state_path)
- return evaluation_result
- def evaluate_middlebury(source_dir, algorithm, evaluation_executable, state, state_path):
- evaluation_result = {}
- img_dir = os.path.join(source_dir, 'middlebury', 'other-data')
- gt_dir = os.path.join(source_dir, 'middlebury', 'other-gt-flow')
- sequences = [f for f in os.listdir(gt_dir)
- if os.path.isdir(os.path.join(gt_dir, f))]
- for seq in sequences:
- img_files = sorted([os.path.join(img_dir, seq, f)
- for f in os.listdir(os.path.join(img_dir, seq))
- if f.endswith(".png")])
- gt_files = sorted([os.path.join(gt_dir, seq, f)
- for f in os.listdir(os.path.join(gt_dir, seq))
- if f.endswith(".flo")])
- evaluation_result[seq] = evaluate_sequence(seq, algorithm, 'middlebury',
- evaluation_executable, img_files, gt_files, state, state_path)
- return evaluation_result
- dataset_eval_functions = {
- "mpi_sintel": evaluate_mpi_sintel,
- "middlebury": evaluate_middlebury
- }
- ###############################################################################
- def create_dir(dir):
- if not os.path.exists(dir):
- os.makedirs(dir)
- def parse_sequence(input_str):
- if len(input_str) == 0:
- return []
- else:
- return [o.strip() for o in input_str.split(",") if o]
- def build_chart(dst_folder, state, dataset):
- fig = plt.figure(figsize=(16, 10))
- markers = ["o", "s", "h", "^", "D"]
- marker_idx = 0
- colors = ["b", "g", "r"]
- color_idx = 0
- for algo in state[dataset].keys():
- for eval_instance in state[dataset][algo]:
- name = algo + "--" + eval_instance["timestamp"]
- average_time = 0.0
- average_error = 0.0
- num_elem = 0
- for seq in eval_instance["eval_results"].keys():
- for frame in eval_instance["eval_results"][seq]:
- average_time += frame["time"]
- average_error += frame["error"]["average"]
- num_elem += 1
- average_time /= num_elem
- average_error /= num_elem
- marker_style = colors[color_idx] + markers[marker_idx]
- color_idx += 1
- if color_idx >= len(colors):
- color_idx = 0
- marker_idx += 1
- if marker_idx >= len(markers):
- marker_idx = 0
- plt.gca().plot([average_time], [average_error],
- marker_style,
- markersize=14,
- label=name)
- plt.gca().set_ylabel('Average Endpoint Error (EPE)', fontsize=20)
- plt.gca().set_xlabel('Average Runtime (seconds per frame)', fontsize=20)
- plt.gca().set_xscale("log")
- plt.gca().set_title('Evaluation on ' + dataset, fontsize=20)
- plt.gca().legend()
- fig.savefig(os.path.join(dst_folder, "evaluation_results_" + dataset + ".png"),
- bbox_inches='tight')
- plt.close()
- if __name__ == '__main__':
- parser = argparse.ArgumentParser(
- description='Optical flow benchmarking script',
- formatter_class=argparse.RawDescriptionHelpFormatter)
- parser.add_argument(
- "bin_path",
- default="./optflow-example-optical_flow_evaluation",
- help="Path to the optical flow evaluation executable")
- parser.add_argument(
- "-a",
- "--algorithms",
- metavar="ALGORITHMS",
- default="",
- help=("Comma-separated list of optical-flow algorithms to evaluate "
- "(example: -a farneback,tvl1,deepflow). Note that previously "
- "evaluated algorithms are also included in the output charts"))
- parser.add_argument(
- "-d",
- "--datasets",
- metavar="DATASETS",
- default="mpi_sintel",
- help=("Comma-separated list of datasets for evaluation (currently only "
- "'mpi_sintel' and 'middlebury' are supported)"))
- parser.add_argument(
- "-f",
- "--dataset_folder",
- metavar="DATASET_FOLDER",
- default="./OF_datasets",
- help=("Path to a folder containing datasets. To enable evaluation on "
- "MPI Sintel dataset, please download it using the following links: "
- "http://files.is.tue.mpg.de/sintel/MPI-Sintel-training_images.zip and "
- "http://files.is.tue.mpg.de/sintel/MPI-Sintel-training_extras.zip and "
- "unzip these archives into the 'mpi_sintel' folder. To enable evaluation "
- "on the Middlebury dataset use the following links: "
- "http://vision.middlebury.edu/flow/data/comp/zip/other-color-twoframes.zip, "
- "http://vision.middlebury.edu/flow/data/comp/zip/other-gt-flow.zip. "
- "These should be unzipped into 'middlebury' folder"))
- parser.add_argument(
- "-o",
- "--out",
- metavar="OUT_DIR",
- default="./OF_evaluation_results",
- help="Output directory where to store benchmark results")
- parser.add_argument(
- "-s",
- "--state",
- metavar="STATE_JSON",
- default="./OF_evaluation_state.json",
- help=("Path to a json file that stores the current evaluation state and "
- "previous evaluation results"))
- args, other_args = parser.parse_known_args()
- if not os.path.isfile(args.bin_path):
- print("Error: " + args.bin_path + " does not exist")
- sys.exit(1)
- if not os.path.exists(args.dataset_folder):
- print("Error: " + args.dataset_folder + (" does not exist. Please, correctly "
- "specify the -f parameter"))
- sys.exit(1)
- state = {}
- if os.path.isfile(args.state):
- state = load_json(args.state)
- algorithm_list = parse_sequence(args.algorithms)
- dataset_list = parse_sequence(args.datasets)
- for dataset in dataset_list:
- if dataset not in dataset_eval_functions.keys():
- print("Error: unsupported dataset " + dataset)
- sys.exit(1)
- if dataset not in os.listdir(args.dataset_folder):
- print("Error: " + os.path.join(args.dataset_folder, dataset) + (" does not exist. "
- "Please, download the dataset and follow the naming conventions "
- "(use -h for more information)"))
- sys.exit(1)
- for dataset in dataset_list:
- if dataset not in state.keys():
- state[dataset] = {}
- for algorithm in algorithm_list:
- if algorithm in state[dataset].keys():
- last_eval_instance = state[dataset][algorithm][-1]
- if "finished" not in last_eval_instance.keys():
- print(("Continuing an unfinished evaluation of " +
- algorithm + " started at " + last_eval_instance["timestamp"]))
- else:
- state[dataset][algorithm].append({"timestamp":
- datetime.datetime.now().strftime("%Y-%m-%d--%H-%M")})
- else:
- state[dataset][algorithm] = [{"timestamp":
- datetime.datetime.now().strftime("%Y-%m-%d--%H-%M")}]
- save_json(state, args.state)
- dataset_eval_functions[dataset](args.dataset_folder, algorithm, args.bin_path,
- state, args.state)
- state[dataset][algorithm][-1]["finished"] = True
- save_json(state, args.state)
- save_json(state, args.state)
- create_dir(args.out)
- for dataset in dataset_list:
- build_chart(args.out, state, dataset)
|