minAreaRect-OpenCV

8 篇文章 0 订阅
7 篇文章 0 订阅

由于要将rRect利用仿射变换裁剪下来并旋正,需要知道rRect.point()的四个点的位置,查了一下资料,记在下面:

简介:Finds a circumscribed rectangle of the minimal area for 2D point set by building convex hull for the set and applying rotating calipers4 technique to the hull.1 建立外凸包,应用旋转卡尺技术来求2维点的最小面积包围矩形。
API reference
OpenCV官方例程

源码:
OpenCV249\opencv\sources\modules\imgproc\src\contours.cpp 1910行-1916行

cv::RotatedRect cv::minAreaRect( InputArray _points )
{
    Mat points = _points.getMat();
    CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S));
    CvMat _cpoints = points;
    return cvMinAreaRect2(&_cpoints, 0);
}

cvMinAreaRect2: 2

http://fossies.org/dox/OpenCV-2.4.4a/rotcalipers_8cpp_source.html
截取自第347行

 347 CV_IMPL  CvBox2D
  348 cvMinAreaRect2( const CvArr* array, CvMemStorage* storage )
  349 {
  350     cv::Ptr<CvMemStorage> temp_storage;
  351     CvBox2D box;
  352     cv::AutoBuffer<CvPoint2D32f> _points;
  353     CvPoint2D32f* points;
  354 
  355     memset(&box, 0, sizeof(box));
  356 
  357     int i, n;
  358     CvSeqReader reader;
  359     CvContour contour_header;
  360     CvSeqBlock block;
  361     CvSeq* ptseq = (CvSeq*)array;
  362     CvPoint2D32f out[3];
  363 
  364     if( CV_IS_SEQ(ptseq) )
  365     {
  366         if( !CV_IS_SEQ_POINT_SET(ptseq) &&
  367             (CV_SEQ_KIND(ptseq) != CV_SEQ_KIND_CURVE ||
  368             CV_SEQ_ELTYPE(ptseq) != CV_SEQ_ELTYPE_PPOINT ))
  369             CV_Error( CV_StsUnsupportedFormat,
  370                 "Input sequence must consist of 2d points or pointers to 2d points" );
  371         if( !storage )
  372             storage = ptseq->storage;
  373     }
  374     else
  375     {
  376         ptseq = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block );
  377     }
  378 
  379     if( storage )
  380     {
  381         temp_storage = cvCreateChildMemStorage( storage );
  382     }
  383     else
  384     {
  385         temp_storage = cvCreateMemStorage(1 << 10);
  386     }
  387 
  388     ptseq = cvConvexHull2( ptseq, temp_storage, CV_CLOCKWISE, 1 );
  389     n = ptseq->total;
  390 
  391     _points.allocate(n);
  392     points = _points;
  393     cvStartReadSeq( ptseq, &reader );
  394 
  395     if( CV_SEQ_ELTYPE( ptseq ) == CV_32SC2 )
  396     {
  397         for( i = 0; i < n; i++ )
  398         {
  399             CvPoint pt;
  400             CV_READ_SEQ_ELEM( pt, reader );
  401             points[i].x = (float)pt.x;
  402             points[i].y = (float)pt.y;
  403         }
  404     }
  405     else
  406     {
  407         for( i = 0; i < n; i++ )
  408         {
  409             CV_READ_SEQ_ELEM( points[i], reader );
  410         }
  411     }
  412 
  413     if( n > 2 )
  414     {
  415         icvRotatingCalipers( points, n, CV_CALIPERS_MINAREARECT, (float*)out );
  416         box.center.x = out[0].x + (out[1].x + out[2].x)*0.5f;
  417         box.center.y = out[0].y + (out[1].y + out[2].y)*0.5f;
  418         box.size.width = (float)sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y);
  419         box.size.height = (float)sqrt((double)out[2].x*out[2].x + (double)out[2].y*out[2].y);
  420         box.angle = (float)atan2( (double)out[1].y, (double)out[1].x );
  421     }
  422     else if( n == 2 )
  423     {
  424         box.center.x = (points[0].x + points[1].x)*0.5f;
  425         box.center.y = (points[0].y + points[1].y)*0.5f;
  426         double dx = points[1].x - points[0].x;
  427         double dy = points[1].y - points[0].y;
  428         box.size.width = (float)sqrt(dx*dx + dy*dy);
  429         box.size.height = 0;
  430         box.angle = (float)atan2( dy, dx );
  431     }
  432     else
  433     {
  434         if( n == 1 )
  435             box.center = points[0];
  436     }
  437 
  438     box.angle = (float)(box.angle*180/CV_PI);
  439     return box;
  440 }
  441

OpenCV以图像的左上角为(0,0),Point(x,y),x对应列,y对应行,

RotatedRect rRect;
rRect = minAreaRect(point);
Point2f vertices[4];
rRect.points(vertices);

rRect.size.widthrRect.size.heightrRect.anglevertices[0]vertices[1]vertices[2]vertices[3]如下图所示,和mine1024博客3里Cvbox2D好像不太一样,改天验证下。

这里写图片描述这里写图片描述

利用仿射变换,将该区域裁剪下来,并旋正:

    vector<Point> point;
    vector<vector<Point>> contours ;
    findContours( Itwe, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE );
    if(!contours.size())
    {
        printf("No contours!\n");
        return 0;
    }
    else
    {
        double maxarea = 0;
        int maxareai = 0;
        for (int i = 0; i<contours.size(); i++)
        {
            double tmparea = fabs(contourArea(contours[i]));
            if(tmparea > maxarea)
            {tmparea = tmparea;
            maxareai = i;}  
        }
        vector<Point> contourspoint = contours[maxareai];
    }
    RotatedRect rRect;
    rRect = minAreaRect(point);
    int dstw,dsth;
    Point2f vertices[4];
    Point2f verdst[4];

    if(rRect.size.width>rRect.size.height)
    {
        //rRect.size.width += 100;  //宽度增加100,以防定位偏差
        rRect.points(vertices);
        dstw = rRect.size.width;
        dsth = rRect.size.height;
        verdst[0] = Point2f(0,dsth);
        verdst[1] = Point2f(0,0);
        verdst[2] = Point2f(dstw,0);
        verdst[3] = Point2f(dstw,dsth); 
    }
    else 
    {
        //rRect.size.height += 100;
        rRect.points(vertices);
        dstw = rRect.size.height;
        dsth = rRect.size.width;
        verdst[0] = Point2f(dstw,dsth);
        verdst[1] = Point2f(0,dsth);
        verdst[2] = Point2f(0,0);
        verdst[3] = Point2f(dstw,0);

    }
    Mat Idst = Mat(dsth,dstw,CV_8UC1);
    Mat warpMatrix = getPerspectiveTransform(vertices, verdst);
    warpPerspective(Isrc, Idst, warpMatrix, Idst.size(), INTER_LINEAR, BORDER_CONSTANT); 
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Python中使用OpenCV绘制矩形框的方法有多种。引用\[1\]中的代码展示了一种方法,通过cv2.minAreaRect()函数获取最小外接矩形的信息,然后使用cv2.boxPoints()函数将其转换为矩形框的四个顶点坐标。引用\[2\]中的代码展示了另一种方法,直接使用cv2.rectangle()函数绘制矩形框。你可以指定矩形框的左上角和右下角坐标,以及线的颜色、线宽等参数。引用\[3\]中的代码展示了如何使用cv2.boundingRect()函数获取轮廓的范围,并使用cv2.rectangle()函数绘制矩形框。你可以指定矩形框的左上角和右下角坐标,以及线的颜色、线宽等参数。这些方法都可以用来绘制矩形框,具体使用哪种方法取决于你的需求和代码结构。 #### 引用[.reference_title] - *1* *3* [OpenCV—Python 轮廓检测 绘出矩形框(findContours\ boundingRect\rectangle)](https://blog.csdn.net/wsp_1138886114/article/details/82945328)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [opencv-python绘制矩形框](https://blog.csdn.net/Vertira/article/details/123788719)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值