由于要将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);}
12345671234567cvMinAreaRect2: 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
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394951234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495OpenCV以图像的左上角为(0,0),Point(x,y),x对应列,y对应行,
RotatedRect rRect;rRect = minAreaRect(point);Point2f vertices[4];rRect.points(vertices);
12341234rRect.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.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);