diff --git a/CHANGELOG.md b/CHANGELOG.md index 3673dbec26be..3b5984ad7afd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ https://github.com/opencv/cvat/issues/750). - Datumaro is an experimental framework to build, analyze, debug and visualize datasets for DL algorithms - Text Detection Auto Annoation Script in OpenVINO format for version 4 - Added in OpenVINO Semantic Segmentation for roads +- Ability to visualize labels when using Auto Annotation runner ### Changed - page_size parameter for all REST API methods diff --git a/utils/auto_annotation/README.md b/utils/auto_annotation/README.md index e4dbd6641546..b2aff7bf9fbd 100644 --- a/utils/auto_annotation/README.md +++ b/utils/auto_annotation/README.md @@ -37,8 +37,21 @@ $ python cvat/utils/auto_annotation/run_model.py --py /path/to/python/interp.py --show-images ``` +If you'd like to see the labels printed on the image, use the `--show-labels` flag + +```shell +$ python cvat/utils/auto_annotation/run_model.py --py /path/to/python/interp.py \ + --xml /path/to/xml/file.xml \ + --bin /path/to/bin/file.bin \ + --json /path/to/json/mapping/mapping.json \ + --image-files /path/to/img.jpg /path2/to/img2.png /path/to/img3.jpg \ + --show-images \ + --show-labels +``` + There's a command that let's you scan quickly by setting the length of time (in milliseconds) to display each image. Use the `--show-image-delay` flag and set the appropriate time. +In this example, 2000 milliseconds is 2 seconds for each image. ```shell # Display each image in a window for 2 seconds diff --git a/utils/auto_annotation/run_model.py b/utils/auto_annotation/run_model.py index d791eb092955..33cd5453f5c8 100644 --- a/utils/auto_annotation/run_model.py +++ b/utils/auto_annotation/run_model.py @@ -29,6 +29,7 @@ def _get_kwargs(): parser.add_argument('--show-images', action='store_true', help='Show the results of the annotation in a window') parser.add_argument('--show-image-delay', default=0, type=int, help='Displays the images for a set duration in milliseconds, default is until a key is pressed') parser.add_argument('--serialize', default=False, action='store_true', help='Try to serialize the result') + parser.add_argument('--show-labels', action='store_true', help='Show the labels on the window') return vars(parser.parse_args()) @@ -45,6 +46,16 @@ def pairwise(iterable): result.append((iterable[i], iterable[i+1])) return np.array(result, dtype=np.int32) +def find_min_y(array): + min_ = sys.maxsize + index = None + for i, pair in enumerate(array): + if pair[1] < min_: + min_ = pair[1] + index = i + + return array[index] + def main(): kwargs = _get_kwargs() @@ -104,34 +115,8 @@ def main(): py_file, restricted=restricted) - if kwargs['serialize']: - os.environ['DJANGO_SETTINGS_MODULE'] = 'cvat.settings.production' - import django - django.setup() - - from cvat.apps.engine.serializers import LabeledDataSerializer - # NOTE: We're actually using `run_inference_engine_annotation` - # incorrectly here. The `mapping` dict is supposed to be a mapping - # of integers -> integers and represents the transition from model - # integers to the labels in the database. We're using a mapping of - # integers -> strings. For testing purposes, this shortcut is fine. - # We just want to make sure everything works. Until, that is.... - # we want to test using the label serializer. Then we have to transition - # back to integers, otherwise the serializer complains about have a string - # where an integer is expected. We'll just brute force that. - - for shape in results['shapes']: - # Change the english label to an integer for serialization validation - shape['label_id'] = 1 - - serializer = LabeledDataSerializer(data=results) - - if not serializer.is_valid(): - logging.critical('Data unable to be serialized correctly!') - serializer.is_valid(raise_exception=True) - - logging.warning('Program didn\'t have any errors.') + logging.warning('Inference didn\'t have any errors.') show_images = kwargs.get('show_images', False) if show_images: @@ -146,23 +131,64 @@ def main(): return show_image_delay = kwargs['show_image_delay'] + show_labels = kwargs.get('show_labels') + for index, data in enumerate(image_data): for detection in results['shapes']: if not detection['frame'] == index: continue points = detection['points'] + label_str = detection['label_id'] + # Cv2 doesn't like floats for drawing points = [int(p) for p in points] color = random_color() + if detection['type'] == 'rectangle': cv2.rectangle(data, (points[0], points[1]), (points[2], points[3]), color, 3) + + if show_labels: + cv2.putText(data, label_str, (points[0], points[1] - 7), cv2.FONT_HERSHEY_COMPLEX, 0.6, color, 1) + elif detection['type'] in ('polygon', 'polyline'): # polylines is picky about datatypes points = pairwise(points) cv2.polylines(data, [points], 1, color) + + if show_labels: + min_point = find_min_y(points) + cv2.putText(data, label_str, (min_point[0], min_point[1] - 7), cv2.FONT_HERSHEY_COMPLEX, 0.6, color, 1) + cv2.imshow(str(index), data) cv2.waitKey(show_image_delay) cv2.destroyWindow(str(index)) + if kwargs['serialize']: + os.environ['DJANGO_SETTINGS_MODULE'] = 'cvat.settings.production' + import django + django.setup() + + from cvat.apps.engine.serializers import LabeledDataSerializer + + # NOTE: We're actually using `run_inference_engine_annotation` + # incorrectly here. The `mapping` dict is supposed to be a mapping + # of integers -> integers and represents the transition from model + # integers to the labels in the database. We're using a mapping of + # integers -> strings. For testing purposes, this shortcut is fine. + # We just want to make sure everything works. Until, that is.... + # we want to test using the label serializer. Then we have to transition + # back to integers, otherwise the serializer complains about have a string + # where an integer is expected. We'll just brute force that. + + for shape in results['shapes']: + # Change the english label to an integer for serialization validation + shape['label_id'] = 1 + + serializer = LabeledDataSerializer(data=results) + + if not serializer.is_valid(): + logging.critical('Data unable to be serialized correctly!') + serializer.is_valid(raise_exception=True) + if __name__ == '__main__': main()