def get_sessions_and_total_times(self, annotation_data, current_user):
     # Paperjs objects are complex, so they will not always be passed. Therefor we update
     # the annotation twice, checking if the paperjs exists.
     sessions = []
     total_time = 0
     for session in annotation_data.get('sessions', []):
         date = datetime.datetime.fromtimestamp(
             int(session.get('start')) / 1e3)
         model = SessionEvent(
             user=current_user.get_username(),
             created_at=date,
             milliseconds=session.get('milliseconds'),
             tools_used=session.get('tools'),
         )
         total_time += session.get('milliseconds')
         sessions.append(model)
     return sessions, total_time
예제 #2
0
def disconnect():
    if current_user.is_authenticated:
        logger.info(
            f'Socket connection has been disconnected with {current_user.username}'
        )
        image_id = session.get('annotating')

        # Remove user from room
        if image_id is not None:
            image = ImageModel.objects(id=image_id).first()
            if image is not None:
                start = session.get('annotating_time', time.time())
                event = SessionEvent.create(start, current_user)

                image.add_event(event)
                image.update(pull__annotating=current_user.username)
                emit('annotating', {
                    'image_id': image_id,
                    'active': False,
                    'username': current_user.username
                },
                     broadcast=True,
                     include_self=False)
예제 #3
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}
예제 #4
0
def annotating(data):
    """
    Socket for handling image locking and time logging
    """

    image_id = data.get('image_id')
    active = data.get('active')

    image = ImageModel.objects(id=image_id).first()
    if image is None:
        # invalid image ID
        return

    emit('annotating', {
        'image_id': image_id,
        'active': active,
        'username': current_user.username
    },
         broadcast=True,
         include_self=False)

    if active:
        logger.info(
            f'{current_user.username} has started annotating image {image_id}')
        # Remove user from pervious room
        previous = session.get('annotating')
        if previous is not None:
            leave_room(previous)
            previous_image = ImageModel.objects(id=previous).first()

            if previous_image is not None:

                start = session.get('annotating_time', time.time())
                event = SessionEvent.create(start, current_user)

                previous_image.add_event(event)
                previous_image.update(pull__annotating=current_user.username)

                emit('annotating', {
                    'image_id': previous,
                    'active': False,
                    'username': current_user.username
                },
                     broadcast=True,
                     include_self=False)

        join_room(image_id)
        session['annotating'] = image_id
        session['annotating_time'] = time.time()
        image.update(add_to_set__annotating=current_user.username)
    else:
        leave_room(image_id)

        start = session.get('annotating_time', time.time())
        event = SessionEvent.create(start, current_user)

        image.add_event(event)
        image.update(pull__annotating=current_user.username)

        session['annotating'] = None
        session['time'] = None