def image_detail(request, image_id): """ View for seeing an image's full size and details/metadata. """ image = get_object_or_404(Image, id=image_id) source = image.source metadata = image.metadata # Get the metadata fields (including the right no. of keys for the source) # and organize into fieldsets. The image detail form already has this # logic, so let's just borrow the form's functionality... imageDetailForm = ImageDetailForm(source=source, initial=model_to_dict(metadata)) fieldsets = imageDetailForm.fieldsets # ...But we don't need the form's "Other" value fields. # (Code note: [:] creates a copy of the list, so we're not iterating over the same list we're removing things from) for field in fieldsets['keys'][:]: if field.name.endswith('_other'): fieldsets['keys'].remove(field) detailsets = dict() for key, fieldset in fieldsets.items(): detailsets[key] = [dict(label=field.label, name=field.name, value=getattr(metadata, field.name)) for field in fieldset] # Feel free to change this constant according to the page layout. MAX_SCALED_WIDTH = 800 if image.original_width > MAX_SCALED_WIDTH: # Parameters into the easy_thumbnails template tag: # (specific width, height that keeps the aspect ratio) thumbnail_dimensions = (MAX_SCALED_WIDTH, 0) else: # No thumbnail needed thumbnail_dimensions = False # Next and previous image links next_image = get_next_image(image) prev_image = get_prev_image(image) # Annotation status if image.status.annotatedByHuman: annotation_status = "Complete" elif image_has_any_human_annotations(image): annotation_status = "Partially annotated" else: annotation_status = "Not started" # Should we include a link to the annotation area edit page? annotation_area_editable = image_annotation_area_is_editable(image) return render_to_response('images/image_detail.html', { 'source': source, 'image': image, 'next_image': next_image, 'prev_image': prev_image, 'metadata': metadata, 'detailsets': detailsets, 'has_thumbnail': bool(thumbnail_dimensions), 'thumbnail_dimensions': thumbnail_dimensions, 'annotation_status': annotation_status, 'annotation_area_editable': annotation_area_editable, }, context_instance=RequestContext(request) )
def annotation_tool(request, image_id): """ View for the annotation tool. """ image = get_object_or_404(Image, id=image_id) source = image.source metadata = image.metadata # Get all labels, ordered first by functional group, then by short code. labels = source.labelset.labels.all().order_by('group', 'code') # Get labels in the form {'code': <short code>, 'group': <functional group>, 'name': <full name>}. # Convert from a ValuesQuerySet to a list to make the structure JSON-serializable. labelValues = list(labels.values('code', 'group', 'name')) form = AnnotationForm(image=image, user=request.user) pointValues = Point.objects.filter(image=image).values( 'point_number', 'row', 'column') annotationValues = Annotation.objects.filter(image=image).values( 'point__point_number', 'label__name', 'label__code') # annotationsDict # keys: point numbers # values: dicts containing the values in pointValues and # annotationValues (if the point has an annotation) above annotationsDict = dict() for p in pointValues: annotationsDict[p['point_number']] = p for a in annotationValues: annotationsDict[a['point__point_number']].update(a) # Get a list of the annotationsDict values (the keys are discarded) # Sort by point_number annotations = list(annotationsDict.values()) annotations.sort(key=lambda x:x['point_number']) # Now we've gotten all the relevant points and annotations # from the database, in a list of dicts: # [{'point_number':1, 'row':294, 'column':749, 'label__name':'Porites', 'label__code':'Porit', 'user_is_robot':False}, # {'point_number':2, ...}, # ...] # TODO: Are we even using anything besides row, column, and point_number? If not, discard the annotation fields to avoid confusion. need_human_anno_next = get_next_image(image, dict(status__annotatedByHuman=False)) need_human_anno_prev = get_prev_image(image, dict(status__annotatedByHuman=False)) # Get the settings object for this user. # If there is no such settings object, then create it. settings_obj, created = AnnotationToolSettings.objects.get_or_create(user=request.user) settings_form = AnnotationToolSettingsForm(instance=settings_obj) # Image tools form (brightness, contrast, etc.) image_options_form = AnnotationImageOptionsForm() IMAGE_AREA_WIDTH = 800 IMAGE_AREA_HEIGHT = 600 source_images = dict(full=dict( url=image.original_file.url, width=image.original_file.width, height=image.original_file.height, )) if image.original_width > IMAGE_AREA_WIDTH: # Set scaled image's dimensions (Specific width, height that keeps the aspect ratio) thumbnail_dimensions = (IMAGE_AREA_WIDTH, 0) # Generate the thumbnail if it doesn't exist, and get the thumbnail's URL and dimensions. thumbnailer = get_thumbnailer(image.original_file) thumb = thumbnailer.get_thumbnail(dict(size=thumbnail_dimensions)) source_images.update(dict(scaled=dict( url=thumb.url, width=thumb.width, height=thumb.height, ))) access = AnnotationToolAccess(image=image, source=source, user=request.user) access.save() return render_to_response('annotations/annotation_tool.html', { 'source': source, 'image': image, 'next_image': need_human_anno_next, 'prev_image': need_human_anno_prev, 'metadata': metadata, 'labels': labelValues, 'form': form, 'settings_form': settings_form, 'image_options_form': image_options_form, 'annotations': annotations, 'annotationsJSON': simplejson.dumps(annotations), 'IMAGE_AREA_WIDTH': IMAGE_AREA_WIDTH, 'IMAGE_AREA_HEIGHT': IMAGE_AREA_HEIGHT, 'source_images': source_images, 'num_of_points': len(annotations), 'num_of_annotations': len(annotationValues), }, context_instance=RequestContext(request) )