Esempio n. 1
0
    def post(self):
        """ Creates a category """
        args = create_category.parse_args()
        name = args.get('name')
        supercategory = args.get('supercategory')
        metadata = args.get('metadata', {})
        color = args.get('color')
        keypoint_edges = args.get('keypoint_edges')
        keypoint_labels = args.get('keypoint_labels')
        keypoint_colors = args.get('keypoint_colors')

        try:
            category = CategoryModel(
                name=name,
                supercategory=supercategory,
                color=color,
                metadata=metadata,
                keypoint_edges=keypoint_edges,
                keypoint_labels=keypoint_labels,
                keypoint_colors=keypoint_colors,
            )
            category.save()
        except NotUniqueError as e:
            return {
                'message':
                'Category already exists. Check the undo tab to fully delete the category.'
            }, 400

        return query_util.fix_ids(category)
 def create_category():
     category = CategoryModel(
         name="category",
         supercategory="supercategory",
         color="red",
         metadata={},
         keypoint_edges=[],
         keypoint_labels=[],
         keypoint_colors=[],
     )
     category.save()
     return category.id
Esempio n. 3
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}
Esempio n. 4
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
    def create_category(self, category_data):

        exist_category = CategoryModel.find_by_name(category_data['name'])
        if exist_category is not None:
            return exist_category.id

        category = CategoryModel(
            name=category_data['name'],
            supercategory="supercategory",
            color="color",
            metadata={},
            keypoint_edges=[],
            keypoint_labels=[],
            keypoint_colors=[],
        )
        category.save()
        return category.id
Esempio n. 6
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
Esempio n. 7
0
    def test_create_category(self):

        query = {"name": category1.get("name")}
        create_category1 = upsert(CategoryModel, query=query, update=category1)

        assert create_category1.name == category1.get("name")
        assert create_category1.color == category1.get("color")

        found = CategoryModel.objects(**query).first()
        assert found.name == category1.get("name")
        assert found.color == category1.get("color")
Esempio n. 8
0
    def post(self):
        """ Creates a dataset """
        args = dataset_create.parse_args()
        name = args['name']
        categories = args.get('categories', [])

        category_ids = CategoryModel.bulk_create(categories)

        try:
            dataset = DatasetModel(name=name, categories=category_ids)
            dataset.save()
        except NotUniqueError:
            return {'message': 'Dataset already exists. Check the undo tab to fully delete the dataset.'}, 400

        return query_util.fix_ids(dataset)
Esempio n. 9
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
Esempio n. 10
0
    def get(self, dataset_id):
        """ All users in the dataset """

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

        category_dict = dict()
        for category in dataset.categories:

            cat_name = CategoryModel.objects(id=category).first()['name']
            category_dict.update({str(cat_name): category})

        res = {
            'categories': category_dict,
        }
        return res
Esempio n. 11
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}
Esempio n. 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()

        # 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
Esempio n. 13
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)
Esempio n. 14
0
    def get(self, dataset_id):
        """ Endpoint called by image viewer client """

        parsed_args = page_data.parse_args()
        per_page = parsed_args.get('limit')
        page = parsed_args.get('page') - 1
        folder = parsed_args.get('folder')
        order = parsed_args.get('order')

        args = dict(request.args)

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

        # Make sure folder starts with is in proper format
        if len(folder) > 0:
            folder = folder[0].strip('/') + folder[1:]
            if folder[-1] != '/':
                folder = folder + '/'

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

        # Remove parsed arguments
        for key in parsed_args:
            args.pop(key, None)

        # Generate query from remaining arugments
        query = {}
        for key, value in args.items():
            lower = value.lower()
            if lower in ["true", "false"]:
                value = json.loads(lower)

            if len(lower) != 0:
                query[key] = value

        # Change category_ids__in to list
        if 'category_ids__in' in query.keys():
            query['category_ids__in'] = [
                int(x) for x in query['category_ids__in'].split(',')
            ]

        # Initialize mongo query with required elements:
        query_build = Q(dataset_id=dataset_id)
        query_build &= Q(path__startswith=directory)
        query_build &= Q(deleted=False)

        # Define query names that should use complex logic:
        complex_query = ['annotated', 'category_ids__in']

        # Add additional 'and' arguments to mongo query that do not require complex_query logic
        for key in query.keys():
            if key not in complex_query:
                query_dict = {}
                query_dict[key] = query[key]
                query_build &= Q(**query_dict)

        # Add additional arguments to mongo query that require more complex logic to construct
        if 'annotated' in query.keys():

            if 'category_ids__in' in query.keys() and query['annotated']:

                # Only show annotated images with selected category_ids
                query_dict = {}
                query_dict['category_ids__in'] = query['category_ids__in']
                query_build &= Q(**query_dict)

            else:

                # Only show non-annotated images
                query_dict = {}
                query_dict['annotated'] = query['annotated']
                query_build &= Q(**query_dict)

        elif 'category_ids__in' in query.keys():

            # Ahow annotated images with selected category_ids or non-annotated images
            query_dict_1 = {}
            query_dict_1['category_ids__in'] = query['category_ids__in']

            query_dict_2 = {}
            query_dict_2['annotated'] = False
            query_build &= (Q(**query_dict_1) | Q(**query_dict_2))

        # Perform mongodb query
        images = current_user.images \
            .filter(query_build) \
            .order_by(order).only('id', 'file_name', 'annotating', 'annotated', 'num_annotations')

        total = images.count()
        pages = int(total / per_page) + 1

        images = images.skip(page * per_page).limit(per_page)
        images_json = query_util.fix_ids(images)
        # for image in images:
        #     image_json = query_util.fix_ids(image)

        #     query = AnnotationModel.objects(image_id=image.id, deleted=False)
        #     category_ids = query.distinct('category_id')
        #     categories = CategoryModel.objects(id__in=category_ids).only('name', 'color')

        #     image_json['annotations'] = query.count()
        #     image_json['categories'] = query_util.fix_ids(categories)

        #     images_json.append(image_json)

        subdirectories = [
            f for f in sorted(gfile.listdir(directory))
            if gfile.isdir(directory + f) and not f.startswith('.')
        ]

        categories = CategoryModel.objects(id__in=dataset.categories).only(
            'id', 'name')

        return {
            "total": total,
            "per_page": per_page,
            "pages": pages,
            "page": page,
            "images": images_json,
            "folder": folder,
            "directory": directory,
            "dataset": query_util.fix_ids(dataset),
            "categories": query_util.fix_ids(categories),
            "subdirectories": subdirectories
        }
 def execute(self, dataset_id, categories):
     dataset = DatasetModel.find_by(dataset_id)
     category_id_list = CategoryModel.bulk_create(categories)
     # dataset.update(set__categories=category_id_list)
     dataset.update_categories(category_id_list)
Esempio n. 16
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)
Esempio n. 17
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
Esempio n. 18
0
def get_image_coco(image_id):
    """
    Generates coco for an image

    :param image: ImageModel
    :return: Coco in dictionary format
    """
    image = ImageModel.objects(id=image_id)\
        .only(*ImageModel.COCO_PROPERTIES)
    
    image = fix_ids(image)[0]
    dataset = DatasetModel.objects(id=image.get('dataset_id')).first()

    bulk_categories = CategoryModel.objects(id__in=dataset.categories, deleted=False) \
        .only(*CategoryModel.COCO_PROPERTIES)

    print(bulk_categories)

    db_annotations = AnnotationModel.objects(deleted=False, image_id=image_id)
    categories = []
    annotations = []

    for category in fix_ids(bulk_categories):

        category_annotations = db_annotations\
            .filter(category_id=category.get('id'))\
            .only(*AnnotationModel.COCO_PROPERTIES)
        
        if category_annotations.count() == 0:
            continue
        
        category_annotations = fix_ids(category_annotations)
        for annotation in category_annotations:

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

            if has_segmentation or has_keypoints:

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

        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']
        
        categories.append(category)

    coco = {
        "images": [image],
        "categories": categories,
        "annotations": annotations
    }

    return coco
Esempio n. 19
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
Esempio n. 20
0
    def get(self, dataset_id):
        """ Endpoint called by image viewer client """

        parsed_args = page_data.parse_args()
        per_page = parsed_args.get('limit')
        page = parsed_args.get('page') - 1
        folder = parsed_args.get('folder')
        order = parsed_args.get('order')

        args = dict(request.args)

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

        # Make sure folder starts with is in proper format
        if len(folder) > 0:
            folder = folder[0].strip('/') + folder[1:]
            if folder[-1] != '/':
                folder = folder + '/'

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

        # Remove parsed arguments
        for key in parsed_args:
            args.pop(key, None)

        # Generate query from remaining arugments
        query = {}
        for key, value in args.items():
            lower = value.lower()
            if lower in ["true", "false"]:
                value = json.loads(lower)

            if len(lower) != 0:
                query[key] = value

        images = current_user.images \
            .filter(dataset_id=dataset_id, path__startswith=directory, deleted=False, **query) \
            .order_by(order).only('id', 'file_name', 'annotating', 'annotated', 'num_annotations')

        total = images.count()
        pages = int(total / per_page) + 1

        images = images.skip(page * per_page).limit(per_page)
        images_json = query_util.fix_ids(images)
        # for image in images:
        #     image_json = query_util.fix_ids(image)

        #     query = AnnotationModel.objects(image_id=image.id, deleted=False)
        #     category_ids = query.distinct('category_id')
        #     categories = CategoryModel.objects(id__in=category_ids).only('name', 'color')

        #     image_json['annotations'] = query.count()
        #     image_json['categories'] = query_util.fix_ids(categories)

        #     images_json.append(image_json)

        subdirectories = [
            f for f in sorted(os.listdir(directory))
            if os.path.isdir(directory + f) and not f.startswith('.')
        ]

        categories = CategoryModel.objects(id__in=dataset.categories).only(
            'id', 'name')

        return {
            "total": total,
            "per_page": per_page,
            "pages": pages,
            "page": page,
            "images": images_json,
            "folder": folder,
            "directory": directory,
            "dataset": query_util.fix_ids(dataset),
            "categories": query_util.fix_ids(categories),
            "subdirectories": subdirectories
        }
Esempio n. 21
0
 def update_all_category(self, data, current_user):
     for category_data in data.get('categories', []):
         db_category = CategoryModel.find_by(category_data.get('id'))
         if db_category is None:
             continue
         self.update_category(db_category, category_data, current_user)
Esempio n. 22
0
def collect_coco_annotations(task, categories, dataset, socket):
    """
    Getting all coco labels from current dataset and creating a dict from it

    :return: COCO labels from current dataset as dict with fields: "images", "categories",
    "annotations".
    """
    # Getting coco annotations
    task.info("===== Getting COCO annotations =====")
    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) * 50, socket=socket)

    total_annotations = db_annotations.count()
    total_images = db_images.count()
    for img_counter, image in enumerate(fix_ids(db_images)):
        progress += 1
        task.set_progress((progress / total_items) * 50, socket=socket)

        annotations = db_annotations.filter(image_id=image.get('id')) \
            .only(*AnnotationModel.COCO_PROPERTIES)
        annotations = fix_ids(annotations)
        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')} ({img_counter+1}/{total_images})")
        coco.get('images').append(image)
    task.info(f"Done export {total_annotations} annotations and {total_images} images from {dataset.name}")
    return coco, category_names
Esempio n. 23
0
    def get(self, dataset_id):
        """ Endpoint called by image viewer client """

        args = page_data.parse_args()
        limit = args['limit']
        page = args['page']
        folder = args['folder']

        args = dict(request.args)
        if args.get('limit') != None:
            del args['limit']
        if args.get('page') != None:
            del args['page']
        if args.get('folder') != None:
            del args['folder']

        query = {}
        for key, value in args.items():
            lower = value.lower()
            if lower in ["true", "false"]:
                value = json.loads(lower)

            if len(lower) != 0:
                query[key] = value

        # print(query, flush=True)

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

        # Make sure folder starts with is in proper format
        if len(folder) > 0:
            folder = folder[0].strip('/') + folder[1:]
            if folder[-1] != '/':
                folder = folder + '/'

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

        images = ImageModel.objects(dataset_id=dataset_id, path__startswith=directory, deleted=False, **query) \
            .order_by('file_name').only('id', 'file_name', 'annotating')

        pagination = Pagination(images.count(), limit, page)
        images = images[pagination.start:pagination.end]

        images_json = []
        for image in images:
            image_json = query_util.fix_ids(image)

            query = AnnotationModel.objects(image_id=image.id, deleted=False)
            category_ids = query.distinct('category_id')

            image_json['annotations'] = query.count()
            image_json['categories'] = query_util.fix_ids(
                CategoryModel.objects(id__in=category_ids).only(
                    'name', 'color'))
            image_json['permissions'] = image.permissions(current_user)

            images_json.append(image_json)

        subdirectories = [
            f for f in sorted(os.listdir(directory))
            if os.path.isdir(directory + f) and not f.startswith('.')
        ]

        categories = CategoryModel.objects(id__in=dataset.categories).only(
            'id', 'name')

        return {
            "pagination": pagination.export(),
            "images": images_json,
            "folder": folder,
            "directory": directory,
            "dataset": query_util.fix_ids(dataset),
            "categories": query_util.fix_ids(categories),
            "subdirectories": subdirectories
        }