Skip to content

Commit a744089

Browse files
authored
Merge pull request openvinotoolkit#1604 from mzuevx/mzuevx/mscoco_semantic_only
Enable CoCoInstanceSegmentationRepresentation in mean_iou metric
2 parents adf82eb + c6f3646 commit a744089

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

tools/accuracy_checker/accuracy_checker/annotation_converters/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ Accuracy Checker supports following list of annotation converters and specific f
101101
* `sort_annotations` - allows to save annotations in a specific order: ascending order of image id or ascending order of image size.
102102
* `sort_key` - key by which annotations will be sorted(supported keys are `image_id` and `image_size`, default is `image_id`).
103103
* `dataset_meta_file` - path path to json file with dataset meta (e.g. label_map, color_encoding).Optional, more details in [Customizing dataset meta](#customizing-dataset-meta) section.
104+
* `semantic_only` - converts MS COCO dataset annotation to `SegmentationAnnotation`. (Optional, default value is False)
105+
* `masks_dir` - path to store segmentation masks in `semantic_only` mode
104106
* `mscoco_mask_rcnn` - converts MS COCO dataset to `ContainerAnnotation` with `DetectionAnnotation` and `CocoInstanceSegmentationAnnotation` named `detection_annotation` and `segmentation_annotation` respectively.
105107
* `annotation_file` - path to annotation file in json format.
106108
* `has_background` - allows convert dataset with/without adding background_label. Accepted values are True or False. (default is False).

tools/accuracy_checker/accuracy_checker/annotation_converters/ms_coco.py

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,30 @@
1515
"""
1616

1717
import numpy as np
18+
from PIL import Image
1819

1920
from ..config import BoolField, PathField, StringField
2021
from ..utils import read_json, convert_bboxes_xywh_to_x1y1x2y2, check_file_existence
2122
from ..representation import (
22-
DetectionAnnotation, PoseEstimationAnnotation, CoCoInstanceSegmentationAnnotation, ContainerAnnotation
23+
DetectionAnnotation,
24+
PoseEstimationAnnotation,
25+
CoCoInstanceSegmentationAnnotation,
26+
ContainerAnnotation,
27+
SegmentationAnnotation,
2328
)
2429
from .format_converter import BaseFormatConverter, FileBasedAnnotationConverter, ConverterReturn, verify_label_map
2530
from ..progress_reporters import PrintProgressReporter
2631

32+
from ..utils import UnsupportedPackage
33+
34+
try:
35+
import pycocotools.mask as maskUtils
36+
except ImportError as import_error:
37+
maskUtils = UnsupportedPackage("pycocotools", import_error.msg)
38+
39+
from ..representation.segmentation_representation import GTMaskLoader
40+
41+
from ..logging import warning
2742

2843
def get_image_annotation(image_id, annotations_):
2944
return list(filter(lambda x: x['image_id'] == image_id, annotations_))
@@ -104,6 +119,7 @@ def configure(self):
104119
self.sort_key = self.get_value_from_config('sort_key')
105120
self.images_dir = self.get_value_from_config('images_dir') or self.annotation_file.parent
106121
self.dataset_meta = self.get_value_from_config('dataset_meta_file')
122+
self.meta = {}
107123

108124
def convert(self, check_content=False, progress_callback=None, progress_interval=100, **kwargs):
109125
full_annotation = read_json(self.annotation_file)
@@ -257,11 +273,57 @@ def convert(self, check_content=False, progress_callback=None, progress_interval
257273

258274
return ConverterReturn(keypoints_annotations, {'label_map': label_map}, None)
259275

276+
def make_segmentation_mask(height, width, path_to_mask, labels, segmentations):
277+
polygons = []
278+
for mask in segmentations:
279+
rles = maskUtils.frPyObjects(mask, height, width)
280+
rle = maskUtils.merge(rles)
281+
polygons.append(rle)
282+
283+
masks = []
284+
for polygon in polygons:
285+
mask = maskUtils.decode(polygon)
286+
if len(mask.shape) < 3:
287+
mask = np.expand_dims(mask, axis=-1)
288+
masks.append(mask)
289+
if masks:
290+
masks = np.stack(masks, axis=-1)
291+
else:
292+
masks = np.zeros((height, width, 0), dtype=np.uint8)
293+
masks = (masks * np.asarray(labels, dtype=np.uint8)).max(axis=-1)
294+
mask = np.squeeze(masks)
295+
296+
image = Image.frombytes('L', (width, height), mask.tostring())
297+
image.save(path_to_mask)
298+
299+
return mask
300+
260301

261302
class MSCocoSegmentationConverter(MSCocoDetectionConverter):
262303
__provider__ = 'mscoco_segmentation'
263304
annotation_types = (CoCoInstanceSegmentationAnnotation, )
264305

306+
@classmethod
307+
def parameters(cls):
308+
configuration_parameters = super().parameters()
309+
configuration_parameters.update({
310+
'semantic_only': BoolField(
311+
optional=True, default=False, description="Semantic segmentation only mode."
312+
),
313+
'masks_dir': PathField(
314+
is_directory=True, optional=True,
315+
check_exists=False,
316+
default='./segmentation_masks',
317+
description='path to segmentation masks, used if semantic_only is True'
318+
),
319+
})
320+
return configuration_parameters
321+
322+
def configure(self):
323+
super().configure()
324+
self.semantic_only = self.get_value_from_config('semantic_only')
325+
self.masks_dir = self.get_value_from_config('masks_dir')
326+
265327
def _create_representations(
266328
self, image_info, annotations, label_id_to_label, check_content, progress_callback, progress_interval
267329
):
@@ -270,13 +332,27 @@ def _create_representations(
270332
num_iterations = len(image_info)
271333
progress_reporter = PrintProgressReporter(print_interval=progress_interval)
272334
progress_reporter.reset(num_iterations, 'annotations')
335+
if self.semantic_only:
336+
if not self.masks_dir.exists():
337+
self.masks_dir.mkdir()
338+
warning('Segmentation masks will be located in {} folder'.format(str(self.masks_dir.resolve())))
273339

274340
for (image_id, image) in enumerate(image_info):
275341
image_labels, _, _, _, _, is_crowd, segmentations = self._read_image_annotation(
276342
image, annotations,
277343
label_id_to_label
278344
)
279-
annotation = CoCoInstanceSegmentationAnnotation(image[1], segmentations, image_labels)
345+
346+
if not self.semantic_only:
347+
annotation = CoCoInstanceSegmentationAnnotation(image[1], segmentations, image_labels)
348+
else:
349+
h, w, _ = image[2]
350+
mask_file = self.masks_dir / "{:012}.png".format(image[0])
351+
make_segmentation_mask(h, w, mask_file, image_labels, segmentations)
352+
annotation = SegmentationAnnotation(image[1],
353+
str(mask_file.relative_to(self.masks_dir.parent)),
354+
mask_loader=GTMaskLoader.PILLOW)
355+
280356
if check_content:
281357
image_full_path = self.images_dir / image[1]
282358
if not check_file_existence(image_full_path):

0 commit comments

Comments
 (0)