前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >获取一般椭圆外接矩形

获取一般椭圆外接矩形

作者头像
为为为什么
发布2022-08-06 17:29:20
1.9K1
发布2022-08-06 17:29:20
举报
文章被收录于专栏:又见苍岚又见苍岚

正椭圆的外接矩形可以直接根据椭圆中心以及长短半轴确定,但一般的斜椭圆就要复杂一些,本文记录计算斜椭圆外接矩形的过程。

问题描述

如上述动图所示,给定一个一般但中心为原点的椭圆,长半轴 a, 短半轴 b,角度 \alpha

  • 需要求得在给定 a,b,\alpha 下椭圆的外接矩形,可以将问题简化为在给定数据下求图中 height 变量。

一般化方程

  • 正椭圆方程为:

  • 当顺时针旋转角度 \alpha 后,x,y 值可以表示为:

  • 带入正椭圆方程得到中心在原点的一般椭圆方程:
\frac { ( x ^ { \prime } \cos \theta - y ^ { \prime } \sin \theta ) ^ { 2 } } { a ^ { 2 } } + \frac { ( x ^ { \prime } \sin \theta + y ^ { \prime } \cos \theta) ^ { 2 } } { b ^ { 2 } } = 1
  • 展开得到:

  • 对此我们将该种类的椭圆方程一般化,有方程:

  • 对应得到:

  • 即我们讨论的椭圆方程总可以化成一般方程的形式,之后我们均在一般化方程基础上讨论解法

方法一

求解思路
  • 需要解得 yx 导数为 0 的点,取绝对值即可
解决方法
  • 我们的目的是寻找 \frac{\partial y}{\partial x} 为 0 的点,那么直接对 x 求偏导:

  • \frac{\partial y}{\partial x} = 0,有:
2Ax+By=0
  • 不考虑 A = 0 的情况下:
x = - \frac{B}{2A}
  • 带入一般方程:

  • 得到高度:
height=|\sqrt{\frac{4AD}{B^2-4AC}}|

方法二

解决思路
  • 将一般方程的 y 看做常数,x 为自变量
  • 如果解得 x,那么就相当于给定 y = t 的情况下,椭圆与该直线的交点 x 坐标
  • 那么问题转化成了一元二次方程,当解的个数仅有一个的时候,直线 y=t与椭圆相切,也就是我们想要找的值
  • height=|t|
解决方法
  • 关于 x 的一元二次方程

  • 解为:
x=\frac{-B y \pm \sqrt{(B y)^{2}-4 \cdot A \cdot\left(C y^{2}+D\right)}}{2 A}
  • x 仅有1个解等价于:

  • 与上一方法殊途同归:
height=|\sqrt{\frac{4AD}{B^2-4AC}}|

python 实现

来自知乎大佬

  • 函数输入为:

参数

含义

major_radius

主轴的半径

minor_radius

短轴半径

angle

(顺时针)旋转角度

center_x

中心点横坐标

center_y

中心点纵坐标

  • 首先是根据前三个函数输入得到椭圆参数方程的参数
代码语言:javascript
复制
'''
根据椭圆的主轴和次轴半径以及旋转角度(默认圆心在原点),得到椭圆参数方程的参数,
椭圆参数方程为:
    A * x^2 + B * x * y + C * y^2 + D = 0
'''
def get_ellipse_param(major_radius, minor_radius, angle):
    a, b = major_radius, minor_radius
    sin_theta = np.sin(-angle)
    cos_theta = np.cos(-angle)
    A = a**2 * sin_theta**2 + b**2 * cos_theta**2
    B = 2 * (a**2 - b**2) * sin_theta * cos_theta
    C = a**2 * cos_theta**2 + b**2 * sin_theta**2
    F = -a**2 * b**2
    return A, B, C, D

  • 根据参数计算矩形框的值两个点的坐标:
代码语言:javascript
复制
'''
根据椭圆参数方程的参数,得到椭圆的外接矩形top-left和right-bottom坐标。
'''
def calculate_rectangle(A, B, C, D):
    '''
    椭圆上下外接点的纵坐标值
    '''
    y = np.sqrt(4*A*D / (B**2 - 4*A*C))
    y1, y2 = -np.abs(y), np.abs(y)
    
    '''
    椭圆左右外接点的横坐标值
    '''
    x = np.sqrt(4*C*D / (B**2 - 4*C*A))
    x1, x2 = -np.abs(x), np.abs(x)
    
    return (x1, y1), (x2, y2)

  • 综合两个函数
代码语言:javascript
复制
'''
按照数据集接口返回矩形框
'''
def get_rectangle(major_radius, minor_radius, angle, center_x, center_y):
    A, B, C, D = get_ellipse_param(major_radius, minor_radius, angle)
    p1, p2 = calculate_rectangle(A, B, C, D)
    return (center_x+p1[0], center_y+p1[1]), (center_x+p2[0], center_y+p2[1])

mtutils 库

  • python 中的 OpenCV 有输出斜椭圆的结构 ellipse
  • 在库 mtutils 中的 ellipse2bbox 可以直接将该椭圆作为输入,得到外接矩形
代码语言:javascript
复制
from mtutils import ellipse2bbox
bbox = ellipse2bbox(ellipse)

参考资料

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022年2月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题描述
  • 如上述动图所示,给定一个一般但中心为原点的椭圆,长半轴 a, 短半轴 b,角度 \alpha。
  • 一般化方程
  • 方法一
    • 求解思路
      • 解决方法
      • 方法二
        • 解决思路
          • 解决方法
          • python 实现
          • mtutils 库
          • 参考资料
          相关产品与服务
          对象存储
          对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档