From d77dbbe7a0c791deaf7f9c612cbfaa36a5e55b0c Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 17 Apr 2024 14:49:28 +0300 Subject: [PATCH] imgproc: sync boundingRect function with 5.x --- modules/imgproc/src/geometry.cpp | 331 ++++++++++++++++++++++++++++ modules/imgproc/src/shapedescr.cpp | 334 ----------------------------- 2 files changed, 331 insertions(+), 334 deletions(-) diff --git a/modules/imgproc/src/geometry.cpp b/modules/imgproc/src/geometry.cpp index ae14590f22..8cf2474787 100644 --- a/modules/imgproc/src/geometry.cpp +++ b/modules/imgproc/src/geometry.cpp @@ -39,7 +39,9 @@ // //M*/ #include "precomp.hpp" +#include "opencv2/core/hal/intrin.hpp" +using namespace cv; CV_IMPL CvRect cvMaxRect( const CvRect* rect1, const CvRect* rect2 ) @@ -592,3 +594,332 @@ float cv::intersectConvexConvex( InputArray _p1, InputArray _p2, OutputArray _p1 } return (float)fabs(area); } + +static Rect maskBoundingRect( const Mat& img ) +{ + CV_Assert( img.depth() <= CV_8S && img.channels() == 1 ); + + Size size = img.size(); + int xmin = size.width, ymin = -1, xmax = -1, ymax = -1, i, j, k; + + for( i = 0; i < size.height; i++ ) + { + const uchar* _ptr = img.ptr(i); + const uchar* ptr = (const uchar*)alignPtr(_ptr, 4); + int have_nz = 0, k_min, offset = (int)(ptr - _ptr); + j = 0; + offset = MIN(offset, size.width); + for( ; j < offset; j++ ) + if( _ptr[j] ) + { + if( j < xmin ) + xmin = j; + if( j > xmax ) + xmax = j; + have_nz = 1; + } + if( offset < size.width ) + { + xmin -= offset; + xmax -= offset; + size.width -= offset; + j = 0; + for( ; j <= xmin - 4; j += 4 ) + if( *((int*)(ptr+j)) ) + break; + for( ; j < xmin; j++ ) + if( ptr[j] ) + { + xmin = j; + if( j > xmax ) + xmax = j; + have_nz = 1; + break; + } + k_min = MAX(j-1, xmax); + k = size.width - 1; + for( ; k > k_min && (k&3) != 3; k-- ) + if( ptr[k] ) + break; + if( k > k_min && (k&3) == 3 ) + { + for( ; k > k_min+3; k -= 4 ) + if( *((int*)(ptr+k-3)) ) + break; + } + for( ; k > k_min; k-- ) + if( ptr[k] ) + { + xmax = k; + have_nz = 1; + break; + } + if( !have_nz ) + { + j &= ~3; + for( ; j <= k - 3; j += 4 ) + if( *((int*)(ptr+j)) ) + break; + for( ; j <= k; j++ ) + if( ptr[j] ) + { + have_nz = 1; + break; + } + } + xmin += offset; + xmax += offset; + size.width += offset; + } + if( have_nz ) + { + if( ymin < 0 ) + ymin = i; + ymax = i; + } + } + + if( xmin >= size.width ) + xmin = ymin = 0; + return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); +} + +// Calculates bounding rectangle of a point set or retrieves already calculated +static Rect pointSetBoundingRect( const Mat& points ) +{ + int npoints = points.checkVector(2); + int depth = points.depth(); + CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S)); + + int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i; + bool is_float = depth == CV_32F; + + if( npoints == 0 ) + return Rect(); + +#if CV_SIMD // TODO: enable for CV_SIMD_SCALABLE, loop tail related. + const int64_t* pts = points.ptr(); + + if( !is_float ) + { + v_int32 minval, maxval; + minval = maxval = v_reinterpret_as_s32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y + for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) + { + v_int32 ptXY2 = v_reinterpret_as_s32(vx_load(pts + i)); + minval = v_min(ptXY2, minval); + maxval = v_max(ptXY2, maxval); + } + minval = v_min(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); + maxval = v_max(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); + if( i <= npoints - VTraits::vlanes()/4 ) + { + v_int32 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); + minval = v_min(ptXY, minval); + maxval = v_max(ptXY, maxval); + i += VTraits::vlanes()/2; + } + for(int j = 16; j < VTraits::vlanes(); j*=2) + { + minval = v_min(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); + maxval = v_max(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); + } + xmin = v_get0(minval); + xmax = v_get0(maxval); + ymin = v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); + ymax = v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); +#if CV_SIMD_WIDTH > 16 + if( i < npoints ) + { + v_int32x4 minval2, maxval2; + minval2 = maxval2 = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + for( i++; i < npoints; i++ ) + { + v_int32x4 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + minval2 = v_min(ptXY, minval2); + maxval2 = v_max(ptXY, maxval2); + } + xmin = min(xmin, v_get0(minval2)); + xmax = max(xmax, v_get0(maxval2)); + ymin = min(ymin, v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval2))))); + ymax = max(ymax, v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval2))))); + } +#endif // CV_SIMD + } + else + { + v_float32 minval, maxval; + minval = maxval = v_reinterpret_as_f32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y + for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) + { + v_float32 ptXY2 = v_reinterpret_as_f32(vx_load(pts + i)); + minval = v_min(ptXY2, minval); + maxval = v_max(ptXY2, maxval); + } + minval = v_min(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval)))); + maxval = v_max(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval)))); + if( i <= npoints - VTraits::vlanes()/4 ) + { + v_float32 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); + minval = v_min(ptXY, minval); + maxval = v_max(ptXY, maxval); + i += VTraits::vlanes()/4; + } + for(int j = 16; j < VTraits::vlanes(); j*=2) + { + minval = v_min(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval)))); + maxval = v_max(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval)))); + } + xmin = cvFloor(v_get0(minval)); + xmax = cvFloor(v_get0(maxval)); + ymin = cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval))))); + ymax = cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval))))); +#if CV_SIMD_WIDTH > 16 + if( i < npoints ) + { + v_float32x4 minval2, maxval2; + minval2 = maxval2 = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + for( i++; i < npoints; i++ ) + { + v_float32x4 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + minval2 = v_min(ptXY, minval2); + maxval2 = v_max(ptXY, maxval2); + } + xmin = min(xmin, cvFloor(v_get0(minval2))); + xmax = max(xmax, cvFloor(v_get0(maxval2))); + ymin = min(ymin, cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval2)))))); + ymax = max(ymax, cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval2)))))); + } +#endif + } +#else + const Point* pts = points.ptr(); + Point pt = pts[0]; + + if( !is_float ) + { + xmin = xmax = pt.x; + ymin = ymax = pt.y; + + for( i = 1; i < npoints; i++ ) + { + pt = pts[i]; + + if( xmin > pt.x ) + xmin = pt.x; + + if( xmax < pt.x ) + xmax = pt.x; + + if( ymin > pt.y ) + ymin = pt.y; + + if( ymax < pt.y ) + ymax = pt.y; + } + } + else + { + Cv32suf v; + // init values + xmin = xmax = CV_TOGGLE_FLT(pt.x); + ymin = ymax = CV_TOGGLE_FLT(pt.y); + + for( i = 1; i < npoints; i++ ) + { + pt = pts[i]; + pt.x = CV_TOGGLE_FLT(pt.x); + pt.y = CV_TOGGLE_FLT(pt.y); + + if( xmin > pt.x ) + xmin = pt.x; + + if( xmax < pt.x ) + xmax = pt.x; + + if( ymin > pt.y ) + ymin = pt.y; + + if( ymax < pt.y ) + ymax = pt.y; + } + + v.i = CV_TOGGLE_FLT(xmin); xmin = cvFloor(v.f); + v.i = CV_TOGGLE_FLT(ymin); ymin = cvFloor(v.f); + // because right and bottom sides of the bounding rectangle are not inclusive + // (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil + v.i = CV_TOGGLE_FLT(xmax); xmax = cvFloor(v.f); + v.i = CV_TOGGLE_FLT(ymax); ymax = cvFloor(v.f); + } +#endif + + return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); +} + + +cv::Rect cv::boundingRect(InputArray array) +{ + CV_INSTRUMENT_REGION(); + + Mat m = array.getMat(); + return m.depth() <= CV_8U ? maskBoundingRect(m) : pointSetBoundingRect(m); +} + + +/* Calculates bounding rectangle of a point set or retrieves already calculated */ +CV_IMPL CvRect +cvBoundingRect( CvArr* array, int update ) +{ + cv::Rect rect; + CvContour contour_header; + CvSeq* ptseq = 0; + CvSeqBlock block; + + CvMat stub, *mat = 0; + int calculate = update; + + if( CV_IS_SEQ( array )) + { + ptseq = (CvSeq*)array; + if( !CV_IS_SEQ_POINT_SET( ptseq )) + CV_Error( cv::Error::StsBadArg, "Unsupported sequence type" ); + + if( ptseq->header_size < (int)sizeof(CvContour)) + { + update = 0; + calculate = 1; + } + } + else + { + mat = cvGetMat( array, &stub ); + if( CV_MAT_TYPE(mat->type) == CV_32SC2 || + CV_MAT_TYPE(mat->type) == CV_32FC2 ) + { + ptseq = cvPointSeqFromMat(CV_SEQ_KIND_GENERIC, mat, &contour_header, &block); + mat = 0; + } + else if( CV_MAT_TYPE(mat->type) != CV_8UC1 && + CV_MAT_TYPE(mat->type) != CV_8SC1 ) + CV_Error( cv::Error::StsUnsupportedFormat, + "The image/matrix format is not supported by the function" ); + update = 0; + calculate = 1; + } + + if( !calculate ) + return ((CvContour*)ptseq)->rect; + + if( mat ) + { + rect = cvRect(maskBoundingRect(cv::cvarrToMat(mat))); + } + else if( ptseq->total ) + { + cv::AutoBuffer abuf; + rect = cvRect(pointSetBoundingRect(cv::cvarrToMat(ptseq, false, false, 0, &abuf))); + } + if( update ) + ((CvContour*)ptseq)->rect = cvRect(rect); + return cvRect(rect); +} diff --git a/modules/imgproc/src/shapedescr.cpp b/modules/imgproc/src/shapedescr.cpp index 9be6038d9d..007bf9ac62 100644 --- a/modules/imgproc/src/shapedescr.cpp +++ b/modules/imgproc/src/shapedescr.cpp @@ -862,282 +862,6 @@ cv::RotatedRect cv::fitEllipseDirect( InputArray _points ) return box; } - -namespace cv -{ - -// Calculates bounding rectangle of a point set or retrieves already calculated -static Rect pointSetBoundingRect( const Mat& points ) -{ - int npoints = points.checkVector(2); - int depth = points.depth(); - CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S)); - - int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i; - bool is_float = depth == CV_32F; - - if( npoints == 0 ) - return Rect(); - -#if CV_SIMD // TODO: enable for CV_SIMD_SCALABLE, loop tail related. - const int64_t* pts = points.ptr(); - - if( !is_float ) - { - v_int32 minval, maxval; - minval = maxval = v_reinterpret_as_s32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y - for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) - { - v_int32 ptXY2 = v_reinterpret_as_s32(vx_load(pts + i)); - minval = v_min(ptXY2, minval); - maxval = v_max(ptXY2, maxval); - } - minval = v_min(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); - maxval = v_max(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); - if( i <= npoints - VTraits::vlanes()/4 ) - { - v_int32 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); - minval = v_min(ptXY, minval); - maxval = v_max(ptXY, maxval); - i += VTraits::vlanes()/2; - } - for(int j = 16; j < VTraits::vlanes(); j*=2) - { - minval = v_min(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); - maxval = v_max(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); - } - xmin = v_get0(minval); - xmax = v_get0(maxval); - ymin = v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); - ymax = v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); -#if CV_SIMD_WIDTH > 16 - if( i < npoints ) - { - v_int32x4 minval2, maxval2; - minval2 = maxval2 = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); - for( i++; i < npoints; i++ ) - { - v_int32x4 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); - minval2 = v_min(ptXY, minval2); - maxval2 = v_max(ptXY, maxval2); - } - xmin = min(xmin, v_get0(minval2)); - xmax = max(xmax, v_get0(maxval2)); - ymin = min(ymin, v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval2))))); - ymax = max(ymax, v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval2))))); - } -#endif // CV_SIMD - } - else - { - v_float32 minval, maxval; - minval = maxval = v_reinterpret_as_f32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y - for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) - { - v_float32 ptXY2 = v_reinterpret_as_f32(vx_load(pts + i)); - minval = v_min(ptXY2, minval); - maxval = v_max(ptXY2, maxval); - } - minval = v_min(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval)))); - maxval = v_max(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval)))); - if( i <= npoints - VTraits::vlanes()/4 ) - { - v_float32 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); - minval = v_min(ptXY, minval); - maxval = v_max(ptXY, maxval); - i += VTraits::vlanes()/4; - } - for(int j = 16; j < VTraits::vlanes(); j*=2) - { - minval = v_min(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval)))); - maxval = v_max(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval)))); - } - xmin = cvFloor(v_get0(minval)); - xmax = cvFloor(v_get0(maxval)); - ymin = cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval))))); - ymax = cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval))))); -#if CV_SIMD_WIDTH > 16 - if( i < npoints ) - { - v_float32x4 minval2, maxval2; - minval2 = maxval2 = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); - for( i++; i < npoints; i++ ) - { - v_float32x4 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); - minval2 = v_min(ptXY, minval2); - maxval2 = v_max(ptXY, maxval2); - } - xmin = min(xmin, cvFloor(v_get0(minval2))); - xmax = max(xmax, cvFloor(v_get0(maxval2))); - ymin = min(ymin, cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval2)))))); - ymax = max(ymax, cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval2)))))); - } -#endif - } -#else - const Point* pts = points.ptr(); - Point pt = pts[0]; - - if( !is_float ) - { - xmin = xmax = pt.x; - ymin = ymax = pt.y; - - for( i = 1; i < npoints; i++ ) - { - pt = pts[i]; - - if( xmin > pt.x ) - xmin = pt.x; - - if( xmax < pt.x ) - xmax = pt.x; - - if( ymin > pt.y ) - ymin = pt.y; - - if( ymax < pt.y ) - ymax = pt.y; - } - } - else - { - Cv32suf v; - // init values - xmin = xmax = CV_TOGGLE_FLT(pt.x); - ymin = ymax = CV_TOGGLE_FLT(pt.y); - - for( i = 1; i < npoints; i++ ) - { - pt = pts[i]; - pt.x = CV_TOGGLE_FLT(pt.x); - pt.y = CV_TOGGLE_FLT(pt.y); - - if( xmin > pt.x ) - xmin = pt.x; - - if( xmax < pt.x ) - xmax = pt.x; - - if( ymin > pt.y ) - ymin = pt.y; - - if( ymax < pt.y ) - ymax = pt.y; - } - - v.i = CV_TOGGLE_FLT(xmin); xmin = cvFloor(v.f); - v.i = CV_TOGGLE_FLT(ymin); ymin = cvFloor(v.f); - // because right and bottom sides of the bounding rectangle are not inclusive - // (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil - v.i = CV_TOGGLE_FLT(xmax); xmax = cvFloor(v.f); - v.i = CV_TOGGLE_FLT(ymax); ymax = cvFloor(v.f); - } -#endif - - return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); -} - - -static Rect maskBoundingRect( const Mat& img ) -{ - CV_Assert( img.depth() <= CV_8S && img.channels() == 1 ); - - Size size = img.size(); - int xmin = size.width, ymin = -1, xmax = -1, ymax = -1, i, j, k; - - for( i = 0; i < size.height; i++ ) - { - const uchar* _ptr = img.ptr(i); - const uchar* ptr = (const uchar*)alignPtr(_ptr, 4); - int have_nz = 0, k_min, offset = (int)(ptr - _ptr); - j = 0; - offset = MIN(offset, size.width); - for( ; j < offset; j++ ) - if( _ptr[j] ) - { - if( j < xmin ) - xmin = j; - if( j > xmax ) - xmax = j; - have_nz = 1; - } - if( offset < size.width ) - { - xmin -= offset; - xmax -= offset; - size.width -= offset; - j = 0; - for( ; j <= xmin - 4; j += 4 ) - if( *((int*)(ptr+j)) ) - break; - for( ; j < xmin; j++ ) - if( ptr[j] ) - { - xmin = j; - if( j > xmax ) - xmax = j; - have_nz = 1; - break; - } - k_min = MAX(j-1, xmax); - k = size.width - 1; - for( ; k > k_min && (k&3) != 3; k-- ) - if( ptr[k] ) - break; - if( k > k_min && (k&3) == 3 ) - { - for( ; k > k_min+3; k -= 4 ) - if( *((int*)(ptr+k-3)) ) - break; - } - for( ; k > k_min; k-- ) - if( ptr[k] ) - { - xmax = k; - have_nz = 1; - break; - } - if( !have_nz ) - { - j &= ~3; - for( ; j <= k - 3; j += 4 ) - if( *((int*)(ptr+j)) ) - break; - for( ; j <= k; j++ ) - if( ptr[j] ) - { - have_nz = 1; - break; - } - } - xmin += offset; - xmax += offset; - size.width += offset; - } - if( have_nz ) - { - if( ymin < 0 ) - ymin = i; - ymax = i; - } - } - - if( xmin >= size.width ) - xmin = ymin = 0; - return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); -} - -} - -cv::Rect cv::boundingRect(InputArray array) -{ - CV_INSTRUMENT_REGION(); - - Mat m = array.getMat(); - return m.depth() <= CV_8U ? maskBoundingRect(m) : pointSetBoundingRect(m); -} - ////////////////////////////////////////////// C API /////////////////////////////////////////// CV_IMPL int @@ -1478,62 +1202,4 @@ cvFitEllipse2( const CvArr* array ) return cvBox2D(cv::fitEllipse(points)); } -/* Calculates bounding rectangle of a point set or retrieves already calculated */ -CV_IMPL CvRect -cvBoundingRect( CvArr* array, int update ) -{ - cv::Rect rect; - CvContour contour_header; - CvSeq* ptseq = 0; - CvSeqBlock block; - - CvMat stub, *mat = 0; - int calculate = update; - - if( CV_IS_SEQ( array )) - { - ptseq = (CvSeq*)array; - if( !CV_IS_SEQ_POINT_SET( ptseq )) - CV_Error( cv::Error::StsBadArg, "Unsupported sequence type" ); - - if( ptseq->header_size < (int)sizeof(CvContour)) - { - update = 0; - calculate = 1; - } - } - else - { - mat = cvGetMat( array, &stub ); - if( CV_MAT_TYPE(mat->type) == CV_32SC2 || - CV_MAT_TYPE(mat->type) == CV_32FC2 ) - { - ptseq = cvPointSeqFromMat(CV_SEQ_KIND_GENERIC, mat, &contour_header, &block); - mat = 0; - } - else if( CV_MAT_TYPE(mat->type) != CV_8UC1 && - CV_MAT_TYPE(mat->type) != CV_8SC1 ) - CV_Error( cv::Error::StsUnsupportedFormat, - "The image/matrix format is not supported by the function" ); - update = 0; - calculate = 1; - } - - if( !calculate ) - return ((CvContour*)ptseq)->rect; - - if( mat ) - { - rect = cvRect(cv::maskBoundingRect(cv::cvarrToMat(mat))); - } - else if( ptseq->total ) - { - cv::AutoBuffer abuf; - rect = cvRect(cv::pointSetBoundingRect(cv::cvarrToMat(ptseq, false, false, 0, &abuf))); - } - if( update ) - ((CvContour*)ptseq)->rect = cvRect(rect); - return cvRect(rect); -} - /* End of file. */