minAreaRect-OpenCV

由于要将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);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

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

RotatedRect rRect;
rRect = minAreaRect(point);
Point2f vertices[4];
rRect.points(vertices);
 
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

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); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值