Coverage for src/bob/bio/face/script/display_face_annotations.py: 84%
79 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-13 00:04 +0200
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-13 00:04 +0200
1#!../bin/python
3"""This script displays the images with annotations provided by any face database.
5By default, all images and their corresponding annotations are displayed, and you have to press ``Enter`` after each image.
6If the database does not include annotations, or you want to display a different set of annotations, you can specify the ``--annotation-directory`` (and if required modify the ``--annotation-file-extension`` and ``--annotation-file-type``.
7The list of images can be narrowed down by the ``--file-ids`` parameter, where the file ids are specific to the database.
9Note that this script can only be used with face image databases, not with video or other biometric databases.
10"""
12from __future__ import print_function
14import logging
15import os
17import click
19from clapper.click import ConfigCommand, ResourceOption, verbosity_option
21from bob.bio.base.utils.annotations import read_annotation_file
22from bob.bio.face.color import gray_to_rgb
24logger = logging.getLogger(__name__)
27@click.command(
28 entry_point_group="bob.bio.config",
29 cls=ConfigCommand,
30 epilog="""\b
31Examples:
33 $ bob bio display-face-annotations -vvv -d <database> -a <annot_dir>
34""",
35)
36@click.option(
37 "-d",
38 "--database",
39 required=True,
40 cls=ResourceOption,
41 entry_point_group="bob.bio.database",
42 help="Select the database for which the images plus annotations should be shown.",
43)
44@click.option(
45 "-V",
46 "--video",
47 "is_video",
48 is_flag=True,
49 help="Provide this flag if your database is a video database. "
50 "For video databases, the annotations for the first frame is shown.",
51)
52@click.option(
53 "-a",
54 "--annotations-dir",
55 help="Use the annotations stored in this directory "
56 "(when annotated with `$ bob bio annnotate` for example). "
57 "If not given, will try to load the annotations from the database.",
58)
59@click.option(
60 "-x",
61 "--annotations-extension",
62 default=".json",
63 show_default=True,
64 help="Annotations files have the given filename extension.",
65)
66@click.option(
67 "-t",
68 "--annotations-type",
69 default="json",
70 show_default=True,
71 help="Annotations type given to bob.bio.base.read_annotations.",
72)
73@click.option(
74 "-n",
75 "--display-names",
76 is_flag=True,
77 help="Plot the names of the annotations, too.",
78)
79@click.option(
80 "-m",
81 "--marker-style",
82 default="rx",
83 show_default=True,
84 help="Select the marker style",
85)
86@click.option(
87 "-M",
88 "--marker-size",
89 type=float,
90 default=10.0,
91 show_default=True,
92 help="Select the marker size",
93)
94@click.option(
95 "-C",
96 "--font-color",
97 default="b",
98 show_default=True,
99 help="Select the color for the annotations names",
100)
101@click.option(
102 "-F",
103 "--font-size",
104 type=int,
105 default=16,
106 show_default=True,
107 help="Select the font size for the annotations names",
108)
109@click.option(
110 "-o",
111 "--output-dir",
112 help="If given, it will save the plots in this output file instead of showing them. This option is useful when you don't have a display server (ssh).",
113)
114@click.option(
115 "-k",
116 "--keep-all",
117 is_flag=True,
118 help="When -o is given: keeps every annotated samples instead of just one.",
119)
120@click.option(
121 "--self-test",
122 is_flag=True,
123 help="Prevents outputing to the screen and waiting for user input.",
124)
125@click.option(
126 "--groups",
127 "-g",
128 multiple=True,
129 default=["dev", "eval"],
130 show_default=True,
131 help="Biometric Database group that will be displayed.",
132)
133@verbosity_option(logger=logger, expose_value=False)
134def display_face_annotations(
135 database,
136 is_video,
137 annotations_dir,
138 annotations_extension,
139 annotations_type,
140 marker_style,
141 marker_size,
142 display_names,
143 font_color,
144 font_size,
145 output_dir,
146 keep_all,
147 self_test,
148 groups,
149 **kwargs,
150):
151 """
152 Plots annotations on the corresponding face picture.
153 """
154 logger.debug("Retrieving samples from database.")
155 samples = database.all_samples(groups)
157 logger.debug(f"{len(samples)} samples loaded from database.")
159 # open figure
160 from matplotlib import pyplot
162 if not self_test and not output_dir:
163 pyplot.ion()
164 pyplot.show()
165 else:
166 pyplot.ioff()
167 pyplot.figure()
169 for sample in samples:
170 # load image
171 logger.info("loading image for sample %s", sample.key)
172 image = sample.data
173 if is_video:
174 frame_id, image, _ = image[0]
175 # convert to color if it is not
176 if image.ndim == 2:
177 image = gray_to_rgb(image)
179 # get annotations
180 annotations = {}
181 if annotations_dir is not None:
182 # Loads the corresponding annotations file
183 annotations_file = os.path.join(
184 annotations_dir, sample.key + annotations_extension
185 )
186 if os.path.exists(annotations_file):
187 logger.info(
188 "Loading annotations from file %s", annotations_file
189 )
190 annotations = read_annotation_file(
191 annotations_file, annotations_type
192 )
193 else:
194 logger.warn(
195 "Could not find annotation file %s", annotations_file
196 )
197 else:
198 # get annotations from database
199 annotations = database.annotations(sample)
201 if not annotations:
202 logger.warn("Could not find annotations for file %s", sample.key)
203 continue
205 if is_video:
206 assert frame_id in annotations, annotations
207 annotations = annotations[frame_id]
209 pyplot.clf()
210 pyplot.imshow(image.transpose(1, 2, 0))
212 global_annotation = []
213 for n, a in annotations.items():
214 if isinstance(a, (list, tuple)) and len(a) == 2:
215 pyplot.plot(
216 a[1],
217 a[0],
218 marker_style,
219 ms=marker_size,
220 mew=marker_size / 5.0,
221 )
222 if display_names:
223 pyplot.annotate(
224 n, (a[1], a[0]), color=font_color, fontsize=font_size
225 )
226 else:
227 global_annotation.append("%s=%s" % (n, a))
229 # plot all global annotations, at the top center of the image
230 pyplot.annotate(
231 ";".join(global_annotation),
232 (image.shape[-1] / 2, 0),
233 color=font_color,
234 fontsize=font_size,
235 ha="center",
236 va="baseline",
237 )
239 pyplot.gca().set_aspect("equal")
240 pyplot.gca().autoscale(tight=True)
242 if output_dir is None:
243 if self_test:
244 raise RuntimeError("Do not run self_test without --output_dir.")
245 pyplot.pause(0.001)
246 else:
247 if keep_all:
248 output_path = os.path.join(output_dir, sample.key + ".png")
249 else:
250 output_path = os.path.join(output_dir, "annotated.png")
251 os.makedirs(os.path.dirname(output_path), exist_ok=True)
252 pyplot.savefig(output_path)
254 if not self_test:
255 input_text = (
256 "Press Enter to continue to the next image (or Ctrl-C to exit)"
257 )
258 input(input_text)