python版本
import math
#包围盒转化为角点
def rbbox_to_corners(rbbox):
# generate clockwise corners and rotate it clockwise
# 顺时针方向返回角点位置
cx, cy, x_d, y_d, angle = rbbox
a_cos = math.cos(angle)
a_sin = math.sin(angle)
corners_x = [-x_d / 2, -x_d / 2, x_d / 2, x_d / 2]
corners_y = [-y_d / 2, y_d / 2, y_d / 2, -y_d / 2]
corners = [0] * 8
for i in range(4):
corners[2 *
i] = a_cos * corners_x[i] + \
a_sin * corners_y[i] + cx
corners[2 * i +
1] = -a_sin * corners_x[i] + \
a_cos * corners_y[i] + cy
return corners
# 点在四边形(矩形)内?
def point_in_quadrilateral(pt_x, pt_y, corners):
ab0 = corners[2] - corners[0]
ab1 = corners[3] - corners[1]
ad0 = corners[6] - corners[0]
ad1 = corners[7] - corners[1]
ap0 = pt_x - corners[0]
ap1 = pt_y - corners[1]
abab = ab0 * ab0 + ab1 * ab1
abap = ab0 * ap0 + ab1 * ap1
adad = ad0 * ad0 + ad1 * ad1
adap = ad0 * ap0 + ad1 * ap1
return abab >= abap and abap >= 0 and adad >= adap and adap >= 0
# 相交后转化为直线交点
def line_segment_intersection(pts1, pts2, i, j):
# pts1, pts2 为corners
# i j 分别表示第几个交点,取其和其后一个点构成的线段
# 返回为 tuple(bool, pts) bool=True pts为交点
A, B, C, D, ret = [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]
A[0] = pts1[2 * i]
A[1] = pts1[2 * i + 1]
B[0] = pts1[2 * ((i + 1) % 4)]
B[1] = pts1[2 * ((i + 1) % 4) + 1]
C[0] = pts2[2 * j]
C[1] = pts2[2 * j + 1]
D[0] = pts2[2 * ((j + 1) % 4)]
D[1] = pts2[2 * ((j + 1) % 4) + 1]
BA0 = B[0] - A[0]
BA1 = B[1] - A[1]
DA0 = D[0] - A[0]
CA0 = C[0] - A[0]
DA1 = D[1] - A[1]
CA1 = C[1] - A[1]
# 叉乘判断方向
acd = DA1 * CA0 > CA1 * DA0
bcd = (D[1] - B[1]) * (C[0] - B[0]) > (C[1] - B[1]) * (D[0] - B[0])
if acd != bcd:
abc = CA1 * BA0 > BA1 * CA0
abd = DA1 * BA0 > BA1 * DA0
# 判断方向
if abc != abd:
DC0 = D[0] - C[0]
DC1 = D[1] - C[1]
ABBA = A[0] * B[1] - B[0] * A[1]
CDDC = C[0] * D[1] - D[0] * C[1]
DH = BA1 * DC0 - BA0 * DC1
Dx = ABBA * DC0 - BA0 * CDDC
Dy = ABBA * DC1 - BA1 * CDDC
ret[0] = Dx / DH
ret[1] = Dy / DH
return True, ret
return False, ret
# 顶点排序
def sort_vertex_in_convex_polygon(int_pts, num_of_inter):
def _cmp(pt, center):
vx = pt[0] - center[0]
vy = pt[1] - center[1]
d = math.sqrt(vx * vx + vy * vy)
vx /= d
vy /= d
if vy < 0:
vx = -2 - vx
return vx
if num_of_inter > 0:
center = [0, 0]
for i in range(num_of_inter):
center[0] += int_pts[i][0]
center[1] += int_pts[i][1]
center[0] /= num_of_inter
center[1] /= num_of_inter
int_pts.sort(key=lambda x: _cmp(x, center))
# 将多边形转化为多个三角形面积之和
def area(int_pts, num_of_inter):
def _trangle_area(a, b, c):
return ((a[0] - c[0]) * (b[1] - c[1]) - (a[1] - c[1]) *
(b[0] - c[0])) / 2.0
area_val = 0.0
for i in range(num_of_inter - 2):
area_val += abs(
_trangle_area(int_pts[0], int_pts[i + 1],
int_pts[i + 2]))
return area_val
if __name__ == '__main__':
rbbox1 = [274 ,614, 48 ,24 ,52.4832583462631987] #x,y,w,h,angle
rbbox2 = [274 ,615 ,49 ,22 ,1.486161712080829]
corners1 = rbbox_to_corners(rbbox1)
corners2 = rbbox_to_corners(rbbox2)
# print(corners1,"\n",corners2)
pts, num_pts = [], 0
for i in range(4):
point = [corners1[2 * i], corners1[2 * i + 1]]
if point_in_quadrilateral(point[0], point[1],
corners2):
num_pts += 1
pts.append(point)
for i in range(4):
point = [corners2[2 * i], corners2[2 * i + 1]]
if point_in_quadrilateral(point[0], point[1],
corners1):
num_pts += 1
pts.append(point)
for i in range(4):
for j in range(4):
ret, point = line_segment_intersection(corners1, corners2, i, j)
if ret:
num_pts += 1
pts.append(point)
sort_vertex_in_convex_polygon(pts, num_pts)
polygon_area = area(pts, num_pts)
area_union=rbbox1[2]*rbbox1[3]+rbbox2[2]*rbbox2[3]-polygon_area
print('area: {}'.format(polygon_area/area_union))
c++
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
// box转化为角点
std::vector<float> rbbox_to_corners(const std::vector<float> &rbbox) {
// generate clockwise corners and rotate it clockwise
// 顺时针方向返回角点位置
float cx = rbbox[0] + rbbox[2] / 2;
float cy = rbbox[1] + rbbox[3] / 2;
float x_d = rbbox[2];
float y_d = rbbox[3];
float angle = rbbox[4];
float a_cos = std::cos(angle);
float a_sin = std::sin(angle);
std::vector<float> corners(8, 0.0);
float corners_x[4] = {-x_d / 2, -x_d / 2, x_d / 2, x_d / 2};
float corners_y[4] = {-y_d / 2, y_d / 2, y_d / 2, -y_d / 2};
for (int i = 0; i < 4; ++i) {
corners[2 * i] = a_cos * corners_x[i] - a_sin * corners_y[i] + cx;
corners[2 * i + 1] = a_sin * corners_x[i] + a_cos * corners_y[i] + cy;
}
return corners;
}
// 检测点是否在四边形内的函数
bool point_in_quadrilateral(float pt_x, float pt_y, const std::vector<float>& corners) {
float ab0 = corners[2] - corners[0];
float ab1 = corners[3] - corners[1];
float ad0 = corners[6] - corners[0];
float ad1 = corners[7] - corners[1];
float ap0 = pt_x - corners[0];
float ap1 = pt_y - corners[1];
float abab = ab0 * ab0 + ab1 * ab1;
float abap = ab0 * ap0 + ab1 * ap1;
float adad = ad0 * ad0 + ad1 * ad1;
float adap = ad0 * ap0 + ad1 * ap1;
return abab >= abap && abap >= 0 && adad >= adap && adap >= 0;
}
// 检测线段相交并计算交点的函数
int line_segment_intersection(const std::vector<float>& pts1, const std::vector<float>& pts2, int i, int j
, bool &ret1,float &point_x,float &point_y) {
// pts1, pts2 分别为 corners
// i j 分别表示第几个交点,取其和其后一个点构成的线段
// 返回 tuple(bool, pts) bool=true pts为交点
std::vector<float> A(2), B(2), C(2), D(2), ret(2);
A[0] = pts1[2 * i];
A[1] = pts1[2 * i + 1];
B[0] = pts1[2 * ((i + 1) % 4)];
B[1] = pts1[2 * ((i + 1) % 4) + 1];
C[0] = pts2[2 * j];
C[1] = pts2[2 * j + 1];
D[0] = pts2[2 * ((j + 1) % 4)];
D[1] = pts2[2 * ((j + 1) % 4) + 1];
float BA0 = B[0] - A[0];
float BA1 = B[1] - A[1];
float DA0 = D[0] - A[0];
float CA0 = C[0] - A[0];
float DA1 = D[1] - A[1];
float CA1 = C[1] - A[1];
// 叉乘判断方向
bool acd = DA1 * CA0 > CA1 * DA0;
bool bcd = (D[1] - B[1]) * (C[0] - B[0]) > (C[1] - B[1]) * (D[0] - B[0]);
if (acd != bcd) {
bool abc = CA1 * BA0 > BA1 * CA0;
bool abd = DA1 * BA0 > BA1 * DA0;
// 判断方向
if (abc != abd) {
float DC0 = D[0] - C[0];
float DC1 = D[1] - C[1];
float ABBA = A[0] * B[1] - B[0] * A[1];
float CDDC = C[0] * D[1] - D[0] * C[1];
float DH = BA1 * DC0 - BA0 * DC1;
float Dx = ABBA * DC0 - BA0 * CDDC;
float Dy = ABBA * DC1 - BA1 * CDDC;
ret[0] = Dx / DH;
ret[1] = Dy / DH;
ret1=true;
point_x=ret[0] ;
point_y=ret[1] ;
return 0;
}
}
ret1=false;
point_x=ret[0] ;
point_y=ret[1] ;
return 0;
}
// 比较函数,用于排序
bool compare_points(const std::vector<float>& pt1, const std::vector<float>& pt2, const std::vector<float>& center) {
float vx1 = pt1[0] - center[0];
float vy1 = pt1[1] - center[1];
float vx2 = pt2[0] - center[0];
float vy2 = pt2[1] - center[1];
float d1 = std::sqrt(vx1 * vx1 + vy1 * vy1);
float d2 = std::sqrt(vx2 * vx2 + vy2 * vy2);
vx1 /= d1;
vy1 /= d1;
vx2 /= d2;
vy2 /= d2;
if (vy1 < 0) {
vx1 = -2 - vx1;
}
if (vy2 < 0) {
vx2 = -2 - vx2;
}
return vx1 < vx2;
}
// 对凸多边形的顶点进行排序
void sort_vertex_in_convex_polygon(std::vector<std::vector<float>>& int_pts, int num_of_inter) {
if (num_of_inter > 0) {
std::vector<float> center(2, 0);
for (int i = 0; i < num_of_inter; ++i) {
center[0] += int_pts[i][0];
center[1] += int_pts[i][1];
}
center[0] /= num_of_inter;
center[1] /= num_of_inter;
std::sort(int_pts.begin(), int_pts.end(), [¢er](const std::vector<float>& pt1, const std::vector<float>& pt2) {
return compare_points(pt1, pt2, center);
});
}
}
// 计算三角形的面积
float triangle_area(const std::vector<float>& a, const std::vector<float>& b, const std::vector<float>& c) {
return std::abs((a[0] - c[0]) * (b[1] - c[1]) - (a[1] - c[1]) * (b[0] - c[0])) / 2.0;
}
// 计算多边形转化为多个三角形面积之和
float polygon_area(const std::vector<std::vector<float>>& int_pts, int num_of_inter) {
float area_val = 0.0;
for (int i = 1; i < num_of_inter - 1; ++i) {
area_val += triangle_area(int_pts[0], int_pts[i], int_pts[i + 1]);
}
return area_val;
}
int main(int argc, char *argv[])
{
// 定义两个包围盒的数据
std::vector<float> rbbox1 = {274 ,614, 48 ,24 ,52.4832583462631987};
std::vector<float> rbbox2 = {274 ,615 ,49 ,22 ,1.486161712080829};
// 调用函数得到角点数据
std::vector<float> corners1 = rbbox_to_corners(rbbox1);
std::vector<float> corners2 = rbbox_to_corners(rbbox2);
std::vector<std::vector<float>> pts;
int num_pts = 0;
// 检测角点是否在对方的四边形内
for (int i = 0; i < 4; ++i) {
float point_x = corners1[2 * i];
float point_y = corners1[2 * i + 1];
if (point_in_quadrilateral(point_x, point_y, corners2)) {
num_pts++;
pts.push_back({point_x, point_y});
}
}
for (int i = 0; i < 4; ++i) {
float point_x = corners2[2 * i];
float point_y = corners2[2 * i + 1];
if (point_in_quadrilateral(point_x, point_y, corners1)) {
num_pts++;
pts.push_back({point_x, point_y});
}
}
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
float point_x,point_y;
bool ret;
line_segment_intersection(corners1, corners2, i, j,ret,point_x,point_y);
if (ret) {
num_pts++;
pts.push_back({point_x, point_y});
}
}
}
sort_vertex_in_convex_polygon(pts, num_pts);
float polygon_area_val = polygon_area(pts, num_pts);
// 计算 area_union
float area_union = rbbox1[2] * rbbox1[3] + rbbox2[2] * rbbox2[3] - polygon_area_val;
// 计算并输出结果
std::cout << "area: " << polygon_area_val / area_union << std::endl;
return 0;
}