因应用要求,需要设计一个计算两个任意方位的矩形IOU的函数,查阅了很多资料,都没有找到。网上大多数代码都是只能实现与坐标轴平行的两个矩形的运算,所以自己写了一个(哎,没有免费的午餐,只能自己生产了,我也很绝望呀)。主要思想就是先算出两个矩阵边的交点,然后生成一个多边形,最后将多边形分割成三角形进行计算。代码详细如下:

1.简单的矩形定义类

#include <algorithm>

#include <csignal>
#include <ctime>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include <math.h>
#include <iostream>

#define Max(a,b) ((a>b)? a:b)
#define Min(a,b) ((a<b)? a:b)
#define Pi 3.1415926
class NormalizedBBox
{
public:
float x;  //矩形中心坐标x
float y;  //矩形中心坐标y
float w;  //矩形宽
float h;  //矩形高
float theta;  //矩形倾角
NormalizedBBox(float x , float y , float w , float h , float theta );

};

2.矩形简单构造函数

#include "bbox_util.h"
NormalizedBBox::NormalizedBBox(float x, float y, float w, float h, float theta)
{
this->x = x;
this->y = y;
this->w = w;
this->h = h;
this->theta = theta;
}

3.主要用于计算的函数

//(1)根据两个矩形的8条边,计算交点。

void getBoxpoint(const vector< vector<float> > &temp_lines, vector< vector<float> >& temp_bbox1_point, vector< vector<float> >& temp_bbox2_point){

vector<float> point(2, 0);
point[0] = (temp_lines[0][1] - temp_lines[3][1]) / (temp_lines[3][0] - temp_lines[0][0]);
point[1] = temp_lines[0][0] * point[0] + temp_lines[0][1];
temp_bbox1_point.push_back(point);
for (int i = 0; i < 3; i++)
{
point[0] = (temp_lines[i][1] - temp_lines[(i + 1) % 4][1]) / (temp_lines[(i + 1) % 4][0] - temp_lines[i][0]);
point[1] = temp_lines[i][0] * point[0] + temp_lines[i][1];
temp_bbox1_point.push_back(point);
}

point[0] = (temp_lines[4][1] - temp_lines[7][1]) / (temp_lines[7][0] - temp_lines[4][0]);
point[1] = temp_lines[4][0] * point[0] + temp_lines[4][1];
temp_bbox2_point.push_back(point);
for (int i = 0; i < 3; i++)
{
point[0] = (temp_lines[i + 4][1] - temp_lines[((i + 1) % 4) + 4][1]) / (temp_lines[((i + 1) % 4) + 4][0] - temp_lines[i + 4][0]);
point[1] = temp_lines[i + 4][0] * point[0] + temp_lines[i + 4][1];
temp_bbox2_point.push_back(point);
}
}
(2)//计算交点
void getcrossshapepoint(const NormalizedBBox& Bbox1, const NormalizedBBox& Bbox2, vector<pair<float, float>>& cross_shape_point){
NormalizedBBox bbox1 = Bbox1;
NormalizedBBox bbox2 = Bbox2;
LARGE_INTEGER start1, stop1;
QueryPerformanceCounter(&start1);
bbox1.theta = Max(Min(bbox1.theta, 89.5 / 180 * Pi), 0.5 / 180 * Pi);
bbox2.theta = Max(Min(bbox2.theta, 89.5 / 180 * Pi), 0.5 / 180 * Pi);
vector<vector<float>> bbox1_point;
vector<vector<float>> bbox2_point;
vector<vector<float>> lines(8);
vector<float> lineParameter(2, 0);
lineParameter[0] = tan(bbox1.theta);
lineParameter[1] = -lineParameter[0] * bbox1.x + bbox1.y + bbox1.h / (2 * cos(bbox1.theta));
lines[0].push_back(lineParameter[0]);
lines[0].push_back(lineParameter[1]);
lineParameter[1] = -lineParameter[0] * bbox1.x + bbox1.y - bbox1.h / (2 * cos(bbox1.theta));
lines[2].push_back(lineParameter[0]);
lines[2].push_back(lineParameter[1]);
float sin_theta;
lineParameter[0] = -1 / tan(bbox1.theta);
sin_theta = sin(bbox1.theta);
lineParameter[1] = -lineParameter[0] * bbox1.x + bbox1.y - bbox1.w / (2 * sin_theta);
lines[1].push_back(lineParameter[0]);
lines[1].push_back(lineParameter[1]);
lineParameter[1] = -lineParameter[0] * bbox1.x + bbox1.y + bbox1.w / (2 * sin_theta);
lines[3].push_back(lineParameter[0]);
lines[3].push_back(lineParameter[1]);

lineParameter[0] = tan(bbox2.theta);
lineParameter[1] = -lineParameter[0] * bbox2.x + bbox2.y + bbox2.h / (2 * cos(bbox2.theta));
lines[4].push_back(lineParameter[0]);
lines[4].push_back(lineParameter[1]);
lineParameter[1] = -lineParameter[0] * bbox2.x + bbox2.y - bbox2.h / (2 * cos(bbox2.theta));
lines[6].push_back(lineParameter[0]);
lines[6].push_back(lineParameter[1]);
sin_theta = sin(bbox2.theta);
lineParameter[0] = -1 / tan(bbox2.theta);
lineParameter[1] = -lineParameter[0] * bbox2.x + bbox2.y - bbox2.w / (2 * sin_theta);
lines[5].push_back(lineParameter[0]);
lines[5].push_back(lineParameter[1]);
lineParameter[1] = -lineParameter[0] * bbox2.x + bbox2.y + bbox2.w / (2 * sin_theta);
lines[7].push_back(lineParameter[0]);
lines[7].push_back(lineParameter[1]);

getBoxpoint(lines, bbox1_point, bbox2_point);  //根据两个矩形的8条边,计算交点。
vector<float> point(2, 0);
float flag;

//验证交点是否在两个矩形相交内部
for (int i = 0; i < 4; i++){
point[0] = bbox1_point[i][0];
point[1] = bbox1_point[i][1];
flag = (point[1] - lines[4][0] * point[0] - lines[4][1])*(point[1] - lines[6][0] * point[0] - lines[6][1]);
if (flag >= 1e-6) continue;
flag = (point[1] - lines[5][0] * point[0] - lines[5][1])*(point[1] - lines[7][0] * point[0] - lines[7][1]);
if (flag >= 1e-6) continue;
cross_shape_point.push_back(make_pair(point[0], point[1]));
}
for (int i = 0; i < 4; i++){
point[0] = bbox2_point[i][0];
point[1] = bbox2_point[i][1];
flag = (point[1] - lines[0][0] * point[0] - lines[0][1])*(point[1] + lines[2][0] * point[0] - lines[2][1]);
if (flag >= 1e-6) continue;
flag = (point[1] - lines[1][0] * point[0] - lines[1][1])*(point[1] - lines[3][0] * point[0] - lines[3][1]);
if (flag >= 1e-6) continue;
cross_shape_point.push_back(make_pair(point[0], point[1]));
}
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++){
if (abs(lines[i][0] - lines[4 + j][0]) <= 1e-6)continue;
point[0] = (lines[4 + j][1] - lines[i][1]) / (lines[i][0] - lines[4 + j][0]);
point[1] = point[0] * lines[i][0] + lines[i][1];
bool flag1 = point[0] >= Max(bbox1_point[i][0], bbox1_point[(i + 1) % 4][0]) || point[0] <= Min(bbox1_point[i][0], bbox1_point[(i + 1) % 4][0]);
bool flag2 = point[1] >= Max(bbox1_point[i][1], bbox1_point[(i + 1) % 4][1]) || point[1] <= Min(bbox1_point[i][1], bbox1_point[(i + 1) % 4][1]);
bool flag3 = point[0] >= Max(bbox2_point[j][0], bbox2_point[(j + 1) % 4][0]) || point[0] <= Min(bbox2_point[j][0], bbox2_point[(j + 1) % 4][0]);
bool flag4 = point[1] >= Max(bbox2_point[j][1], bbox2_point[(j + 1) % 4][1]) || point[1] <= Min(bbox2_point[j][1], bbox2_point[(j + 1) % 4][1]);
if (flag1 || flag2 || flag3 || flag4)continue;
cross_shape_point.push_back(make_pair(point[0], point[1]));
}
}

//生成多边形
if (cross_shape_point.size() < 3) return;
else{
for (int i = 0; i < cross_shape_point.size(); i++){
for (int j = 0; j < cross_shape_point.size() - i - 1; j++){
if (cross_shape_point[j].first > cross_shape_point[j + 1].first)
swap(cross_shape_point[j], cross_shape_point[j + 1]);
}
}
vector<pair<float, float>> temp_shape_point(cross_shape_point);
pair<float, float>line;
line.first = ((cross_shape_point.end() - 1)->second - cross_shape_point.begin()->second) / ((cross_shape_point.end() - 1)->first - cross_shape_point.begin()->first);
line.second = cross_shape_point.begin()->second - line.first*cross_shape_point.begin()->first;
vector<int> ranking;
int n = 1; int m = 0;
for (int i = 0; i < int(cross_shape_point.size()); i++){
if (cross_shape_point[i].second <= line.first*cross_shape_point[i].first + line.second){
ranking.push_back(m);
m++;
}
else{
ranking.push_back(cross_shape_point.size() - n);
n++;
}
}
for (int i = 0; i < int(ranking.size()); i++){
cross_shape_point[ranking[i]] = (temp_shape_point[i]);
}
}
}
 
float JaccardOverlap(const NormalizedBBox& bbox1, const NormalizedBBox& bbox2, const bool normalized = true){
vector<pair<float, float>> all_shape_point;
if ((bbox1.theta == bbox2.theta) && (bbox1.x == bbox2.x) && (bbox1.y == bbox2.y) && (bbox1.w == bbox2.w) && (bbox1.h == bbox2.h))return 1;
if (abs(bbox2.theta - bbox1.theta)>Pi / 6) return 0;
getcrossshapepoint(bbox1, bbox2, all_shape_point);
if (all_shape_point.size() < 3) return 0;
//cout << all_shape_point.size() << endl;
float area = 0.0;

//多边形面积计算
for (int i = 0; i < int(all_shape_point.size() - 1); i++){
area += all_shape_point[i].first*all_shape_point[i + 1].second - all_shape_point[i + 1].first*all_shape_point[i].second;
}
area = area / 2;
int i = all_shape_point.size() - 1;
area = area - (all_shape_point[0].first*all_shape_point[i].second - all_shape_point[i].first*all_shape_point[0].second) / 2;
float bbox1_size = bbox1.w*bbox1.h;
float bbox2_size = bbox2.w*bbox2.h;

//cout << "area:" << area << "  " << bbox1_size << "  " << bbox2_size << endl;
return area / (bbox1_size + bbox2_size - area);
}

4.主函数

int main(){
float theta1 = 30;
theta1 = Pi*theta1 / 180;
float theta2 = 30;
theta2 = Pi*theta2 / 180;
NormalizedBBox box1(0, 0, 1, 2, theta1);
NormalizedBBox box2(0, 0, 2, 2, theta2);
float area= JaccardOverlap(box1, box2);
cout << area << endl;
system("pause");
}

代码写得比较粗糙,还请见谅,该代码能实现任意方位的两个矩形的相交面积的近似估计,但是速度有待提高,运行一次需要大概800us,暂时满足不了我自己的应用,欢迎大家来交流。

任意方位矩形相交面积计算相关推荐

  1. java判断线与矩形相交_判断任意多边形与矩形的相交(线段与矩形相交或线段与线段相交)...

    任意多边形与矩形的相交,其实就是判断多条线段是否与这个矩形相交,再简单点就是判断线段是否与矩形的每一条边相交了.那现在,我们先来看看判断一条线段与矩形的其中一条线段的相交的情况(上方水平线): (图形 ...

  2. 判断两个矩形相交以及求出相交的区域

    问题:给定两个矩形A和B,矩形A的左上角坐标为(Xa1,Ya1),右下角坐标为(Xa2,Ya2),矩形B的左上角坐标为(Xb1,Yb1),右下角 坐标为(Xb2,Yb2). (1)设计一个算法,确定两 ...

  3. 如何判断两个矩形相交

    假定矩形是用一对点表达的(minx, miny) (maxx, maxy),那么两个矩形        rect1{(minx1, miny1)(maxx1, maxy1)}        rect2 ...

  4. java判断两个矩形是否相交_判断矩形相交以及求出相交的区域

    问题:给定两个矩形A和B,矩形A的左上角坐标为(Xa1,Ya1),右下角坐标为(Xa2,Ya2),矩形B的左上角坐标为(Xb1,Yb1),右下角 坐标为(Xb2,Yb2). (1)设计一个算法,确定两 ...

  5. c语言两个矩形相交部分坐标,C++判断矩形相交的方法

    本文实例讲述了C++判断矩形相交的方法.分享给大家供大家参考.具体如下: 已知2矩形原点和宽高,判断2矩形相交,相交矩形 相交判断原理: 假定矩形是用一对点表达的(minx, miny) (maxx, ...

  6. 计算机与数学 —— 圆与矩形相交判定算法的优化

    这篇博客介绍了用于判定圆与矩形相交的Arvo's algorithm的优化版本以及对应思路. Arvo's Algorithm 在用于判定圆与AABB矩形的判定中,Arvo提出的算法被广泛运用.关于这 ...

  7. 蓝桥杯 油漆面积【第八届】【省赛】【A组】线段树扫面线/求矩形相交面积/模拟

    资源限制 内存限制:256.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s X星球的一批考古机器人正在一片废墟上考古. 该区域的地面坚硬如 ...

  8. 线与线相交、线与矩形相交判断

    /// /// 只要线与矩形有一条线有相交,则线与矩形相交 /// public class LineWithRect : MonoBehaviour { public Rect rect = new ...

  9. 两个矩形相交的面积c语言,关于算法:两个旋转矩形的相交面积

    我有两个2D矩形,分别定义为原点(x,y),大小(高度,宽度)和旋转角度(0-360°). 我可以保证两个矩形的大小相同. 我需要计算这两个矩形的相交区域. 尽管可以,但计算不一定要精确. 我将结果与 ...

最新文章

  1. 水系影像分析_“天眼”助力 甘肃运用卫星影像精准研判灾情
  2. .Net学习笔记----2015-07-10(GDI绘图)
  3. android ztree,ztree实现权限功能(横向显示)
  4. 【PKUSC2018】星际穿越【结论】【倍增dp】
  5. 警惕成教自考_不,保持警惕不会伤害Java。 关于Java许可的评论。
  6. html 语义化标签拾遗
  7. 北斗轨迹记录_北斗定位+智慧4G视频校车行业解决方案
  8. java web js_JAVA Web JS
  9. 华为隐藏功能扩大内存代码大全_发现将华为手机这3个功能打开,竟然可以将手机性能极限发挥...
  10. 云HBase内核解析
  11. C++ template 学习归纳总结4
  12. Innosetup打包自动下载.net framework 动态库及替换卸载程序图标.
  13. latex在行末出现百分号的作用
  14. 百度指数查关键词(惊到我啦)
  15. 用windows命令开启远程桌面
  16. 工具--nssm详解
  17. Ubuntu 11.10ibus万能五笔
  18. 使用GeoServer发布Shapfile数据
  19. 面向移动设备的html5开发框架
  20. 【转载】SCI投稿过程总结、投稿状态解析、拒稿后对策及接受后期相关问答

热门文章

  1. python 获取时间并加8小时
  2. C语言贪吃蛇详解4,c语言贪吃蛇详解4.食物的投放与蛇的变长
  3. oracle查询语句
  4. freenas安装出错
  5. 浏览器F12查看接口信息
  6. Spring Boot做后端框架遇到的一些问题
  7. php 输出数组内容_php如何输出数组
  8. 聚类分析实验(一)数据预处理
  9. H5解决IOS拍照横屏问题,含后端上传
  10. 所有品牌信息查询api