Issue
My question is simple yet I haven't found any solution on Google, all the answers are for adding padding which in my case I don't want...
It's basically resizing images the WordPress way (resize and crop intelligently)... for square aspect ratio without pad... please help and thank you in advance.
Here is the image input example:
And here is the result I want for example (150x150 or any square size):
This is what I have so far tried:
import cv2
import numpy as np
from os import listdir
from os.path import isfile, join
from pathlib import Path
import argparse
import numpy
mypath = 'images'
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
images = numpy.empty(len(onlyfiles), dtype=object)
for n in range(0, len(onlyfiles)):
path = join(mypath, onlyfiles[n])
images[n] = cv2.imread(join(mypath, onlyfiles[n]),
cv2.IMREAD_UNCHANGED)
try:
img = cv2.imread(path, 1)
resized_dimensions = (400, 400)
resized_image = cv2.resize(img, resized_dimensions, interpolation=cv2.INTER_AREA)
if not cv2.imwrite('output/' +str(n)+ '.jpg', resized_image):
raise Exception("Could not write image")
except Exception as e:
print(str(e))
print("Images resized Successfully")
The code works but the images are distorted...
Solution
This answer assumes you are able to use Pillow (since I can't comment to ask), which makes this so much more simple.
Pillows Image.resize
function allows you to pass in a box that you want the resized image to come from, which is exactly what you are looking for.
From the docs:
Image.resize(size, resample=None, box=None, reducing_gap=None)[source]¶ Returns a resized copy of this image.Parameters
size – The requested size in pixels, as a 2-tuple: (width, height).
box – An optional 4-tuple of floats providing the source image region to be scaled. The values must be within (0, 0, width, height) rectangle. If omitted or None, the entire source is used.
Here's my solution
from PIL import Image
def smart_resize(input_image, new_size):
width = input_image.width
height = input_image.height
# Image is portrait or square
if height >= width:
crop_box = (0, (height-width)//2, width, (height-width)//2 + width)
return input_image.resize(size = (new_size,new_size),
box = crop_box)
# Image is landscape
if width > height:
crop_box = ((width-height)//2, 0, (width-height)//2 + height, height)
return input_image.resize(size = (new_size,new_size),
box = crop_box)
Here's how it works, and since a picture is worth a thousand words, here's a picture of what it does:
It checks for portrait or landscape because in portrait, the crop area fills the width and is offset from the height; vice versa in landscape. You could probably do it in one statement with clever min
and max
statements if you really wanted.
Answered By - Lone Survivr
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.