旋转+最小外接圆

import math

def rotated_bbox(x, y, w, h, angle_deg):
    """
    计算矩形 (x, y, w, h) 旋转 angle_deg 度后最小外接矩形的 xywh
    (x, y) 为左上角坐标,旋转中心为矩形中心
    返回 (new_x, new_y, new_w, new_h)
    """
    # 转弧度
    angle = math.radians(angle_deg)

    # 计算中心点
    cx = x + w / 2
    cy = y + h / 2

    # 矩形四个角点(以中心为原点前的坐标)
    corners = [
        (x - cx, y - cy),  # 左上
        (x + w - cx, y - cy),  # 右上
        (x + w - cx, y + h - cy),  # 右下
        (x - cx, y + h - cy),  # 左下
    ]

    # 旋转每个点
    rotated = []
    for px, py in corners:
        rx = px * math.cos(angle) - py * math.sin(angle)
        ry = px * math.sin(angle) + py * math.cos(angle)
        rotated.append((rx, ry))
		print(f'旋转后顶点坐标:{rotated}')
		
    # 找出旋转后坐标的最小外接矩形
    xs = [cx + p[0] for p in rotated]
    ys = [cy + p[1] for p in rotated]

    new_x = min(xs)
    new_y = min(ys)
    new_w = max(xs) - min(xs)
    new_h = max(ys) - min(ys)

    return new_x, new_y, new_w, new_h

可视化

import math
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, Polygon

def rotated_bbox(x, y, w, h, angle_deg, ax=None):
    """
    计算矩形 (x, y, w, h) 旋转 angle_deg 度后最小外接矩形的 xywh,
    同时在 ax 上可视化。
    """
    angle = math.radians(angle_deg)
    cx = x + w / 2
    cy = y + h / 2

    # 原始矩形四个角点
    corners = [(x, y), (x + w, y), (x + w, y + h), (x, y + h)]

    # 旋转后的四个角点
    rotated = []
    for px, py in corners:
        rx = cx + (px - cx) * math.cos(angle) - (py - cy) * math.sin(angle)
        ry = cy + (px - cx) * math.sin(angle) + (py - cy) * math.cos(angle)
        rotated.append((rx, ry))

    # 最小外接矩形
    xs = [p[0] for p in rotated]
    ys = [p[1] for p in rotated]
    new_x, new_y = min(xs), min(ys)
    new_w, new_h = max(xs) - min(xs), max(ys) - min(ys)

    if ax is not None:
        # 原始矩形(蓝色虚线)
        ax.add_patch(
            Rectangle(
                (x, y),
                w,
                h,
                fill=False,
                edgecolor="blue",
                linestyle="--",
                linewidth=1.5,
                label="original-rect",
            )
        )

        # 旋转后矩形(红色多边形)
        ax.add_patch(
            Polygon(
                rotated,
                closed=True,
                fill=False,
                edgecolor="red",
                linewidth=2,
                label="roated-rect",
            )
        )

        # 最小外接矩形(绿色实线)
        ax.add_patch(
            Rectangle(
                (new_x, new_y),
                new_w,
                new_h,
                fill=False,
                edgecolor="green",
                linewidth=1.5,
                label="outer-rect",
            )
        )

        ax.scatter([cx], [cy], color="black", marker="x", label="center")
        ax.set_aspect("equal")
        ax.legend()
        ax.set_title(f"rotation {angle_deg}° ")

    return new_x, new_y, new_w, new_h


# === 示例演示 ===
if __name__ == "__main__":
    fig, ax = plt.subplots(figsize=(6, 6))
    x, y, w, h = 100, 50, 80, 40
    angle = 30
    new_box = rotated_bbox(x, y, w, h, angle, ax=ax)
    print("旋转后最小外接矩形 xywh:", new_box)
    plt.show()

在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐