1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00

Added new data types to cv::Mat & UMat (#23865)

* started working on adding 32u, 64u, 64s, bool and 16bf types to OpenCV

* core & imgproc tests seem to pass

* fixed a few compile errors and test failures on macOS x86

* hopefully fixed some compile problems and test failures

* fixed some more warnings and test failures

* trying to fix small deviations in perf_core & perf_imgproc by revering randf_64f to exact version used before

* trying to fix behavior of the new OpenCV with old plugins; there is (quite strong) assumption that video capture would give us frames with depth == CV_8U (0) or CV_16U (2). If depth is > 7 then it means that the plugin is built with the old OpenCV. It needs to be recompiled, of course and then this hack can be removed.

* try to repair the case when target arch does not have FP64 SIMD

* 1. fixed bug in itoa() found by alalek
2. restored ==, !=, > and < univ. intrinsics on ARM32/ARM64.
This commit is contained in:
Vadim Pisarevsky
2023-08-04 10:50:03 +03:00
committed by GitHub
parent fa91c1445e
commit 518486ed3d
52 changed files with 2363 additions and 859 deletions
+126 -16
View File
@@ -72,10 +72,10 @@ int randomType(RNG& rng, _OutputArray::DepthMask typeMask, int minChannels, int
{
int channels = rng.uniform(minChannels, maxChannels+1);
int depth = 0;
CV_Assert((typeMask & _OutputArray::DEPTH_MASK_ALL_16F) != 0);
CV_Assert((typeMask & _OutputArray::DEPTH_MASK_ALL) != 0);
for(;;)
{
depth = rng.uniform(CV_8U, CV_16F+1);
depth = rng.uniform(CV_8U, CV_DEPTH_CURR_MAX);
if( ((1 << depth) & typeMask) != 0 )
break;
}
@@ -246,8 +246,43 @@ convert_(const _Tp1* src, _Tp2* dst, size_t total, double alpha, double beta)
dst[i] = saturate_cast<_Tp2>(src[i]*alpha + beta);
}
template<typename _Tp1> inline void
convert_to_bool(const _Tp1* src, bool* dst,
size_t total, double alpha, double beta)
{
size_t i;
if( alpha == 1 && beta == 0 )
for( i = 0; i < total; i++ )
dst[i] = src[i] != 0;
else if( beta == 0 )
for( i = 0; i < total; i++ )
dst[i] = src[i]*alpha != 0;
else
for( i = 0; i < total; i++ )
dst[i] = src[i]*alpha + beta != 0;
}
template<typename _Tp2>
inline void
convert_(const bool* src_, _Tp2* dst,
size_t total, double alpha, double beta)
{
size_t i;
const uint8_t* src = (const uint8_t*)src_;
if( alpha == 1 && beta == 0 )
for( i = 0; i < total; i++ )
dst[i] = saturate_cast<_Tp2>(src[i] != 0);
else if( beta == 0 )
for( i = 0; i < total; i++ )
dst[i] = saturate_cast<_Tp2>((src[i] != 0)*alpha);
else
for( i = 0; i < total; i++ )
dst[i] = saturate_cast<_Tp2>((src[i] != 0)*alpha + beta);
}
template<typename _Tp> inline void
convertTo(const _Tp* src, void* dst, int dtype, size_t total, double alpha, double beta)
convertTo(const _Tp* src, void* dst, int dtype,
size_t total, double alpha, double beta)
{
switch( CV_MAT_DEPTH(dtype) )
{
@@ -263,6 +298,9 @@ convertTo(const _Tp* src, void* dst, int dtype, size_t total, double alpha, doub
case CV_16S:
convert_(src, (short*)dst, total, alpha, beta);
break;
case CV_32U:
convert_(src, (unsigned*)dst, total, alpha, beta);
break;
case CV_32S:
convert_(src, (int*)dst, total, alpha, beta);
break;
@@ -272,16 +310,35 @@ convertTo(const _Tp* src, void* dst, int dtype, size_t total, double alpha, doub
case CV_64F:
convert_(src, (double*)dst, total, alpha, beta);
break;
case CV_64U:
convert_(src, (uint64_t*)dst, total, alpha, beta);
break;
case CV_64S:
convert_(src, (int64_t*)dst, total, alpha, beta);
break;
case CV_16F:
convert_(src, (cv::float16_t*)dst, total, alpha, beta);
break;
case CV_16BF:
convert_(src, (cv::bfloat16_t*)dst, total, alpha, beta);
break;
case CV_Bool:
convert_to_bool(src, (bool*)dst, total, alpha, beta);
break;
default:
CV_Assert(0);
}
}
void convert(const Mat& src, cv::OutputArray _dst, int dtype, double alpha, double beta)
void convert(const Mat& src, cv::OutputArray _dst,
int dtype, double alpha, double beta)
{
if (dtype < 0) dtype = _dst.depth();
dtype = CV_MAKETYPE(CV_MAT_DEPTH(dtype), src.channels());
int sdepth = src.depth();
int ddepth = CV_MAT_DEPTH(dtype);
dtype = CV_MAKETYPE(ddepth, src.channels());
_dst.create(src.dims, &src.size[0], dtype);
Mat dst = _dst.getMat();
if( alpha == 0 )
@@ -307,7 +364,7 @@ void convert(const Mat& src, cv::OutputArray _dst, int dtype, double alpha, doub
const uchar* sptr = planes[0].ptr();
uchar* dptr = planes[1].ptr();
switch( src.depth() )
switch( sdepth )
{
case CV_8U:
convertTo((const uchar*)sptr, dptr, dtype, total, alpha, beta);
@@ -315,12 +372,18 @@ void convert(const Mat& src, cv::OutputArray _dst, int dtype, double alpha, doub
case CV_8S:
convertTo((const schar*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_Bool:
convertTo((const bool*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_16U:
convertTo((const ushort*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_16S:
convertTo((const short*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_32U:
convertTo((const unsigned*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_32S:
convertTo((const int*)sptr, dptr, dtype, total, alpha, beta);
break;
@@ -330,6 +393,20 @@ void convert(const Mat& src, cv::OutputArray _dst, int dtype, double alpha, doub
case CV_64F:
convertTo((const double*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_64U:
convertTo((const uint64_t*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_64S:
convertTo((const int64_t*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_16F:
convertTo((const cv::float16_t*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_16BF:
convertTo((const cv::bfloat16_t*)sptr, dptr, dtype, total, alpha, beta);
break;
default:
CV_Error(CV_StsNotImplemented, "unknown/unsupported depth");
}
}
}
@@ -1351,7 +1428,7 @@ double norm(InputArray _src, int normType, InputArray _mask)
double norm(InputArray _src1, InputArray _src2, int normType, InputArray _mask)
{
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
if( src1.depth() == CV_16F )
if( src1.depth() == CV_16F || src1.depth() == CV_16BF )
{
Mat src1_32f, src2_32f;
src1.convertTo(src1_32f, CV_32F);
@@ -1769,10 +1846,10 @@ cmpUlpsInt_(const _Tp* src1, const _Tp* src2, size_t total, int imaxdiff,
size_t startidx, size_t& idx)
{
size_t i;
int realmaxdiff = 0;
int64_t realmaxdiff = 0;
for( i = 0; i < total; i++ )
{
int diff = std::abs(src1[i] - src2[i]);
int64_t diff = (int64_t)std::abs((int64_t)src1[i] - (int64_t)src2[i]);
if( realmaxdiff < diff )
{
realmaxdiff = diff;
@@ -1780,7 +1857,7 @@ cmpUlpsInt_(const _Tp* src1, const _Tp* src2, size_t total, int imaxdiff,
idx = i + startidx;
}
}
return realmaxdiff;
return (double)realmaxdiff;
}
@@ -2008,7 +2085,7 @@ int cmpEps( const Mat& arr_, const Mat& refarr_, double* _realmaxdiff,
{
Mat arr = arr_, refarr = refarr_;
CV_Assert( arr.type() == refarr.type() && arr.size == refarr.size );
if( arr.depth() == CV_16F )
if( arr.depth() == CV_16F || arr.depth() == CV_16BF )
{
Mat arr32f, refarr32f;
arr.convertTo(arr32f, CV_32F);
@@ -2017,7 +2094,8 @@ int cmpEps( const Mat& arr_, const Mat& refarr_, double* _realmaxdiff,
refarr = refarr32f;
}
int ilevel = refarr.depth() <= CV_32S ? cvFloor(success_err_level) : 0;
int depth = refarr.depth();
int ilevel = depth <= CV_32S || depth == CV_32U || depth == CV_64U || depth == CV_64S ? cvFloor(success_err_level) : 0;
int result = CMP_EPS_OK;
const Mat *arrays[]={&arr, &refarr, 0};
@@ -2025,14 +2103,13 @@ int cmpEps( const Mat& arr_, const Mat& refarr_, double* _realmaxdiff,
NAryMatIterator it(arrays, planes);
size_t total = planes[0].total()*planes[0].channels(), j = total;
size_t i, nplanes = it.nplanes;
int depth = arr.depth();
size_t startidx = 1, idx = 0;
double realmaxdiff = 0, maxval = 0;
if(_realmaxdiff)
*_realmaxdiff = 0;
if( refarr.depth() >= CV_32F && !element_wise_relative_error )
if( !CV_IS_INT_TYPE(depth) && !element_wise_relative_error )
{
maxval = cvtest::norm( refarr, NORM_INF );
maxval = MAX(maxval, 1.);
@@ -2048,6 +2125,9 @@ int cmpEps( const Mat& arr_, const Mat& refarr_, double* _realmaxdiff,
case CV_8U:
realmaxdiff = cmpUlpsInt_((const uchar*)sptr1, (const uchar*)sptr2, total, ilevel, startidx, idx);
break;
case CV_Bool:
realmaxdiff = cmpUlpsInt_((const uchar*)sptr1, (const uchar*)sptr2, total, ilevel, startidx, idx);
break;
case CV_8S:
realmaxdiff = cmpUlpsInt_((const schar*)sptr1, (const schar*)sptr2, total, ilevel, startidx, idx);
break;
@@ -2060,6 +2140,15 @@ int cmpEps( const Mat& arr_, const Mat& refarr_, double* _realmaxdiff,
case CV_32S:
realmaxdiff = cmpUlpsInt_((const int*)sptr1, (const int*)sptr2, total, ilevel, startidx, idx);
break;
case CV_32U:
realmaxdiff = cmpUlpsInt_((const unsigned*)sptr1, (const unsigned*)sptr2, total, ilevel, startidx, idx);
break;
case CV_64S:
realmaxdiff = cmpUlpsInt_((const int64_t*)sptr1, (const int64_t*)sptr2, total, ilevel, startidx, idx);
break;
case CV_64U:
realmaxdiff = cmpUlpsInt_((const uint64_t*)sptr1, (const uint64_t*)sptr2, total, ilevel, startidx, idx);
break;
case CV_32F:
for( j = 0; j < total; j++ )
{
@@ -2887,7 +2976,7 @@ std::ostream& operator << (std::ostream& out, const MatInfo& m)
out << "<Empty>";
else
{
static const char* depthstr[] = {"8u", "8s", "16u", "16s", "32s", "32f", "64f", "?"};
static const char* depthstr[] = {"8u", "8s", "16u", "16s", "32s", "32f", "64f", "16f", "16bf", "Bool", "64u", "64s", "32u", "?", "?", "?"};
out << depthstr[m.m->depth()] << "C" << m.m->channels() << " " << m.m->dims << "-dim (";
for( int i = 0; i < m.m->dims; i++ )
out << m.m->size[i] << (i < m.m->dims-1 ? " x " : ")");
@@ -2930,7 +3019,6 @@ writeElems(std::ostream& out, const void* data, int nelems, int starpos)
}
}
static void writeElems(std::ostream& out, const void* data, int nelems, int depth, int starpos)
{
if(depth == CV_8U)
@@ -2943,6 +3031,28 @@ static void writeElems(std::ostream& out, const void* data, int nelems, int dept
writeElems<short, int>(out, data, nelems, starpos);
else if(depth == CV_32S)
writeElems<int, int>(out, data, nelems, starpos);
else if(depth == CV_32U)
writeElems<unsigned, unsigned>(out, data, nelems, starpos);
else if(depth == CV_64U)
writeElems<uint64_t, uint64_t>(out, data, nelems, starpos);
else if(depth == CV_64S)
writeElems<int64_t, int64_t>(out, data, nelems, starpos);
else if(depth == CV_Bool)
writeElems<bool, int>(out, data, nelems, starpos);
else if(depth == CV_16F)
{
std::streamsize pp = out.precision();
out.precision(4);
writeElems<cv::float16_t, float>(out, data, nelems, starpos);
out.precision(pp);
}
else if(depth == CV_16BF)
{
std::streamsize pp = out.precision();
out.precision(4);
writeElems<cv::bfloat16_t, float>(out, data, nelems, starpos);
out.precision(pp);
}
else if(depth == CV_32F)
{
std::streamsize pp = out.precision();
+9
View File
@@ -465,6 +465,15 @@ void Regression::verify(cv::FileNode node, cv::InputArray array, double eps, ERR
{
int expected_kind = (int)node["kind"];
int expected_type = (int)node["type"];
int array_type = array.type();
if (array_type != expected_type) {
// temporary hack; we optimistically assume that type in the computed and expected array should be the same.
// if they are different, it must be because of the change in type representation between OpenCV 5.x and OpenCV 2.x,3.x,4.x.
// need to add "type5" or something like that and use it in the newer files. Then type will always mean 'earlier than 5.x type'.
int depth = expected_type & 7;
int channels = ((expected_type >> 3) & 127) + 1;
expected_type = CV_MAKETYPE(depth, channels);
}
ASSERT_EQ(expected_kind, array.kind()) << " Argument \"" << node.name() << "\" has unexpected kind";
ASSERT_EQ(expected_type, array.type()) << " Argument \"" << node.name() << "\" has unexpected type";