Merge pull request #29989 from vrabaud:variant

Add compile-time fast paths for _InputArray/_OutputArray
This commit is contained in:
Alexander Smorkalov
2026-10-09 09:01:51 +03:00
committed by GitHub
6 changed files with 157 additions and 44 deletions

View File

@@ -391,6 +391,15 @@ protected:
void init(int _flags, const void* _obj);
void init(int _flags, const void* _obj, Size _sz);
private:
int dims_(int i=-1) const;
int cols_(int i=-1) const;
int rows_(int i=-1) const;
Size size_(int i=-1) const;
int type_(int i=-1) const;
int depth_(int i=-1) const;
bool empty_() const;
};
CV_ENUM_FLAGS(_InputArray::KindFlag)
__CV_ENUM_FLAGS_BITWISE_AND(_InputArray::KindFlag, int, _InputArray::KindFlag)
@@ -533,6 +542,10 @@ public:
void move(UMat& u) const;
void move(Mat& m) const;
private:
void create_(Size sz, int type, int i=-1, bool allowTransposed=false, _OutputArray::DepthMask fixedDepthMask=static_cast<_OutputArray::DepthMask>(0)) const;
void create_(int rows, int cols, int type, int i=-1, bool allowTransposed=false, _OutputArray::DepthMask fixedDepthMask=static_cast<_OutputArray::DepthMask>(0)) const;
};

View File

@@ -158,6 +158,9 @@ inline void _InputArray::init(int _flags, const void* _obj, Size _sz)
{ flags = _flags; obj = (void*)_obj; sz = _sz; }
inline void* _InputArray::getObj() const { return obj; }
inline _InputArray::KindFlag _InputArray::kind() const {
return static_cast<KindFlag>(flags & KIND_MASK);
}
inline int _InputArray::getFlags() const { return flags; }
inline Size _InputArray::getSz() const { return sz; }
@@ -249,13 +252,94 @@ _InputArray _InputArray::rawIn(const std::array<_Tp, _Nm>& arr)
inline _InputArray::~_InputArray() {}
#if defined(__GNUC__) || defined(__clang__)
# define CV_IS_COMPILE_TIME_CONSTANT(x) __builtin_constant_p(x)
#else
# define CV_IS_COMPILE_TIME_CONSTANT(x) 0
#endif
inline Mat _InputArray::getMat(int i) const
{
if( kind() == MAT && i < 0 )
return *(const Mat*)obj;
if (i < 0 && CV_IS_COMPILE_TIME_CONSTANT(flags)) {
const int k = flags & KIND_MASK;
if (k == MAT)
return *static_cast<const Mat*>(getObj());
if (k == MATX)
return Mat(sz, flags, getObj());
if (k == NONE)
return Mat();
}
return getMat_(i);
}
inline int _InputArray::depth(int i) const {
if (i < 0 && CV_IS_COMPILE_TIME_CONSTANT(flags)) {
if (flags & FIXED_TYPE) return CV_MAT_DEPTH(flags);
if ((flags & KIND_MASK) == MAT)
return static_cast<const Mat*>(getObj())->depth();
}
return depth_(i);
}
inline int _InputArray::type(int i) const {
if (i < 0 && CV_IS_COMPILE_TIME_CONSTANT(flags)) {
if (flags & FIXED_TYPE) return CV_MAT_TYPE(flags);
if ((flags & KIND_MASK) == MAT)
return static_cast<const Mat*>(getObj())->type();
}
return type_(i);
}
inline int _InputArray::channels(int i) const { return CV_MAT_CN(type(i)); }
inline bool _InputArray::empty() const {
if (CV_IS_COMPILE_TIME_CONSTANT(flags)) {
const int k = flags & KIND_MASK;
if (k == MAT) return static_cast<const Mat*>(getObj())->empty();
if (k == MATX) return false;
if (k == STD_VECTOR)
return static_cast<const std::vector<uchar>*>(getObj())->empty();
if (k == NONE) return true;
}
return empty_();
}
inline int _InputArray::dims(int i) const {
if (i < 0 && CV_IS_COMPILE_TIME_CONSTANT(flags)) {
const int k = flags & KIND_MASK;
if (k == MAT) return static_cast<const Mat*>(getObj())->dims;
if (k == MATX || k == STD_VECTOR) return 2;
}
return dims_(i);
}
inline int _InputArray::rows(int i) const {
if (i < 0 && CV_IS_COMPILE_TIME_CONSTANT(flags)) {
const int k = flags & KIND_MASK;
if (k == MAT) return static_cast<const Mat*>(getObj())->rows;
if (k == MATX) return sz.height;
}
return rows_(i);
}
inline int _InputArray::cols(int i) const {
if (i < 0 && CV_IS_COMPILE_TIME_CONSTANT(flags)) {
const int k = flags & KIND_MASK;
if (k == MAT) return static_cast<const Mat*>(getObj())->cols;
if (k == MATX) return sz.width;
}
return cols_(i);
}
inline Size _InputArray::size(int i) const {
if (i < 0 && CV_IS_COMPILE_TIME_CONSTANT(flags)) {
const int k = flags & KIND_MASK;
if (k == MAT) return static_cast<const Mat*>(getObj())->size();
if (k == MATX) return sz;
}
return size_(i);
}
inline bool _InputArray::isMat() const { return kind() == _InputArray::MAT; }
inline bool _InputArray::isUMat() const { return kind() == _InputArray::UMAT; }
inline bool _InputArray::isMatVector() const { return kind() == _InputArray::STD_VECTOR_MAT; }
@@ -428,6 +512,34 @@ std::vector<std::vector<_Tp> >& _OutputArray::getVecVecRef() const
return *(std::vector<std::vector<_Tp> >*)obj;
}
inline void _OutputArray::create(Size _sz, int _type, int i,
bool allowTransposed,
_OutputArray::DepthMask fixedDepthMask) const {
if (i < 0 && !allowTransposed && fixedDepthMask == 0 &&
CV_IS_COMPILE_TIME_CONSTANT(flags)) {
if ((flags & (KIND_MASK | FIXED_SIZE | FIXED_TYPE)) == MAT) {
static_cast<Mat*>(getObj())->create(_sz, _type);
return;
}
}
create_(_sz, _type, i, allowTransposed, fixedDepthMask);
}
inline void _OutputArray::create(int _rows, int _cols, int _type, int i,
bool allowTransposed,
_OutputArray::DepthMask fixedDepthMask) const {
if (i < 0 && !allowTransposed && fixedDepthMask == 0 &&
CV_IS_COMPILE_TIME_CONSTANT(flags)) {
if ((flags & (KIND_MASK | FIXED_SIZE | FIXED_TYPE)) == MAT) {
static_cast<Mat*>(getObj())->create(_rows, _cols, _type);
return;
}
}
create_(_rows, _cols, _type, i, allowTransposed, fixedDepthMask);
}
#undef CV_IS_COMPILE_TIME_CONSTANT
///////////////////////////////////////////////////////////////////////////////////////////
inline _InputOutputArray::_InputOutputArray() { init(0+ACCESS_RW, 0); }

View File

@@ -28,7 +28,7 @@ inline bool isOpenCLActivated() { return false; }
#ifdef CV_OPENCL_RUN_VERBOSE
#define CV_OCL_RUN_(condition, func, ...) \
{ \
if (cv::ocl::isOpenCLActivated() && (condition) && func) \
if ((condition) && cv::ocl::isOpenCLActivated() && func) \
{ \
printf("%s: OpenCL implementation is running\n", CV_Func); \
fflush(stdout); \
@@ -44,7 +44,7 @@ inline bool isOpenCLActivated() { return false; }
#elif defined CV_OPENCL_RUN_ASSERT
#define CV_OCL_RUN_(condition, func, ...) \
{ \
if (cv::ocl::isOpenCLActivated() && (condition)) \
if ((condition) && cv::ocl::isOpenCLActivated()) \
{ \
if(func) \
{ \
@@ -59,18 +59,21 @@ inline bool isOpenCLActivated() { return false; }
}
#else
#define CV_OCL_RUN_(condition, func, ...) \
try \
{ \
if (cv::ocl::isOpenCLActivated() && (condition) && func) \
if (condition) \
{ \
CV_IMPL_ADD(CV_IMPL_OCL); \
return __VA_ARGS__; \
} \
} \
catch (const cv::Exception& e) \
{ \
CV_UNUSED(e); /* TODO: Add some logging here */ \
}
try \
{ \
if (cv::ocl::isOpenCLActivated() && func) \
{ \
CV_IMPL_ADD(CV_IMPL_OCL); \
return __VA_ARGS__; \
} \
} \
catch (const cv::Exception& e) \
{ \
CV_UNUSED(e); /* TODO: Add some logging here */ \
} \
}
#endif
#else

View File

@@ -462,17 +462,7 @@ ogl::Buffer _InputArray::getOGlBuffer() const
return *gl_buf;
}
_InputArray::KindFlag _InputArray::kind() const
{
KindFlag k = flags & KIND_MASK;
#if CV_VERSION_MAJOR < 5
CV_DbgAssert(k != EXPR);
CV_DbgAssert(k != STD_ARRAY);
#endif
return k;
}
int _InputArray::rows(int i) const
int _InputArray::rows_(int i) const
{
#ifdef HAVE_CUDA
_InputArray::KindFlag k = kind();
@@ -483,10 +473,10 @@ int _InputArray::rows(int i) const
}
#endif
return size(i).height;
return size_(i).height;
}
int _InputArray::cols(int i) const
int _InputArray::cols_(int i) const
{
#ifdef HAVE_CUDA
_InputArray::KindFlag k = kind();
@@ -497,10 +487,10 @@ int _InputArray::cols(int i) const
}
#endif
return size(i).width;
return size_(i).width;
}
Size _InputArray::size(int i) const
Size _InputArray::size_(int i) const
{
_InputArray::KindFlag k = kind();
@@ -832,7 +822,7 @@ bool _InputArray::sameSize(const _InputArray& arr) const
return sz1 == arr.size();
}
int _InputArray::dims(int i) const
int _InputArray::dims_(int i) const
{
_InputArray::KindFlag k = kind();
@@ -1011,7 +1001,7 @@ size_t _InputArray::total(int i) const
return size(i).area();
}
int _InputArray::type(int i) const
int _InputArray::type_(int i) const
{
_InputArray::KindFlag k = kind();
@@ -1110,17 +1100,12 @@ int _InputArray::type(int i) const
CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type");
}
int _InputArray::depth(int i) const
int _InputArray::depth_(int i) const
{
return CV_MAT_DEPTH(type(i));
}
int _InputArray::channels(int i) const
{
return CV_MAT_CN(type(i));
}
bool _InputArray::empty() const
bool _InputArray::empty_() const
{
_InputArray::KindFlag k = kind();
@@ -1463,7 +1448,7 @@ bool _OutputArray::fixedType() const
return (flags & FIXED_TYPE) == FIXED_TYPE;
}
void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, _OutputArray::DepthMask fixedDepthMask) const
void _OutputArray::create_(Size _sz, int mtype, int i, bool allowTransposed, _OutputArray::DepthMask fixedDepthMask) const
{
_InputArray::KindFlag k = kind();
if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
@@ -1529,7 +1514,7 @@ void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, _Out
create(2, sizes, mtype, i, allowTransposed, fixedDepthMask);
}
void _OutputArray::create(int _rows, int _cols, int mtype, int i, bool allowTransposed, _OutputArray::DepthMask fixedDepthMask) const
void _OutputArray::create_(int _rows, int _cols, int mtype, int i, bool allowTransposed, _OutputArray::DepthMask fixedDepthMask) const
{
_InputArray::KindFlag k = kind();
if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )

View File

@@ -3611,7 +3611,7 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
srcUMat = _src.getUMat();
Mat src = _src.getMat();
_dst.create(dsize, src.type());
_dst.create(dsize, _src.type());
Mat dst = _dst.getMat();
if (dsize == ssize)
@@ -3621,5 +3621,5 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
return;
}
hal::resize(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, inv_scale_x, inv_scale_y, interpolation);
hal::resize(_src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, inv_scale_x, inv_scale_y, interpolation);
}

View File

@@ -1100,7 +1100,7 @@ void FarnebackOpticalFlowImpl::calc(InputArray _prev0, InputArray _next0,
{
CV_INSTRUMENT_REGION();
CV_OCL_RUN(_flow0.isUMat() &&
CV_OCL_RUN(ocl::isOpenCLActivated() && _flow0.isUMat() &&
ocl::Image2D::isFormatSupported(CV_32F, 1, false),
calc_ocl(_prev0,_next0,_flow0))
Mat prev0 = _prev0.getMat(), next0 = _next0.getMat();