First off part of me feels like this is a stupid question, sorry about that. Currently the most accurate way I've found of calculating the optimum scaling factor (best width and height for target pixel count while retaining aspect ratio) is iterating through and choosing the best one however there must be a better way of doing this.
An example:
import cv2, numpy as np
img = cv2.imread("arnold.jpg")
img.shape[1] # e.g. width = 700
img.shape[0] # e.g. height = 979
# e.g. Total pixels : 685,300
TARGET_PIXELS = 100000
MAX_FACTOR = 0.9
STEP_FACTOR = 0.001
iter_factor = STEP_FACTOR
results = dict()
while iter_factor < MAX_RATIO:
img2 = cv2.resize(img, (0,0), fx=iter_factor, fy=iter_factor)
results[img2.shape[0]*img2.shape[1]] = iter_factor
iter_factor += step_factor
best_pixels = min(results, key=lambda x:abs(x-TARGET_PIXELS))
best_ratio = results[best_pixels]
print best_pixels # e.g. 99750
print best_ratio # e.g. 0.208
I know there are probably some errors lying around in the code above i.e. there is no check in the results dictionary for an existing key but I am more concerned with a different approach which I cannot figure out was looking into lagrangian optimisation but that seems quite complex also for a simple problem. Any ideas?
** EDIT AFTER ANSWER **
Going to provide the code if anyone is interested in the answer
import math, cv2, numpy as np
# load up an image
img = cv2.imread("arnold.jpg")
TARGET_PIXEL_AREA = 100000.0
ratio = float(img.shape[1]) / float(img.shape[0])
new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
new_w = int((new_h * ratio) + 0.5)
img2 = cv2.resize(img, (new_w,new_h))
Here is my approach,
aspectRatio = currentWidth / currentHeight
heigth * width = area
So,
height * (height * aspectRatio) = area
height² = area / aspectRatio
height = sqrt(area / aspectRatio)
At that point we know the target height, and width = height * aspectRatio
.
Ex:
area = 100 000
height = sqrt(100 000 / (700/979)) = 373.974
width = 373.974 * (700/979) = 267.397
I think the fastest and cleaner way is:
from PIL import Image
from math import sqrt
img=Image.open(PATH)
img.thumbnails([round(sqrt(TARGET_PIXEL_AREA))]*2)
I hope it will help
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