Home > Enterprise >  Resize image to use as a blurred background but with a zoom aspect in relation to the original image
Resize image to use as a blurred background but with a zoom aspect in relation to the original image

Time:06-27

The original image is this:

enter image description here

Using this enter image description here

The final result that I am trying to reproduce (the only difference is that I'm going to add a readjustment to the image that is on top, have 1080 width too) here is this:

enter image description here

It is clear that there is a zoom effect in the blurred image, so when I use resize to keep the aspect ratio and the highest quality possible, I use im = im.resize((1080,1080), resample=Image.Resampling.LANCZOS), but as I don't want that, I removed resample=Image.Resampling.LANCZOS imagining that the image would be generated without proportion generating a zoom:

from PIL import Image, ImageFilter, ImageChops
import numpy
import cv2

def remove_border(file_img):
    im = Image.open(file_img)
    bg = Image.new("RGB", im.size, im.getpixel((0,0)))
    diff = ImageChops.difference(im.convert("RGB"), bg)
    diff = ImageChops.add(diff, diff, 2.0, -30)
    bbox = diff.getbbox()
    if bbox:
        return im.crop(bbox)

def resize_blur(img_blur,sizers):
    img_blur = img_blur.resize(sizers, resample=Image.Resampling.LANCZOS)
    img_blur = img_blur.filter(ImageFilter.GaussianBlur(10))
    return img_blur

def resize_width_main(img_border,size_width):
    img_width = img_border
    basewidth = size_width
    wpercent = (basewidth/float(img_width.size[0]))
    hsize = int((float(img_width.size[1])*float(wpercent)))
    img_width = img_width.resize((basewidth,hsize), Image.Resampling.LANCZOS)
    return img_width

def center_overlay(name_file,overlay,background):
    img = numpy.asarray(overlay)
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    h, w = img.shape[:2]
    back = numpy.asarray(background)
    back = cv2.cvtColor(back, cv2.COLOR_RGB2BGR)
    hh, ww = back.shape[:2]
    yoff = round((hh-h)/2)
    xoff = round((ww-w)/2)
    result = back.copy()
    result[yoff:yoff h, xoff:xoff w] = img
    cv2.imwrite(name_file, result)

def main():
    img_border = remove_border('resized_download.png')
    img_blur = resize_blur(img_border, (1080,1080))
    img_width = resize_width_main(img_border, 1080)
    center_overlay('resized.png', img_width, img_blur)

if __name__ == '__main__':
    main()

But the current result is this:

enter image description here

CodePudding user response:

A few observations.

Your remove_border function isn't doing a lot; when I tried it with your test image, all it did was remove 9 pixels from the left side. Maybe it has a bug. At the risk of ignoring the lesson of Chesterton's Fence I'd say you don't need it and could eliminate it entirely.

Blurring before you resize makes more sense than doing it the other way around.

When you resize a blurred image, you don't need to worry much about the quality of the resampling filter. I wouldn't use NEAREST, but BILINEAR should be perfectly adequate and reasonably fast.

When you resize an image, the old and new size should have the same aspect ratio or you will get distortion. The resample method makes no difference in this. You are resizing a rectangle into a square, resulting in bad distortion. You can crop your original to the desired aspect ratio before you resize, or crop it after you resize. It will be more efficient to crop first.

def resize_to_target(im, target_size, resample=Image.BILINEAR):
    ''' Resize an image to a target size.  If the aspect ratio
        of the original image is different from the target, the
        image will be cropped to the destination aspect ratio
        before resizing.
    '''
    if (im.size[0] / im.size[1]) < (target_size[0] / target_size[1]):
        # if (im.size[0] * target_size[1]) != (target_size[0] * im.size[1]):
        # Existing image is narrower, crop top and bottom
        crop_height = round(im.size[0] * target_size[1] / target_size[0])
        if crop_height < im.size[1]:
            top = (im.size[1] - crop_height) // 2
            bottom = top   crop_height
            im = im.crop((0, top, im.size[0], bottom))
    else:
        # existing image is wider, crop left and right
        crop_width = round(im.size[1] * target_size[0] / target_size[1])
        if crop_width < im.size[0]:
            left = (im.size[0] - crop_width) // 2
            right = left   crop_width
            im = im.crop((left, 0, right, im.size[1]))
    return im.resize(target_size, resample=resample)
  • Related