Python 剪切具有相同纵横比的旋转图像
当输入图像旋转给定角度,然后进行裁剪以避免任何非图像区域,同时保持原始图像纵横比时,如何确定最终图像的宽度和高度 例如: 定义:Python 剪切具有相同纵横比的旋转图像,python,image-processing,rotation,crop,Python,Image Processing,Rotation,Crop,当输入图像旋转给定角度,然后进行裁剪以避免任何非图像区域,同时保持原始图像纵横比时,如何确定最终图像的宽度和高度 例如: 定义: W0和H0是原始矩形的宽度和高度 D0是原始矩形的对角线(斜边) W1和H1是旋转矩形的填充宽度和高度 W2和H2是目标矩形的宽度和高度 D2是目标矩形的对角线(斜边) E是复杂的、瞬时的 您可能需要预计算sin(A)、cos(A)和tan(A),因为它们被反复使用 计算W1和H1: 它们由两个组件组成,两个三角形边组成每个长度 W1=W0*co
- W0和H0是原始矩形的宽度和高度
- D0是原始矩形的对角线(斜边)
- W1和H1是旋转矩形的填充宽度和高度
- W2和H2是目标矩形的宽度和高度
- D2是目标矩形的对角线(斜边)
- E是复杂的、瞬时的
- 您可能需要预计算sin(A)、cos(A)和tan(A),因为它们被反复使用
- W1=W0*cos(A)+H0*sin(A)
- H1=H0*cos(A)+W0*sin(A)
- E=W0/(1+tan(A)/W0*H0)
- W2=E/tan(A)
- H2=W2/W0*H0
编辑:根据请求,我对E的意思做出了最好的猜测:
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
vsb
,使用纵横比和sin/cos来计算。取消了条款,提高了声音,这就是我的结局。
- 红色矩形是具有原始纵横比的原始图像
旋转矩形(由绿色和黄色三角形包围) 图像宽高比,带W/t
extend=True
w
和h
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
image=image.open(…)
旋转=图像。旋转(度,image.BICUBIC,真)
纵横比=浮点(image.size[0])/image.size[1]
旋转的纵横比=浮动(旋转的.size[0])/rotated.size[1]
角度=math.fabs(度)*math.pi/180
如果纵横比<1:
总高度=浮动(图像大小[0])/旋转的纵横比
其他:
总高度=浮动(image.size[1])
h=总高度/(纵横比*数学sin(角度)+数学cos(角度))
w=h*纵横比
现在,旋转后的图像可以在中心用w
xh
尺寸裁剪到
获取最终图像。此代码返回此块的坐标 我导入PIL仅用于获取图像真实大小。
您不能导入PIL,相反,您可以通过任何其他方式获取图像大小。这是一个很好的问题,我也不介意知道答案,但这是否更适合数学堆栈交换?也许。我想也许有人知道这里发布的Python PIL中的一个技巧。祝你好运。我在努力…我实际上刚刚想出了怎么做。结果很简单。现在写解决方案。哦,感谢上帝。当我意识到我的方程依赖于知道一个变量时,我正准备弃船!如果
纵横比=a=w/h
那么它不是w=a/h
不是w=h*a
吗?你将两边乘以h,因此ha=hw/h,但h/h是1,所以被取消。在代码中发现一个错误:你需要取正弦和余弦的绝对值,否则它会因旋转>90°而中断。什么是E?可能是维基链接,没有链接。我自己推导了这个,E是我需要的一个维度。我会用图片更新帖子。它和你的大不相同!也许我错过了一些琐碎的东西,但我仍然没有理解什么是e。也许晚上我会再试一次。-1:这不可能是正确的:除以tan(alpha)。tan(ε)=ε。根据你的公式,微小的旋转会导致你除以一个微小的数字,从而导致完全错误的宽度。
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
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