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)
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)
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, )))
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)
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, )))
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,)))
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, )))