Esempio n. 1
0
def image_annotation_area_is_editable(image):
    """
    Returns True if the image's annotation area is editable; False otherwise.
    The annotation area is editable only if:
    (1) there are no human annotations for the image yet, and
    (2) the points are not imported.
    """
    return (not image_has_any_human_annotations(image))\
    and (PointGen.db_to_args_format(image.point_generation_method)['point_generation_type'] != PointGen.Types.IMPORTED)
Esempio n. 2
0
def generate_points(img, usesourcemethod=True):
    """
    Generate annotation points for the Image img,
    and delete any points that had previously existed.

    Does nothing if the image already has human annotations,
    because we don't want to delete any human work.
    """

    # If there are any human annotations for this image,
    # abort point generation.
    human_annotations = Annotation.objects.filter(image = img).exclude(user = get_robot_user()).exclude(user = get_alleviate_user())
    if human_annotations:
        return

    # Find the annotation area, expressed in pixels.
    d = AnnotationAreaUtils.db_format_to_numbers(img.metadata.annotation_area)
    annoarea_type = d.pop('type')
    if annoarea_type == AnnotationAreaUtils.TYPE_PERCENTAGES:
        annoarea_dict = AnnotationAreaUtils.percentages_to_pixels(width=img.original_width, height=img.original_height, **d)
    elif annoarea_type == AnnotationAreaUtils.TYPE_PIXELS:
        annoarea_dict = d
    else:
        raise ValueError("Can't generate points with annotation area type '{0}'.".format(annoarea_type))

    # Calculate points.
    if usesourcemethod:
        point_gen_method = img.source.default_point_generation_method
    else:
        point_gen_method = img.point_generation_method
    
    new_points = calculate_points(
        img, annotation_area=annoarea_dict,
        **PointGen.db_to_args_format(point_gen_method)
    )

    # Delete old points for this image, if any.
    old_points = Point.objects.filter(image=img)
    for old_point in old_points:
        old_point.delete()

    # Save the newly calculated points.
    for new_point in new_points:
        Point(row=new_point['row'],
              column=new_point['column'],
              point_number=new_point['point_number'],
              image=img,
        ).save()

    # Update image status.
    # Make sure the image goes through the feature-making step again.
    status = img.status
    status.hasRandomPoints = True
    status.save()
Esempio n. 3
0
    def __init__(self, *args, **kwargs):
        """
        If a Source is passed in as an argument, then get
        the point generation method of that Source,
        and use that to fill the form fields' initial values.
        """
        if kwargs.has_key('source'):
            source = kwargs.pop('source')
            kwargs['initial'] = PointGen.db_to_args_format(source.default_point_generation_method)

        self.form_help_text = Source._meta.get_field('default_point_generation_method').help_text

        super(PointGenForm, self).__init__(*args, **kwargs)
Esempio n. 4
0
    def pointgen_check(self, image_id):
        """
        Check that an image had annotation points generated as
        specified in the point generation method field.

        :param image_id: The id of the image to check.
        """
        img = Image.objects.get(pk=image_id)
        img_width = img.original_width
        img_height = img.original_height
        pointgen_args = PointGen.db_to_args_format(img.point_generation_method)

        points = Point.objects.filter(image=img)
        self.assertEqual(points.count(), pointgen_args['simple_number_of_points'])

        # Find the expected annotation area, expressed in pixels.
        d = AnnotationAreaUtils.db_format_to_numbers(img.metadata.annotation_area)
        annoarea_type = d.pop('type')
        if annoarea_type == AnnotationAreaUtils.TYPE_PERCENTAGES:
            area = AnnotationAreaUtils.percentages_to_pixels(width=img_width, height=img_height, **d)
        elif annoarea_type == AnnotationAreaUtils.TYPE_PIXELS:
            area = d
        elif annoarea_type == AnnotationAreaUtils.TYPE_IMPORTED:
            area = dict(min_x=1, max_x=img_width, min_y=1, max_y=img_height)
        else:
            raise ValueError("Unknown annotation area type.")

        if settings.UNIT_TEST_VERBOSITY >= 1:
            print "{pointgen_method}".format(
                pointgen_method=img.point_gen_method_display(),
            )
            print "{annotation_area}".format(
                annotation_area=img.annotation_area_display(),
            )
            print "Image dimensions: {width} x {height} pixels".format(
                width=img_width, height=img_height,
            )
            print "X bounds: ({min_x}, {max_x}) Y bounds: ({min_y}, {max_y})".format(
                **area
            )

        for pt in points:
            self.assertTrue(area['min_x'] <= pt.column)
            self.assertTrue(pt.column <= area['max_x'])
            self.assertTrue(area['min_y'] <= pt.row)
            self.assertTrue(pt.row <= area['max_y'])

            if settings.UNIT_TEST_VERBOSITY >= 1:
                print "({col}, {row})".format(col=pt.column, row=pt.row)
Esempio n. 5
0
    def upload_image_test_with_field_checks(self, filename,
                                            expecting_dupe=False,
                                            expected_error=None,
                                            **options):
        """
        Like upload_image_test(), but with additional checks that the
        various image fields are set correctly.
        """
        datetime_before_upload = datetime.datetime.now().replace(microsecond=0)

        image_id, response = self.upload_image_test(
            filename,
            expecting_dupe,
            expected_error,
            **options
        )

        img = Image.objects.get(pk=image_id)

        # Not sure if we can check the file location in a cross-platform way,
        # so we'll skip a check of original_file.path for now.
        if settings.UNIT_TEST_VERBOSITY >= 1:
            print "Uploaded file's path: {path}".format(path=img.original_file.path)

        self.assertEqual(img.original_height, 400)
        self.assertEqual(img.original_width, 400)

        # This check is of limited use since database datetimes (in
        # MySQL 5.1 at least) get truncated to whole seconds. But it still
        # doesn't hurt to check.
        self.assertTrue(datetime_before_upload <= img.upload_date)
        self.assertTrue(img.upload_date <= datetime.datetime.now().replace(microsecond=0))

        # Check that the user who uploaded the image is the
        # currently logged in user.
        self.assertEqual(img.uploaded_by.id, self.client.session['_auth_user_id'])

        # Status fields.
        self.assertFalse(img.status.preprocessed)
        self.assertTrue(img.status.hasRandomPoints)
        self.assertFalse(img.status.featuresExtracted)
        self.assertFalse(img.status.annotatedByRobot)
        self.assertFalse(img.status.featureFileHasHumanLabels)
        self.assertFalse(img.status.usedInCurrentModel)

        # cm height.
        self.assertEqual(img.metadata.height_in_cm, img.source.image_height_in_cm)

        full_options = self.get_full_upload_options(options)

        if full_options['is_uploading_points_or_annotations'] == True:

            # Uploading with points/annotations.

            # Pointgen method and annotation area should both indicate that
            # points have been imported.
            self.assertEqual(
                PointGen.db_to_args_format(img.point_generation_method)['point_generation_type'],
                PointGen.Types.IMPORTED,
            )
            self.assertEqual(
                img.metadata.annotation_area,
                AnnotationAreaUtils.IMPORTED_STR,
            )

            # Depending on whether we're uploading annotations, the
            # annotatedByHuman status flag may or may not apply.
            if full_options['is_uploading_annotations_not_just_points'] == 'yes':
                # Points + annotations upload.
                self.assertTrue(img.status.annotatedByHuman)

            else:  # 'no'
                # Points only upload.
                self.assertFalse(img.status.annotatedByHuman)

        else:  # False

            self.check_fields_for_non_annotation_upload(img)

        # Other metadata fields aren't covered here because:
        # - name, photo_date, value1/2/3/4/5: covered by filename tests
        # - latitude, longitude, depth, camera, photographer, water_quality,
        #   strobes, framing, balance, comments: not specifiable from the
        #   upload page

        return image_id, response