裁剪具有相同宽高比的旋转图像

时间:2014-01-25 04:34:14

标签: python image-processing rotation crop

当输入图像旋转给定的度数时,如何找出最终图像的宽度和高度,然后裁剪以避免任何非图像区域,同时保持原始图像宽高比。

例如: example

3 个答案:

答案 0 :(得分:6)

enter image description here

  • 红色矩形是原始宽高比的原始图像。
  • W/t矩形(由绿色和黄色三角形包围)旋转 图像宽高比为extend=True

以下是获取wh

的方法
image = Image.open(...)
rotated = image.rotate(degrees, Image.BICUBIC, True)

aspect_ratio = float(image.size[0]) / image.size[1]
rotated_aspect_ratio = float(rotated.size[0]) / rotated.size[1]
angle = math.fabs(degrees) * math.pi / 180

if aspect_ratio < 1:
    total_height = float(image.size[0]) / rotated_aspect_ratio
else:
    total_height = float(image.size[1])

h = total_height / (aspect_ratio * math.sin(angle) + math.cos(angle))
w = h * aspect_ratio

现在可以在w x h尺寸的中心裁剪旋转的图像 得到最终的图像。

答案 1 :(得分:1)

enter image description here

说明:

  • W 0 且H 0 是原始矩形的宽度和高度
  • D 0 是原始矩形的对角线(斜边)
  • W 1 且H 1 是旋转矩形的填充宽度和高度
  • W 2 和H 2 是目标矩形的宽度和高度
  • D 2 是目标矩形的对角线(斜边)
  • E是复杂而短暂的

  • 您可能希望重复使用sin(A),cos(A)和tan(A)预先计算

计算W 1 和H 1

它们由两个组成部分组成,即构成每个长度的两个三角形边

  • W 1 = W 0 * cos(A)+ H 0 * sin(A)
  • H 1 = H 0 * cos(A)+ W 0 * sin(A)

计算W 2 和H 2

  • E = W 0 /(1 + tan(A)/ W 0 * H 0
  • W 2 = E / tan(A)
  • H 2 = W 2 / W 0 * H 0

正如Python:

W0 = # original rectangle width
H0 = # original rectangle height
cosA = cos(A)
sinA = sin(A)
tanA = tan(A)
W1 = W0 * cosA + H0 * sinA
H1 = H0 * cosA + W0 * sinA
E = W0 / (1 + tanA / W0 * H0)
W2 = E / tanA       # requested width
H2 = W2 / W0 * H0   # requested height

免责声明:这都是未经测试的


编辑:根据要求,我最好猜测我的意思是:

r0 = w2/h2
h2 = (w0-e1) / sin(A)
h2 = e1/ cos(A) / r0
(w0-e1) / sin(A) = e1/ cos(A) / r0
x = cos(A) / sin(A)
e1 = w0 * x / (1/r0 + x)

E是w2的水平分量,通过a + b线延伸。然后是关于计算a vs b的内容,使用纵横比和sin / cos来计算出来。条款被取消,声音被提出,这就是我最终的结果。

答案 2 :(得分:0)

此代码返回此块的坐标

returned box - is the coords of this block

from PIL import Image
def cropp_rotated(image, degrees):
    x, y = image.size
    cosA = abs(math.cos(math.radians(degrees)))
    sinA = abs(math.sin(math.radians(degrees)))

    a = x * cosA 
    b = x * sinA

    relation = a / (a + b)
    right_indent1 = a - x * relation * cosA

    relation = b / (a + b)
    bottom_ident1 = b - x * relation *sinA


    c = y * cosA 
    d = y * sinA

    relation = c / (c + d)
    right_indent2 = c - y * relation * cosA

    relation = d / (c + d)
    bottom_ident2 = d - y * relation *sinA

    right_indent = max(right_indent1, right_indent2)
    top_indent = max(bottom_ident1, bottom_ident2)

    #size of rotated image:
    w_rotated = x * cosA + y * sinA
    h_rotated = y * cosA + x * sinA


    box = (
    int(right_indent), 
    int(top_indent), 
    int(w_rotated - right_indent), 
    int(h_rotated - top_indent))

    return box

我只导入PIL以获取实际尺寸的图像。 您无法导入PIL,而是可以通过任何其他方式获取图像大小。