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)
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, )
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, )
def test_from_point(self): rect = Rect.from_point(100, 200, 50, 20) self.assertEqual(rect, Rect(75, 190, 125, 210))
def run(self, willow, image, env): 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
def run(self, willow, image, env): 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