Example #1
0
def update_annotation(request) -> Response:
    try:
        annotation_id = int(request.data['annotation_id'])
        image_id = int(request.data['image_id'])
        annotation_type_id = int(request.data['annotation_type_id'])
        vector = request.data['vector']
    except (KeyError, TypeError, ValueError):
        raise ParseError

    annotation = get_object_or_404(Annotation, pk=annotation_id)
    annotation_type = get_object_or_404(AnnotationType, pk=annotation_type_id)

    if annotation.image_id != image_id:
        raise ParseError('the image id does not match the annotation id.')

    if not annotation.image.image_set.has_perm('edit_annotation',
                                               request.user):
        return Response(
            {
                'detail':
                'permission for updating annotations in this image set missing.',
            },
            status=HTTP_403_FORBIDDEN)

    if not Annotation.validate_vector(vector,
                                      Annotation.VECTOR_TYPE.BOUNDING_BOX):
        return Response({'detail': 'the vector is invalid.'},
                        status=HTTP_400_BAD_REQUEST)

    if Annotation.similar_annotations(vector,
                                      annotation.image,
                                      annotation_type,
                                      exclude={annotation.id}):
        annotation.delete()
        return Response({
            'detail': 'similar annotation exists.',
        })

    with transaction.atomic():
        annotation.annotation_type = annotation_type
        annotation.vector = vector
        annotation.last_editor = request.user
        annotation.save()
        annotation.annotation_type = annotation_type

        # Automatically verify for owner
        annotation.verify(request.user, True)

    serializer = AnnotationSerializer(
        annotation.image.annotations.select_related() \
            .order_by('annotation_type__name'), many=True)
    return Response({
        'annotations': serializer.data,
    }, status=HTTP_200_OK)
Example #2
0
def edit_annotation_save(request, annotation_id):
    annotation = get_object_or_404(Annotation, id=annotation_id)
    prev_view = request.GET.get("prev_view")
    if prev_view == '1':
        go_to = reverse('annotations:verify', args=(annotation.image.id, ))
    elif prev_view == '2':
        go_to = reverse('annotations:manage_annotations',
                        args=(annotation.image.image_set.id, ))
    else:
        go_to = reverse('annotations:annotate', args=(annotation.id, ))

    # TODO: Give feedback in case of missing permissions
    if request.method == 'POST' and (request.user is annotation.user
                                     or annotation.image.image_set.has_perm(
                                         'edit_annotation', request.user)):
        try:
            annotation.vector = {
                'x1': request.POST['x1Field'],
                'y1': request.POST['y1Field'],
                'x2': request.POST['x2Field'],
                'y2': request.POST['y2Field'],
            }
            if 'not_in_image' in request.POST:
                annotation.vector = None
            annotation.last_change_time = datetime.now()
            annotation.last_editor = (
                request.user if request.user.is_authenticated() else None)
            annotation.annotation_type = get_object_or_404(
                AnnotationType, id=request.POST['selected_annotation_type'])
        except (KeyError, ValueError):
            return HttpResponseBadRequest()

        if not Annotation.validate_vector(annotation.vector,
                                          Annotation.VECTOR_TYPE.BOUNDING_BOX):
            messages.warning(request, _('No valid bounding box found.'))
            return redirect(go_to)

        if Annotation.similar_annotations(annotation.vector,
                                          annotation.image,
                                          annotation.annotation_type,
                                          exclude={annotation.pk}):
            messages.info(
                request,
                _('A similar annotation already exists. The edited annotation was deleted.'
                  ))
            annotation.delete()
            return redirect(go_to)

        with transaction.atomic():
            annotation.verified_by.clear()
            annotation.save()
            annotation.verify(request.user, True)
    return redirect(go_to)
Example #3
0
def annotate_set(request, imageset_id):
    if request.method == 'POST' and 'nii_annotation_type' in request.POST.keys(
    ):
        annotation_type = get_object_or_404(
            AnnotationType, id=int(request.POST['nii_annotation_type']))
        imageset = get_object_or_404(ImageSet, id=imageset_id)
        verify_annotations = 'verify' in request.POST.keys()
        if 'edit_set' in imageset.get_perms(request.user):
            images = Image.objects.filter(image_set=imageset)
            for image in images:
                if not Annotation.similar_annotations(None, image,
                                                      annotation_type):
                    with transaction.atomic():
                        annotation = Annotation.objects.create(
                            vector=None,
                            image=image,
                            annotation_type=annotation_type,
                            user=None)
                        # Automatically verify for owner
                        if verify_annotations:
                            annotation.verify(request.user, True)
        else:
            messages.error(
                request,
                'You have no permission to annotate all images in the set!')
    else:
        messages.error(request, 'There was a form error!')
    return redirect(reverse('images:view_imageset', args=(imageset_id, )))
Example #4
0
def create_annotation(request) -> Response:
    try:
        image_id = int(request.data['image_id'])
        annotation_type_id = int(request.data['annotation_type_id'])
        vector = request.data['vector']
    except (KeyError, TypeError, ValueError):
        raise ParseError

    image = get_object_or_404(Image, pk=image_id)
    annotation_type = get_object_or_404(AnnotationType, pk=annotation_type_id)

    if not image.image_set.has_perm('annotate', request.user):
        return Response(
            {
                'detail':
                'permission for annotating in this image set missing.',
            },
            status=HTTP_403_FORBIDDEN)

    if not Annotation.validate_vector(vector,
                                      Annotation.VECTOR_TYPE.BOUNDING_BOX):
        return Response({'detail': 'the vector is invalid.'},
                        status=HTTP_400_BAD_REQUEST)

    if Annotation.similar_annotations(vector, image, annotation_type):
        return Response({
            'detail': 'similar annotation exists.',
        })

    with transaction.atomic():
        annotation = Annotation.objects.create(vector=vector,
                                               image=image,
                                               annotation_type=annotation_type,
                                               user=request.user)

        # Automatically verify for owner
        annotation.verify(request.user, True)

    serializer = AnnotationSerializer(
        annotation.image.annotations.select_related() \
            .order_by('annotation_type__name'), many=True)
    return Response({
        'annotations': serializer.data,
    },
                    status=HTTP_201_CREATED)
Example #5
0
def label_upload(request, imageset_id):
    imageset = get_object_or_404(ImageSet, id=imageset_id)
    if not imageset.has_perm('annotate', request.user):
        messages.warning(
            request,
            _('You do not have permission to upload the annotations to this set.'
              ))
        return redirect(reverse('images:view_imageset', args=(imageset_id, )))

    images = Image.objects.filter(image_set=imageset)
    report_list = list()
    if request.method == 'POST':
        error_count = 0
        similar_count = 0
        verify = 'verify' in request.POST.keys()
        for line in request.FILES['file']:
            # filter empty lines
            print(line)
            if line in ('', "b'\n'"):
                continue
            dec_line = line.decode().replace('\n', '').replace(',}', '}')
            line_frags = dec_line.split('|')
            image = images.filter(name=line_frags[0])
            if image.exists():
                image = image[0]
                annotation_type = AnnotationType.objects.filter(
                    name=line_frags[1], active=True)
                if annotation_type.exists():
                    annotation_type = annotation_type[0]
                    vector = False
                    blurred = False
                    concealed = False
                    if len(line_frags) > 3:
                        flags = line_frags[3]
                        test_flags = flags.replace('b', '')
                        test_flags = test_flags.replace('c', '')
                        if len(test_flags) > 0:
                            report_list.append(
                                'unknown flags: \"{}\" for image: \"{}\"'.
                                format(test_flags, line_frags[0]))
                        blurred = 'b' in flags
                        concealed = 'c' in flags
                    if line_frags[2] == 'not in image' or line_frags[2] == '{}':
                        vector = None

                    else:
                        try:
                            vector = json.loads(line_frags[2])
                        except Exception as error:
                            report_list.append(
                                "In image \"{}\" the annotation:"
                                " \"{}\" was not accepted as valid JSON".
                                format(line_frags[0], line_frags[2]))

                    if annotation_type.validate_vector(vector):
                        if not Annotation.similar_annotations(
                                vector, image, annotation_type):
                            annotation = Annotation()
                            annotation.annotation_type = annotation_type
                            annotation.image = image
                            annotation.user = request.user
                            annotation.vector = vector
                            annotation._blurred = blurred
                            annotation._concealed = concealed
                            annotation.save()
                            if verify:
                                verification = Verification()
                                verification.user = request.user
                                verification.annotation = annotation
                                verification.verified = True
                                verification.save()
                        else:
                            similar_count += 1
                            report_list.append(
                                'For the image ' + line_frags[0] +
                                ' the annotation ' + line_frags[2] +
                                ' was too similar to an already existing one')
                    else:
                        error_count += 1
                        report_list.append(
                            'For the image ' + line_frags[0] +
                            ' the annotation ' + line_frags[2] +
                            ' was not a valid vector or '
                            'bounding box for the annotation type')
                else:
                    error_count += 1
                    report_list.append('For the image ' + line_frags[0] +
                                       ' the annotation type \"' +
                                       line_frags[1] +
                                       '\" does not exist in this ImageTagger')
            else:
                error_count += 1
                report_list.append('The image \"' + line_frags[0] +
                                   '\" does not exist in this imageset')

        for element in report_list[:20]:
            messages.error(request, element)
            if len(report_list) > 20:
                messages.warning(request,
                                 'Only the first 20 errors are displayed.')
        if error_count + similar_count > 0:
            messages.warning(
                request,
                _('The label upload ended with {} errors and {} similar existing labels.'
                  ).format(error_count, similar_count))
        else:
            messages.success(
                request,
                _('The label upload ended with {} errors and {} similar existing labels.'
                  ).format(error_count, similar_count))
    return redirect(reverse('images:view_imageset', args=(imageset_id, )))
Example #6
0
def annotate(request, image_id):
    selected_image = get_object_or_404(Image, id=image_id)
    if selected_image.image_set.has_perm('annotate', request.user) or selected_image.image_set.public:
        # TODO: Make sure that integer coordinate values are stored in vector

        # here the stuff we got via POST gets put in the DB
        last_annotation_type_id = -1
        if request.method == 'POST' and request.POST.get("annotate") is not None:
            try:
                image = get_object_or_404(Image, id=request.POST['image_id'])
                vector = {
                    'x1': int(request.POST['x1Field']),
                    'y1': int(request.POST['y1Field']),
                    'x2': int(request.POST['x2Field']),
                    'y2': int(request.POST['y2Field']),
                }
                if 'not_in_image' in request.POST:
                    vector = None
            except (KeyError, ValueError):
                return HttpResponseBadRequest()

            if (vector is not None and
                    not Annotation.validate_vector(
                        vector, Annotation.VECTOR_TYPE.BOUNDING_BOX)):
                messages.warning(request, _('No valid bounding box found.'))
            else:
                last_annotation_type_id = request.POST['selected_annotation_type']
                annotation_type = get_object_or_404(AnnotationType, id=request.POST['selected_annotation_type'])
                annotation = Annotation(
                    vector=vector, image=image, annotation_type=annotation_type,
                    user=request.user if request.user.is_authenticated() else None)

                if not Annotation.similar_annotations(
                        vector, selected_image, annotation_type):
                    annotation.save()
                    # the creator of the annotation verifies it instantly
                    annotation.verify(request.user, True)
                else:
                    messages.warning(request, "This tag already exists!")

        set_images = selected_image.image_set.images.all()
        annotation_types = AnnotationType.objects.filter(active=True)  # for the dropdown option

        filtered = request.GET.get("selected_annotation_type")
        new_filter = request.GET.get("filter")
        if filtered is not None:
            # filter images for missing annotationtype
            set_images = set_images.exclude(annotations__annotation_type_id=filtered)
            if not set_images:
                messages.info(request, 'All images in this set have been tagged with this tag!')
                set_images = Image.objects.filter(image_set=selected_image.image_set)
                filtered = None
            if new_filter is not None:
                # sets the current viewed image to the one on top of the filtered list
                selected_image = set_images[0]
        set_images = set_images.order_by('id')

        # detecting next and last image in the set
        next_image = set_images.filter(id__gt=selected_image.id).order_by('id').first()
        last_image = set_images.filter(id__lt=selected_image.id).order_by('id').last()

        return render(request, 'annotations/annotate.html', {
            'selected_image': selected_image,
            'next_image': next_image,
            'last_image': last_image,
            'set_images': set_images,
            'annotation_types': annotation_types,
            'image_annotations': Annotation.objects.filter(
                image=selected_image).select_related(),
            'last_annotation_type_id': int(last_annotation_type_id),
            'filtered' : filtered,
            'vector_fields': (
                'x1',
                'x2',
                'y1',
                'y2',
            ),
        })
    else:
        return redirect(reverse('images:view_imageset', args=(selected_image.image_set.id,)))
Example #7
0
def label_upload(request, imageset_id):
    imageset = get_object_or_404(ImageSet, id=imageset_id)
    if not imageset.has_perm('annotate', request.user):
        messages.warning(
            request,
            _('You do not have permission to upload the annotations to this set.'
              ))
        return redirect(reverse('images:view_imageset', args=(imageset_id, )))

    images = Image.objects.filter(image_set=imageset)
    if request.method == 'POST':
        error_count = 0
        similar_count = 0
        verify = 'verify' in request.POST.keys()
        for line in request.FILES['file']:
            dec_line = line.decode().replace('\n', '')
            line_frags = dec_line.split('|')
            image = images.filter(name=line_frags[0])
            if image.exists():
                image = image[0]
                annotation_type = AnnotationType.objects.filter(
                    name=line_frags[1])
                if annotation_type.exists():
                    annotation_type = annotation_type[0]
                    vector = False
                    if line_frags[2] == 'not in image':
                        vector = None
                    elif int(line_frags[2]) and int(line_frags[3]) and int(
                            line_frags[4]) and int(line_frags[5]):
                        vector = {
                            'x1': int(line_frags[2]),
                            'y1': int(line_frags[3]),
                            'x2': int(line_frags[4]),
                            'y2': int(line_frags[5]),
                        }
                    if Annotation.validate_vector(
                            vector, Annotation.VECTOR_TYPE.BOUNDING_BOX):
                        if not Annotation.similar_annotations(
                                vector, image, annotation_type):
                            annotation = Annotation()
                            annotation.annotation_type = annotation_type
                            annotation.image = image
                            annotation.user = request.user
                            annotation.vector = vector
                            annotation.save()
                            if verify:
                                verification = Verification()
                                verification.user = request.user
                                verification.annotation = annotation
                                verification.verified = True
                                verification.save()
                        else:
                            similar_count += 1
                    else:
                        error_count += 1
                else:
                    error_count += 1

            else:
                error_count += 1
        messages.warning(
            request,
            _('The label upload ended with {} errors and {} similar existing labels.'
              ).format(error_count, similar_count))
    return redirect(reverse('images:view_imageset', args=(imageset_id, )))