in utils_cv/detection/dataset.py [0:0]
def _read_annos(self) -> None:
""" Parses all Pascal VOC formatted annotation files to extract all
possible labels. """
# All annotation files are assumed to be in the anno_dir directory.
# If im_dir is provided then find all images in that directory, and
# it's assumed that the annotation filenames end with .xml.
# If im_dir is not provided, then the image paths are read from inside
# the .xml annotations.
im_paths = None
if self.im_dir is None:
anno_filenames = sorted(os.listdir(self.root / self.anno_dir))
else:
im_filenames = sorted(os.listdir(self.root / self.im_dir))
im_paths = [
os.path.join(self.root / self.im_dir, s) for s in im_filenames
]
anno_filenames = [
os.path.splitext(s)[0] + ".xml" for s in im_filenames
]
# Reduce number of images if max_num_images is set
if self.max_num_images and len(anno_filenames) > self.max_num_images:
indices = np.unique(np.floor(np.linspace(0, len(anno_filenames)-1, self.max_num_images)).astype(int))
anno_filenames = [anno_filenames[i] for i in indices]
if im_paths:
im_paths = [im_paths[i] for i in indices]
# Read all annotations
self.im_paths = []
self.anno_paths = []
self.anno_bboxes = []
self.mask_paths = []
self.keypoints = []
for anno_idx, anno_filename in enumerate(anno_filenames):
anno_path = self.root / self.anno_dir / str(anno_filename)
# Parse annotation file if present
if os.path.exists(anno_path):
anno_bboxes, im_path, keypoints = parse_pascal_voc_anno(
anno_path, keypoint_meta=self.keypoint_meta
)
# When meta provided, we assume this is keypoint
# detection.
if self.keypoint_meta is not None:
self.keypoints.append(keypoints)
else:
if not self.allow_negatives:
raise FileNotFoundError(anno_path)
anno_bboxes = []
im_path = im_paths[anno_idx]
# Torchvision needs at least one ground truth bounding box per image. Hence for images without a single
# annotated object, adding a tiny bounding box with "background" label 0.
if len(anno_bboxes) == 0:
anno_bboxes = [
AnnotationBbox.from_array(
[1, 1, 5, 5],
label_name=None,
label_idx=0,
im_path=im_path,
)
]
if self.im_dir is None:
self.im_paths.append(im_path)
else:
self.im_paths.append(im_paths[anno_idx])
if self.mask_dir:
# Assume mask image name matches image name but has .png
# extension
mask_name = os.path.basename(self.im_paths[-1])
mask_name = mask_name[: mask_name.rindex(".")] + ".png"
mask_path = self.root / self.mask_dir / mask_name
# For mask prediction, if no mask provided and negatives not
# allowed (), raise exception
if not mask_path.exists():
if not self.allow_negatives:
raise FileNotFoundError(mask_path)
else:
self.mask_paths.append(None)
else:
self.mask_paths.append(mask_path)
self.anno_paths.append(anno_path)
self.anno_bboxes.append(anno_bboxes)
assert len(self.im_paths) == len(self.anno_paths)
# Get list of all labels
if not self.labels:
labels = []
for anno_bboxes in self.anno_bboxes:
for anno_bbox in anno_bboxes:
if anno_bbox.label_name is not None:
labels.append(anno_bbox.label_name)
self.labels = list(set(labels))
# Set for each bounding box label name also what its integer representation is
for anno_bboxes in self.anno_bboxes:
for anno_bbox in anno_bboxes:
if (
anno_bbox.label_name is None
): # background rectangle is assigned id 0 by design
anno_bbox.label_idx = 0
else:
#if not self.label_id_map:
label = self.labels.index(anno_bbox.label_name) + 1
#else:
# label = self.label_id_map[anno_bbox.label_name]
anno_bbox.label_idx = (label)
# Get images sized. Note that Image.open() only loads the image header,
# not the full images and is hence fast.
self.im_sizes = np.array([Image.open(p).size for p in self.im_paths])