5 from typing import Callable, List, NamedTuple, Set
11 parser = config.add_commandline_args(
12 f"ML Quick Labeler ({__file__})",
13 "Args related to quick labeling of ML training data",
16 "--ml_quick_label_skip_list_path",
17 default="./qlabel_skip_list.txt",
19 type=argparse_utils.valid_filename,
20 help="Path to file in which to store already labeled data",
24 class InputSpec(NamedTuple):
26 image_file_to_features_file: Callable[[str], str]
28 valid_keystrokes: List[str]
30 keystroke_to_label: Callable[[str], str]
33 def read_skip_list() -> Set[str]:
35 quick_skip_file = config.config['ml_quick_label_skip_list_path']
36 if not os.path.exists(quick_skip_file):
38 with open(quick_skip_file, 'r') as f:
47 def write_skip_list(skip_list) -> None:
48 quick_skip_file = config.config['ml_quick_label_skip_list_path']
49 with open(quick_skip_file, 'w') as f:
50 for filename in skip_list:
51 filename = filename.strip()
53 f.write(f'{filename}\n')
56 def label(in_spec: InputSpec) -> None:
57 images = glob.glob(in_spec.image_file_glob)
59 skip_list = read_skip_list()
61 if image in skip_list:
63 features = in_spec.image_file_to_features_file(image)
64 if features is None or not os.path.exists(features):
67 # Render features and image.
68 with open(features, "r") as f:
73 if in_spec.label in line:
79 os.system(f'xv {image} &')
80 keystroke = input_utils.single_keystroke_response(
81 in_spec.valid_keystrokes,
82 prompt=in_spec.prompt,
84 os.system('killall xv')
86 label_value = in_spec.keystroke_to_label(keystroke)
87 with open(features, "a") as f:
88 f.write(f"{in_spec.label}: {label_value}\n")
91 write_skip_list(skip_list)