回答
你还应该添加矢量形式输入,所以我们可以对数据进行测试...我将接近这样的:
- 发现轴的中心对齐BBOX
O(n)
计算每个角度的最大距离
O(n)
只需创建足够的表格
m
角度(如5 deg stepm = 360/5
)对于每个角度区域,您只记得最大远距离点距离。计算最大垂直距离为每次旋转
O(m^2)
因此每个角部分的计算值是:
value[actual_section] = max(distance[i]*cos(section_angle[i]-section_angle[actual_section]))
其中
i
占地面积+/- 90 deg
各地的实际节角所以现在你得到了最大垂直每个角度的距离...挑最好的解决办法
O(m)
所以看所有旋转从0到90度,记得有最小OBB区域之一。只是要确保OBB对准部分的角度和轴系的大小是角度的
value
和所有的90度增量...围绕中心
这不会导致在最佳解决方案,但非常接近它。为了提高精度,您可以使用更多的角度部分,或者甚至用更小和更小的角度步长递归搜索找到的解决方案(第一次运行后无需计算其他角度区域。
[EDIT1]
我试着在C++实现代码作为概念验证和使用您的图像(如设定点的处理)作为输入,所以这里的结果,所以你得到的东西来比较(用于调试)
灰色检测到来自你的形象加分,绿色重ctangle轴对齐BBox红色矩形发现OBBox。 aqua点被发现每个角度间隔的最大距离和绿色点是最大垂直距离+/-90deg
相邻角度间隔。我用400
角度,你可以看到结果是相当接近... 360/400 deg
准确性所以这种方法效果很好...
这里C++源:
//---------------------------------------------------------------------------
struct _pnt2D
{
double x,y;
// inline
_pnt2D() {}
_pnt2D(_pnt2D& a) { *this=a; }
~_pnt2D() {}
_pnt2D* operator = (const _pnt2D *a) { *this=*a; return this; }
//_pnt2D* operator = (const _pnt2D &a) { ...copy... return this; }
};
struct _ang
{
double ang; // center angle of section
double dis; // max distance of ang section
double pdis; // max perpendicular distance of +/-90deg section
// inline
_ang() {}
_ang(_ang& a) { *this=a; }
~_ang() {}
_ang* operator = (const _ang *a) { *this=*a; return this; }
//_ang* operator = (const _ang &a) { ...copy... return this; }
};
const int angs=400; // must be divisible by 4
const int angs4=angs>>2;
const double dang=2.0*M_PI/double(angs);
const double dang2=0.5*dang;
_ang ang[angs];
List<_pnt2D> pnt;
_pnt2D bbox[2],obb[4],center;
//---------------------------------------------------------------------------
void compute_OBB()
{
_pnt2D ppp[4];
int i,j; double a,b,dx,dy;
_ang *aa,*bb;
_pnt2D p,*pp; DWORD *q;
// convert bmp -> pnt[]
pnt.num=0;
Graphics::TBitmap *bmp=new Graphics::TBitmap;
bmp->LoadFromFile("in.bmp");
bmp->HandleType=bmDIB;
bmp->PixelFormat=pf32bit;
for (p.y=0;p.y<bmp->Height;p.y++)
for (q=(DWORD*)bmp->ScanLine[int(p.y)],p.x=0;p.x<bmp->Width;p.x++)
if ((q[int(p.x)]&255)<20)
pnt.add(p);
delete bmp;
// axis aligned bbox
bbox[0]=pnt[0];
bbox[1]=pnt[0];
for (pp=pnt.dat,i=0;i<pnt.num;i++,pp++)
{
if (bbox[0].x>pp->x) bbox[0].x=pp->x;
if (bbox[0].y>pp->y) bbox[0].y=pp->y;
if (bbox[1].x<pp->x) bbox[1].x=pp->x;
if (bbox[1].y<pp->y) bbox[1].y=pp->y;
}
center.x=(bbox[0].x+bbox[1].x)*0.5;
center.y=(bbox[0].y+bbox[1].y)*0.5;
// ang[] table init
for (aa=ang,a=0.0,i=0;i<angs;i++,aa++,a+=dang)
{
aa->ang=a;
aa-> dis=0.0;
aa->pdis=0.0;
}
// ang[].dis
for (pp=pnt.dat,i=0;i<pnt.num;i++,pp++)
{
dx=pp->x-center.x;
dy=pp->y-center.y;
a=atan2(dy,dx);
j=floor((a/dang)+0.5); if (j<0) j+=angs; j%=angs;
a=(dx*dx)+(dy*dy);
if (ang[j].dis<a) ang[j].dis=a;
}
for (aa=ang,i=0;i<angs;i++,aa++) aa->dis=sqrt(aa->dis);
// ang[].adis
for (aa=ang,i=0;i<angs;i++,aa++)
for (bb=ang,j=0;j<angs;j++,bb++)
{
a=fabs(aa->ang-bb->ang);
if (a>M_PI) a=(2.0*M_PI)-a;
if (a<=0.5*M_PI)
{
a=bb->dis*cos(a);
if (aa->pdis<a) aa->pdis=a;
}
}
// find best oriented bbox (the best angle is ang[j].ang)
for (b=0,j=0,i=0;i<angs;i++)
{
dx =ang[i].pdis; i+=angs4; i%=angs;
dy =ang[i].pdis; i+=angs4; i%=angs;
dx+=ang[i].pdis; i+=angs4; i%=angs;
dy+=ang[i].pdis; i+=angs4; i%=angs;
a=dx*dy; if ((b>a)||(i==0)) { b=a; j=i; }
}
// compute endpoints for OBB
i=j;
ppp[0].x=ang[i].pdis*cos(ang[i].ang);
ppp[0].y=ang[i].pdis*sin(ang[i].ang); i+=angs4; i%=angs;
ppp[1].x=ang[i].pdis*cos(ang[i].ang);
ppp[1].y=ang[i].pdis*sin(ang[i].ang); i+=angs4; i%=angs;
ppp[2].x=ang[i].pdis*cos(ang[i].ang);
ppp[2].y=ang[i].pdis*sin(ang[i].ang); i+=angs4; i%=angs;
ppp[3].x=ang[i].pdis*cos(ang[i].ang);
ppp[3].y=ang[i].pdis*sin(ang[i].ang); i+=angs4; i%=angs;
obb[0].x=center.x+ppp[0].x+ppp[3].x;
obb[0].y=center.y+ppp[0].y+ppp[3].y;
obb[1].x=center.x+ppp[1].x+ppp[0].x;
obb[1].y=center.y+ppp[1].y+ppp[0].y;
obb[2].x=center.x+ppp[2].x+ppp[1].x;
obb[2].y=center.y+ppp[2].y+ppp[1].y;
obb[3].x=center.x+ppp[3].x+ppp[2].x;
obb[3].y=center.y+ppp[3].y+ppp[2].y;
}
//---------------------------------------------------------------------------
我用我的动态列表模板所以:
List<double> xxx;
相同double xxx[];
xxx.add(5);
增加5
结束列表的xxx[7]
访问数组元素(安全) xxx.dat[7]
访问数组元素(不安全的,但快速直达) xxx.num
是数组 xxx.reset()
的实际使用的大小将清除阵列,并设置xxx.num=0
xxx.allocate(100)
为100
项目预分配的空间
您可以忽略// convert bmp -> pnt[]
VCL部分,因为您已经获得了您的数据。
很好,非常感谢您提供的详细和复杂的解决方案。 –
- 1. 如何计算线条和曲线的最近点? ..或曲线和曲线?
- 2. 如何计算曲线上的点?
- 3. 在SAS如何计算曲线
- 4. 计算基数样条曲线的切线
- 5. 贝塞尔曲线计算
- 6. 计算平均曲线
- 7. Java游戏,计算曲线
- 8. OpenCV:如何合并多条线到一条曲线
- 9. 如何计算Javascript中线性浮点数的曲线?
- 10. 多条曲线数据帧
- 11. 批量多条曲线
- 12. 多条曲线使用Matplotlib
- 13. 如何计算不同大小的两条曲线(矩阵)的残差?
- 14. 计算样条曲线的最佳数量从集合点
- 15. 计算2条曲线之间的面积
- 16. 计算两条曲线(即正态分布)之间的面积
- 17. 如何在计算机视觉算法中绘制ROC曲线?
- 18. Prolog - 计算Koch曲线的坐标
- 19. 以编程方式计算的曲线?
- 20. 计算曲线之间的距离
- 21. 如何计算利萨如曲线的周期
- 22. 如何从R中的ACc曲线计算Vcmax的多个结果?
- 23. 如何计算平滑曲线的斜率中的R
- 24. 如何用条件计算多行
- 25. 如何计算网格曲面上的一致切线向量?
- 26. 如何计算曲线绘制三点之间的点数?
- 27. 如何进行多线程计算Android
- 28. 如何计算边界框内绘制线条中的线宽
- 29. 使用ZedGraph的多条曲线
- 30. 更新图中的多条曲线R
为什么使用OBB作为线段?线段本身的OBB不是线段吗? – gue
是的,这确实对于单线段,但是这个算法是用来计算多条曲线的OBB?如果有2个非共线线段,则OBB不会是线段。 –
@My_Cat_Jessica添加图像与真实数据...和C++源我用于创建图像我作为概念验证 – Spektre