mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
Merge pull request #27479 from fengyuentau:4x/imgproc/boundingRect-simd
imgproc: supports CV_SIMD_SCALABLE in pointSetBoundingRect #27479 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -710,171 +710,108 @@ static Rect pointSetBoundingRect( const Mat& points )
|
||||
int depth = points.depth();
|
||||
CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S));
|
||||
|
||||
int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i;
|
||||
int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i = 0;
|
||||
bool is_float = depth == CV_32F;
|
||||
|
||||
if( npoints == 0 )
|
||||
return Rect();
|
||||
|
||||
#if CV_SIMD // TODO: enable for CV_SIMD_SCALABLE, loop tail related.
|
||||
if( !is_float )
|
||||
{
|
||||
const int32_t* pts = points.ptr<int32_t>();
|
||||
int64_t firstval = 0;
|
||||
std::memcpy(&firstval, pts, sizeof(pts[0]) * 2);
|
||||
xmin = xmax = pts[0];
|
||||
ymin = ymax = pts[1];
|
||||
#if CV_SIMD || CV_SIMD_SCALABLE
|
||||
v_int32 minval, maxval;
|
||||
minval = maxval = v_reinterpret_as_s32(vx_setall_s64(firstval)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y
|
||||
for( i = 1; i <= npoints - VTraits<v_int32>::vlanes()/2; i+= VTraits<v_int32>::vlanes()/2 )
|
||||
const int nlanes = VTraits<v_int32>::vlanes()/2;
|
||||
for (; i < npoints; i += nlanes)
|
||||
{
|
||||
if (i > npoints - nlanes)
|
||||
{
|
||||
if (i == 0)
|
||||
break;
|
||||
i = npoints - nlanes;
|
||||
}
|
||||
v_int32 ptXY2 = vx_load(pts + 2 * 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<v_int32>::vlanes()/4 )
|
||||
constexpr int max_nlanes = VTraits<v_int32>::max_nlanes;
|
||||
int arr_minval[max_nlanes], arr_maxval[max_nlanes];
|
||||
vx_store(arr_minval, minval);
|
||||
vx_store(arr_maxval, maxval);
|
||||
for (int j = 0; j < nlanes; j++)
|
||||
{
|
||||
v_int32 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + 2 * i))));
|
||||
minval = v_min(ptXY, minval);
|
||||
maxval = v_max(ptXY, maxval);
|
||||
i += VTraits<v_int64>::vlanes()/2;
|
||||
xmin = std::min(xmin, arr_minval[2*j]);
|
||||
ymin = std::min(ymin, arr_minval[2*j+1]);
|
||||
xmax = std::max(xmax, arr_maxval[2*j]);
|
||||
ymax = std::max(ymax, arr_maxval[2*j+1]);
|
||||
}
|
||||
for(int j = 16; j < VTraits<v_uint8>::vlanes(); j*=2)
|
||||
#endif
|
||||
for( ; i < npoints; i++ )
|
||||
{
|
||||
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))));
|
||||
int pt_x = pts[2*i];
|
||||
int pt_y = pts[2*i+1];
|
||||
|
||||
xmin = std::min(xmin, pt_x);
|
||||
xmax = std::max(xmax, pt_x);
|
||||
ymin = std::min(ymin, pt_y);
|
||||
ymax = std::max(ymax, pt_y);
|
||||
}
|
||||
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 + 2 * i))));
|
||||
for( i++; i < npoints; i++ )
|
||||
{
|
||||
v_int32x4 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + 2 * 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
|
||||
{
|
||||
const float* pts = points.ptr<float>();
|
||||
int64_t firstval = 0;
|
||||
std::memcpy(&firstval, pts, sizeof(pts[0]) * 2);
|
||||
xmin = xmax = cvFloor(pts[0]);
|
||||
ymin = ymax = cvFloor(pts[1]);
|
||||
#if CV_SIMD || CV_SIMD_SCALABLE
|
||||
v_float32 minval, maxval;
|
||||
minval = maxval = v_reinterpret_as_f32(vx_setall_s64(firstval)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y
|
||||
for( i = 1; i <= npoints - VTraits<v_float32>::vlanes()/2; i+= VTraits<v_float32>::vlanes()/2 )
|
||||
const int nlanes = VTraits<v_float32>::vlanes()/2;
|
||||
for (; i < npoints; i += nlanes)
|
||||
{
|
||||
if (i > npoints - nlanes)
|
||||
{
|
||||
if (i == 0)
|
||||
break;
|
||||
i = npoints - nlanes;
|
||||
}
|
||||
v_float32 ptXY2 = vx_load(pts + 2 * 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<v_float32>::vlanes()/4 )
|
||||
constexpr int max_nlanes = VTraits<v_int32>::max_nlanes;
|
||||
float arr_minval[max_nlanes], arr_maxval[max_nlanes];
|
||||
vx_store(arr_minval, minval);
|
||||
vx_store(arr_maxval, maxval);
|
||||
for (int j = 0; j < nlanes; j++)
|
||||
{
|
||||
v_float32 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + 2 * i))));
|
||||
minval = v_min(ptXY, minval);
|
||||
maxval = v_max(ptXY, maxval);
|
||||
i += VTraits<v_float32>::vlanes()/4;
|
||||
}
|
||||
for(int j = 16; j < VTraits<v_uint8>::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 + 2 * i))));
|
||||
for( i++; i < npoints; i++ )
|
||||
{
|
||||
v_float32x4 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + 2 * 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))))));
|
||||
int _xmin = cvFloor(arr_minval[2*j]), _ymin = cvFloor(arr_minval[2*j+1]);
|
||||
int _xmax = cvFloor(arr_maxval[2*j]), _ymax = cvFloor(arr_maxval[2*j+1]);
|
||||
xmin = std::min(xmin, _xmin);
|
||||
ymin = std::min(ymin, _ymin);
|
||||
xmax = std::max(xmax, _xmax);
|
||||
ymax = std::max(ymax, _ymax);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
const Point* pts = points.ptr<Point>();
|
||||
Point pt = pts[0];
|
||||
|
||||
if( !is_float )
|
||||
{
|
||||
xmin = xmax = pt.x;
|
||||
ymin = ymax = pt.y;
|
||||
|
||||
for( i = 1; i < npoints; i++ )
|
||||
for( ; i < npoints; i++ )
|
||||
{
|
||||
pt = pts[i];
|
||||
// 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
|
||||
int pt_x = cvFloor(pts[2*i]);
|
||||
int pt_y = cvFloor(pts[2*i+1]);
|
||||
|
||||
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;
|
||||
xmin = std::min(xmin, pt_x);
|
||||
xmax = std::max(xmax, pt_x);
|
||||
ymin = std::min(ymin, pt_y);
|
||||
ymax = std::max(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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user