由于要将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
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
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);
rRect.size.width
,rRect.size.height
,rRect.angle
,vertices[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.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.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);