Ejemplo n.º 1
0
    def get_suggested_focal_point(self):
        with self.get_willow_image() as willow:
            faces = willow.detect_faces()

            if faces:
                # Create a bounding box around all faces
                left = min(face[0] for face in faces)
                top = min(face[1] for face in faces)
                right = max(face[2] for face in faces)
                bottom = max(face[3] for face in faces)
                focal_point = Rect(left, top, right, bottom)
            else:
                features = willow.detect_features()
                if features:
                    # Create a bounding box around all features
                    left = min(feature[0] for feature in features)
                    top = min(feature[1] for feature in features)
                    right = max(feature[0] for feature in features)
                    bottom = max(feature[1] for feature in features)
                    focal_point = Rect(left, top, right, bottom)
                else:
                    return None

        # Add 20% to width and height and give it a minimum size
        x, y = focal_point.centroid
        width, height = focal_point.size

        width *= 1.20
        height *= 1.20

        width = max(width, 100)
        height = max(height, 100)

        return Rect.from_point(x, y, width, height)
Ejemplo n.º 2
0
    def get_suggested_focal_point(self, backend_name='default'):
        backend = get_image_backend(backend_name)
        image_file = self.file.file

        # Make sure image is open and seeked to the beginning
        image_file.open('rb')
        image_file.seek(0)

        # Load the image
        image = backend.open_image(self.file.file)
        image_data = backend.image_data_as_rgb(image)

        # Make sure we have image data
        # If the image is animated, image_data_as_rgb will return None
        if image_data is None:
            return

        # Use feature detection to find a focal point
        feature_detector = FeatureDetector(image.size, image_data[0],
                                           image_data[1])

        faces = feature_detector.detect_faces()
        if faces:
            # Create a bounding box around all faces
            left = min(face.left for face in faces)
            top = min(face.top for face in faces)
            right = max(face.right for face in faces)
            bottom = max(face.bottom for face in faces)
            focal_point = Rect(left, top, right, bottom)
        else:
            features = feature_detector.detect_features()
            if features:
                # Create a bounding box around all features
                left = min(feature[0] for feature in features)
                top = min(feature[1] for feature in features)
                right = max(feature[0] for feature in features)
                bottom = max(feature[1] for feature in features)
                focal_point = Rect(left, top, right, bottom)
            else:
                return None

        # Add 20% to width and height and give it a minimum size
        x, y = focal_point.centroid
        width, height = focal_point.size

        width *= 1.20
        height *= 1.20

        width = max(width, 100)
        height = max(height, 100)

        return Rect.from_point(x, y, width, height)
Ejemplo n.º 3
0
 def test_getitem(self):
     rect = Rect(100, 150, 200, 250)
     self.assertEqual(rect[0], 100)
     self.assertEqual(rect[1], 150)
     self.assertEqual(rect[2], 200)
     self.assertEqual(rect[3], 250)
     self.assertRaises(IndexError, rect.__getitem__, 4)
Ejemplo n.º 4
0
    def get_suggested_focal_point(self):
        with self.get_willow_image() as willow:
            faces = willow.detect_faces()

            if faces:
                # Create a bounding box around all faces
                left = min(face[0] for face in faces)
                top = min(face[1] for face in faces)
                right = max(face[2] for face in faces)
                bottom = max(face[3] for face in faces)
                focal_point = Rect(left, top, right, bottom)
            else:
                features = willow.detect_features()
                if features:
                    # Create a bounding box around all features
                    left = min(feature[0] for feature in features)
                    top = min(feature[1] for feature in features)
                    right = max(feature[0] for feature in features)
                    bottom = max(feature[1] for feature in features)
                    focal_point = Rect(left, top, right, bottom)
                else:
                    return None

        # Add 20% to width and height and give it a minimum size
        x, y = focal_point.centroid
        width, height = focal_point.size

        width *= 1.20
        height *= 1.20

        width = max(width, 100)
        height = max(height, 100)

        return Rect.from_point(x, y, width, height)
Ejemplo n.º 5
0
 def test_centroid(self):
     rect = Rect(100, 150, 200, 350)
     self.assertIsInstance(rect.centroid, Vector)
     self.assertEqual(rect.centroid, (150, 250))
     self.assertEqual(rect.x, 150)
     self.assertEqual(rect.y, 250)
     self.assertEqual(rect.centroid_x, 150)
     self.assertEqual(rect.centroid_y, 250)
Ejemplo n.º 6
0
 def get_focal_point(self):
     if (
         self.focal_point_x is not None
         and self.focal_point_y is not None
         and self.focal_point_width is not None
         and self.focal_point_height is not None
     ):
         return Rect.from_point(
             self.focal_point_x, self.focal_point_y, self.focal_point_width, self.focal_point_height
         )
Ejemplo n.º 7
0
 def get_focal_point(self):
     if self.focal_point_x is not None and \
        self.focal_point_y is not None and \
        self.focal_point_width is not None and \
        self.focal_point_height is not None:
         return Rect.from_point(
             self.focal_point_x,
             self.focal_point_y,
             self.focal_point_width,
             self.focal_point_height,
         )
Ejemplo n.º 8
0
    def test_fill_filter_with_focal_point(self):
        image = Image.objects.create(
            title="Test image",
            file=get_test_image_file(filename='test_rf3.png'),
        )
        image.set_focal_point(Rect(100, 100, 200, 200))
        image.save()

        rendition = image.get_rendition('fill-100x100')

        self.assertEqual(rendition.file.name, 'images/test_rf3.15ee4958.fill-100x100.png')
Ejemplo n.º 9
0
    def test_filter_with_pipe_gets_dotted(self):
        image = Image.objects.create(
            title="Test image",
            file=get_test_image_file(filename='test_rf4.png'),
        )
        image.set_focal_point(Rect(100, 100, 200, 200))
        image.save()

        rendition = image.get_rendition('fill-200x200|height-150')

        self.assertEqual(rendition.file.name, 'images/test_rf4.15ee4958.fill-200x200.height-150.png')
Ejemplo n.º 10
0
    def test_get_focal_point(self):
        self.assertEqual(self.image.get_focal_point(), None)

        # Add a focal point to the image
        self.image.focal_point_x = 100
        self.image.focal_point_y = 200
        self.image.focal_point_width = 50
        self.image.focal_point_height = 20

        # Get it
        self.assertEqual(self.image.get_focal_point(), Rect(75, 190, 125, 210))
Ejemplo n.º 11
0
    def get_suggested_focal_point(self, backend_name='default'):
        backend = get_image_backend(backend_name)
        image_file = self.file.file

        # Make sure image is open and seeked to the beginning
        image_file.open('rb')
        image_file.seek(0)

        # Load the image
        image = backend.open_image(self.file.file)
        image_data = backend.image_data_as_rgb(image)

        # Make sure we have image data
        # If the image is animated, image_data_as_rgb will return None
        if image_data is None:
            return

        # Use feature detection to find a focal point
        feature_detector = FeatureDetector(image.size, image_data[0], image_data[1])

        faces = feature_detector.detect_faces()
        if faces:
            # Create a bounding box around all faces
            left = min(face.left for face in faces)
            top = min(face.top for face in faces)
            right = max(face.right for face in faces)
            bottom = max(face.bottom for face in faces)
            focal_point = Rect(left, top, right, bottom)
        else:
            features = feature_detector.detect_features()
            if features:
                # Create a bounding box around all features
                left = min(feature[0] for feature in features)
                top = min(feature[1] for feature in features)
                right = max(feature[0] for feature in features)
                bottom = max(feature[1] for feature in features)
                focal_point = Rect(left, top, right, bottom)
            else:
                return None

        # Add 20% to width and height and give it a minimum size
        x, y = focal_point.centroid
        width, height = focal_point.size

        width *= 1.20
        height *= 1.20

        width = max(width, 100)
        height = max(height, 100)

        return Rect.from_point(x, y, width, height)
Ejemplo n.º 12
0
    def test_set_focal_point(self):
        self.assertEqual(self.image.focal_point_x, None)
        self.assertEqual(self.image.focal_point_y, None)
        self.assertEqual(self.image.focal_point_width, None)
        self.assertEqual(self.image.focal_point_height, None)

        self.image.set_focal_point(Rect(100, 150, 200, 350))

        self.assertEqual(self.image.focal_point_x, 150)
        self.assertEqual(self.image.focal_point_y, 250)
        self.assertEqual(self.image.focal_point_width, 100)
        self.assertEqual(self.image.focal_point_height, 200)

        self.image.set_focal_point(None)

        self.assertEqual(self.image.focal_point_x, None)
        self.assertEqual(self.image.focal_point_y, None)
        self.assertEqual(self.image.focal_point_width, None)
        self.assertEqual(self.image.focal_point_height, None)
Ejemplo n.º 13
0
    def detect_faces(self):
        if opencv_available:
            cascade_filename = os.path.join(os.path.dirname(__file__), 'face_detection', 'haarcascade_frontalface_alt2.xml')
            cascade = cv.Load(cascade_filename)
            image = self.opencv_grey_image()

            cv.EqualizeHist(image, image)

            min_size = (40, 40)
            haar_scale = 1.1
            min_neighbors = 3
            haar_flags = 0

            faces = cv.HaarDetectObjects(
                image, cascade, cv.CreateMemStorage(0),
                haar_scale, min_neighbors, haar_flags, min_size
            )

            if faces:
                return [Rect(face[0][0], face[0][1], face[0][0] + face[0][2], face[0][1] + face[0][3]) for face in faces]

        return []
Ejemplo n.º 14
0
 def test_set_centroid_with_vector(self):
     rect = Rect(100, 150, 200, 350)
     rect.centroid = Vector(500, 500)
     self.assertEqual(rect, (450, 400, 550, 600))
Ejemplo n.º 15
0
 def test_as_tuple(self):
     rect = Rect(100, 150, 200, 250)
     self.assertEqual(rect.as_tuple(), (100, 150, 200, 250))
Ejemplo n.º 16
0
 def test_set_size_with_vector(self):
     rect = Rect(100, 150, 200, 350)
     rect.size = Vector(200, 400)
     self.assertEqual(rect, (50, 50, 250, 450))
Ejemplo n.º 17
0
 def test_repr(self):
     rect = Rect(100, 150, 200, 250)
     self.assertEqual(repr(rect),
                      "Rect(left: 100, top: 150, right: 200, bottom: 250)")
Ejemplo n.º 18
0
 def test_from_point(self):
     rect = Rect.from_point(100, 200, 50, 20)
     self.assertEqual(rect, Rect(75, 190, 125, 210))
Ejemplo n.º 19
0
 def test_get_key(self):
     rect = Rect(100, 150, 200, 250)
     self.assertEqual(rect.get_key(), '150-200-100x100')
Ejemplo n.º 20
0
 def test_set_centroid_with_vector(self):
     rect = Rect(100, 150, 200, 350)
     rect.centroid = Vector(500, 500)
     self.assertEqual(rect, (450, 400, 550, 600))
Ejemplo n.º 21
0
 def test_size(self):
     rect = Rect(100, 150, 200, 350)
     self.assertIsInstance(rect.size, Vector)
     self.assertEqual(rect.size, (100, 200))
     self.assertEqual(rect.width, 100)
     self.assertEqual(rect.height, 200)
Ejemplo n.º 22
0
 def test_set_size_with_vector(self):
     rect = Rect(100, 150, 200, 350)
     rect.size = Vector(200, 400)
     self.assertEqual(rect, (50, 50, 250, 450))
Ejemplo n.º 23
0
 def test_centroid(self):
     rect = Rect(100, 150, 200, 350)
     self.assertEqual(rect.centroid, (150, 250))
     self.assertEqual(rect.centroid_x, 150)
     self.assertEqual(rect.centroid_y, 250)
Ejemplo n.º 24
0
    def run(self, willow, image):
        image_width, image_height = willow.get_size()
        focal_point = image.get_focal_point()

        # Get crop aspect ratio
        crop_aspect_ratio = self.width / self.height

        # Get crop max
        crop_max_scale = min(image_width, image_height * crop_aspect_ratio)
        crop_max_width = crop_max_scale
        crop_max_height = crop_max_scale / crop_aspect_ratio

        # Initialise crop width and height to max
        crop_width = crop_max_width
        crop_height = crop_max_height

        # Use crop closeness to zoom in
        if focal_point is not None:
            # Get crop min
            crop_min_scale = max(focal_point.width,
                                 focal_point.height * crop_aspect_ratio)
            crop_min_width = crop_min_scale
            crop_min_height = crop_min_scale / crop_aspect_ratio

            # Sometimes, the focal point may be bigger than the image...
            if not crop_min_scale >= crop_max_scale:
                # Calculate max crop closeness to prevent upscaling
                max_crop_closeness = max(
                    1 - (self.width - crop_min_width) /
                    (crop_max_width - crop_min_width),
                    1 - (self.height - crop_min_height) /
                    (crop_max_height - crop_min_height))

                # Apply max crop closeness
                crop_closeness = min(self.crop_closeness, max_crop_closeness)

                if 1 >= crop_closeness >= 0:
                    # Get crop width and height
                    crop_width = crop_max_width + (
                        crop_min_width - crop_max_width) * crop_closeness
                    crop_height = crop_max_height + (
                        crop_min_height - crop_max_height) * crop_closeness

        # Find focal point UV
        if focal_point is not None:
            fp_x, fp_y = focal_point.centroid
        else:
            # Fall back to positioning in the centre
            fp_x = image_width / 2
            fp_y = image_height / 2

        fp_u = fp_x / image_width
        fp_v = fp_y / image_height

        # Position crop box based on focal point UV
        crop_x = fp_x - (fp_u - 0.5) * crop_width
        crop_y = fp_y - (fp_v - 0.5) * crop_height

        # Convert crop box into rect
        rect = Rect.from_point(crop_x, crop_y, crop_width, crop_height)

        # Make sure the entire focal point is in the crop box
        if focal_point is not None:
            rect = rect.move_to_cover(focal_point)

        # Don't allow the crop box to go over the image boundary
        rect = rect.move_to_clamp(Rect(0, 0, image_width, image_height))

        # Crop!
        willow.crop(rect.round())

        # Get scale for resizing
        # The scale should be the same for both the horizontal and
        # vertical axes
        aftercrop_width, aftercrop_height = willow.get_size()
        scale = self.width / aftercrop_width

        # Only resize if the image is too big
        if scale < 1.0:
            # Resize!
            willow.resize((self.width, self.height))
Ejemplo n.º 25
0
 def test_from_point(self):
     rect = Rect.from_point(100, 200, 50, 20)
     self.assertEqual(rect, Rect(75, 190, 125, 210))
Ejemplo n.º 26
0
 def test_init(self):
     rect = Rect(100, 150, 200, 250)
     self.assertEqual(rect.left, 100)
     self.assertEqual(rect.top, 150)
     self.assertEqual(rect.right, 200)
     self.assertEqual(rect.bottom, 250)
Ejemplo n.º 27
0
 def test_get_rect(self):
     self.assertTrue(self.image.get_rect(), Rect(0, 0, 640, 480))
Ejemplo n.º 28
0
 def get_rect(self):
     return Rect(0, 0, self.width, self.height)
Ejemplo n.º 29
0
 def test_as_tuple(self):
     rect = Rect(100, 150, 200, 250)
     self.assertEqual(rect.as_tuple(), (100, 150, 200, 250))
Ejemplo n.º 30
0
 def test_equality(self):
     self.assertEqual(Rect(100, 150, 200, 250), Rect(100, 150, 200, 250))
     self.assertNotEqual(Rect(100, 150, 200, 250), Rect(10, 15, 20, 25))
Ejemplo n.º 31
0
    def resize_to_fill(self, image, arg, focal_point=None):
        """
        Resize down and crop image to fill the given dimensions. Most suitable for thumbnails.
        (The final image will match the requested size, unless one or the other dimension is
        already smaller than the target size)
        """
        size = arg[:2]

        # Get crop closeness if it's set
        if len(arg) > 2 and arg[2] is not None:
            crop_closeness = arg[2] / 100

            # Clamp it
            if crop_closeness > 1:
                crop_closeness = 1
        else:
            crop_closeness = 0

        # Get image width and height
        (im_width, im_height) = image.size

        # Get filter width and height
        fl_width = size[0]
        fl_height = size[1]

        # Get crop aspect ratio
        crop_aspect_ratio = fl_width / fl_height

        # Get crop max
        crop_max_scale = min(im_width, im_height * crop_aspect_ratio)
        crop_max_width = crop_max_scale
        crop_max_height = crop_max_scale / crop_aspect_ratio

        # Initialise crop width and height to max
        crop_width = crop_max_width
        crop_height = crop_max_height

        # Use crop closeness to zoom in
        if focal_point is not None:
            fp_width = focal_point.width
            fp_height = focal_point.height

            # Get crop min
            crop_min_scale = max(fp_width, fp_height * crop_aspect_ratio)
            crop_min_width = crop_min_scale
            crop_min_height = crop_min_scale / crop_aspect_ratio

            # Sometimes, the focal point may be bigger than the image...
            if not crop_min_scale >= crop_max_scale:
                # Calculate max crop closeness to prevent upscaling
                max_crop_closeness = max(
                    1 - (fl_width - crop_min_width) / (crop_max_width - crop_min_width),
                    1 - (fl_height - crop_min_height) / (crop_max_height - crop_min_height)
                )

                # Apply max crop closeness
                crop_closeness = min(crop_closeness, max_crop_closeness)

                if 1 >= crop_closeness >= 0:
                    # Get crop width and height
                    crop_width = crop_max_width + (crop_min_width - crop_max_width) * crop_closeness
                    crop_height = crop_max_height + (crop_min_height - crop_max_height) * crop_closeness

        # Find focal point UV
        if focal_point is not None:
            fp_x, fp_y = focal_point.centroid
        else:
            # Fall back to positioning in the centre
            fp_x = im_width / 2
            fp_y = im_height / 2

        fp_u = fp_x / im_width
        fp_v = fp_y / im_height

        # Position crop box based on focal point UV
        crop_x = fp_x - (fp_u - 0.5) * crop_width
        crop_y = fp_y - (fp_v - 0.5) * crop_height

        # Convert crop box into rect
        left = crop_x - crop_width / 2
        top = crop_y - crop_height / 2
        right = crop_x + crop_width / 2
        bottom = crop_y + crop_height / 2

        # Make sure the entire focal point is in the crop box
        if focal_point is not None:
            focal_point_left = focal_point.left
            focal_point_top = focal_point.top
            focal_point_right = focal_point.right
            focal_point_bottom = focal_point.bottom

            if left > focal_point_left:
                right -= left - focal_point_left
                left = focal_point_left

            if top > focal_point_top:
                bottom -= top - focal_point_top
                top = focal_point_top

            if right < focal_point_right:
                left += focal_point_right - right
                right = focal_point_right

            if bottom < focal_point_bottom:
                top += focal_point_bottom - bottom
                bottom = focal_point_bottom

        # Don't allow the crop box to go over the image boundary
        if left < 0:
            right -= left
            left = 0

        if top < 0:
            bottom -= top
            top = 0

        if right > im_width:
            left -= right - im_width
            right = im_width

        if bottom > im_height:
            top -= bottom - im_height
            bottom = im_height

        # Crop!
        return self.resize_to_min(self.crop(image, Rect(left, top, right, bottom)), size)
Ejemplo n.º 32
0
    def run(self, willow, image):
        image_width, image_height = willow.get_size()
        focal_point = image.get_focal_point()

        # Get crop aspect ratio
        crop_aspect_ratio = self.width / self.height

        # Get crop max
        crop_max_scale = min(image_width, image_height * crop_aspect_ratio)
        crop_max_width = crop_max_scale
        crop_max_height = crop_max_scale / crop_aspect_ratio

        # Initialise crop width and height to max
        crop_width = crop_max_width
        crop_height = crop_max_height

        # Use crop closeness to zoom in
        if focal_point is not None:
            # Get crop min
            crop_min_scale = max(focal_point.width, focal_point.height * crop_aspect_ratio)
            crop_min_width = crop_min_scale
            crop_min_height = crop_min_scale / crop_aspect_ratio

            # Sometimes, the focal point may be bigger than the image...
            if not crop_min_scale >= crop_max_scale:
                # Calculate max crop closeness to prevent upscaling
                max_crop_closeness = max(
                    1 - (self.width - crop_min_width) / (crop_max_width - crop_min_width),
                    1 - (self.height - crop_min_height) / (crop_max_height - crop_min_height)
                )

                # Apply max crop closeness
                crop_closeness = min(self.crop_closeness, max_crop_closeness)

                if 1 >= crop_closeness >= 0:
                    # Get crop width and height
                    crop_width = crop_max_width + (crop_min_width - crop_max_width) * crop_closeness
                    crop_height = crop_max_height + (crop_min_height - crop_max_height) * crop_closeness

        # Find focal point UV
        if focal_point is not None:
            fp_x, fp_y = focal_point.centroid
        else:
            # Fall back to positioning in the centre
            fp_x = image_width / 2
            fp_y = image_height / 2

        fp_u = fp_x / image_width
        fp_v = fp_y / image_height

        # Position crop box based on focal point UV
        crop_x = fp_x - (fp_u - 0.5) * crop_width
        crop_y = fp_y - (fp_v - 0.5) * crop_height

        # Convert crop box into rect
        rect = Rect.from_point(crop_x, crop_y, crop_width, crop_height)

        # Make sure the entire focal point is in the crop box
        if focal_point is not None:
            rect = rect.move_to_cover(focal_point)

        # Don't allow the crop box to go over the image boundary
        rect = rect.move_to_clamp(Rect(0, 0, image_width, image_height))

        # Crop!
        willow = willow.crop(rect.round())

        # Get scale for resizing
        # The scale should be the same for both the horizontal and
        # vertical axes
        aftercrop_width, aftercrop_height = willow.get_size()
        scale = self.width / aftercrop_width

        # Only resize if the image is too big
        if scale < 1.0:
            # Resize!
            willow = willow.resize((self.width, self.height))

        return willow
Ejemplo n.º 33
0
 def test_get_key(self):
     rect = Rect(100, 150, 200, 250)
     self.assertEqual(rect.get_key(), "150-200-100x100")