且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在给定目标大小的情况下,如何在python中调整图像大小的同时保持宽高比?

更新时间:2023-01-02 13:28:04

这是我的方法,

aspectRatio = currentWidth / currentHeight
heigth * width = area

所以

height * (height * aspectRatio) = area
height² = area / aspectRatio
height = sqrt(area / aspectRatio)

到那时,我们知道目标高度和width = height * aspectRatio.

例如:

area = 100 000
height = sqrt(100 000 / (700/979)) = 373.974
width = 373.974 * (700/979) = 267.397

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