`
jgsj
  • 浏览: 1051020 次
文章分类
社区版块
存档分类
最新评论

利用cvMinAreaRect2求取轮廓最小外接矩形

 
阅读更多

转自:http://blog.csdn.net/mine1024/article/details/6044856

对给定的 2D 点集,寻找最小面积的包围矩形,使用函数:

CvBox2DcvMinAreaRect2(constCvArr*points,CvMemStorage*storage=NULL);

points
点序列或点集数组
storage
可选的临时存储仓
函数 cvMinAreaRect2 通过建立凸外形并且旋转外形以寻找给定 2D 点集的最小面积的包围矩形。

其中返回的2D盒子定义如下:

1 typedefstructCvBox2D
2 {
3 CvPoint2D32fcenter;/*盒子的中心*/
4 CvSize2D32fsize;/*盒子的长和宽*/
5 floatangle;/*水平轴与第一个边的夹角,用弧度表示*/
6 }CvBox2D;
注意夹角 angle 是水平轴逆时针旋转,与碰到的第一个边(不管是高还是宽)的夹角。如下图

2010-11-25 9-05-42

可用函数 cvBoxPoints(box[count], point); 寻找盒子的顶点

1 voidcvBoxPoints(CvBox2Dbox,CvPoint2D32fpt[4])
2 {
3 doubleangle=box.angle*CV_PI/180.
4 floata=(float)cos(angle)*0.5f;
5 floatb=(float)sin(angle)*0.5f;
6
7 pt[0].x=box.center.x-a*box.size.height-b*box.size.width;
8 pt[0].y=box.center.y+b*box.size.height-a*box.size.width;
9 pt[1].x=box.center.x+a*box.size.height-b*box.size.width;
10 pt[1].y=box.center.y-b*box.size.height-a*box.size.width;
11 pt[2].x=2*box.center.x-pt[0].x;
12 pt[2].y=2*box.center.y-pt[0].y;
13 pt[3].x=2*box.center.x-pt[1].x;
14 pt[3].y=2*box.center.y-pt[1].y;
15 }
简单证明此函数的计算公式:
计算x,由图可得到三个方程式: pt[1].x-pt[0].x=width*sin(angle)
pt[2].x-pt[1].x=height*cos(angle)
pt[2].x-pt[0].x=2(box.center.x-pt[0].x)
联立方程可解得函数里的计算式,算 y 略。

写了个函数绘制CvBox2D

1 voidDrawBox(CvBox2Dbox,IplImage*img)
2 {
3 CvPoint2D32fpoint[4];
4 inti;
5 for(i=0;i<4;i++)
6 {
7 point[i].x=0;
8 point[i].y=0;
9 }
10 cvBoxPoints(box,point);//计算二维盒子顶点
11 CvPointpt[4];
12 for(i=0;i<4;i++)
13 {
14 pt[i].x=(int)point[i].x;
15 pt[i].y=(int)point[i].y;
16 }
17 cvLine(img,pt[0],pt[1],CV_RGB(255,0,0),2,8,0);
18 cvLine(img,pt[1],pt[2],CV_RGB(255,0,0),2,8,0);
19 cvLine(img,pt[2],pt[3],CV_RGB(255,0,0),2,8,0);
20 cvLine(img,pt[3],pt[0],CV_RGB(255,0,0),2,8,0);
21 }

转自:http://www.opencv.org.cn/forum/viewtopic.php?t=8886

CvBox2D和CvRect最大的区别在于Box是带有角度angle的,而Rect则只能是水平和垂直。
相应的,绘制Box时就不能用cvRectangle()了,可以先算出Box的4个顶点,再用多边形绘制函数cvPolyLine()来画出Box。
同理,要找到最大的矩形,就不能用cvMaxRect,可以逐个计算每个Box的面积 box_area = box.size.width * box.size.height 来找出最大矩形。

//找出完整包含轮廓的最小矩形
CvBox2D rect = cvMinAreaRect2(contour);
//用cvBoxPoints找出矩形的4个顶点
CvPoint2D32f rect_pts0[4];
cvBoxPoints(rect, rect_pts0);
//因为cvPolyLine要求点集的输入类型是CvPoint**
//所以要把 CvPoint2D32f 型的 rect_pts0 转换为 CvPoint 型的 rect_pts
//并赋予一个对应的指针 *pt
int npts = 4;
CvPoint rect_pts[4], *pt = rect_pts;
for (int rp=0; rp<4; rp++)
rect_pts[rp]= cvPointFrom32f(rect_pts0[rp]);
//画出Box
cvPolyLine(dst_img, &pt, &npts, 1, 1, CV_RGB(255,0,0), 2);

分享到:
评论

相关推荐

    连通区域内目标的最小外接矩形及其长、宽.

    对于每个检测到的连通区域,使用`cvMinAreaRect2()`函数计算其最小外接矩形。 - `cvMinAreaRect2()`函数返回一个`CvBox2D`结构体,包含了矩形的中心坐标、尺寸和旋转角度。 #### 4. 长宽计算 根据最小外接矩形的四...

    opencv求取外接矩形

    接着,我们计算了轮廓的长度和面积,并使用`cvMinAreaRect2`函数来计算外接矩形。然后,我们使用`cvMinEnclosingCircle`函数来计算外接圆,并使用`cvFitEllipse2`函数来计算椭圆。最后,我们使用`cvDrawContours`...

    opencv 编写程序-寻找轮廓

    在描述中提到的程序可能是通过以上步骤实现的,具体实现细节可能包括自定义阈值设定、轮廓筛选(例如,只保留面积超过一定值的轮廓)、轮廓拟合(如椭圆或矩形)等。 标签“opencv 寻找轮廓”表明这是一个专注于...

    opencv轮廓的简单应用

    cvFindContours,cvThreshold,cvContourArea,cvArcLength,cvBoundingRect,cvMinAreaRect2,cvBoxPoints,cvMinEnclosingCircle,cvDrawContours。 1.查找轮廓 2.按地址依次取出轮廓 3.计算轮廓的相关参数 4、...

    opencv椭圆检测识别并画出轮廓.docx

    - 对每个轮廓,使用`cvMinAreaRect2`函数来拟合最小外接矩形,再进一步计算椭圆参数。 - 使用`cvEllipse`函数在原图上绘制拟合的椭圆轮廓。 ### 5. 获取椭圆中心点 文档中的代码还提供了一个`GetCPoint`函数,用于...

    aabcdef.rar_CVArcLength_cvBoundingRect_cvFindContours_cvMinAreaR

    cvFindContours,cvThreshold,cvContourArea,cvArcLength,cvBoundingRect,cvMinAreaRect2,cvBoxPoints,cvMinEnclosingCircle,cvDrawContours。 1.查找轮廓 2.按地址依次取出轮廓 3.计算轮廓的相关参数 4...

Global site tag (gtag.js) - Google Analytics