By default, the thumbnail
method preserves aspect ratio which may result in inconsistently sized thumbnails.
Image.thumbnail(size, resample=3) Make this image into a thumbnail. This method modifies the image to contain a thumbnail version of itself, no larger than the given size. This method calculates an appropriate thumbnail size to preserve the aspect of the image, calls the draft() method to configure the file reader (where applicable), and finally resizes the image.
I want it to crop the image so that the thumbnail fills the entire canvas provided, such that the image isn't warped. For example, Image.thumbnail((200, 200), Image.ANTIALIAS)
on an image that's 640 by 480 would crop to the center 480 by 480, then scale to exactly 200 by 200 (not 199 or 201). How can this be done?
There is no specific function for cropping using OpenCV, NumPy array slicing is what does the job. Every image that is read in, gets stored in a 2D array (for each color channel). Simply specify the height and width (in pixels) of the area to be cropped. And it's done!
This is easiest to do in two stages: crop first, then generate a thumbnail. Cropping to a given aspect ratio is common enough that there really should be a function for it in PILLOW, but as far as I know there isn't. Here's a simple implementation, monkey-patched onto the Image class:
from PIL import Image
class _Image(Image.Image):
def crop_to_aspect(self, aspect, divisor=1, alignx=0.5, aligny=0.5):
"""Crops an image to a given aspect ratio.
Args:
aspect (float): The desired aspect ratio.
divisor (float): Optional divisor. Allows passing in (w, h) pair as the first two arguments.
alignx (float): Horizontal crop alignment from 0 (left) to 1 (right)
aligny (float): Vertical crop alignment from 0 (left) to 1 (right)
Returns:
Image: The cropped Image object.
"""
if self.width / self.height > aspect / divisor:
newwidth = int(self.height * (aspect / divisor))
newheight = self.height
else:
newwidth = self.width
newheight = int(self.width / (aspect / divisor))
img = self.crop((alignx * (self.width - newwidth),
aligny * (self.height - newheight),
alignx * (self.width - newwidth) + newwidth,
aligny * (self.height - newheight) + newheight))
return img
Image.Image.crop_to_aspect = _Image.crop_to_aspect
Given this, you can just write
cropped = img.crop_to_aspect(200,200)
cropped.thumbnail((200, 200), Image.ANTIALIAS)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With