一 计算矩形重叠面积的三种方法
方法1.两个矩形的宽之和,减去组合之后的宽就得到重叠区域的宽;高同理
def IOU(Reframe,GTframe):
"""
自定义函数,计算两矩形 IOU,传入为均为矩形对角线,(x,y) 坐标。·
"""
x1 = Reframe[0];
y1 = Reframe[1];
width1 = Reframe[2]-Reframe[0];
height1 = Reframe[3]-Reframe[1];
x2 = GTframe[0];
y2 = GTframe[1];
width2 = GTframe[2]-GTframe[0];
height2 = GTframe[3]-GTframe[1];
endx = max(x1+width1,x2+width2);
startx = min(x1,x2);
width = width1+width2-(endx-startx);
endy = max(y1+height1,y2+height2);
starty = min(y1,y2);
height = height1+height2-(endy-starty);
if width <=0 or height <= 0:
ratio = 0 # 重叠率为 0
else:
Area = width*height; # 两矩形相交面积
Area1 = width1*height1;
Area2 = width2*height2;
ratio = Area*1./(Area1+Area2-Area)
# return IOU
return ratio
方法2.两右下角顶点的小x减去两左上顶点的大x就得到重叠区域的宽;高同理
def calc_area(rect1, rect2):
xl1, yb1, xr1, yt1 = rect1
xl2, yb2, xr2, yt2 = rect2
xmin = max(xl1, xl2)
ymin = max(yb1, yb2)
xmax = min(xr1, xr2)
ymax = min(yt1, yt2)
width = xmax - xmin
height = ymax - ymin
if width <= 0 or height <= 0:
return 0
cross_square = width * height
return cross_square
方法3.若不想交返回0,若相交abs(x[1]-x[2])*abs(y[1]-y[2])
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
double x[4],y[4];
while (scanf("%lf%lf",&x[0],&y[0])!=-1){
for (int i=1;i<=3;i++) scanf("%lf%lf",&x[i],&y[i]);
if (max(x[0],x[1])<min(x[2],x[3]) || min(x[0],x[1])>max(x[2],x[3]) || max(y[0],y[1])<min(y[2],y[3]) || min(y[0],y[1])>max(y[2],y[3])) printf("0.00\n");
//判断 两个矩形是否相交
else
{
//如果相交,直接求阴影面积,这点很巧妙、
sort(x,x+4); sort(y,y+4);
printf("%.2lf\n",abs(x[1]-x[2])*abs(y[1]-y[2]));
}
}
}
二 计算旋转矩形的重叠面积
参考:https://blog.csdn.net/sda42342342423/article/details/79746736
cv2.rotatedRectangleIntersection(rect1, rect2)
- 计算两个旋转矩形的交集,返回值 0,1,2分别表示没有,有,包含;以及交点的坐标的一个array。很遗憾的是这个坐标是不是逆时针也不是顺时针。而cv2.contourArea()需要点是顺时针或者逆时针。
- 例子程序
# 中心点 矩形的w h, 旋转的theta(角度,不是弧度)
rect1 = ((0,0),(1,1),45)
rect2 = ((1.5,0),(4,3),0)
r1 = cv2.rotatedRectangleIntersection(rect1, rect2)
print r1
- 多边形的点逆时针排序
- Python 的自定义的排序程序只能返回0,1,-1。没有true,false。所以没
return a > b
种写法 - 主要是根据所求出的重心,按照向量的叉积,然后排序
- 排序函数如下:
- Python 的自定义的排序程序只能返回0,1,-1。没有true,false。所以没
def cmp(a, b):
if a.x >= 0 and b.x < 0:
return -1
if a.x == 0 and b.x == 0:
# return a.y > b.y
if a.y > b.y:
return -1
elif a.y < b.y:
return 1
return 0
det = (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y)
if det < 0:
return 1
if det > 0:
return -1
d1 = (a.x - c.x) * (a.x - c.x) + (a.y - c.y) * (a.y - c.y)
d2 = (b.x - c.x) * (b.x - c.x) + (b.y - c.y) * (b.y - c.y)
# return d1 > d2
if d1 > d2:
return -1
elif d1 < d2:
return 1
return 0
- cv2.contourArea()
- 计算点所包围的面积
- 坑点 dtype=’float32’
# 可行
r = ((2,-2),(-2,-2),(-2,2),(2,2))
r2 = cv2.contourArea(np.array(r))
# 可行
r = [[1,-1],[-1,-1],[-1,1],[1,1]]
r2 = cv2.contourArea(np.array(r))
# 不可行
r = np.full((len_p, 2), 0.0)
for i in range(len(pp)):
print pp[i].x, pp[i].y
r[i][0] = pp[i].x
r[i][1] = pp[i].y
r2 = cv2.contourArea(r)
# 可行
r = np.full((len_p, 2), 0.0, dtype='float32')
for i in range(len(pp)):
print pp[i].x, pp[i].y
r[i][0] = pp[i].x
r[i][1] = pp[i].y
r2 = cv2.contourArea(r)
代码
import cv2
import numpy as np
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def cmp(a, b, c):
if a.x >= 0 and b.x < 0:
return -1
if a.x == 0 and b.x == 0:
# return a.y > b.y
if a.y > b.y:
return -1
elif a.y < b.y:
return 1
return 0
det = (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y)
if det < 0:
return 1
if det > 0:
return -1
d1 = (a.x - c.x) * (a.x - c.x) + (a.y - c.y) * (a.y - c.y)
d2 = (b.x - c.x) * (b.x - c.x) + (b.y - c.y) * (b.y - c.y)
# return d1 > d2
if d1 > d2:
return -1
elif d1 < d2:
return 1
return 0
## centerx, centery w, h, thetta
rect1 = ((0,0),(1,1),45)
rect2 = ((1.5,0),(4,3),0)
r1 = cv2.rotatedRectangleIntersection(rect1, rect2)
x = 0
y = 0
p = []
len_p = r1[1].shape[0]
for i in range(len_p):
p.append(Point(r1[1][i][0][0], r1[1][i][0][1]))
x += r1[1][i][0][0]
y += r1[1][i][0][1]
c = Point(x / len_p, y/len_p)
pp = sorted(p, lambda x,y: cmp(x, y, c))
r = np.full((len_p, 2), 0.0, dtype='float32')
for i in range(len(pp)):
print pp[i].x, pp[i].y
r[i][0] = pp[i].x
r[i][1] = pp[i].y
r2 = cv2.contourArea(r)
print r2
三 计算任意两个四边形的重叠面积
凸多边形相交,直接用一个裁切另外一个(Sutherland-Hodgman算法(多边形裁剪)),得到一个新的凸多边形(也可能不相交),然后求一下面积就行了(Mathwords: Area of a Convex Polygon)。
除此之外,还有1982年的 O’Rourke-Chien-Olson-Naddor algorithm,O(m+n)的时间复杂度。
C++代码参考:
https://blog.csdn.net/lcc_633/article/details/60321522
https://blog.csdn.net/nanhaizhixin/article/details/6531896
另外网友自己实现的任意矩形重叠的面积计算参考: