如何计算容纳完整旋转图像所需的输出零矩阵尺寸?
解决图像旋转后的截断问题:计算外接框尺寸
要解决旋转后图像被截断的问题,核心是通过数学计算确定能容纳完整旋转图像的最小外接矩形尺寸,再基于这个尺寸创建输出矩阵,同时调整坐标映射逻辑确保图像居中显示。
一、外接框尺寸的数学推导
假设原图像高度为h、宽度为w,旋转角度为θ(转换为弧度制):
- 旋转变换依赖三角函数,取
cosθ和sinθ的绝对值(正负旋转角度对外接框尺寸无影响)。 - 旋转后外接框的宽度和高度公式:
该公式本质是计算原图像四个顶点旋转后,在x轴和y轴上的最大跨度,确保所有旋转后的像素都能被容纳。最后将计算结果取整,得到整数尺寸的图像矩阵。new_w = w * |cosθ| + h * |sinθ| new_h = h * |cosθ| + w * |sinθ|
二、修改后的旋转函数代码
以下是完整的rotate_image函数实现,包含新尺寸计算和坐标映射逻辑:
import numpy as np def rotate_image(image, angle_deg): h, w = image.shape[:2] # 将角度从度转换为弧度 angle_rad = np.radians(angle_deg) cos_theta = np.abs(np.cos(angle_rad)) sin_theta = np.abs(np.sin(angle_rad)) # 计算能容纳完整旋转图像的新尺寸,取整确保为整数像素 new_w = int(np.round(w * cos_theta + h * sin_theta)) new_h = int(np.round(h * cos_theta + w * sin_theta)) # 创建对应尺寸的输出矩阵 rotated = np.zeros((new_h, new_w, 3), dtype=np.uint8) # 计算原图像和新图像的中心坐标 orig_center = (w // 2, h // 2) new_center = (new_w // 2, new_h // 2) # 反向映射:遍历新图像的每个像素,找到原图像中对应的位置 for y_new in range(new_h): for x_new in range(new_w): # 将新图像坐标转换为以新中心为原点的相对坐标 x_rel = x_new - new_center[0] y_rel = y_new - new_center[1] # 逆旋转得到原图像中以原中心为原点的相对坐标 x_orig_rel = x_rel * cos_theta + y_rel * sin_theta y_orig_rel = -x_rel * sin_theta + y_rel * cos_theta # 转换为原图像的实际像素坐标并取整 x_orig = int(np.round(x_orig_rel + orig_center[0])) y_orig = int(np.round(y_orig_rel + orig_center[1])) # 检查坐标是否在原图像范围内,有效则赋值 if 0 <= x_orig < w and 0 <= y_orig < h: rotated[y_new, x_new] = image[y_orig, x_orig] return rotated
三、关键细节说明
- 反向映射的优势:遍历新图像像素找原图像对应位置,相比正向映射(遍历原图像像素放到新位置),能避免出现像素空洞,确保所有有效像素都被准确映射。
- 中心对齐:通过将原图像和新图像的中心作为旋转基准,旋转后的图像会居中显示,不会偏移到输出矩阵的角落。
- 取整处理:使用
np.round对坐标取整,减少因浮点运算导致的像素错位问题。
内容的提问来源于stack exchange,提问作者HiRelax
相关产品推荐
相关产品推荐

