python - 调整图像大小,使其大小与指定的宽高比匹配

标签 python opencv math image-processing python-imaging-library

我正在解决一个问题,需要将图像大小调整为特定的宽高比。我想不出任何解决办法。我正在共享一个示例图像以及来自 Pixelz 的处理图像。 例如,输入图像尺寸为 1833 x 2133,它会调整为 1623 x 2164,即 3:4 的比例。输出图像尺寸不固定,可以是任何最接近的尺寸,比例为 3:4。

也许我们可以通过查找比例为 3:4 的最接近的数字对来解决这个问题。

enter image description here

最佳答案

裁剪

首先,您需要确定图像对于所需的比例是否太宽或太高。

然后调整相应的尺寸。

我不知道你正在使用哪个Python图像处理库,所以我的答案只包含计算新宽度和高度的算术代码,而不是转换图像的实际代码。

def cropped_dims(width, height, ratio):
    if width > height*ratio:
        width = int(height*ratio + 0.5)
    else:
        height = int(width/ratio + 0.5)
    return (width, height)

print(cropped_dims(1833, 2133, 3/4))
# (1600, 2133)

最接近的数字对

在您给出的示例中,1833 x 2133 的大小调整为 1623 x 2164,而不是 1600 x 2133。您提到寻找具有适当比例的“最近的数字对”,而不是裁剪到适当的比例。

使用笛卡尔坐标,数字对可以表示为平面上的点。

在此表示下,具有适当比率的数字对恰好是斜率为该比率的直线上的点(除了没有比率的点 (0,0) 之外)。

图像的原始尺寸也是一个数对,这个数对用平面上的一个点来表示;先验,这一点不就行了。

您正在寻找的解决方案是直线上最近的点。这是一个非常经典的几何问题,有一个简单的解决方案。有关如何解决此问题的说明,请参阅以下问题:Point on a line closest to third point .

线 L 包含比率 ratio 的点由 (ratio * t, t) 形式的点组成对于一些实数 t .

线 L 的垂线 D 穿过 (width, height)(width+s, height - ratio * s) 形式的点组成对于一些实数 s .

距离(width, height)最近的点L 线上的点是 L 和 D 的交点。通过求解未知数可以找到它的坐标 (s,t)方程组(ratio * t, t) == (width+s, height - ratio * s) .

解决方案是t = (ratio * width + height) / (1 + ratio**2) .

因此Python代码:

def resized_dims(width, height, ratio):
   t = (height + ratio * width) / (ratio**2 + 1)
   new_width = int(t*ratio + 0.5)
   new_height = int(t + 0.5)
   return new_width, new_height

print(resized_dims(1833, 2133, 3/4))
# (1684, 2245)

比较不同的解决方案:

import math

w, h = (1833, 2133)
cropped_w, cropped_h = cropped_dims(1833, 2133, 3/4) # (1600, 2133)
closest_w, closest_h = resized_dims(1833, 2133, 3/4) # (1684, 2245)
your_w, your_h = (1623, 2164)

print('Original ratio:           ', w/h)
print('Wanted ratio:             ', 3/4)
print('Ratio of cropped:         ', cropped_w/cropped_h)
print('Ratio of closest:         ', closest_w/closest_h)
print('Ratio of your solution:   ', your_w/your_h)
print()
print('Distance of cropped:      ', math.dist((w,h), (cropped_w,cropped_h)))
print('Distance of closest:      ', math.dist((w,h), (closest_w,closest_h)))
print('Distance of your solution:', math.dist((w,h), (your_w,your_h)))

# Original ratio:            0.8594
# Wanted ratio:              0.75
# Ratio of cropped:          0.7501
# Ratio of closest:          0.7501
# Ratio of your solution:    0.75
# 
# Distance of cropped:       233.0
# Distance of closest:       186.40
# Distance of your solution: 212.28

关于python - 调整图像大小,使其大小与指定的宽高比匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69913172/

相关文章:

python - Aruco 标记世界坐标

javascript - 具有相等值的数组的 Math.max 方法

c - 我怎样才能得到这个数学表达式的结果?

python - 更改 __new__ 中的参数不会传递到 __init__

python - 在 PyQT 应用程序的主线程中使用回调方法在 Python 中启动一个新线程

python - 详尽的 SQL 查询,count(*) 限制器不起作用

c++ - 定位涉及线和圆相交的小部件?

python - 找不到静态文件 (gunicorn)

opencv - 寻找手部图像中的谷点

python - 在python-OpenCV中确定相机和人/脸之间的距离