(十三) minAreaRect函数

minAreaRect函数

*
1.背景
2.minAreaRect 函数
3.以新版为例
参考资料

欢迎访问个人网络日志🌹🌹知行空间🌹🌹

1.背景

在做旋转物体检测时,通常期望得到对象的带角度最小面积包围矩形,如下图对卫星图像航空母舰的检测:

(十三) minAreaRect函数

若已经获取了对象的轮廓,可以通过 OpenCV中的 minAreaRect方法获取对象的最小面积包围框。

; 2.minAreaRect 函数

RotatedRect cv::minAreaRect(InputArray  points)

入参

  • points 是点的集合,如轮廓

返回值

center(x,y), (width, height)分别是旋转矩形框中心的坐标和矩形的宽和高。值得注意的是最后一个元素 angle of rotation旋转角的定义。旧版本和新版本的定义有些许的差异,具体是以 4.5.1为分界,小于 4.5.1使用了旧的定义方法, 4.5.1及之后都采用了新的旋转角定义方法。具体可见OpenCV GitHub Issue。新旧版本旋转角度的定义如下【图片来自于 mmRotate】:

(十三) minAreaRect函数

对于新版的定义,以旋转矩形框 y最小,y相等时x最小的点为旋转点,以 x轴正方向开始顺时针旋转碰到旋转矩形框第一条边时所转过的角度,旋转重合的第一条边算做 width,另一条算做 height,其取值范围为( 0 , π / 2 ] (0, \pi/2](0 ,π/2 ],当x轴与一条边重合时取π / 2 \pi/2 π/2。对于旧版的定义,以旋转矩形框 y最大,y相等时x最小的点为旋转点, 逆时针方向旋转碰到的第一条边与 x轴所成的角,其取值范围为[ − π / 2 , 0 ) [-\pi/2,0)[−π/2 ,0 )

; 3.以新版为例

img = np.zeros((300, 500), dtype=np.uint8)
contour = np.array([[20, 100], [100, 20], [320, 220], [380, 290]], dtype=np.int32)
cv2.drawContours(img, [contour], -1, 255, cv2.FILLED )
rotRect = cv2.minAreaRect(contour)
print(rotRect)
rect = cv2.boxPoints(rotRect).astype(np.int32)
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.drawContours(img, [rect], -1, (0,0, 255), 4)
cv2.imwrite("img.png", img)

(十三) minAreaRect函数

cv2.minAreaRect函数的返回值是旋转矩形框中心点的坐标和框的宽高,想要在图像画出旋转矩形框还需要将其转成4个顶点的形式,使用 boxPoints即可求出四个顶点的坐标。此外还可以手动的来求,也比较简单,假设以旋转点为原点,矩形框 width的边为新的 x轴建立新的坐标系,则和原图像坐标系之间是只有旋转变换,求出其旋转矩阵即可完成点的变换,可参考,代码如下,可见结果很接近(计算精度存在误差):


def rotate_oc_points(bbox):
    xc, yc, w, h, ag = bbox[:5]
    ag = ag/180*np.pi
    wx, wy = w / 2 * np.cos(ag), w / 2 * np.sin(ag)
    hx, hy = -h / 2 * np.sin(ag), h / 2 * np.cos(ag)
    p1 = (xc - wx - hx, yc - wy - hy)
    p2 = (xc + wx - hx, yc + wy - hy)
    p3 = (xc + wx + hx, yc + wy + hy)
    p4 = (xc - wx + hx, yc - wy + hy)
    return np.array([p1, p2, p3, p4], dtype=np.int32)

img = np.zeros((300, 500), dtype=np.uint8)
contour = np.array([[20, 100], [100, 20], [320, 220], [380, 290]], dtype=np.int32)
cv2.drawContours(img, [contour], -1, 255, cv2.FILLED )
rotRect = cv2.minAreaRect(contour)
rect = cv2.boxPoints(rotRect).astype(np.int32)
print(f"by boxPoints:\n {rect}")
rect = rotate_oc_points([*rotRect[0], *rotRect[1], rotRect[2]])
print(f"by rotate_oc_points:\n {rect}")
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.drawContours(img, [rect], -1, (0,0, 255), 4)
cv2.imwrite("img.png", img)

欢迎访问个人网络日志🌹🌹知行空间🌹🌹

参考资料

Original: https://blog.csdn.net/lx_ros/article/details/126275103
Author: 恒友成
Title: (十三) minAreaRect函数

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/729603/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球