mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Merge pull request #26254 from vpisarev:extra_tests_for_reshape
Added extra tests for reshape #26254 Attempt to reproduce problems described in #25174. No success; everything works as expected. Probably, the function has been used improperly. Slightly modified the code of Mat::reshape() to provide better diagnostic. - [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 - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -329,17 +329,25 @@ void Mat::copyTo( OutputArray _dst ) const
|
||||
}
|
||||
#endif
|
||||
|
||||
int stype = type();
|
||||
int dtype = _dst.type();
|
||||
if( _dst.fixedType() && dtype != type() )
|
||||
if( _dst.fixedType() && dtype != stype )
|
||||
{
|
||||
CV_Assert( channels() == CV_MAT_CN(dtype) );
|
||||
CV_Assert( CV_MAT_CN(stype) == CV_MAT_CN(dtype) );
|
||||
convertTo( _dst, dtype );
|
||||
return;
|
||||
}
|
||||
|
||||
if( empty() )
|
||||
if( dims == 0 && empty() )
|
||||
{
|
||||
_dst.release();
|
||||
void* obj = _dst.getObj();
|
||||
if (_dst.isMat())
|
||||
reinterpret_cast<Mat*>(obj)->flags = Mat::MAGIC_VAL | Mat::CONTINUOUS_FLAG | stype;
|
||||
else if (_dst.isUMat())
|
||||
reinterpret_cast<UMat*>(obj)->flags = UMat::MAGIC_VAL | UMat::CONTINUOUS_FLAG | stype;
|
||||
else if (_dst.isGpuMat())
|
||||
reinterpret_cast<cuda::GpuMat*>(obj)->flags = stype;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -348,10 +356,12 @@ void Mat::copyTo( OutputArray _dst ) const
|
||||
(_dst.fixedSize() && _dst.dims() == 1);
|
||||
if( _dst.isUMat() )
|
||||
{
|
||||
_dst.create( dims, size.p, type(), -1, allowTransposed );
|
||||
_dst.create( dims, size.p, stype, -1, allowTransposed );
|
||||
if (empty())
|
||||
return;
|
||||
UMat dst = _dst.getUMat();
|
||||
CV_Assert(dst.u != NULL);
|
||||
size_t i, sz[CV_MAX_DIM] = {1}, dstofs[CV_MAX_DIM] = {0}, esz = elemSize();
|
||||
size_t i, sz[CV_MAX_DIM] = {1}, dstofs[CV_MAX_DIM] = {0}, esz = CV_ELEM_SIZE(stype);
|
||||
CV_Assert(dims >= 0 && dims < CV_MAX_DIM);
|
||||
for( i = 0; i < (size_t)dims; i++ )
|
||||
sz[i] = size.p[i];
|
||||
@@ -365,7 +375,7 @@ void Mat::copyTo( OutputArray _dst ) const
|
||||
|
||||
if( dims <= 2 )
|
||||
{
|
||||
_dst.create( dims, size.p, type(), -1, allowTransposed );
|
||||
_dst.create( dims, size.p, stype, -1, allowTransposed );
|
||||
Mat dst = _dst.getMat();
|
||||
if( data == dst.data )
|
||||
return;
|
||||
@@ -389,7 +399,7 @@ void Mat::copyTo( OutputArray _dst ) const
|
||||
return;
|
||||
}
|
||||
|
||||
_dst.create( dims, size, type() );
|
||||
_dst.create( dims, size, stype );
|
||||
Mat dst = _dst.getMat();
|
||||
if( data == dst.data )
|
||||
return;
|
||||
|
||||
+32
-25
@@ -1725,27 +1725,26 @@ Mat Mat::reshape(int new_cn, int new_rows) const
|
||||
int cn = channels();
|
||||
Mat hdr = *this;
|
||||
|
||||
if( new_cn == 0 )
|
||||
new_cn = cn;
|
||||
|
||||
if( dims > 2 )
|
||||
{
|
||||
if( new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 )
|
||||
if( new_rows == 0 )
|
||||
{
|
||||
// special case: just change the number of channnels; retain the same shape,
|
||||
// except for the last, innermost dimension
|
||||
CV_Assert(size[dims-1]*cn % new_cn == 0);
|
||||
hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
|
||||
hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags);
|
||||
hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn;
|
||||
return hdr;
|
||||
}
|
||||
if( new_rows > 0 )
|
||||
{
|
||||
int sz[] = { new_rows, (int)(total()*cn/new_rows) };
|
||||
return reshape(new_cn, 2, sz);
|
||||
}
|
||||
CV_Assert( new_rows > 0 );
|
||||
int sz[] = { new_rows, (int)(total()*cn/new_rows) };
|
||||
return reshape(new_cn, 2, sz);
|
||||
}
|
||||
|
||||
CV_Assert( dims <= 2 );
|
||||
|
||||
if( new_cn == 0 )
|
||||
new_cn = cn;
|
||||
|
||||
int total_width = cols * cn;
|
||||
|
||||
if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )
|
||||
@@ -1758,9 +1757,6 @@ Mat Mat::reshape(int new_cn, int new_rows) const
|
||||
CV_Error( cv::Error::BadStep,
|
||||
"The matrix is not continuous, thus its number of rows can not be changed" );
|
||||
|
||||
if( (unsigned)new_rows > (unsigned)total_size )
|
||||
CV_Error( cv::Error::StsOutOfRange, "Bad new number of rows" );
|
||||
|
||||
total_width = total_size / new_rows;
|
||||
|
||||
if( total_width * new_rows != total_size )
|
||||
@@ -1810,22 +1806,33 @@ Mat Mat::reshape(int _cn, int _newndims, const int* _newsz) const
|
||||
|
||||
AutoBuffer<int, 4> newsz_buf( (size_t)_newndims );
|
||||
|
||||
int m1_idx = -1;
|
||||
|
||||
for (int i = 0; i < _newndims; i++)
|
||||
{
|
||||
CV_Assert(_newsz[i] >= 0);
|
||||
|
||||
if (_newsz[i] > 0)
|
||||
newsz_buf[i] = _newsz[i];
|
||||
else if (i < dims)
|
||||
newsz_buf[i] = this->size[i];
|
||||
else
|
||||
CV_Error(cv::Error::StsOutOfRange, "Copy dimension (which has zero size) is not present in source matrix");
|
||||
|
||||
total_elem1 *= (size_t)newsz_buf[i];
|
||||
if (_newsz[i] >= 0) {
|
||||
if (_newsz[i] == 0 && i < dims)
|
||||
newsz_buf[i] = size.p[i];
|
||||
else
|
||||
newsz_buf[i] = _newsz[i];
|
||||
total_elem1 *= (size_t)newsz_buf[i];
|
||||
} else {
|
||||
if (m1_idx >= 0)
|
||||
CV_Error(cv::Error::StsBadSize, "More than one '-1' occured in the new shape");
|
||||
m1_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (total_elem1 != total_elem1_ref)
|
||||
if (m1_idx >= 0) {
|
||||
if (total_elem1 == 0) {
|
||||
CV_Assert(total_elem1_ref == 0);
|
||||
total_elem1 = 1;
|
||||
}
|
||||
CV_Assert(total_elem1_ref % total_elem1 == 0);
|
||||
newsz_buf[m1_idx] = (int)(total_elem1_ref / total_elem1);
|
||||
} else if (total_elem1 != total_elem1_ref) {
|
||||
CV_Error(cv::Error::StsUnmatchedSizes, "Requested and source matrices have different count of elements");
|
||||
}
|
||||
|
||||
Mat hdr = *this;
|
||||
hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((_cn-1) << CV_CN_SHIFT);
|
||||
|
||||
@@ -1063,9 +1063,6 @@ UMat UMat::reshape(int new_cn, int new_rows) const
|
||||
CV_Error( cv::Error::BadStep,
|
||||
"The matrix is not continuous, thus its number of rows can not be changed" );
|
||||
|
||||
if( (unsigned)new_rows > (unsigned)total_size )
|
||||
CV_Error( cv::Error::StsOutOfRange, "Bad new number of rows" );
|
||||
|
||||
total_width = total_size / new_rows;
|
||||
|
||||
if( total_width * new_rows != total_size )
|
||||
@@ -1127,7 +1124,7 @@ UMat UMat::reshape(int _cn, int _newndims, const int* _newsz) const
|
||||
|
||||
if (isContinuous())
|
||||
{
|
||||
CV_Assert(_cn >= 0 && _newndims >= 0 && _newndims <= CV_MAX_DIM && _newsz);
|
||||
CV_Assert(_cn >= 0 && _newndims >= 0 && _newndims <= CV_MAX_DIM && (_newndims == 0 || _newsz != 0));
|
||||
|
||||
if (_cn == 0)
|
||||
_cn = this->channels();
|
||||
@@ -1139,22 +1136,33 @@ UMat UMat::reshape(int _cn, int _newndims, const int* _newsz) const
|
||||
|
||||
AutoBuffer<int, 4> newsz_buf( (size_t)std::max(_newndims, 1) );
|
||||
|
||||
int m1_idx = -1;
|
||||
|
||||
for (int i = 0; i < _newndims; i++)
|
||||
{
|
||||
CV_Assert(_newsz[i] >= 0);
|
||||
|
||||
if (_newsz[i] > 0)
|
||||
newsz_buf[i] = _newsz[i];
|
||||
else if (i < dims)
|
||||
newsz_buf[i] = this->size[i];
|
||||
else
|
||||
CV_Error(cv::Error::StsOutOfRange, "Copy dimension (which has zero size) is not present in source matrix");
|
||||
|
||||
total_elem1 *= (size_t)newsz_buf[i];
|
||||
if (_newsz[i] >= 0) {
|
||||
if (_newsz[i] == 0 && i < dims)
|
||||
newsz_buf[i] = size.p[i];
|
||||
else
|
||||
newsz_buf[i] = _newsz[i];
|
||||
total_elem1 *= (size_t)newsz_buf[i];
|
||||
} else {
|
||||
if (m1_idx >= 0)
|
||||
CV_Error(cv::Error::StsBadSize, "More than one '-1' occured in the new shape");
|
||||
m1_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (total_elem1 != total_elem1_ref)
|
||||
if (m1_idx >= 0) {
|
||||
if (total_elem1 == 0) {
|
||||
CV_Assert(total_elem1_ref == 0);
|
||||
total_elem1 = 1;
|
||||
}
|
||||
CV_Assert(total_elem1_ref % total_elem1 == 0);
|
||||
newsz_buf[m1_idx] = (int)(total_elem1_ref / total_elem1);
|
||||
} else if (total_elem1 != total_elem1_ref) {
|
||||
CV_Error(cv::Error::StsUnmatchedSizes, "Requested and source matrices have different count of elements");
|
||||
}
|
||||
|
||||
UMat hdr = *this;
|
||||
hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((_cn-1) << CV_CN_SHIFT);
|
||||
@@ -1249,22 +1257,30 @@ void UMat::copyTo(OutputArray _dst) const
|
||||
}
|
||||
#endif
|
||||
|
||||
int stype = type();
|
||||
int dtype = _dst.type();
|
||||
if( _dst.fixedType() && dtype != type() )
|
||||
if( _dst.fixedType() && dtype != stype )
|
||||
{
|
||||
CV_Assert( channels() == CV_MAT_CN(dtype) );
|
||||
CV_Assert( CV_MAT_CN(stype) == CV_MAT_CN(dtype) );
|
||||
convertTo( _dst, dtype );
|
||||
return;
|
||||
}
|
||||
|
||||
if( empty() )
|
||||
if( dims == 0 && empty() )
|
||||
{
|
||||
_dst.release();
|
||||
void* obj = _dst.getObj();
|
||||
if (_dst.isMat())
|
||||
reinterpret_cast<Mat*>(obj)->flags = Mat::MAGIC_VAL | Mat::CONTINUOUS_FLAG | stype;
|
||||
else if (_dst.isUMat())
|
||||
reinterpret_cast<UMat*>(obj)->flags = UMat::MAGIC_VAL | UMat::CONTINUOUS_FLAG | stype;
|
||||
else if (_dst.isGpuMat())
|
||||
reinterpret_cast<cuda::GpuMat*>(obj)->flags = stype;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t sz[CV_MAX_DIM] = {1}, srcofs[CV_MAX_DIM]={0}, dstofs[CV_MAX_DIM]={0};
|
||||
size_t esz = elemSize();
|
||||
size_t esz = CV_ELEM_SIZE(stype);
|
||||
int i, d = std::max(dims, 1);
|
||||
for( i = 0; i < d; i++ )
|
||||
sz[i] = size.p[i];
|
||||
@@ -1272,7 +1288,10 @@ void UMat::copyTo(OutputArray _dst) const
|
||||
ndoffset(srcofs);
|
||||
srcofs[d-1] *= esz;
|
||||
|
||||
_dst.create( dims, size.p, type() );
|
||||
_dst.create( dims, size.p, stype );
|
||||
if (empty())
|
||||
return;
|
||||
|
||||
if( _dst.isUMat() )
|
||||
{
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
Reference in New Issue
Block a user