CakeMaster
CakeMaster

Reputation: 49

How to digitally zoom into an image using python PIL

This is more theory than anything, but let's suppose that I have 2 images of the same object that were taken at different, but known, distances.

image_1, taken at distance_1 (further away, say 2 meters) image_2, taken at distance_2 (closer, say 1 meter)

If I want to digitally 'zoom' into the image_1, is this as simple as cropping distance_2/distance_1 pixels from image_1?

Below is my code trying to attempt a center digital zoom.

from PIL import Image

img = Image.open('example.jpg')
w, h = img.size
x = w // 2
y = h // 2
zoom2 = distance_2/distance_1
img = img.crop((x - w / zoom2, y - h / zoom2, x + w / zoom2, y + h / zoom2))
img.resize((w, h), Image.LANCZOS)

d = img.resize((w,h), resample=Image.BOX)

Main Question: Am I correctly choosing the 'zoom' factor by comparing the relationship of the distances?

Thank you for any help!

Related: PIL zoom into image at a particular point Python upscale image without blur PIL

Upvotes: 0

Views: 54

Answers (2)

CakeMaster
CakeMaster

Reputation: 49

After the helpful advice of the above, here is what I was able to come up with:

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

img = Image.open('level.jpg') #open the image that you want to zoom into
img_save = img
w, h = img.size

distance = 2 # in this case this image will be zoomed in by 10
distance2 = 1

zm=distance/distance2 #should be bigger than 1 to make it work

wn = w // zm # this is the *new size* of the image after being zoomed in
hn = h // zm

widthStart  = (w - wn) // 2
heightStart = (h - hn) // 2
widthEnd    = widthStart + wn
heightEnd   = heightStart + hn

img = img.crop((widthStart, heightStart, widthEnd, heightEnd))
img = img.resize((w, h), Image.LANCZOS)

plt.imshow(np.array(img))
plt.show()
plt.imshow(np.array(img_save))
plt.show()

Upvotes: 0

Onuralp Arslan
Onuralp Arslan

Reputation: 360

img = img.crop((x - w / zoom2, y - h / zoom2, x + w / zoom2, y + h / zoom2))

this part can raise problems since it uses orignal width as a summation (and extraction) causing a possible shift in center

For example if you have 2x zoom to CENTER you need from 1/4 of x to 3/4 of x and same for y if you have 5x zoom to center you want 4/10 of x to 6/10 of x and same for y. ho it works? simply for 5x zoom you get center 2/10 and multiply by 5 makes it 10/10 aka full picture before digital zoom to center.

for talking zm times center zoom so your crop will be targetted on from (zm-1)/zm2 to (zm+1)/zm2 for each axis.

so you can

zm=distance/distance2 #should be bigger than 1 to make it work
startPoint=(zm-1)/zm*2
endPoint=(zm+1)/zm*2

widthStart=Image.w * startPoint
heightStart=Image.h * startPoint
widthEnd=Image.w * endPoint
heightEnd=Image.h * endPoint

img = img.crop((widthStart, heightStart, widthEnd, heightEnd))

Then just upscale your image with the lanczos as you did.

This calculation allows you get center zoom without moving center. And makes sure your zoom calculation works.

Upvotes: 1

Related Questions