示例#1
0
    def post(self, dataset_id):
        """ Updates dataset by ID """

        dataset = current_user.find_exist_dataset_by_id(dataset_id)
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        args = Parser.update_dataset_parser().parse_args()
        categories = args.get('categories')
        default_annotation_metadata = args.get('default_annotation_metadata')
        set_default_annotation_metadata = args.get(
            'set_default_annotation_metadata')

        if categories is not None:
            from usecase.changeDatasetCategoriesUseCase import ChangeDatasetCategoriesUseCase
            ChangeDatasetCategoriesUseCase().execute(dataset_id, categories)

        if default_annotation_metadata is not None:

            update = {}
            for key, value in default_annotation_metadata.items():
                if key not in dataset.default_annotation_metadata:
                    update[f'set__metadata__{key}'] = value

            dataset.default_annotation_metadata = default_annotation_metadata

            if len(update.keys()) > 0:
                AnnotationModel.objects(dataset_id=dataset.id, deleted=False)\
                    .update(**update)

        dataset.update(
            #categories=dataset.categories,
            default_annotation_metadata=dataset.default_annotation_metadata)

        return {"success": True}
示例#2
0
    def post(self, dataset_id):
        """ Updates dataset by ID """

        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        args = update_dataset.parse_args()
        categories = args.get('categories')
        default_annotation_metadata = args.get('default_annotation_metadata')
        set_default_annotation_metadata = args.get(
            'set_default_annotation_metadata')

        if categories is not None:
            dataset.categories = CategoryModel.bulk_create(categories)

        if default_annotation_metadata is not None:

            update = {}
            for key, value in default_annotation_metadata.items():
                if key not in dataset.default_annotation_metadata:
                    update[f'set__metadata__{key}'] = value

            dataset.default_annotation_metadata = default_annotation_metadata

            if len(update.keys()) > 0:
                AnnotationModel.objects(dataset_id=dataset.id, deleted=False)\
                    .update(**update)

        dataset.update(
            categories=dataset.categories,
            default_annotation_metadata=dataset.default_annotation_metadata)

        return {"success": True}
示例#3
0
    def post(self):
        """ Creates an annotation """
        args = create_annotation.parse_args()
        image_id = args.get('image_id')
        category_id = args.get('category_id')
        isbbox = args.get('isbbox')
        metadata = args.get('metadata', {})
        segmentation = args.get('segmentation', [])
        keypoints = args.get('keypoints', [])

        image = current_user.images.filter(id=image_id, deleted=False).first()
        if image is None:
            return {"message": "Invalid image id"}, 400

        logger.info(
            f'{current_user.username} has created an annotation for image {image_id} with {isbbox}'
        )
        logger.info(
            f'{current_user.username} has created an annotation for image {image_id}'
        )

        try:
            annotation = AnnotationModel(image_id=image_id,
                                         category_id=category_id,
                                         metadata=metadata,
                                         segmentation=segmentation,
                                         keypoints=keypoints,
                                         isbbox=isbbox)
            annotation.save()
        except (ValueError, TypeError) as e:
            return {'message': str(e)}, 400

        return query_util.fix_ids(annotation)
示例#4
0
    def get(self, dataset_id):
        """ All users in the dataset """
        args = dataset_generate.parse_args()

        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        images = ImageModel.objects(dataset_id=dataset.id, deleted=False)
        annotated_images = images.filter(annotated=True)
        annotations = AnnotationModel.objects(dataset_id=dataset_id,
                                              deleted=False)

        # Calculate annotation counts by category in this dataset
        category_count = dict()
        image_category_count = dict()
        for category in dataset.categories:

            # Calculate the annotation count in the current category in this dataset
            cat_name = CategoryModel.objects(id=category).first()['name']
            cat_count = AnnotationModel.objects(dataset_id=dataset_id,
                                                category_id=category,
                                                deleted=False).count()
            category_count.update({str(cat_name): cat_count})

            # Calculate the annotated images count in the current category in this dataset
            image_count = len(
                AnnotationModel.objects(dataset_id=dataset_id,
                                        category_id=category,
                                        deleted=False).distinct('image_id'))
            image_category_count.update({str(cat_name): image_count})

        stats = {
            'total': {
                'Users': dataset.get_users().count(),
                'Images': images.count(),
                'Annotated Images': annotated_images.count(),
                'Annotations': annotations.count(),
                'Categories': len(dataset.categories),
                'Time Annotating (s)': (images.sum('milliseconds') or 0) / 1000
            },
            'average': {
                'Image Size (px)':
                images.average('width'),
                'Image Height (px)':
                images.average('height'),
                'Annotation Area (px)':
                annotations.average('area'),
                'Time (ms) per Image':
                images.average('milliseconds') or 0,
                'Time (ms) per Annotation':
                annotations.average('milliseconds') or 0
            },
            'categories': category_count,
            'images_per_category': image_category_count
        }
        return stats
示例#5
0
    def get(self, dataset_id):
        args = dataset_generate.parse_args()
        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        AnnotationModel.objects(dataset_id=dataset.id).delete()
        ImageModel.objects(dataset_id=dataset.id).update(
            set__annotated=False, set__num_annotations=0)
        return {'success': True}
 def create_annotation(image_id):
     annotation = AnnotationModel(
         image_id=image_id,
         category_id=0,
         metadata={},
         segmentation=[[1, 2, 3, 4]],
         keypoints=[1, 2, 3, 4],
         isbbox=False
     )
     annotation.save()
     return annotation.id
示例#7
0
    def get(self, refset_id):
        """ All users in the refset """
        args = refset_generate.parse_args()

        refset = current_user.refsets.filter(id=refset_id, deleted=False).first()
        if refset is None:
            return {"message": "Invalid refset id"}, 400

        AnnotationModel.objects(refset_id=refset.id)\
            .update(metadata=refset.default_annotation_metadata)
        PixelModel.objects(refset_id=refset.id)\
            .update(metadata={})

        return {'success': True}
示例#8
0
    def get(self, dataset_id):
        """ All users in the dataset """
        args = dataset_generate.parse_args()

        dataset = current_user.find_exist_dataset_by_id(dataset_id)
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        AnnotationModel.objects(dataset_id=dataset.id)\
            .update(metadata=dataset.default_annotation_metadata)
        ImageModel.objects(dataset_id=dataset.id)\
            .update(metadata={})

        return {'success': True}
示例#9
0
    def get(self, dataset_id):
        """ All users in the dataset """
        args = dataset_generate.parse_args()

        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        AnnotationModel.objects(dataset_id=dataset.id).update(
            metadata=dataset.default_annotation_metadata)
        ImageModel.objects(dataset_id=dataset.id).update(metadata={})

        return {'success': True}
示例#10
0
    def get(self, category_id):
        """"Endpoint called by category image list """
        args = page_data.parse_args()
        limit = args['limit']
        page = args['page']

        category = current_user.categories.filter(id=category_id).first()

        # check if the id exits
        if category is None:
            return {"message": "Invalid category id"}, 400

        image_ids = AnnotationModel.objects(category_id=category_id).distinct('image_id')
        image_ids.sort()

        pagination = Pagination(len(image_ids), limit, page)
        image_ids = image_ids[pagination.start:pagination.end]

        images = []
        for image_id in image_ids:
          img = ImageModel.objects(id=image_id, annotated=True).first()
          if img:
            images.append(query_util.fix_ids(img))

        return {
          "category": query_util.fix_ids(category),
          "pagination": pagination.export(),
          "page": page,
          "images": images,
        }
示例#11
0
    def post(self, from_id, to_id):
        args = copy_annotations.parse_args()
        category_ids = args.get('category_ids')

        image_from = current_user.images.filter(id=from_id).first()
        image_to = current_user.images.filter(id=to_id).first()

        if image_from is None or image_to is None:
            return {'success': False, 'message': 'Invalid image ids'}, 400

        if image_from == image_to:
            return {'success': False, 'message': 'Cannot copy self'}, 400

        if image_from.width != image_to.width or image_from.height != image_to.height:
            return {
                'success': False,
                'message': 'Image sizes do not match'
            }, 400

        if category_ids is None:
            category_ids = DatasetModel.objects(
                id=image_from.dataset_id).first().categories

        query = AnnotationModel.objects(image_id=image_from.id,
                                        category_id__in=category_ids,
                                        deleted=False)

        return {'annotations_created': image_to.copy_annotations(query)}
示例#12
0
    def get(self, image_id):
        """ Called when loading from the annotator client """
        image = ImageModel.objects(id=image_id)\
            .exclude('events').first()

        if image is None:
            return {'success': False, 'message': 'Could not load image'}, 400

        dataset = current_user.datasets.filter(id=image.dataset_id).first()
        if dataset is None:
            return {
                'success': False,
                'message': 'Could not find associated dataset'
            }, 400

        categories = CategoryModel.objects(deleted=False)\
            .in_bulk(dataset.categories).items()

        # Get next and previous image
        images = ImageModel.objects(dataset_id=dataset.id, deleted=False)
        pre = images.filter(
            file_name__lt=image.file_name).order_by('-file_name').first()
        nex = images.filter(
            file_name__gt=image.file_name).order_by('file_name').first()

        preferences = {}
        if not Config.LOGIN_DISABLED:
            preferences = current_user.preferences

        # Generate data about the image to return to client
        data = {
            'image': query_util.fix_ids(image),
            'categories': [],
            'dataset': query_util.fix_ids(dataset),
            'preferences': preferences,
            'permissions': {
                'dataset': dataset.permissions(current_user),
                'image': image.permissions(current_user)
            }
        }

        data['image']['previous'] = pre.id if pre else None
        data['image']['next'] = nex.id if nex else None

        for category in categories:
            category = query_util.fix_ids(category[1])

            category_id = category.get('id')
            annotations = AnnotationModel.objects(image_id=image_id, category_id=category_id, deleted=False)\
                .exclude('events').all()

            category['show'] = True
            category['visualize'] = False
            category[
                'annotations'] = [] if annotations is None else query_util.fix_ids(
                    annotations)
            data.get('categories').append(category)

        return data
示例#13
0
    def get(self, refset_id):
        """ All users in the refset """
        args = refset_generate.parse_args()

        refset = current_user.refsets.filter(id=refset_id, deleted=False).first()
        if refset is None:
            return {"message": "Invalid refset id"}, 400

        pixels = PixelModel.objects(refset_id=refset.id, deleted=False)
        annotated_pixels = pixels.filter(annotated=True)
        annotations = AnnotationModel.objects(refset_id=refset_id, deleted=False)

        # Calculate annotation counts by category in this refset
        category_count = dict()
        image_category_count = dict()
        for category in refset.categories:

            # Calculate the annotation count in the current category in this refset
            cat_name = CategoryModel.objects(id=category).first()['name']
            cat_count = AnnotationModel.objects(refset_id=refset_id, category_id=category, deleted=False).count()
            category_count.update({str(cat_name): cat_count})

            # Calculate the annotated pixels count in the current category in this refset
            image_count = len(AnnotationModel.objects(refset_id=refset_id, category_id=category, deleted=False).distinct('image_id'))
            image_category_count.update({str(cat_name): image_count})

        stats = {
            'total': {
                'Users': refset.get_users().count(),
                'Pixels': pixels.count(),
                'Annotated Pixels': annotated_pixels.count(),
                'Annotations': annotations.count(),
                'Categories': len(refset.categories),
                'Time Annotating (s)': (pixels.sum('milliseconds') or 0) / 1000
            },
            'average': {
                'Pixel Size (px)': pixels.average('width'),
                'Pixel Height (px)': pixels.average('height'),
                'Annotation Area (px)': annotations.average('area'),
                'Time (ms) per Pixel': pixels.average('milliseconds') or 0,
                'Time (ms) per Annotation': annotations.average('milliseconds') or 0
            },
            'categories': category_count,
            'pixels_per_category': image_category_count
        }
        return stats
示例#14
0
    def post(self, image_id):
        """ COCO data test """
        print("Origin Model")

        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        #image = Image.open(image_model.path)
        annotations = AnnotationModel.objects(image_id=image_id)

        for annotation in annotations:

            for segmentation in annotation.segmentation:
                print(segmentation)
                origin(image_model.path, segmentation)

        AnnotationModel.objects(image_id=image_id).delete()

        return {"success": True}
示例#15
0
    def post(self):
        """ Creates an annotation """
        args = create_annotation.parse_args()
        image_id = args.get('image_id')
        category_id = args.get('category_id')
        isbbox = args.get('isbbox')
        metadata = args.get('metadata', {})
        segmentation = args.get('segmentation', [])
        bbox = args.get('bbox', [])
        keypoints = args.get('keypoints', [])

        # change appro after setting login_user
        # image = current_user.images.filter(id=image_id, deleted=False).first()
        # image = ImageModel.objects.get(id=image_id, deleted=False).first()
        image = ImageModel.objects(id=image_id).first()
        if image is None:
            return {"message": "Invalid image id"}, 400

        logger.info(
            f'{current_user.username} has created an annotation for image {image_id} with {isbbox}'
        )
        logger.info(
            f'{current_user.username} has created an annotation for image {image_id}'
        )

        # add condition if user is not authenticed or dataset is public
        try:
            annotation = AnnotationModel(image_id=image_id,
                                         category_id=category_id,
                                         metadata=metadata,
                                         segmentation=segmentation,
                                         bbox=bbox,
                                         keypoints=keypoints,
                                         isbbox=isbbox)
            annotation.save()
        except (ValueError, TypeError) as e:
            return {'message': str(e)}, 400

        return query_util.fix_ids(annotation)
示例#16
0
    def post(self, image_id):
        """ COCO data test """
        print("Converter Model")

        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        #image = Image.open(image_model.path)
        annotations = AnnotationModel.objects(image_id=image_id)

        for annotation in annotations:
            category_id = annotation.category_id
            category = CategoryModel.objects(id=category_id).first()

            for segmentation in annotation.segmentation:
                print(segmentation)
                convert(image_model.path, segmentation, category.color)

        AnnotationModel.objects(image_id=image_id).delete()

        return {"success": True}
示例#17
0
    def post(self):
        """ Creates an annotation """
        args = create_annotation.parse_args()
        image_id = args.get('image_id')
        category_id = args.get('category_id')
        metadata = args.get('metadata', {})
        segmentation = args.get('segmentation', [])
        keypoints = args.get('keypoints', [])

        logger.info(
            f'{current_user.username} has created an annotation for image {image_id}'
        )

        try:
            annotation = AnnotationModel(image_id=image_id,
                                         category_id=category_id,
                                         metadata=metadata,
                                         segmentation=segmentation,
                                         keypoints=keypoints)
            annotation.save()
        except (ValueError, TypeError) as e:
            return {'message': str(e)}, 400

        return query_util.fix_ids(annotation)
示例#18
0
    def get(self):
        """ Endpoint called by category viewer client """
        args = page_data.parse_args()
        limit = args['limit']
        page = args['page']

        categories = current_user.categories.filter(deleted=False)

        pagination = Pagination(categories.count(), limit, page)
        categories = query_util.fix_ids(categories[pagination.start:pagination.end])

        for category in categories:
            category['numberAnnotations'] = AnnotationModel.objects(deleted=False, category_id=category.get('id')).count()

        return {
            "pagination": pagination.export(),
            "page": page,
            "categories": categories
        }
    def create_annotation_from(self, annotation_data, image_id):
        collect_annotation_data = {}
        self.append_events_ant_times_to(collect_annotation_data,
                                        annotation_data)
        self.append_papers_object_to(collect_annotation_data, annotation_data,
                                     image_id)
        self.append_other_data_to(collect_annotation_data, annotation_data,
                                  image_id)

        return AnnotationModel(
            image_id=image_id,
            category_id=annotation_data['category_id'],
            events=collect_annotation_data['events'],
            milliseconds=collect_annotation_data['milliseconds'],
            paper_object=collect_annotation_data['paper_object'],
            segmentation=collect_annotation_data['segmentation'],
            area=collect_annotation_data['area'],
            bbox=collect_annotation_data['bbox'],
            isbbox=collect_annotation_data['isbbox'],
            keypoints=collect_annotation_data['keypoints'],
            metadata=collect_annotation_data['metadata'],
            color=collect_annotation_data['color'],
        )
示例#20
0
    def get(self, image_id):
        """ Called when loading from the annotator client """
        image = ImageModel.objects(id=image_id)\
            .exclude('events').first()

        if image is None:
            return {'success': False, 'message': 'Could not load image'}, 400

        dataset = current_user.datasets.filter(id=image.dataset_id).first()
        if dataset is None:
            return {
                'success': False,
                'message': 'Could not find associated dataset'
            }, 400

        categories = CategoryModel.objects(deleted=False)\
            .in_bulk(dataset.categories).items()

        # Generate data about the image to return to client
        data = {'categories': []}

        for category in categories:
            category = query_util.fix_ids(category[1])

            category_id = category.get('id')
            annotations = AnnotationModel.objects(image_id=image_id, category_id=category_id, deleted=False)\
                .exclude('events').all()

            category['show'] = True
            category['visualize'] = False
            category[
                'annotations'] = [] if annotations is None else query_util.fix_ids(
                    annotations)
            data.get('categories').append(category)

        return data
示例#21
0
    def get(self, dataset_id):
        """ All users in the dataset """
        args = dataset_generate.parse_args()

        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        images = ImageModel.objects(dataset_id=dataset.id, deleted=False)
        annotated_images = images.filter(annotated=True)
        annotations = AnnotationModel.objects(dataset_id=dataset_id,
                                              deleted=False)
        stats = {
            'total': {
                'Users': dataset.get_users().count(),
                'Images': images.count(),
                'Annotated Images': annotated_images.count(),
                'Annotations': annotations.count(),
                'Categories': len(dataset.categories),
                'Time Annotating (s)': (images.sum('milliseconds') or 0) / 1000
            },
            'average': {
                'Image Size (px)':
                images.average('width'),
                'Image Height (px)':
                images.average('height'),
                'Annotation Area (px)':
                annotations.average('area'),
                'Time (ms) per Image':
                images.average('milliseconds') or 0,
                'Time (ms) per Annotation':
                annotations.average('milliseconds') or 0
            }
        }
        return stats
示例#22
0
 def find_all_annotations():
     return AnnotationModel.objects()
示例#23
0
 def find_annotations_by(image_id):
     return AnnotationModel.objects(image_id=image_id)
示例#24
0
 def find_annotation_list_by_image_id(image_id):
     return AnnotationModel.objects(image_id=image_id)
示例#25
0
 def find_annotations_by_category_id(category_id):
     return AnnotationModel.objects(category_id=category_id)
示例#26
0
def import_annotations(task_id, dataset_id, coco_json):

    task = TaskModel.objects.get(id=task_id)
    dataset = DatasetModel.objects.get(id=dataset_id)

    task.update(status="PROGRESS")
    socket = create_socket()

    task.info("Beginning Import")

    images = ImageModel.objects(dataset_id=dataset.id)
    categories = CategoryModel.objects

    coco_images = coco_json.get('images', [])
    coco_annotations = coco_json.get('annotations', [])
    coco_categories = coco_json.get('categories', [])

    task.info(f"Importing {len(coco_categories)} categories, "
              f"{len(coco_images)} images, and "
              f"{len(coco_annotations)} annotations")

    total_items = sum(
        [len(coco_categories),
         len(coco_annotations),
         len(coco_images)])
    progress = 0

    task.info("===== Importing Categories =====")
    # category id mapping  ( file : database )
    categories_id = {}

    # Create any missing categories
    for category in coco_categories:

        category_name = category.get('name')
        category_id = category.get('id')
        category_model = categories.filter(name__iexact=category_name).first()

        if category_model is None:
            task.warning(
                f"{category_name} category not found (creating a new one)")

            new_category = CategoryModel(
                name=category_name,
                keypoint_edges=category.get('skeleton', []),
                keypoint_labels=category.get('keypoints', []))
            new_category.save()

            category_model = new_category
            dataset.categories.append(new_category.id)

        task.info(f"{category_name} category found")
        # map category ids
        categories_id[category_id] = category_model.id

        # update progress
        progress += 1
        task.set_progress((progress / total_items) * 100, socket=socket)

    dataset.update(set__categories=dataset.categories)

    task.info("===== Loading Images =====")
    # image id mapping ( file: database )
    images_id = {}
    categories_by_image = {}

    # Find all images
    for image in coco_images:
        image_id = image.get('id')
        image_filename = image.get('file_name')

        # update progress
        progress += 1
        task.set_progress((progress / total_items) * 100, socket=socket)

        image_model = images.filter(file_name__exact=image_filename).all()

        if len(image_model) == 0:
            task.warning(f"Could not find image {image_filename}")
            continue

        if len(image_model) > 1:
            task.error(
                f"Too many images found with the same file name: {image_filename}"
            )
            continue

        task.info(f"Image {image_filename} found")
        image_model = image_model[0]
        images_id[image_id] = image_model
        categories_by_image[image_id] = list()

    task.info("===== Import Annotations =====")
    for annotation in coco_annotations:

        image_id = annotation.get('image_id')
        category_id = annotation.get('category_id')
        segmentation = annotation.get('segmentation', [])
        keypoints = annotation.get('keypoints', [])
        # is_crowd = annotation.get('iscrowed', False)
        area = annotation.get('area', 0)
        bbox = annotation.get('bbox', [0, 0, 0, 0])
        isbbox = annotation.get('isbbox', False)

        progress += 1
        task.set_progress((progress / total_items) * 100, socket=socket)

        has_segmentation = len(segmentation) > 0
        has_keypoints = len(keypoints) > 0
        if not has_segmentation and not has_keypoints:
            task.warning(
                f"Annotation {annotation.get('id')} has no segmentation or keypoints"
            )
            continue

        try:
            image_model = images_id[image_id]
            category_model_id = categories_id[category_id]
            image_categories = categories_by_image[image_id]
        except KeyError:
            task.warning(
                f"Could not find image assoicated with annotation {annotation.get('id')}"
            )
            continue

        annotation_model = AnnotationModel.objects(
            image_id=image_model.id,
            category_id=category_model_id,
            segmentation=segmentation,
            keypoints=keypoints).first()

        if annotation_model is None:
            task.info(f"Creating annotation data ({image_id}, {category_id})")

            annotation_model = AnnotationModel(image_id=image_model.id)
            annotation_model.category_id = category_model_id

            annotation_model.color = annotation.get('color')
            annotation_model.metadata = annotation.get('metadata', {})

            if has_segmentation:
                annotation_model.segmentation = segmentation
                annotation_model.area = area
                annotation_model.bbox = bbox

            if has_keypoints:
                annotation_model.keypoints = keypoints

            annotation_model.isbbox = isbbox
            annotation_model.save()

            image_categories.append(category_id)
        else:
            annotation_model.update(deleted=False, isbbox=isbbox)
            task.info(
                f"Annotation already exists (i:{image_id}, c:{category_id})")

    for image_id in images_id:
        image_model = images_id[image_id]
        category_ids = categories_by_image[image_id]
        all_category_ids = list(image_model.category_ids)
        all_category_ids += category_ids

        num_annotations = AnnotationModel.objects(
            Q(image_id=image_id) & Q(deleted=False)
            & (Q(area__gt=0) | Q(keypoints__size__gt=0))).count()

        image_model.update(set__annotated=True,
                           set__category_ids=list(set(all_category_ids)),
                           set__num_annotations=num_annotations)

    task.set_progress(100, socket=socket)
示例#27
0
    def get(self, image_id):
        """ Called when loading from the annotator client """

        data = folder_data.parse_args()
        folder = data.get('folder')
        order = data.get('order')

        image = ImageModel.objects(id=image_id)\
            .exclude('events').first()

        if image is None:
            return {'success': False, 'message': 'Could not load image'}, 400

        dataset = current_user.datasets.filter(id=image.dataset_id).first()
        if dataset is None:
            return {
                'success': False,
                'message': 'Could not find associated dataset'
            }, 400

        categories = CategoryModel.objects(deleted=False)\
            .in_bulk(dataset.categories).items()

        if len(folder) > 0:
            folder = folder[0].strip('/') + folder[1:]
            if folder[-1] != '/':
                folder = folder + '/'
        else:
            folder = ''

        # Get directory
        directory = os.path.join(dataset.directory, folder)
        if not os.path.exists(directory):
            return {'message': 'Directory does not exist.'}, 400

        # Get next and previous image
        # images = ImageModel.objects(dataset_id=dataset.id, deleted=False)
        # pre = images.filter(file_name__lt=image.file_name).order_by('-file_name').first()
        # nex = images.filter(file_name__gt=image.file_name).order_by('file_name').first()

        images = ImageModel.objects(dataset_id=dataset.id,
                                    deleted=False,
                                    path__startswith=directory)
        pre = images.filter(
            file_name__lt=image.file_name).order_by('-' + order).first()
        nex = images.filter(
            file_name__gt=image.file_name).order_by(order).first()

        preferences = {}
        if not Config.LOGIN_DISABLED:
            preferences = current_user.preferences

        # Generate data about the image to return to client
        data = {
            'image': query_util.fix_ids(image),
            'categories': [],
            'dataset': query_util.fix_ids(dataset),
            'preferences': preferences,
            'permissions': {
                'dataset': dataset.permissions(current_user),
                'image': image.permissions(current_user)
            }
        }

        data['image']['previous'] = pre.id if pre else None
        data['image']['next'] = nex.id if nex else None

        for category in categories:
            category = query_util.fix_ids(category[1])

            category_id = category.get('id')
            annotations = AnnotationModel.objects(image_id=image_id, category_id=category_id, deleted=False)\
                .exclude('events').all()

            category['show'] = True
            category['visualize'] = False
            category[
                'annotations'] = [] if annotations is None else query_util.fix_ids(
                    annotations)
            data.get('categories').append(category)

        return data
示例#28
0
def export_annotations(task_id,
                       dataset_id,
                       categories,
                       with_empty_images=False):

    task = TaskModel.objects.get(id=task_id)
    dataset = DatasetModel.objects.get(id=dataset_id)

    task.update(status="PROGRESS")
    socket = create_socket()

    task.info("Beginning Export (COCO Format)")

    db_categories = CategoryModel.objects(id__in=categories, deleted=False) \
        .only(*CategoryModel.COCO_PROPERTIES)
    db_images = ImageModel.objects(
        deleted=False, dataset_id=dataset.id).only(*ImageModel.COCO_PROPERTIES)
    db_annotations = AnnotationModel.objects(deleted=False,
                                             category_id__in=categories)

    total_items = db_categories.count()

    coco = {'images': [], 'categories': [], 'annotations': []}

    total_items += db_images.count()
    progress = 0

    # iterate though all categoires and upsert
    category_names = []
    for category in fix_ids(db_categories):

        if len(category.get('keypoint_labels', [])) > 0:
            category['keypoints'] = category.pop('keypoint_labels', [])
            category['skeleton'] = category.pop('keypoint_edges', [])
        else:
            if 'keypoint_edges' in category:
                del category['keypoint_edges']
            if 'keypoint_labels' in category:
                del category['keypoint_labels']

        task.info(f"Adding category: {category.get('name')}")
        coco.get('categories').append(category)
        category_names.append(category.get('name'))

        progress += 1
        task.set_progress((progress / total_items) * 100, socket=socket)

    total_annotations = db_annotations.count()
    total_images = db_images.count()
    for image in db_images:
        image = fix_ids(image)

        progress += 1
        task.set_progress((progress / total_items) * 100, socket=socket)

        annotations = db_annotations.filter(image_id=image.get('id'))\
            .only(*AnnotationModel.COCO_PROPERTIES)
        annotations = fix_ids(annotations)

        if len(annotations) == 0:
            if with_empty_images:
                coco.get('images').append(image)
            continue

        num_annotations = 0
        for annotation in annotations:

            has_keypoints = len(annotation.get('keypoints', [])) > 0
            has_segmentation = len(annotation.get('segmentation', [])) > 0

            if has_keypoints or has_segmentation:

                if not has_keypoints:
                    if 'keypoints' in annotation:
                        del annotation['keypoints']
                else:
                    arr = np.array(annotation.get('keypoints', []))
                    arr = arr[2::3]
                    annotation['num_keypoints'] = len(arr[arr > 0])

                num_annotations += 1
                coco.get('annotations').append(annotation)

        task.info(
            f"Exporting {num_annotations} annotations for image {image.get('id')}"
        )
        coco.get('images').append(image)

    task.info(
        f"Done export {total_annotations} annotations and {total_images} images from {dataset.name}"
    )

    timestamp = time.time()
    directory = f"{dataset.directory}.exports/"
    file_path = f"{directory}coco-{timestamp}.json"

    if not os.path.exists(directory):
        os.makedirs(directory)

    task.info(f"Writing export to file {file_path}")
    with open(file_path, 'w') as fp:
        json.dump(coco, fp)

    task.info("Creating export object")
    export = ExportModel(dataset_id=dataset.id,
                         path=file_path,
                         tags=["COCO", *category_names])
    export.save()

    task.set_progress(100, socket=socket)
示例#29
0
    def post(self):
        """
        Called when saving data from the annotator client
        """
        data = request.get_json(force=True)
        image = data.get('image')
        dataset = data.get('dataset')
        image_id = image.get('id')

        image_model = ImageModel.objects(id=image_id).first()

        if image_model is None:
            return {'success': False, 'message': 'Image does not exist'}, 400

        # Check if current user can access dataset
        db_dataset = current_user.datasets.filter(
            id=image_model.dataset_id).first()
        if dataset is None:
            return {
                'success': False,
                'message': 'Could not find associated dataset'
            }

        db_dataset.update(annotate_url=dataset.get('annotate_url', ''))

        categories = CategoryModel.objects.all()
        annotations = AnnotationModel.objects(image_id=image_id)

        current_user.update(preferences=data.get('user', {}))

        annotated = False
        # Iterate every category passed in the data
        for category in data.get('categories', []):
            category_id = category.get('id')

            # Find corresponding category object in the database
            db_category = categories.filter(id=category_id).first()
            if db_category is None:
                continue

            category_update = {'color': category.get('color')}
            if current_user.can_edit(db_category):
                category_update['keypoint_edges'] = category.get(
                    'keypoint_edges', [])
                category_update['keypoint_labels'] = category.get(
                    'keypoint_labels', [])

            db_category.update(**category_update)

            # Iterate every annotation from the data annotations
            for annotation in category.get('annotations', []):

                # Find corresponding annotation object in database
                annotation_id = annotation.get('id')
                db_annotation = annotations.filter(id=annotation_id).first()

                if db_annotation is None:
                    continue

                # Paperjs objects are complex, so they will not always be passed. Therefor we update
                # the annotation twice, checking if the paperjs exists.

                # Update annotation in database
                sessions = []
                total_time = 0
                for session in annotation.get('sessions', []):
                    date = datetime.datetime.fromtimestamp(
                        int(session.get('start')) / 1e3)
                    model = SessionEvent(
                        user=current_user.username,
                        created_at=date,
                        milliseconds=session.get('milliseconds'),
                        tools_used=session.get('tools'))
                    total_time += session.get('milliseconds')
                    sessions.append(model)

                db_annotation.update(add_to_set__events=sessions,
                                     inc__milliseconds=total_time,
                                     set__keypoints=annotation.get(
                                         'keypoints', []),
                                     set__metadata=annotation.get('metadata'),
                                     set__color=annotation.get('color'))

                paperjs_object = annotation.get('compoundPath', [])

                # Update paperjs if it exists
                if len(paperjs_object) == 2:

                    width = db_annotation.width
                    height = db_annotation.height

                    # Generate coco formatted segmentation data
                    segmentation, area, bbox = coco_util.\
                        paperjs_to_coco(width, height, paperjs_object)

                    db_annotation.update(
                        set__segmentation=segmentation,
                        set__area=area,
                        set__bbox=bbox,
                        set__paper_object=paperjs_object,
                    )

                    if area > 0:
                        annotated = True

        image_model.update(set__metadata=image.get('metadata', {}),
                           set__annotated=annotated,
                           set__category_ids=image.get('category_ids', []),
                           set__regenerate_thumbnail=annotated)

        return {"success": True}
示例#30
0
def get_dataset_coco(dataset):
    """
    Generates coco for all images in dataset

    :param dataset: DatasetModel
    :return: Coco in dictionary format
    """

    categories = CategoryModel.objects(deleted=False) \
        .exclude('deleted_date').in_bulk(dataset.categories).items()

    dataset = fix_ids(dataset)

    images = ImageModel.objects(deleted=False, dataset_id=dataset.get('id')).exclude('deleted_date')
    all_annotations = AnnotationModel.objects(deleted=False).exclude('deleted_date', 'paper_object')

    coco = {
        'images': [],
        'categories': [],
        'annotations': []
    }

    for category in categories:
        category = fix_ids(category[1])

        del category['deleted']
        if len(category.get('keypoint_labels', [])) > 0:
            category['keypoints'] = category.pop('keypoint_labels')
            category['skeleton'] = category.pop('keypoint_edges')
        else:
            del category['keypoint_edges']
            del category['keypoint_labels']

        coco.get('categories').append(category)

    for image in images:
        annotations = all_annotations.filter(image_id=image.id)
        if annotations.count() == 0:
            continue

        annotations = fix_ids(annotations.all())

        for annotation in annotations:

            has_keypoints = len(annotation.get('keypoints', [])) > 0
            has_segmentation = len(annotation.get('segmentation', [])) > 0

            if has_keypoints or has_segmentation:
                del annotation['deleted']

                if not has_keypoints:
                    del annotation['keypoints']
                else:
                    arr = np.array(annotation.get('keypoints', []))
                    arr = arr[2::3]
                    annotation['num_keypoints'] = len(arr[arr > 0])
                
                coco.get('annotations').append(annotation)

        image = fix_ids(image)
        del image['deleted']
        coco.get('images').append(image)

    return coco