mirror of
https://github.com/opencv/opencv.git
synced 2026-09-25 04:09:57 +03:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -458,158 +458,6 @@ CV__DEBUG_NS_END
|
||||
|
||||
//////////////////////////////////////////// Mat //////////////////////////////////////////
|
||||
|
||||
inline
|
||||
Mat::Mat()
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{}
|
||||
|
||||
inline
|
||||
Mat::Mat(int _rows, int _cols, int _type)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_rows, _cols, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_rows, _cols, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(Size _sz, int _type)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create( _sz.height, _sz.width, _type );
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(Size _sz, int _type, const Scalar& _s)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_sz.height, _sz.width, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(int _dims, const int* _sz, int _type)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_dims, _sz, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_dims, _sz, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(const std::vector<int>& _sz, int _type)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_sz, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(const std::vector<int>& _sz, int _type, const Scalar& _s)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_sz, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(const Mat& m)
|
||||
: flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data),
|
||||
datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit), allocator(m.allocator),
|
||||
u(m.u), size(&rows), step(0)
|
||||
{
|
||||
if( u )
|
||||
CV_XADD(&u->refcount, 1);
|
||||
if( m.dims <= 2 )
|
||||
{
|
||||
step[0] = m.step[0]; step[1] = m.step[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
dims = 0;
|
||||
copySize(m);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step)
|
||||
: flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols),
|
||||
data((uchar*)_data), datastart((uchar*)_data), dataend(0), datalimit(0),
|
||||
allocator(0), u(0), size(&rows)
|
||||
{
|
||||
CV_Assert(total() == 0 || data != NULL);
|
||||
|
||||
size_t esz = CV_ELEM_SIZE(_type), esz1 = CV_ELEM_SIZE1(_type);
|
||||
size_t minstep = cols * esz;
|
||||
if( _step == AUTO_STEP )
|
||||
{
|
||||
_step = minstep;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_DbgAssert( _step >= minstep );
|
||||
if (_step % esz1 != 0)
|
||||
{
|
||||
CV_Error(Error::BadStep, "Step must be a multiple of esz1");
|
||||
}
|
||||
}
|
||||
step[0] = _step;
|
||||
step[1] = esz;
|
||||
datalimit = datastart + _step * rows;
|
||||
dataend = datalimit - _step + minstep;
|
||||
updateContinuityFlag();
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::Mat(Size _sz, int _type, void* _data, size_t _step)
|
||||
: flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_sz.height), cols(_sz.width),
|
||||
data((uchar*)_data), datastart((uchar*)_data), dataend(0), datalimit(0),
|
||||
allocator(0), u(0), size(&rows)
|
||||
{
|
||||
CV_Assert(total() == 0 || data != NULL);
|
||||
|
||||
size_t esz = CV_ELEM_SIZE(_type), esz1 = CV_ELEM_SIZE1(_type);
|
||||
size_t minstep = cols*esz;
|
||||
if( _step == AUTO_STEP )
|
||||
{
|
||||
_step = minstep;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_DbgAssert( _step >= minstep );
|
||||
|
||||
if (_step % esz1 != 0)
|
||||
{
|
||||
CV_Error(Error::BadStep, "Step must be a multiple of esz1");
|
||||
}
|
||||
}
|
||||
step[0] = _step;
|
||||
step[1] = esz;
|
||||
datalimit = datastart + _step*rows;
|
||||
dataend = datalimit - _step + minstep;
|
||||
updateContinuityFlag();
|
||||
}
|
||||
|
||||
template<typename _Tp> inline
|
||||
Mat::Mat(const std::vector<_Tp>& vec, bool copyData)
|
||||
: flags(MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
|
||||
@@ -743,43 +591,6 @@ Mat::Mat(const MatCommaInitializer_<_Tp>& commaInitializer)
|
||||
*this = commaInitializer.operator Mat_<_Tp>();
|
||||
}
|
||||
|
||||
inline
|
||||
Mat::~Mat()
|
||||
{
|
||||
release();
|
||||
if( step.p != step.buf )
|
||||
fastFree(step.p);
|
||||
}
|
||||
|
||||
inline
|
||||
Mat& Mat::operator = (const Mat& m)
|
||||
{
|
||||
if( this != &m )
|
||||
{
|
||||
if( m.u )
|
||||
CV_XADD(&m.u->refcount, 1);
|
||||
release();
|
||||
flags = m.flags;
|
||||
if( dims <= 2 && m.dims <= 2 )
|
||||
{
|
||||
dims = m.dims;
|
||||
rows = m.rows;
|
||||
cols = m.cols;
|
||||
step[0] = m.step[0];
|
||||
step[1] = m.step[1];
|
||||
}
|
||||
else
|
||||
copySize(m);
|
||||
data = m.data;
|
||||
datastart = m.datastart;
|
||||
dataend = m.dataend;
|
||||
datalimit = m.datalimit;
|
||||
allocator = m.allocator;
|
||||
u = m.u;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
Mat Mat::row(int y) const
|
||||
{
|
||||
@@ -816,67 +627,6 @@ Mat Mat::colRange(const Range& r) const
|
||||
return Mat(*this, Range::all(), r);
|
||||
}
|
||||
|
||||
inline
|
||||
Mat Mat::clone() const
|
||||
{
|
||||
Mat m;
|
||||
copyTo(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
inline
|
||||
void Mat::assignTo( Mat& m, int _type ) const
|
||||
{
|
||||
if( _type < 0 )
|
||||
m = *this;
|
||||
else
|
||||
convertTo(m, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
void Mat::create(int _rows, int _cols, int _type)
|
||||
{
|
||||
_type &= TYPE_MASK;
|
||||
if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && data )
|
||||
return;
|
||||
int sz[] = {_rows, _cols};
|
||||
create(2, sz, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
void Mat::create(Size _sz, int _type)
|
||||
{
|
||||
create(_sz.height, _sz.width, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
void Mat::addref()
|
||||
{
|
||||
if( u )
|
||||
CV_XADD(&u->refcount, 1);
|
||||
}
|
||||
|
||||
inline
|
||||
void Mat::release()
|
||||
{
|
||||
if( u && CV_XADD(&u->refcount, -1) == 1 )
|
||||
deallocate();
|
||||
u = NULL;
|
||||
datastart = dataend = datalimit = data = 0;
|
||||
for(int i = 0; i < dims; i++)
|
||||
size.p[i] = 0;
|
||||
#ifdef _DEBUG
|
||||
flags = MAGIC_VAL;
|
||||
dims = rows = cols = 0;
|
||||
if(step.p != step.buf)
|
||||
{
|
||||
fastFree(step.p);
|
||||
step.p = step.buf;
|
||||
size.p = &rows;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
Mat Mat::operator()( Range _rowRange, Range _colRange ) const
|
||||
{
|
||||
@@ -945,40 +695,6 @@ int Mat::channels() const
|
||||
return CV_MAT_CN(flags);
|
||||
}
|
||||
|
||||
inline
|
||||
size_t Mat::step1(int i) const
|
||||
{
|
||||
return step.p[i] / elemSize1();
|
||||
}
|
||||
|
||||
inline
|
||||
bool Mat::empty() const
|
||||
{
|
||||
return data == 0 || total() == 0 || dims == 0;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t Mat::total() const
|
||||
{
|
||||
if( dims <= 2 )
|
||||
return (size_t)rows * cols;
|
||||
size_t p = 1;
|
||||
for( int i = 0; i < dims; i++ )
|
||||
p *= size[i];
|
||||
return p;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t Mat::total(int startDim, int endDim) const
|
||||
{
|
||||
CV_Assert( 0 <= startDim && startDim <= endDim);
|
||||
size_t p = 1;
|
||||
int endDim_ = endDim <= dims ? endDim : dims;
|
||||
for( int i = startDim; i < endDim_; i++ )
|
||||
p *= size[i];
|
||||
return p;
|
||||
}
|
||||
|
||||
inline
|
||||
uchar* Mat::ptr(int y)
|
||||
{
|
||||
@@ -1503,22 +1219,6 @@ MatSize::operator const int*() const
|
||||
return p;
|
||||
}
|
||||
|
||||
inline
|
||||
bool MatSize::operator == (const MatSize& sz) const
|
||||
{
|
||||
int d = dims();
|
||||
int dsz = sz.dims();
|
||||
if( d != dsz )
|
||||
return false;
|
||||
if( d == 2 )
|
||||
return p[0] == sz.p[0] && p[1] == sz.p[1];
|
||||
|
||||
for( int i = 0; i < d; i++ )
|
||||
if( p[i] != sz.p[i] )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool MatSize::operator != (const MatSize& sz) const
|
||||
{
|
||||
@@ -1775,9 +1475,7 @@ template<typename _Tp> inline
|
||||
void Mat_<_Tp>::release()
|
||||
{
|
||||
Mat::release();
|
||||
#ifdef _DEBUG
|
||||
flags = (flags & ~CV_MAT_TYPE_MASK) + traits::Type<_Tp>::value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename _Tp> inline
|
||||
@@ -2132,51 +1830,6 @@ Mat_<_Tp>::Mat_(MatExpr&& e)
|
||||
|
||||
///////////////////////////// SparseMat /////////////////////////////
|
||||
|
||||
inline
|
||||
SparseMat::SparseMat()
|
||||
: flags(MAGIC_VAL), hdr(0)
|
||||
{}
|
||||
|
||||
inline
|
||||
SparseMat::SparseMat(int _dims, const int* _sizes, int _type)
|
||||
: flags(MAGIC_VAL), hdr(0)
|
||||
{
|
||||
create(_dims, _sizes, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
SparseMat::SparseMat(const SparseMat& m)
|
||||
: flags(m.flags), hdr(m.hdr)
|
||||
{
|
||||
addref();
|
||||
}
|
||||
|
||||
inline
|
||||
SparseMat::~SparseMat()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
inline
|
||||
SparseMat& SparseMat::operator = (const SparseMat& m)
|
||||
{
|
||||
if( this != &m )
|
||||
{
|
||||
if( m.hdr )
|
||||
CV_XADD(&m.hdr->refcount, 1);
|
||||
release();
|
||||
flags = m.flags;
|
||||
hdr = m.hdr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
SparseMat& SparseMat::operator = (const Mat& m)
|
||||
{
|
||||
return (*this = SparseMat(m));
|
||||
}
|
||||
|
||||
inline
|
||||
SparseMat SparseMat::clone() const
|
||||
{
|
||||
@@ -2185,30 +1838,6 @@ SparseMat SparseMat::clone() const
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline
|
||||
void SparseMat::assignTo( SparseMat& m, int _type ) const
|
||||
{
|
||||
if( _type < 0 )
|
||||
m = *this;
|
||||
else
|
||||
convertTo(m, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
void SparseMat::addref()
|
||||
{
|
||||
if( hdr )
|
||||
CV_XADD(&hdr->refcount, 1);
|
||||
}
|
||||
|
||||
inline
|
||||
void SparseMat::release()
|
||||
{
|
||||
if( hdr && CV_XADD(&hdr->refcount, -1) == 1 )
|
||||
delete hdr;
|
||||
hdr = 0;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t SparseMat::elemSize() const
|
||||
{
|
||||
@@ -2268,36 +1897,6 @@ size_t SparseMat::nzcount() const
|
||||
return hdr ? hdr->nodeCount : 0;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t SparseMat::hash(int i0) const
|
||||
{
|
||||
return (size_t)i0;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t SparseMat::hash(int i0, int i1) const
|
||||
{
|
||||
return (size_t)(unsigned)i0 * HASH_SCALE + (unsigned)i1;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t SparseMat::hash(int i0, int i1, int i2) const
|
||||
{
|
||||
return ((size_t)(unsigned)i0 * HASH_SCALE + (unsigned)i1) * HASH_SCALE + (unsigned)i2;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t SparseMat::hash(const int* idx) const
|
||||
{
|
||||
size_t h = (unsigned)idx[0];
|
||||
if( !hdr )
|
||||
return 0;
|
||||
int d = hdr->dims;
|
||||
for(int i = 1; i < d; i++ )
|
||||
h = h * HASH_SCALE + (unsigned)idx[i];
|
||||
return h;
|
||||
}
|
||||
|
||||
template<typename _Tp> inline
|
||||
_Tp& SparseMat::ref(int i0, size_t* hashval)
|
||||
{
|
||||
@@ -3617,74 +3216,6 @@ const Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const MatExpr& b)
|
||||
|
||||
//////////////////////////////// UMat ////////////////////////////////
|
||||
|
||||
inline
|
||||
UMat::UMat(UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{}
|
||||
|
||||
inline
|
||||
UMat::UMat(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_rows, _cols, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
UMat::UMat(int _rows, int _cols, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_rows, _cols, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
inline
|
||||
UMat::UMat(Size _sz, int _type, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create( _sz.height, _sz.width, _type );
|
||||
}
|
||||
|
||||
inline
|
||||
UMat::UMat(Size _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_sz.height, _sz.width, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
inline
|
||||
UMat::UMat(int _dims, const int* _sz, int _type, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_dims, _sz, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
UMat::UMat(int _dims, const int* _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_dims, _sz, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
inline
|
||||
UMat::UMat(const UMat& m)
|
||||
: flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), allocator(m.allocator),
|
||||
usageFlags(m.usageFlags), u(m.u), offset(m.offset), size(&rows)
|
||||
{
|
||||
addref();
|
||||
if( m.dims <= 2 )
|
||||
{
|
||||
step[0] = m.step[0]; step[1] = m.step[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
dims = 0;
|
||||
copySize(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename _Tp> inline
|
||||
UMat::UMat(const std::vector<_Tp>& vec, bool copyData)
|
||||
: flags(MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
|
||||
@@ -3701,33 +3232,6 @@ cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows)
|
||||
Mat((int)vec.size(), 1, traits::Type<_Tp>::value, (uchar*)&vec[0]).copyTo(*this);
|
||||
}
|
||||
|
||||
inline
|
||||
UMat& UMat::operator = (const UMat& m)
|
||||
{
|
||||
if( this != &m )
|
||||
{
|
||||
const_cast<UMat&>(m).addref();
|
||||
release();
|
||||
flags = m.flags;
|
||||
if( dims <= 2 && m.dims <= 2 )
|
||||
{
|
||||
dims = m.dims;
|
||||
rows = m.rows;
|
||||
cols = m.cols;
|
||||
step[0] = m.step[0];
|
||||
step[1] = m.step[1];
|
||||
}
|
||||
else
|
||||
copySize(m);
|
||||
allocator = m.allocator;
|
||||
if (usageFlags == USAGE_DEFAULT)
|
||||
usageFlags = m.usageFlags;
|
||||
u = m.u;
|
||||
offset = m.offset;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
UMat UMat::row(int y) const
|
||||
{
|
||||
@@ -3764,55 +3268,6 @@ UMat UMat::colRange(const Range& r) const
|
||||
return UMat(*this, Range::all(), r);
|
||||
}
|
||||
|
||||
inline
|
||||
UMat UMat::clone() const
|
||||
{
|
||||
UMat m;
|
||||
copyTo(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
inline
|
||||
void UMat::assignTo( UMat& m, int _type ) const
|
||||
{
|
||||
if( _type < 0 )
|
||||
m = *this;
|
||||
else
|
||||
convertTo(m, _type);
|
||||
}
|
||||
|
||||
inline
|
||||
void UMat::create(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags)
|
||||
{
|
||||
_type &= TYPE_MASK;
|
||||
if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && u )
|
||||
return;
|
||||
int sz[] = {_rows, _cols};
|
||||
create(2, sz, _type, _usageFlags);
|
||||
}
|
||||
|
||||
inline
|
||||
void UMat::create(Size _sz, int _type, UMatUsageFlags _usageFlags)
|
||||
{
|
||||
create(_sz.height, _sz.width, _type, _usageFlags);
|
||||
}
|
||||
|
||||
inline
|
||||
void UMat::addref()
|
||||
{
|
||||
if( u )
|
||||
CV_XADD(&(u->urefcount), 1);
|
||||
}
|
||||
|
||||
inline void UMat::release()
|
||||
{
|
||||
if( u && CV_XADD(&(u->urefcount), -1) == 1 )
|
||||
deallocate();
|
||||
for(int i = 0; i < dims; i++)
|
||||
size.p[i] = 0;
|
||||
u = 0;
|
||||
}
|
||||
|
||||
inline
|
||||
UMat UMat::operator()( Range _rowRange, Range _colRange ) const
|
||||
{
|
||||
@@ -3887,23 +3342,6 @@ size_t UMat::step1(int i) const
|
||||
return step.p[i] / elemSize1();
|
||||
}
|
||||
|
||||
inline
|
||||
bool UMat::empty() const
|
||||
{
|
||||
return u == 0 || total() == 0 || dims == 0;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t UMat::total() const
|
||||
{
|
||||
if( dims <= 2 )
|
||||
return (size_t)rows * cols;
|
||||
size_t p = 1;
|
||||
for( int i = 0; i < dims; i++ )
|
||||
p *= size[i];
|
||||
return p;
|
||||
}
|
||||
|
||||
inline
|
||||
UMat::UMat(UMat&& m)
|
||||
: flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), allocator(m.allocator),
|
||||
|
||||
+279
-1
@@ -204,6 +204,21 @@ MatAllocator* Mat::getStdAllocator()
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
bool MatSize::operator==(const MatSize& sz) const
|
||||
{
|
||||
int d = dims();
|
||||
int dsz = sz.dims();
|
||||
if( d != dsz )
|
||||
return false;
|
||||
if( d == 2 )
|
||||
return p[0] == sz.p[0] && p[1] == sz.p[1];
|
||||
|
||||
for( int i = 0; i < d; i++ )
|
||||
if( p[i] != sz.p[i] )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void setSize( Mat& m, int _dims, const int* _sz, const size_t* _steps, bool autoSteps)
|
||||
{
|
||||
CV_Assert( 0 <= _dims && _dims <= CV_MAX_DIM );
|
||||
@@ -320,7 +335,270 @@ void finalizeHdr(Mat& m)
|
||||
m.dataend = m.datalimit = 0;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
//======================================= Mat ======================================================
|
||||
|
||||
Mat::Mat()
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{}
|
||||
|
||||
Mat::Mat(int _rows, int _cols, int _type)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_rows, _cols, _type);
|
||||
}
|
||||
|
||||
Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_rows, _cols, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
Mat::Mat(Size _sz, int _type)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create( _sz.height, _sz.width, _type );
|
||||
}
|
||||
|
||||
Mat::Mat(Size _sz, int _type, const Scalar& _s)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_sz.height, _sz.width, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
Mat::Mat(int _dims, const int* _sz, int _type)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_dims, _sz, _type);
|
||||
}
|
||||
|
||||
Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_dims, _sz, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
Mat::Mat(const std::vector<int>& _sz, int _type)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_sz, _type);
|
||||
}
|
||||
|
||||
Mat::Mat(const std::vector<int>& _sz, int _type, const Scalar& _s)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
|
||||
datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
create(_sz, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
Mat::Mat(const Mat& m)
|
||||
: flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data),
|
||||
datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit), allocator(m.allocator),
|
||||
u(m.u), size(&rows), step(0)
|
||||
{
|
||||
if( u )
|
||||
CV_XADD(&u->refcount, 1);
|
||||
if( m.dims <= 2 )
|
||||
{
|
||||
step[0] = m.step[0]; step[1] = m.step[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
dims = 0;
|
||||
copySize(m);
|
||||
}
|
||||
}
|
||||
|
||||
Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step)
|
||||
: flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols),
|
||||
data((uchar*)_data), datastart((uchar*)_data), dataend(0), datalimit(0),
|
||||
allocator(0), u(0), size(&rows)
|
||||
{
|
||||
CV_Assert(total() == 0 || data != NULL);
|
||||
|
||||
size_t esz = CV_ELEM_SIZE(_type), esz1 = CV_ELEM_SIZE1(_type);
|
||||
size_t minstep = cols * esz;
|
||||
if( _step == AUTO_STEP )
|
||||
{
|
||||
_step = minstep;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( _step >= minstep );
|
||||
if (_step % esz1 != 0)
|
||||
{
|
||||
CV_Error(Error::BadStep, "Step must be a multiple of esz1");
|
||||
}
|
||||
}
|
||||
step[0] = _step;
|
||||
step[1] = esz;
|
||||
datalimit = datastart + _step * rows;
|
||||
dataend = datalimit - _step + minstep;
|
||||
updateContinuityFlag();
|
||||
}
|
||||
|
||||
Mat::Mat(Size _sz, int _type, void* _data, size_t _step)
|
||||
: flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_sz.height), cols(_sz.width),
|
||||
data((uchar*)_data), datastart((uchar*)_data), dataend(0), datalimit(0),
|
||||
allocator(0), u(0), size(&rows)
|
||||
{
|
||||
CV_Assert(total() == 0 || data != NULL);
|
||||
|
||||
size_t esz = CV_ELEM_SIZE(_type), esz1 = CV_ELEM_SIZE1(_type);
|
||||
size_t minstep = cols*esz;
|
||||
if( _step == AUTO_STEP )
|
||||
{
|
||||
_step = minstep;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert(_step >= minstep);
|
||||
|
||||
if (_step % esz1 != 0)
|
||||
{
|
||||
CV_Error(Error::BadStep, "Step must be a multiple of esz1");
|
||||
}
|
||||
}
|
||||
step[0] = _step;
|
||||
step[1] = esz;
|
||||
datalimit = datastart + _step*rows;
|
||||
dataend = datalimit - _step + minstep;
|
||||
updateContinuityFlag();
|
||||
}
|
||||
|
||||
|
||||
Mat::~Mat()
|
||||
{
|
||||
release();
|
||||
if( step.p != step.buf )
|
||||
fastFree(step.p);
|
||||
}
|
||||
|
||||
Mat& Mat::operator=(const Mat& m)
|
||||
{
|
||||
if( this != &m )
|
||||
{
|
||||
if( m.u )
|
||||
CV_XADD(&m.u->refcount, 1);
|
||||
release();
|
||||
flags = m.flags;
|
||||
if( dims <= 2 && m.dims <= 2 )
|
||||
{
|
||||
dims = m.dims;
|
||||
rows = m.rows;
|
||||
cols = m.cols;
|
||||
step[0] = m.step[0];
|
||||
step[1] = m.step[1];
|
||||
}
|
||||
else
|
||||
copySize(m);
|
||||
data = m.data;
|
||||
datastart = m.datastart;
|
||||
dataend = m.dataend;
|
||||
datalimit = m.datalimit;
|
||||
allocator = m.allocator;
|
||||
u = m.u;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Mat Mat::clone() const
|
||||
{
|
||||
Mat m;
|
||||
copyTo(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
void Mat::assignTo( Mat& m, int _type ) const
|
||||
{
|
||||
if( _type < 0 )
|
||||
m = *this;
|
||||
else
|
||||
convertTo(m, _type);
|
||||
}
|
||||
|
||||
void Mat::create(int _rows, int _cols, int _type)
|
||||
{
|
||||
_type &= TYPE_MASK;
|
||||
if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && data )
|
||||
return;
|
||||
int sz[] = {_rows, _cols};
|
||||
create(2, sz, _type);
|
||||
}
|
||||
|
||||
void Mat::create(Size _sz, int _type)
|
||||
{
|
||||
create(_sz.height, _sz.width, _type);
|
||||
}
|
||||
|
||||
void Mat::addref()
|
||||
{
|
||||
if( u )
|
||||
CV_XADD(&u->refcount, 1);
|
||||
}
|
||||
|
||||
void Mat::release()
|
||||
{
|
||||
if( u && CV_XADD(&u->refcount, -1) == 1 )
|
||||
deallocate();
|
||||
u = NULL;
|
||||
datastart = dataend = datalimit = data = 0;
|
||||
for(int i = 0; i < dims; i++)
|
||||
size.p[i] = 0;
|
||||
#ifdef _DEBUG
|
||||
flags = MAGIC_VAL;
|
||||
dims = rows = cols = 0;
|
||||
if(step.p != step.buf)
|
||||
{
|
||||
fastFree(step.p);
|
||||
step.p = step.buf;
|
||||
size.p = &rows;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t Mat::step1(int i) const
|
||||
{
|
||||
return step.p[i] / elemSize1();
|
||||
}
|
||||
|
||||
bool Mat::empty() const
|
||||
{
|
||||
return data == 0 || total() == 0 || dims == 0;
|
||||
}
|
||||
|
||||
size_t Mat::total() const
|
||||
{
|
||||
if( dims <= 2 )
|
||||
return (size_t)rows * cols;
|
||||
size_t p = 1;
|
||||
for( int i = 0; i < dims; i++ )
|
||||
p *= size[i];
|
||||
return p;
|
||||
}
|
||||
|
||||
size_t Mat::total(int startDim, int endDim) const
|
||||
{
|
||||
CV_Assert( 0 <= startDim && startDim <= endDim);
|
||||
size_t p = 1;
|
||||
int endDim_ = endDim <= dims ? endDim : dims;
|
||||
for( int i = startDim; i < endDim_; i++ )
|
||||
p *= size[i];
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Mat::create(int d, const int* _sizes, int _type)
|
||||
{
|
||||
|
||||
@@ -176,6 +176,94 @@ void SparseMat::Hdr::clear()
|
||||
nodeCount = freeList = 0;
|
||||
}
|
||||
|
||||
///////////////////////////// SparseMat /////////////////////////////
|
||||
|
||||
SparseMat::SparseMat()
|
||||
: flags(MAGIC_VAL), hdr(0)
|
||||
{}
|
||||
|
||||
SparseMat::SparseMat(int _dims, const int* _sizes, int _type)
|
||||
: flags(MAGIC_VAL), hdr(0)
|
||||
{
|
||||
create(_dims, _sizes, _type);
|
||||
}
|
||||
|
||||
SparseMat::SparseMat(const SparseMat& m)
|
||||
: flags(m.flags), hdr(m.hdr)
|
||||
{
|
||||
addref();
|
||||
}
|
||||
|
||||
SparseMat::~SparseMat()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
SparseMat& SparseMat::operator = (const SparseMat& m)
|
||||
{
|
||||
if( this != &m )
|
||||
{
|
||||
if( m.hdr )
|
||||
CV_XADD(&m.hdr->refcount, 1);
|
||||
release();
|
||||
flags = m.flags;
|
||||
hdr = m.hdr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SparseMat& SparseMat::operator=(const Mat& m)
|
||||
{
|
||||
return (*this = SparseMat(m));
|
||||
}
|
||||
|
||||
void SparseMat::assignTo(SparseMat& m, int _type) const
|
||||
{
|
||||
if( _type < 0 )
|
||||
m = *this;
|
||||
else
|
||||
convertTo(m, _type);
|
||||
}
|
||||
|
||||
void SparseMat::addref()
|
||||
{
|
||||
if( hdr )
|
||||
CV_XADD(&hdr->refcount, 1);
|
||||
}
|
||||
|
||||
void SparseMat::release()
|
||||
{
|
||||
if( hdr && CV_XADD(&hdr->refcount, -1) == 1 )
|
||||
delete hdr;
|
||||
hdr = 0;
|
||||
}
|
||||
|
||||
size_t SparseMat::hash(int i0) const
|
||||
{
|
||||
return (size_t)i0;
|
||||
}
|
||||
|
||||
size_t SparseMat::hash(int i0, int i1) const
|
||||
{
|
||||
return (size_t)(unsigned)i0 * HASH_SCALE + (unsigned)i1;
|
||||
}
|
||||
|
||||
size_t SparseMat::hash(int i0, int i1, int i2) const
|
||||
{
|
||||
return ((size_t)(unsigned)i0 * HASH_SCALE + (unsigned)i1) * HASH_SCALE + (unsigned)i2;
|
||||
}
|
||||
|
||||
size_t SparseMat::hash(const int* idx) const
|
||||
{
|
||||
size_t h = (unsigned)idx[0];
|
||||
if( !hdr )
|
||||
return 0;
|
||||
int d = hdr->dims;
|
||||
for(int i = 1; i < d; i++ )
|
||||
h = h * HASH_SCALE + (unsigned)idx[i];
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
SparseMat::SparseMat(const Mat& m)
|
||||
: flags(MAGIC_VAL), hdr(0)
|
||||
|
||||
@@ -228,6 +228,152 @@ UMatDataAutoLock::~UMatDataAutoLock()
|
||||
getUMatDataAutoLocker().release(u1, u2);
|
||||
}
|
||||
|
||||
//////////////////////////////// UMat ////////////////////////////////
|
||||
|
||||
UMat::UMat(UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{}
|
||||
|
||||
UMat::UMat(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_rows, _cols, _type);
|
||||
}
|
||||
|
||||
UMat::UMat(int _rows, int _cols, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_rows, _cols, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
UMat::UMat(Size _sz, int _type, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create( _sz.height, _sz.width, _type );
|
||||
}
|
||||
|
||||
UMat::UMat(Size _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_sz.height, _sz.width, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
UMat::UMat(int _dims, const int* _sz, int _type, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_dims, _sz, _type);
|
||||
}
|
||||
|
||||
UMat::UMat(int _dims, const int* _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
|
||||
: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
|
||||
{
|
||||
create(_dims, _sz, _type);
|
||||
*this = _s;
|
||||
}
|
||||
|
||||
UMat::UMat(const UMat& m)
|
||||
: flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), allocator(m.allocator),
|
||||
usageFlags(m.usageFlags), u(m.u), offset(m.offset), size(&rows)
|
||||
{
|
||||
addref();
|
||||
if( m.dims <= 2 )
|
||||
{
|
||||
step[0] = m.step[0]; step[1] = m.step[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
dims = 0;
|
||||
copySize(m);
|
||||
}
|
||||
}
|
||||
|
||||
UMat& UMat::operator=(const UMat& m)
|
||||
{
|
||||
if( this != &m )
|
||||
{
|
||||
const_cast<UMat&>(m).addref();
|
||||
release();
|
||||
flags = m.flags;
|
||||
if( dims <= 2 && m.dims <= 2 )
|
||||
{
|
||||
dims = m.dims;
|
||||
rows = m.rows;
|
||||
cols = m.cols;
|
||||
step[0] = m.step[0];
|
||||
step[1] = m.step[1];
|
||||
}
|
||||
else
|
||||
copySize(m);
|
||||
allocator = m.allocator;
|
||||
if (usageFlags == USAGE_DEFAULT)
|
||||
usageFlags = m.usageFlags;
|
||||
u = m.u;
|
||||
offset = m.offset;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
UMat UMat::clone() const
|
||||
{
|
||||
UMat m;
|
||||
copyTo(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
void UMat::assignTo(UMat& m, int _type) const
|
||||
{
|
||||
if( _type < 0 )
|
||||
m = *this;
|
||||
else
|
||||
convertTo(m, _type);
|
||||
}
|
||||
|
||||
void UMat::create(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags)
|
||||
{
|
||||
_type &= TYPE_MASK;
|
||||
if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && u )
|
||||
return;
|
||||
int sz[] = {_rows, _cols};
|
||||
create(2, sz, _type, _usageFlags);
|
||||
}
|
||||
|
||||
void UMat::create(Size _sz, int _type, UMatUsageFlags _usageFlags)
|
||||
{
|
||||
create(_sz.height, _sz.width, _type, _usageFlags);
|
||||
}
|
||||
|
||||
void UMat::addref()
|
||||
{
|
||||
if( u )
|
||||
CV_XADD(&(u->urefcount), 1);
|
||||
}
|
||||
|
||||
void UMat::release()
|
||||
{
|
||||
if( u && CV_XADD(&(u->urefcount), -1) == 1 )
|
||||
deallocate();
|
||||
for(int i = 0; i < dims; i++)
|
||||
size.p[i] = 0;
|
||||
u = 0;
|
||||
}
|
||||
|
||||
bool UMat::empty() const
|
||||
{
|
||||
return u == 0 || total() == 0 || dims == 0;
|
||||
}
|
||||
|
||||
size_t UMat::total() const
|
||||
{
|
||||
if( dims <= 2 )
|
||||
return (size_t)rows * cols;
|
||||
size_t p = 1;
|
||||
for( int i = 0; i < dims; i++ )
|
||||
p *= size[i];
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
MatAllocator* UMat::getStdAllocator()
|
||||
{
|
||||
|
||||
@@ -103,7 +103,7 @@ def make_umd(opencvjs, cvjs):
|
||||
Module = {};
|
||||
return cv(Module);
|
||||
}));
|
||||
""" % (content)).lstrip())
|
||||
""" % (content)).lstrip().encode())
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 2:
|
||||
|
||||
@@ -699,6 +699,15 @@ public:
|
||||
*/
|
||||
CV_WRAP std::string decode(InputArray img, InputArray points, OutputArray straight_qrcode = noArray());
|
||||
|
||||
/** @brief Decodes QR code on a curved surface in image once it's found by the detect() method.
|
||||
|
||||
Returns UTF8-encoded output string or empty string if the code cannot be decoded.
|
||||
@param img grayscale or color (BGR) image containing QR code.
|
||||
@param points Quadrangle vertices found by detect() method (or some other algorithm).
|
||||
@param straight_qrcode The optional output image containing rectified and binarized QR code
|
||||
*/
|
||||
CV_WRAP cv::String decodeCurved(InputArray img, InputArray points, OutputArray straight_qrcode = noArray());
|
||||
|
||||
/** @brief Both detects and decodes QR code
|
||||
|
||||
@param img grayscale or color (BGR) image containing QR code.
|
||||
@@ -707,6 +716,16 @@ public:
|
||||
*/
|
||||
CV_WRAP std::string detectAndDecode(InputArray img, OutputArray points=noArray(),
|
||||
OutputArray straight_qrcode = noArray());
|
||||
|
||||
/** @brief Both detects and decodes QR code on a curved surface
|
||||
|
||||
@param img grayscale or color (BGR) image containing QR code.
|
||||
@param points optional output array of vertices of the found QR code quadrangle. Will be empty if not found.
|
||||
@param straight_qrcode The optional output image containing rectified and binarized QR code
|
||||
*/
|
||||
CV_WRAP std::string detectAndDecodeCurved(InputArray img, OutputArray points=noArray(),
|
||||
OutputArray straight_qrcode = noArray());
|
||||
|
||||
/** @brief Detects QR codes in image and returns the vector of the quadrangles containing the codes.
|
||||
@param img grayscale or color (BGR) image containing (or not) QR codes.
|
||||
@param points Output vector of vector of vertices of the minimum-area quadrangle containing the codes.
|
||||
|
||||
+1334
-45
@@ -18,6 +18,7 @@
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -63,7 +64,40 @@ static void updatePointsResult(OutputArray points_, const vector<Point2f>& point
|
||||
}
|
||||
}
|
||||
|
||||
static Point2f intersectionLines(Point2f a1, Point2f a2, Point2f b1, Point2f b2)
|
||||
{
|
||||
const float divisor = (a1.x - a2.x) * (b1.y - b2.y) - (a1.y - a2.y) * (b1.x - b2.x);
|
||||
const float eps = 0.001f;
|
||||
if (abs(divisor) < eps)
|
||||
return a2;
|
||||
Point2f result_square_angle(
|
||||
((a1.x * a2.y - a1.y * a2.x) * (b1.x - b2.x) -
|
||||
(b1.x * b2.y - b1.y * b2.x) * (a1.x - a2.x)) /
|
||||
divisor,
|
||||
((a1.x * a2.y - a1.y * a2.x) * (b1.y - b2.y) -
|
||||
(b1.x * b2.y - b1.y * b2.x) * (a1.y - a2.y)) /
|
||||
divisor
|
||||
);
|
||||
return result_square_angle;
|
||||
}
|
||||
|
||||
// / | b
|
||||
// / |
|
||||
// / |
|
||||
// a/ | c
|
||||
|
||||
static inline double getCosVectors(Point2f a, Point2f b, Point2f c)
|
||||
{
|
||||
return ((a - b).x * (c - b).x + (a - b).y * (c - b).y) / (norm(a - b) * norm(c - b));
|
||||
}
|
||||
|
||||
static bool arePointsNearest(Point2f a, Point2f b, float delta = 0.0)
|
||||
{
|
||||
if ((abs(a.x - b.x) < delta) && (abs(a.y - b.y) < delta))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
class QRDetect
|
||||
{
|
||||
@@ -74,15 +108,13 @@ public:
|
||||
Mat getBinBarcode() { return bin_barcode; }
|
||||
Mat getStraightBarcode() { return straight_barcode; }
|
||||
vector<Point2f> getTransformationPoints() { return transformation_points; }
|
||||
static Point2f intersectionLines(Point2f a1, Point2f a2, Point2f b1, Point2f b2);
|
||||
protected:
|
||||
vector<Vec3d> searchHorizontalLines();
|
||||
vector<Point2f> separateVerticalLines(const vector<Vec3d> &list_lines);
|
||||
vector<Point2f> extractVerticalLines(const vector<Vec3d> &list_lines, double eps);
|
||||
void fixationPoints(vector<Point2f> &local_point);
|
||||
vector<Point2f> getQuadrilateral(vector<Point2f> angle_list);
|
||||
bool testBypassRoute(vector<Point2f> hull, int start, int finish);
|
||||
inline double getCosVectors(Point2f a, Point2f b, Point2f c);
|
||||
bool testByPassRoute(vector<Point2f> hull, int start, int finish);
|
||||
|
||||
Mat barcode, bin_barcode, resized_barcode, resized_bin_barcode, straight_barcode;
|
||||
vector<Point2f> localization_points, transformation_points;
|
||||
@@ -361,7 +393,6 @@ void QRDetect::fixationPoints(vector<Point2f> &local_point)
|
||||
Point2f(static_cast<float>(bin_barcode.cols - 1),
|
||||
static_cast<float>(bin_barcode.rows - 1))));
|
||||
|
||||
|
||||
vector<Point2f> list_area_pnt;
|
||||
list_area_pnt.push_back(current_point);
|
||||
|
||||
@@ -629,7 +660,6 @@ bool QRDetect::computeTransformationPoints()
|
||||
transformation_points.push_back(
|
||||
intersectionLines(down_left_edge_point, down_max_delta_point,
|
||||
up_right_edge_point, up_max_delta_point));
|
||||
|
||||
vector<Point2f> quadrilateral = getQuadrilateral(transformation_points);
|
||||
transformation_points = quadrilateral;
|
||||
|
||||
@@ -643,23 +673,8 @@ bool QRDetect::computeTransformationPoints()
|
||||
return true;
|
||||
}
|
||||
|
||||
Point2f QRDetect::intersectionLines(Point2f a1, Point2f a2, Point2f b1, Point2f b2)
|
||||
{
|
||||
Point2f result_square_angle(
|
||||
((a1.x * a2.y - a1.y * a2.x) * (b1.x - b2.x) -
|
||||
(b1.x * b2.y - b1.y * b2.x) * (a1.x - a2.x)) /
|
||||
((a1.x - a2.x) * (b1.y - b2.y) -
|
||||
(a1.y - a2.y) * (b1.x - b2.x)),
|
||||
((a1.x * a2.y - a1.y * a2.x) * (b1.y - b2.y) -
|
||||
(b1.x * b2.y - b1.y * b2.x) * (a1.y - a2.y)) /
|
||||
((a1.x - a2.x) * (b1.y - b2.y) -
|
||||
(a1.y - a2.y) * (b1.x - b2.x))
|
||||
);
|
||||
return result_square_angle;
|
||||
}
|
||||
|
||||
// test function (if true then ------> else <------ )
|
||||
bool QRDetect::testBypassRoute(vector<Point2f> hull, int start, int finish)
|
||||
bool QRDetect::testByPassRoute(vector<Point2f> hull, int start, int finish)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
int index_hull = start, next_index_hull, hull_size = (int)hull.size();
|
||||
@@ -764,7 +779,7 @@ vector<Point2f> QRDetect::getQuadrilateral(vector<Point2f> angle_list)
|
||||
int index_hull, extra_index_hull, next_index_hull, extra_next_index_hull;
|
||||
Point result_side_begin[4], result_side_end[4];
|
||||
|
||||
bool bypass_orientation = testBypassRoute(hull, start_line[0], finish_line[0]);
|
||||
bool bypass_orientation = testByPassRoute(hull, start_line[0], finish_line[0]);
|
||||
|
||||
min_norm = std::numeric_limits<double>::max();
|
||||
index_hull = start_line[0];
|
||||
@@ -805,7 +820,7 @@ vector<Point2f> QRDetect::getQuadrilateral(vector<Point2f> angle_list)
|
||||
|
||||
min_norm = std::numeric_limits<double>::max();
|
||||
index_hull = start_line[1];
|
||||
bypass_orientation = testBypassRoute(hull, start_line[1], finish_line[1]);
|
||||
bypass_orientation = testByPassRoute(hull, start_line[1], finish_line[1]);
|
||||
do
|
||||
{
|
||||
if (bypass_orientation) { next_index_hull = index_hull + 1; }
|
||||
@@ -840,8 +855,8 @@ vector<Point2f> QRDetect::getQuadrilateral(vector<Point2f> angle_list)
|
||||
result_side_end[1] = angle_list[1];
|
||||
}
|
||||
|
||||
bypass_orientation = testBypassRoute(hull, start_line[0], unstable_pnt);
|
||||
const bool extra_bypass_orientation = testBypassRoute(hull, finish_line[1], unstable_pnt);
|
||||
bypass_orientation = testByPassRoute(hull, start_line[0], unstable_pnt);
|
||||
const bool extra_bypass_orientation = testByPassRoute(hull, finish_line[1], unstable_pnt);
|
||||
|
||||
vector<Point2f> result_angle_list(4), test_result_angle_list(4);
|
||||
double min_diff_area = std::numeric_limits<double>::max();
|
||||
@@ -918,16 +933,6 @@ vector<Point2f> QRDetect::getQuadrilateral(vector<Point2f> angle_list)
|
||||
return result_angle_list;
|
||||
}
|
||||
|
||||
// / | b
|
||||
// / |
|
||||
// / |
|
||||
// a/ | c
|
||||
|
||||
inline double QRDetect::getCosVectors(Point2f a, Point2f b, Point2f c)
|
||||
{
|
||||
return ((a - b).x * (c - b).x + (a - b).y * (c - b).y) / (norm(a - b) * norm(c - b));
|
||||
}
|
||||
|
||||
struct QRCodeDetector::Impl
|
||||
{
|
||||
public:
|
||||
@@ -966,17 +971,79 @@ public:
|
||||
Mat getStraightBarcode() { return straight; }
|
||||
size_t getVersion() { return version; }
|
||||
std::string getDecodeInformation() { return result_info; }
|
||||
bool fullDecodingProcess();
|
||||
bool straightDecodingProcess();
|
||||
bool curvedDecodingProcess();
|
||||
protected:
|
||||
bool updatePerspective();
|
||||
bool versionDefinition();
|
||||
bool samplingForVersion();
|
||||
bool decodingProcess();
|
||||
Mat original, no_border_intermediate, intermediate, straight;
|
||||
inline double pointPosition(Point2f a, Point2f b , Point2f c);
|
||||
float distancePointToLine(Point2f a, Point2f b , Point2f c);
|
||||
void getPointsInsideQRCode(const vector<Point2f> &angle_list);
|
||||
bool computeClosestPoints(const vector<Point> &result_integer_hull);
|
||||
bool computeSidesPoints(const vector<Point> &result_integer_hull);
|
||||
vector<Point> getPointsNearUnstablePoint(const vector<Point> &side, int start, int end, int step);
|
||||
bool findAndAddStablePoint(const vector<Point> &result_integer_hull);
|
||||
bool findIndexesCurvedSides();
|
||||
bool findIncompleteIndexesCurvedSides();
|
||||
Mat getPatternsMask();
|
||||
Point findClosestZeroPoint(Point2f original_point);
|
||||
bool findPatternsContours(vector<vector<Point> > &patterns_contours);
|
||||
bool findPatternsVerticesPoints(vector<vector<Point> > &patterns_vertices_points);
|
||||
bool findTempPatternsAddingPoints(vector<std::pair<int, vector<Point> > > &temp_patterns_add_points);
|
||||
bool computePatternsAddingPoints(std::map<int, vector<Point> > &patterns_add_points);
|
||||
bool addPointsToSides();
|
||||
void completeAndSortSides();
|
||||
vector<vector<float> > computeSpline(const vector<int> &x_arr, const vector<int> &y_arr);
|
||||
bool createSpline(vector<vector<Point2f> > &spline_lines);
|
||||
bool divideIntoEvenSegments(vector<vector<Point2f> > &segments_points);
|
||||
bool straightenQRCodeInParts();
|
||||
bool preparingCurvedQRCodes();
|
||||
|
||||
const static int NUM_SIDES = 2;
|
||||
Mat original, bin_barcode, no_border_intermediate, intermediate, straight, curved_to_straight, test_image;
|
||||
vector<Point2f> original_points;
|
||||
vector<Point2f> original_curved_points;
|
||||
vector<Point> qrcode_locations;
|
||||
vector<std::pair<size_t, Point> > closest_points;
|
||||
vector<vector<Point> > sides_points;
|
||||
std::pair<size_t, Point> unstable_pair;
|
||||
vector<int> curved_indexes, curved_incomplete_indexes;
|
||||
std::map<int, vector<Point> > complete_curved_sides;
|
||||
std::string result_info;
|
||||
uint8_t version, version_size;
|
||||
float test_perspective_size;
|
||||
struct sortPairAsc
|
||||
{
|
||||
bool operator()(const std::pair<size_t, double> &a,
|
||||
const std::pair<size_t, double> &b) const
|
||||
{
|
||||
return a.second < b.second;
|
||||
}
|
||||
};
|
||||
struct sortPairDesc
|
||||
{
|
||||
bool operator()(const std::pair<size_t, double> &a,
|
||||
const std::pair<size_t, double> &b) const
|
||||
{
|
||||
return a.second > b.second;
|
||||
}
|
||||
};
|
||||
struct sortPointsByX
|
||||
{
|
||||
bool operator()(const Point &a, const Point &b) const
|
||||
{
|
||||
return a.x < b.x;
|
||||
}
|
||||
};
|
||||
struct sortPointsByY
|
||||
{
|
||||
bool operator()(const Point &a, const Point &b) const
|
||||
{
|
||||
return a.y < b.y;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void QRDecode::init(const Mat &src, const vector<Point2f> &points)
|
||||
@@ -984,6 +1051,8 @@ void QRDecode::init(const Mat &src, const vector<Point2f> &points)
|
||||
CV_TRACE_FUNCTION();
|
||||
vector<Point2f> bbox = points;
|
||||
original = src.clone();
|
||||
test_image = src.clone();
|
||||
adaptiveThreshold(original, bin_barcode, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 83, 2);
|
||||
intermediate = Mat::zeros(original.size(), CV_8UC1);
|
||||
original_points = bbox;
|
||||
version = 0;
|
||||
@@ -992,11 +1061,1168 @@ void QRDecode::init(const Mat &src, const vector<Point2f> &points)
|
||||
result_info = "";
|
||||
}
|
||||
|
||||
inline double QRDecode::pointPosition(Point2f a, Point2f b , Point2f c)
|
||||
{
|
||||
return (a.x - b.x) * (c.y - b.y) - (c.x - b.x) * (a.y - b.y);
|
||||
}
|
||||
|
||||
float QRDecode::distancePointToLine(Point2f a, Point2f b , Point2f c)
|
||||
{
|
||||
float A, B, C, result;
|
||||
A = c.y - b.y;
|
||||
B = c.x - b.x;
|
||||
C = c.x * b.y - b.x * c.y;
|
||||
float dist = sqrt(A*A + B*B);
|
||||
if (dist == 0) return 0;
|
||||
result = abs((A * a.x - B * a.y + C)) / dist;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void QRDecode::getPointsInsideQRCode(const vector<Point2f> &angle_list)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
size_t angle_size = angle_list.size();
|
||||
Mat contour_mask = Mat::zeros(bin_barcode.size(), CV_8UC1);
|
||||
for (size_t i = 0; i < angle_size; i++)
|
||||
{
|
||||
LineIterator line_iter(bin_barcode, angle_list[ i % angle_size],
|
||||
angle_list[(i + 1) % angle_size]);
|
||||
for(int j = 0; j < line_iter.count; j++, ++line_iter)
|
||||
{
|
||||
Point p = line_iter.pos();
|
||||
contour_mask.at<uint8_t>(p + Point(1, 1)) = 255;
|
||||
}
|
||||
}
|
||||
Point2f center_point = intersectionLines(angle_list[0], angle_list[2],
|
||||
angle_list[1], angle_list[3]);
|
||||
floodFill(contour_mask, center_point, 255, 0, Scalar(), Scalar(), FLOODFILL_FIXED_RANGE);
|
||||
|
||||
vector<Point> locations;
|
||||
findNonZero(contour_mask, locations);
|
||||
|
||||
Mat fill_bin_barcode = bin_barcode.clone();
|
||||
Mat qrcode_mask = Mat::zeros(bin_barcode.rows + 2, bin_barcode.cols + 2, CV_8UC1);
|
||||
uint8_t value, mask_value;
|
||||
for(size_t i = 0; i < locations.size(); i++)
|
||||
{
|
||||
value = bin_barcode.at<uint8_t>(locations[i]);
|
||||
mask_value = qrcode_mask.at<uint8_t>(locations[i] + Point(1, 1));
|
||||
if (value == 0 && mask_value == 0)
|
||||
{
|
||||
floodFill(fill_bin_barcode, qrcode_mask, locations[i], 255,
|
||||
0, Scalar(), Scalar(), FLOODFILL_MASK_ONLY);
|
||||
}
|
||||
}
|
||||
Mat qrcode_mask_roi = qrcode_mask(Range(1, qrcode_mask.rows - 1), Range(1, qrcode_mask.cols - 1));
|
||||
findNonZero(qrcode_mask_roi, qrcode_locations);
|
||||
}
|
||||
|
||||
bool QRDecode::computeClosestPoints(const vector<Point> &result_integer_hull)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
double min_norm, max_norm = 0.0;
|
||||
size_t idx_min;
|
||||
for (size_t i = 0; i < original_points.size(); i++)
|
||||
{
|
||||
min_norm = std::numeric_limits<double>::max();
|
||||
|
||||
Point closest_pnt;
|
||||
for (size_t j = 0; j < result_integer_hull.size(); j++)
|
||||
{
|
||||
Point integer_original_point = original_points[i];
|
||||
double temp_norm = norm(integer_original_point - result_integer_hull[j]);
|
||||
if (temp_norm < min_norm)
|
||||
{
|
||||
min_norm = temp_norm;
|
||||
closest_pnt = result_integer_hull[j];
|
||||
idx_min = j;
|
||||
}
|
||||
}
|
||||
if (min_norm > max_norm)
|
||||
{
|
||||
max_norm = min_norm;
|
||||
unstable_pair = std::pair<size_t,Point>(i, closest_pnt);
|
||||
}
|
||||
closest_points.push_back(std::pair<size_t,Point>(idx_min, closest_pnt));
|
||||
}
|
||||
|
||||
if (closest_points.size() != 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::computeSidesPoints(const vector<Point> &result_integer_hull)
|
||||
{
|
||||
size_t num_closest_points = closest_points.size();
|
||||
vector<Point> points;
|
||||
|
||||
for(size_t i = 0; i < num_closest_points; i++)
|
||||
{
|
||||
points.clear();
|
||||
size_t start = closest_points[i].first,
|
||||
end = closest_points[(i + 1) % num_closest_points].first;
|
||||
if (start < end)
|
||||
{
|
||||
points.insert(points.end(),
|
||||
result_integer_hull.begin() + start,
|
||||
result_integer_hull.begin() + end + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
points.insert(points.end(),
|
||||
result_integer_hull.begin() + start,
|
||||
result_integer_hull.end());
|
||||
points.insert(points.end(),
|
||||
result_integer_hull.begin(),
|
||||
result_integer_hull.begin() + end + 1);
|
||||
}
|
||||
if (abs(result_integer_hull[start].x - result_integer_hull[end].x) >
|
||||
abs(result_integer_hull[start].y - result_integer_hull[end].y))
|
||||
{
|
||||
if (points.front().x > points.back().x)
|
||||
{
|
||||
reverse(points.begin(), points.end());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (points.front().y > points.back().y)
|
||||
{
|
||||
reverse(points.begin(), points.end());
|
||||
}
|
||||
}
|
||||
if (points.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
sides_points.push_back(points);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
vector<Point> QRDecode::getPointsNearUnstablePoint(const vector<Point> &side, int start, int end, int step)
|
||||
{
|
||||
vector<Point> points;
|
||||
Point p1, p2, p3;
|
||||
|
||||
double max_neighbour_angle = 1.0;
|
||||
int index_max_angle = start + step;
|
||||
bool enough_points = true;
|
||||
|
||||
if(side.size() < 3)
|
||||
{
|
||||
points.insert(points.end(), side.begin(), side.end());
|
||||
return points;
|
||||
}
|
||||
const double cos_angle_threshold = -0.97;
|
||||
for (int i = start + step; i != end; i+= step)
|
||||
{
|
||||
p1 = side[i + step];
|
||||
if (norm(p1 - side[i]) < 5) { continue; }
|
||||
p2 = side[i];
|
||||
if (norm(p2 - side[i - step]) < 5) { continue; }
|
||||
p3 = side[i - step];
|
||||
|
||||
double neighbour_angle = getCosVectors(p1, p2, p3);
|
||||
neighbour_angle = floor(neighbour_angle*1000)/1000;
|
||||
|
||||
if ((neighbour_angle <= max_neighbour_angle) && (neighbour_angle < cos_angle_threshold))
|
||||
{
|
||||
max_neighbour_angle = neighbour_angle;
|
||||
index_max_angle = i;
|
||||
}
|
||||
else if (i == end - step)
|
||||
{
|
||||
enough_points = false;
|
||||
index_max_angle = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (enough_points)
|
||||
{
|
||||
p1 = side[index_max_angle + step];
|
||||
p2 = side[index_max_angle];
|
||||
p3 = side[index_max_angle - step];
|
||||
|
||||
points.push_back(p1);
|
||||
points.push_back(p2);
|
||||
points.push_back(p3);
|
||||
}
|
||||
else
|
||||
{
|
||||
p1 = side[index_max_angle];
|
||||
p2 = side[index_max_angle - step];
|
||||
|
||||
points.push_back(p1);
|
||||
points.push_back(p2);
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
bool QRDecode::findAndAddStablePoint(const vector<Point> &result_integer_hull)
|
||||
{
|
||||
size_t idx_unstable_point = unstable_pair.first;
|
||||
Point unstable_point = unstable_pair.second;
|
||||
|
||||
vector<Point> current_side_points, next_side_points;
|
||||
Point a1, a2, b1, b2;
|
||||
int start_current, end_current, step_current, start_next, end_next, step_next;
|
||||
vector<Point>::iterator it_a, it_b;
|
||||
|
||||
vector<Point> ¤t_side = sides_points[(idx_unstable_point + 3) % 4];
|
||||
vector<Point> &next_side = sides_points[idx_unstable_point];
|
||||
|
||||
if(current_side.size() < 2 || next_side.size() < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(arePointsNearest(unstable_point, current_side.front(), 3.0))
|
||||
{
|
||||
start_current = (int)current_side.size() - 1;
|
||||
end_current = 0;
|
||||
step_current = -1;
|
||||
it_a = current_side.begin();
|
||||
}
|
||||
else if(arePointsNearest(unstable_point, current_side.back(), 3.0))
|
||||
{
|
||||
start_current = 0;
|
||||
end_current = (int)current_side.size() - 1;
|
||||
step_current = 1;
|
||||
it_a = current_side.end() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(arePointsNearest(unstable_point, next_side.front(), 3.0))
|
||||
{
|
||||
start_next = (int)next_side.size() - 1;
|
||||
end_next = 0;
|
||||
step_next = -1;
|
||||
it_b = next_side.begin();
|
||||
}
|
||||
else if(arePointsNearest(unstable_point, next_side.back(), 3.0))
|
||||
{
|
||||
start_next = 0;
|
||||
end_next = (int)next_side.size() - 1;
|
||||
step_next = 1;
|
||||
it_b = next_side.end() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
current_side_points = getPointsNearUnstablePoint(current_side, start_current, end_current, step_current);
|
||||
next_side_points = getPointsNearUnstablePoint(next_side, start_next, end_next, step_next);
|
||||
|
||||
if (current_side_points.size() < 2 || next_side_points.size() < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
a1 = current_side_points[0];
|
||||
a2 = current_side_points[1];
|
||||
|
||||
b1 = next_side_points[0];
|
||||
b2 = next_side_points[1];
|
||||
|
||||
if(norm(a1 - b1) < 10 && next_side_points.size() > 2)
|
||||
{
|
||||
b1 = next_side_points[1];
|
||||
b2 = next_side_points[2];
|
||||
}
|
||||
|
||||
Point stable_point = intersectionLines(a1, a2, b1, b2);
|
||||
|
||||
const double max_side = std::max(bin_barcode.size().width, bin_barcode.size().height);
|
||||
if ((abs(stable_point.x) > max_side) || (abs(stable_point.y) > max_side))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (*it_a != a1)
|
||||
{
|
||||
it_a = current_side.erase(it_a);
|
||||
if (it_a == current_side.end())
|
||||
{
|
||||
it_a -= step_current;
|
||||
}
|
||||
Point point_to_remove_from_current = *it_a;
|
||||
if (point_to_remove_from_current.x > max_side || point_to_remove_from_current.y > max_side)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (*it_b != b1)
|
||||
{
|
||||
it_b = next_side.erase(it_b);
|
||||
if (it_b == next_side.end())
|
||||
{
|
||||
it_b -= step_next;
|
||||
}
|
||||
Point point_to_remove_from_next = *it_b;
|
||||
if (point_to_remove_from_next.x > max_side || point_to_remove_from_next.y > max_side)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool add_stable_point = true;
|
||||
|
||||
for (size_t i = 0; i < result_integer_hull.size(); i++)
|
||||
{
|
||||
if(arePointsNearest(stable_point, original_points[i], 3.0))
|
||||
{
|
||||
add_stable_point = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(add_stable_point)
|
||||
{
|
||||
current_side.insert(it_a, stable_point);
|
||||
next_side.insert(it_b, stable_point);
|
||||
closest_points[unstable_pair.first].second = stable_point;
|
||||
}
|
||||
else
|
||||
{
|
||||
stable_point = original_points[unstable_pair.first];
|
||||
closest_points[unstable_pair.first].second = stable_point;
|
||||
current_side.insert(it_a, stable_point);
|
||||
next_side.insert(it_b, stable_point);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::findIndexesCurvedSides()
|
||||
{
|
||||
double max_dist_to_arc_side = 0.0;
|
||||
size_t num_closest_points = closest_points.size();
|
||||
int idx_curved_current = -1, idx_curved_opposite = -1;
|
||||
|
||||
for (size_t i = 0; i < num_closest_points; i++)
|
||||
{
|
||||
double dist_to_arc = 0.0;
|
||||
|
||||
Point arc_start = closest_points[i].second;
|
||||
Point arc_end = closest_points[(i + 1) % num_closest_points].second;
|
||||
|
||||
for (size_t j = 0; j < sides_points[i].size(); j++)
|
||||
{
|
||||
Point arc_point = sides_points[i][j];
|
||||
double dist = distancePointToLine(arc_point, arc_start, arc_end);
|
||||
dist_to_arc += dist;
|
||||
}
|
||||
dist_to_arc /= sides_points[i].size();
|
||||
|
||||
if (dist_to_arc > max_dist_to_arc_side)
|
||||
{
|
||||
max_dist_to_arc_side = dist_to_arc;
|
||||
idx_curved_current = (int)i;
|
||||
idx_curved_opposite = (int)(i + 2) % num_closest_points;
|
||||
}
|
||||
}
|
||||
if (idx_curved_current == -1 || idx_curved_opposite == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
curved_indexes.push_back(idx_curved_current);
|
||||
curved_indexes.push_back(idx_curved_opposite);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::findIncompleteIndexesCurvedSides()
|
||||
{
|
||||
int num_closest_points = (int)closest_points.size();
|
||||
|
||||
for (int i = 0; i < NUM_SIDES; i++)
|
||||
{
|
||||
int idx_side = curved_indexes[i];
|
||||
int side_size = (int)sides_points[idx_side].size();
|
||||
|
||||
double max_norm = norm(closest_points[idx_side].second -
|
||||
closest_points[(idx_side + 1) % num_closest_points].second);
|
||||
double real_max_norm = 0;
|
||||
|
||||
for (int j = 0; j < side_size - 1; j++)
|
||||
{
|
||||
double temp_norm = norm(sides_points[idx_side][j] -
|
||||
sides_points[idx_side][j + 1]);
|
||||
if (temp_norm > real_max_norm)
|
||||
{
|
||||
real_max_norm = temp_norm;
|
||||
}
|
||||
}
|
||||
if (real_max_norm > (0.5 * max_norm))
|
||||
{
|
||||
curved_incomplete_indexes.push_back(curved_indexes[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (curved_incomplete_indexes.size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Point QRDecode::findClosestZeroPoint(Point2f original_point)
|
||||
{
|
||||
int orig_x = static_cast<int>(original_point.x);
|
||||
int orig_y = static_cast<int>(original_point.y);
|
||||
uint8_t value;
|
||||
Point zero_point;
|
||||
|
||||
const int step = 2;
|
||||
for (int i = orig_x - step; i >= 0 && i <= orig_x + step; i++)
|
||||
{
|
||||
for (int j = orig_y - step; j >= 0 && j <= orig_y + step; j++)
|
||||
{
|
||||
Point p(i, j);
|
||||
value = bin_barcode.at<uint8_t>(p);
|
||||
if (value == 0) zero_point = p;
|
||||
}
|
||||
}
|
||||
|
||||
return zero_point;
|
||||
}
|
||||
|
||||
Mat QRDecode::getPatternsMask()
|
||||
{
|
||||
Mat mask(bin_barcode.rows + 2, bin_barcode.cols + 2, CV_8UC1, Scalar(0));
|
||||
Mat patterns_mask(bin_barcode.rows + 2, bin_barcode.cols + 2, CV_8UC1, Scalar(0));
|
||||
Mat fill_bin_barcode = bin_barcode.clone();
|
||||
for (size_t i = 0; i < original_points.size(); i++)
|
||||
{
|
||||
if (i == 2) continue;
|
||||
Point p = findClosestZeroPoint(original_points[i]);
|
||||
floodFill(fill_bin_barcode, mask, p, 255,
|
||||
0, Scalar(), Scalar(), FLOODFILL_MASK_ONLY);
|
||||
patterns_mask += mask;
|
||||
}
|
||||
Mat mask_roi = patterns_mask(Range(1, bin_barcode.rows - 1), Range(1, bin_barcode.cols - 1));
|
||||
|
||||
return mask_roi;
|
||||
}
|
||||
|
||||
bool QRDecode::findPatternsContours(vector<vector<Point> > &patterns_contours)
|
||||
{
|
||||
Mat patterns_mask = getPatternsMask();
|
||||
findContours(patterns_mask, patterns_contours, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0));
|
||||
if (patterns_contours.size() != 3) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::findPatternsVerticesPoints(vector<vector<Point> > &patterns_vertices_points)
|
||||
{
|
||||
vector<vector<Point> > patterns_contours;
|
||||
if(!findPatternsContours(patterns_contours))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const int num_vertices = 4;
|
||||
for(size_t i = 0; i < patterns_contours.size(); i++)
|
||||
{
|
||||
vector<Point> convexhull_contours, new_convexhull_contours;
|
||||
convexHull(patterns_contours[i], convexhull_contours);
|
||||
|
||||
size_t number_pnts_in_hull = convexhull_contours.size();
|
||||
vector<std::pair<size_t, double> > cos_angles_in_hull;
|
||||
vector<size_t> min_angle_pnts_indexes;
|
||||
|
||||
for(size_t j = 1; j < number_pnts_in_hull + 1; j++)
|
||||
{
|
||||
double cos_angle = getCosVectors(convexhull_contours[(j - 1) % number_pnts_in_hull],
|
||||
convexhull_contours[ j % number_pnts_in_hull],
|
||||
convexhull_contours[(j + 1) % number_pnts_in_hull]);
|
||||
cos_angles_in_hull.push_back(std::pair<size_t, double>(j, cos_angle));
|
||||
}
|
||||
|
||||
sort(cos_angles_in_hull.begin(), cos_angles_in_hull.end(), sortPairDesc());
|
||||
|
||||
for (size_t j = 0; j < cos_angles_in_hull.size(); j++)
|
||||
{
|
||||
bool add_edge = true;
|
||||
for(size_t k = 0; k < min_angle_pnts_indexes.size(); k++)
|
||||
{
|
||||
if(norm(convexhull_contours[cos_angles_in_hull[j].first % number_pnts_in_hull] -
|
||||
convexhull_contours[min_angle_pnts_indexes[k] % number_pnts_in_hull]) < 3)
|
||||
{
|
||||
add_edge = false;
|
||||
}
|
||||
}
|
||||
if (add_edge)
|
||||
{
|
||||
min_angle_pnts_indexes.push_back(cos_angles_in_hull[j].first % number_pnts_in_hull);
|
||||
}
|
||||
if ((int)min_angle_pnts_indexes.size() == num_vertices) { break; }
|
||||
}
|
||||
sort(min_angle_pnts_indexes.begin(), min_angle_pnts_indexes.end());
|
||||
|
||||
vector<Point> contour_vertices_points;
|
||||
|
||||
for (size_t k = 0; k < min_angle_pnts_indexes.size(); k++)
|
||||
{
|
||||
contour_vertices_points.push_back(convexhull_contours[min_angle_pnts_indexes[k]]);
|
||||
}
|
||||
patterns_vertices_points.push_back(contour_vertices_points);
|
||||
}
|
||||
if (patterns_vertices_points.size() != 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::findTempPatternsAddingPoints(vector<std::pair<int, vector<Point> > > &temp_patterns_add_points)
|
||||
{
|
||||
vector<vector<Point> >patterns_contours, patterns_vertices_points;
|
||||
if(!findPatternsVerticesPoints(patterns_vertices_points))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!findPatternsContours(patterns_contours))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < curved_incomplete_indexes.size(); i++)
|
||||
{
|
||||
int idx_curved_side = curved_incomplete_indexes[i];
|
||||
Point close_transform_pnt_curr = original_points[idx_curved_side];
|
||||
Point close_transform_pnt_next = original_points[(idx_curved_side + 1) % 4];
|
||||
|
||||
vector<size_t> patterns_indexes;
|
||||
|
||||
for (size_t j = 0; j < patterns_vertices_points.size(); j++)
|
||||
{
|
||||
for (size_t k = 0; k < patterns_vertices_points[j].size(); k++)
|
||||
{
|
||||
if (norm(close_transform_pnt_curr - patterns_vertices_points[j][k]) < 5)
|
||||
{
|
||||
patterns_indexes.push_back(j);
|
||||
break;
|
||||
}
|
||||
if (norm(close_transform_pnt_next - patterns_vertices_points[j][k]) < 5)
|
||||
{
|
||||
patterns_indexes.push_back(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t j = 0; j < patterns_indexes.size(); j++)
|
||||
{
|
||||
vector<Point> vertices = patterns_vertices_points[patterns_indexes[j]];
|
||||
vector<std::pair<int, double> > vertices_dist_pair;
|
||||
vector<Point> points;
|
||||
for (size_t k = 0; k < vertices.size(); k++)
|
||||
{
|
||||
double dist_to_side = distancePointToLine(vertices[k], close_transform_pnt_curr,
|
||||
close_transform_pnt_next);
|
||||
vertices_dist_pair.push_back(std::pair<int, double>((int)k, dist_to_side));
|
||||
}
|
||||
if (vertices_dist_pair.size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
sort(vertices_dist_pair.begin(), vertices_dist_pair.end(), sortPairAsc());
|
||||
Point p1, p2;
|
||||
int index_p1_in_vertices = 0, index_p2_in_vertices = 0;
|
||||
for (int k = 4; k > 0; k--)
|
||||
{
|
||||
if((vertices_dist_pair[0].first == k % 4) && (vertices_dist_pair[1].first == (k - 1) % 4))
|
||||
{
|
||||
index_p1_in_vertices = vertices_dist_pair[0].first;
|
||||
index_p2_in_vertices = vertices_dist_pair[1].first;
|
||||
}
|
||||
else if((vertices_dist_pair[1].first == k % 4) && (vertices_dist_pair[0].first == (k - 1) % 4))
|
||||
{
|
||||
index_p1_in_vertices = vertices_dist_pair[1].first;
|
||||
index_p2_in_vertices = vertices_dist_pair[0].first;
|
||||
}
|
||||
}
|
||||
if (index_p1_in_vertices == index_p2_in_vertices) return false;
|
||||
|
||||
p1 = vertices[index_p1_in_vertices];
|
||||
p2 = vertices[index_p2_in_vertices];
|
||||
|
||||
size_t index_p1_in_contour = 0, index_p2_in_contour = 0;
|
||||
vector<Point> add_points = patterns_contours[patterns_indexes[j]];
|
||||
|
||||
for(size_t k = 0; k < add_points.size(); k++)
|
||||
{
|
||||
if (add_points[k] == p1)
|
||||
{
|
||||
index_p1_in_contour = k;
|
||||
}
|
||||
if (add_points[k] == p2)
|
||||
{
|
||||
index_p2_in_contour = k;
|
||||
}
|
||||
}
|
||||
|
||||
if (index_p1_in_contour > index_p2_in_contour)
|
||||
{
|
||||
for (size_t k = index_p1_in_contour; k < add_points.size(); k++)
|
||||
{
|
||||
points.push_back(add_points[k]);
|
||||
}
|
||||
for (size_t k = 0; k <= index_p2_in_contour; k++)
|
||||
{
|
||||
points.push_back(add_points[k]);
|
||||
}
|
||||
}
|
||||
else if (index_p1_in_contour < index_p2_in_contour)
|
||||
{
|
||||
for (size_t k = index_p1_in_contour; k <= index_p2_in_contour; k++)
|
||||
{
|
||||
points.push_back(add_points[k]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (abs(p1.x - p2.x) > abs(p1.y - p2.y))
|
||||
{
|
||||
sort(points.begin(), points.end(), sortPointsByX());
|
||||
}
|
||||
else
|
||||
{
|
||||
sort(points.begin(), points.end(), sortPointsByY());
|
||||
}
|
||||
|
||||
temp_patterns_add_points.push_back(std::pair<int, vector<Point> >(idx_curved_side,points));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::computePatternsAddingPoints(std::map<int, vector<Point> > &patterns_add_points)
|
||||
{
|
||||
vector<std::pair<int, vector<Point> > > temp_patterns_add_points;
|
||||
if(!findTempPatternsAddingPoints(temp_patterns_add_points))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const int num_points_in_pattern = 3;
|
||||
for(size_t i = 0; i < temp_patterns_add_points.size(); i++)
|
||||
{
|
||||
int idx_side = temp_patterns_add_points[i].first;
|
||||
int size = (int)temp_patterns_add_points[i].second.size();
|
||||
|
||||
float step = static_cast<float>(size) / num_points_in_pattern;
|
||||
vector<Point> temp_points;
|
||||
for (int j = 0; j < num_points_in_pattern; j++)
|
||||
{
|
||||
float val = j * step;
|
||||
int idx = cvRound(val) >= size ? size - 1 : cvRound(val);
|
||||
temp_points.push_back(temp_patterns_add_points[i].second[idx]);
|
||||
}
|
||||
temp_points.push_back(temp_patterns_add_points[i].second.back());
|
||||
if(patterns_add_points.count(idx_side) == 1)
|
||||
{
|
||||
patterns_add_points[idx_side].insert(patterns_add_points[idx_side].end(),
|
||||
temp_points.begin(), temp_points.end());
|
||||
}
|
||||
patterns_add_points.insert(std::pair<int, vector<Point> >(idx_side, temp_points));
|
||||
|
||||
}
|
||||
if (patterns_add_points.size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::addPointsToSides()
|
||||
{
|
||||
if(!computePatternsAddingPoints(complete_curved_sides))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::map<int, vector<Point> >::iterator it;
|
||||
double mean_step = 0.0;
|
||||
size_t num_points_at_side = 0;
|
||||
for (it = complete_curved_sides.begin(); it != complete_curved_sides.end(); ++it)
|
||||
{
|
||||
int count = -1;
|
||||
const size_t num_points_at_pattern = it->second.size();
|
||||
for(size_t j = 0; j < num_points_at_pattern - 1; j++, count++)
|
||||
{
|
||||
if (count == 3) continue;
|
||||
double temp_norm = norm(it->second[j] -
|
||||
it->second[j + 1]);
|
||||
mean_step += temp_norm;
|
||||
}
|
||||
num_points_at_side += num_points_at_pattern;
|
||||
}
|
||||
if (num_points_at_side == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
mean_step /= num_points_at_side;
|
||||
|
||||
const size_t num_incomplete_sides = curved_incomplete_indexes.size();
|
||||
for (size_t i = 0; i < num_incomplete_sides; i++)
|
||||
{
|
||||
int idx = curved_incomplete_indexes[i];
|
||||
vector<int> sides_points_indexes;
|
||||
|
||||
const int num_points_at_side_to_add = (int)sides_points[idx].size();
|
||||
for (int j = 0; j < num_points_at_side_to_add; j++)
|
||||
{
|
||||
bool not_too_close = true;
|
||||
const size_t num_points_at_side_exist = complete_curved_sides[idx].size();
|
||||
for (size_t k = 0; k < num_points_at_side_exist; k++)
|
||||
{
|
||||
double temp_norm = norm(sides_points[idx][j] - complete_curved_sides[idx][k]);
|
||||
if (temp_norm < mean_step)
|
||||
{
|
||||
not_too_close = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (not_too_close)
|
||||
{
|
||||
sides_points_indexes.push_back(j);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < sides_points_indexes.size(); j++)
|
||||
{
|
||||
bool not_equal = true;
|
||||
for (size_t k = 0; k < complete_curved_sides[idx].size(); k++)
|
||||
{
|
||||
if (sides_points[idx][sides_points_indexes[j]] ==
|
||||
complete_curved_sides[idx][k])
|
||||
{
|
||||
not_equal = false;
|
||||
}
|
||||
}
|
||||
if (not_equal)
|
||||
{
|
||||
complete_curved_sides[idx].push_back(sides_points[idx][sides_points_indexes[j]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QRDecode::completeAndSortSides()
|
||||
{
|
||||
if (complete_curved_sides.size() < 2)
|
||||
{
|
||||
for (int i = 0; i < NUM_SIDES; i++)
|
||||
{
|
||||
if(complete_curved_sides.count(curved_indexes[i]) == 0)
|
||||
{
|
||||
int idx_second_cur_side = curved_indexes[i];
|
||||
complete_curved_sides.insert(std::pair<int,vector<Point> >(idx_second_cur_side, sides_points[idx_second_cur_side]));
|
||||
}
|
||||
}
|
||||
}
|
||||
std::map<int,vector<Point> >::iterator it;
|
||||
for (it = complete_curved_sides.begin(); it != complete_curved_sides.end(); ++it)
|
||||
{
|
||||
Point p1 = it->second.front();
|
||||
Point p2 = it->second.back();
|
||||
if (abs(p1.x - p2.x) > abs(p1.y - p2.y))
|
||||
{
|
||||
sort(it->second.begin(), it->second.end(), sortPointsByX());
|
||||
}
|
||||
else
|
||||
{
|
||||
sort(it->second.begin(), it->second.end(), sortPointsByY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<vector<float> > QRDecode::computeSpline(const vector<int> &x_arr, const vector<int> &y_arr)
|
||||
{
|
||||
const int n = (int)x_arr.size();
|
||||
vector<float> a, b(n - 1), d(n - 1), h(n - 1), alpha(n - 1), c(n), l(n), mu(n), z(n);
|
||||
|
||||
for (int i = 0; i < (int)y_arr.size(); i++)
|
||||
{
|
||||
a.push_back(static_cast<float>(x_arr[i]));
|
||||
}
|
||||
for (int i = 0; i < n - 1; i++)
|
||||
{
|
||||
h[i] = static_cast<float>(y_arr[i + 1] - y_arr[i]);
|
||||
}
|
||||
for (int i = 1; i < n - 1; i++)
|
||||
{
|
||||
alpha[i] = 3 / h[i] * (a[i + 1] - a[i]) - 3 / (h[i - 1]) * (a[i] - a[i - 1]);
|
||||
}
|
||||
l[0] = 1;
|
||||
mu[0] = 0;
|
||||
z[0] = 0;
|
||||
|
||||
for (int i = 1; i < n - 1; i++)
|
||||
{
|
||||
l[i] = 2 * (y_arr[i + 1] - y_arr[i - 1]) - h[i - 1] * mu[i - 1];
|
||||
mu[i] = h[i] / l[i];
|
||||
z[i] = (alpha[i] - h[i - 1] * z[i - 1]) / l[i];
|
||||
}
|
||||
l[n - 1] = 1;
|
||||
z[n - 1] = 0;
|
||||
c[n - 1] = 0;
|
||||
|
||||
for(int j = n - 2; j >= 0; j--)
|
||||
{
|
||||
c[j] = z[j] - mu[j] * c[j + 1];
|
||||
b[j] = (a[j + 1] - a[j]) / h[j] - (h[j] * (c[j + 1] + 2 * c[j])) / 3;
|
||||
d[j] = (c[j + 1] - c[j]) / (3 * h[j]);
|
||||
}
|
||||
|
||||
vector<vector<float> > S(n - 1);
|
||||
for (int i = 0; i < n - 1; i++)
|
||||
{
|
||||
S[i].push_back(a[i]);
|
||||
S[i].push_back(b[i]);
|
||||
S[i].push_back(c[i]);
|
||||
S[i].push_back(d[i]);
|
||||
}
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
bool QRDecode::createSpline(vector<vector<Point2f> > &spline_lines)
|
||||
{
|
||||
int start, end;
|
||||
vector<vector<float> > S;
|
||||
|
||||
for (int idx = 0; idx < NUM_SIDES; idx++)
|
||||
{
|
||||
int idx_curved_side = curved_indexes[idx];
|
||||
|
||||
vector<Point> spline_points = complete_curved_sides.find(idx_curved_side)->second;
|
||||
vector<int> x_arr, y_arr;
|
||||
|
||||
for (size_t j = 0; j < spline_points.size(); j++)
|
||||
{
|
||||
x_arr.push_back(cvRound(spline_points[j].x));
|
||||
y_arr.push_back(cvRound(spline_points[j].y));
|
||||
}
|
||||
|
||||
bool horizontal_order = abs(x_arr.front() - x_arr.back()) > abs(y_arr.front() - y_arr.back());
|
||||
vector<int>& second_arr = horizontal_order ? x_arr : y_arr;
|
||||
vector<int>& first_arr = horizontal_order ? y_arr : x_arr;
|
||||
|
||||
S = computeSpline(first_arr, second_arr);
|
||||
|
||||
int closest_point_first = horizontal_order ? closest_points[idx_curved_side].second.x
|
||||
: closest_points[idx_curved_side].second.y;
|
||||
int closest_point_second = horizontal_order ? closest_points[(idx_curved_side + 1) % 4].second.x
|
||||
: closest_points[(idx_curved_side + 1) % 4].second.y;
|
||||
|
||||
start = idx_curved_side;
|
||||
end = (idx_curved_side + 1) % 4;
|
||||
if(closest_point_first > closest_point_second)
|
||||
{
|
||||
start = (idx_curved_side + 1) % 4;
|
||||
end = idx_curved_side;
|
||||
}
|
||||
|
||||
int closest_point_start = horizontal_order ? closest_points[start].second.x : closest_points[start].second.y;
|
||||
int closest_point_end = horizontal_order ? closest_points[end].second.x : closest_points[end].second.y;
|
||||
|
||||
for (int index = closest_point_start; index <= closest_point_end; index++)
|
||||
{
|
||||
if (index == second_arr.front())
|
||||
{
|
||||
spline_lines[idx].push_back(closest_points[start].second);
|
||||
}
|
||||
for (size_t i = 0; i < second_arr.size() - 1; i++)
|
||||
{
|
||||
if ((index > second_arr[i]) && (index <= second_arr[i + 1]))
|
||||
{
|
||||
float val = S[i][0] + S[i][1] * (index - second_arr[i]) + S[i][2] * (index - second_arr[i]) * (index - second_arr[i])
|
||||
+ S[i][3] * (index - second_arr[i]) * (index - second_arr[i]) * (index - second_arr[i]);
|
||||
spline_lines[idx].push_back(horizontal_order ? Point2f(static_cast<float>(index), val) : Point2f(val, static_cast<float>(index)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::divideIntoEvenSegments(vector<vector<Point2f> > &segments_points)
|
||||
{
|
||||
vector<vector<Point2f> > spline_lines(NUM_SIDES);
|
||||
if (!createSpline(spline_lines))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float mean_num_points_in_line = 0.0;
|
||||
for (int i = 0; i < NUM_SIDES; i++)
|
||||
{
|
||||
mean_num_points_in_line += spline_lines[i].size();
|
||||
}
|
||||
mean_num_points_in_line /= NUM_SIDES;
|
||||
const int min_num_points = 1, max_num_points = cvRound(mean_num_points_in_line / 2.0);
|
||||
float linear_threshold = 0.5f;
|
||||
for (int num = min_num_points; num < max_num_points; num++)
|
||||
{
|
||||
for (int i = 0; i < NUM_SIDES; i++)
|
||||
{
|
||||
segments_points[i].clear();
|
||||
|
||||
int size = (int)spline_lines[i].size();
|
||||
float step = static_cast<float>(size) / num;
|
||||
for (int j = 0; j < num; j++)
|
||||
{
|
||||
float val = j * step;
|
||||
int idx = cvRound(val) >= size ? size - 1 : cvRound(val);
|
||||
segments_points[i].push_back(spline_lines[i][idx]);
|
||||
}
|
||||
segments_points[i].push_back(spline_lines[i].back());
|
||||
}
|
||||
float mean_of_two_sides = 0.0;
|
||||
for (int i = 0; i < NUM_SIDES; i++)
|
||||
{
|
||||
float mean_dist_in_segment = 0.0;
|
||||
for (size_t j = 0; j < segments_points[i].size() - 1; j++)
|
||||
{
|
||||
Point2f segment_start = segments_points[i][j];
|
||||
Point2f segment_end = segments_points[i][j + 1];
|
||||
vector<Point2f>::iterator it_start, it_end, it;
|
||||
it_start = find(spline_lines[i].begin(), spline_lines[i].end(), segment_start);
|
||||
it_end = find(spline_lines[i].begin(), spline_lines[i].end(), segment_end);
|
||||
float max_dist_to_line = 0.0;
|
||||
for (it = it_start; it != it_end; it++)
|
||||
{
|
||||
float temp_dist = distancePointToLine(*it, segment_start, segment_end);
|
||||
if (temp_dist > max_dist_to_line)
|
||||
{
|
||||
max_dist_to_line = temp_dist;
|
||||
}
|
||||
}
|
||||
mean_dist_in_segment += max_dist_to_line;
|
||||
}
|
||||
mean_dist_in_segment /= segments_points[i].size();
|
||||
mean_of_two_sides += mean_dist_in_segment;
|
||||
}
|
||||
mean_of_two_sides /= NUM_SIDES;
|
||||
if (mean_of_two_sides < linear_threshold)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::straightenQRCodeInParts()
|
||||
{
|
||||
vector<vector<Point2f> > segments_points(NUM_SIDES);
|
||||
if (!divideIntoEvenSegments(segments_points))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vector<Point2f> current_curved_side, opposite_curved_side;
|
||||
|
||||
for (int i = 0; i < NUM_SIDES; i++)
|
||||
{
|
||||
Point2f temp_point_start = segments_points[i].front();
|
||||
Point2f temp_point_end = segments_points[i].back();
|
||||
bool horizontal_order = (abs(temp_point_start.x - temp_point_end.x) >
|
||||
abs(temp_point_start.y - temp_point_end.y));
|
||||
float compare_point_current = horizontal_order ? segments_points[i].front().y
|
||||
: segments_points[(i + 1) % 2].front().x;
|
||||
float compare_point_opposite = horizontal_order ? segments_points[(i + 1) % 2].front().y
|
||||
: segments_points[i].front().x;
|
||||
|
||||
if (compare_point_current > compare_point_opposite)
|
||||
{
|
||||
current_curved_side = segments_points[i];
|
||||
opposite_curved_side = segments_points[(i + 1) % 2];
|
||||
}
|
||||
}
|
||||
if (current_curved_side.size() != opposite_curved_side.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
size_t number_pnts_to_cut = current_curved_side.size();
|
||||
if (number_pnts_to_cut == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float perspective_curved_size = 251.0;
|
||||
const Size temporary_size(cvRound(perspective_curved_size), cvRound(perspective_curved_size));
|
||||
|
||||
float dist = perspective_curved_size / (number_pnts_to_cut - 1);
|
||||
Mat perspective_result = Mat::zeros(temporary_size, CV_8UC1);
|
||||
vector<Point2f> curved_parts_points;
|
||||
|
||||
float start_cut = 0.0;
|
||||
vector<Point2f> temp_closest_points(4);
|
||||
|
||||
for (size_t i = 1; i < number_pnts_to_cut; i++)
|
||||
{
|
||||
curved_parts_points.clear();
|
||||
Mat test_mask = Mat::zeros(bin_barcode.size(), CV_8UC1);
|
||||
|
||||
Point2f start_point = current_curved_side[i];
|
||||
Point2f prev_start_point = current_curved_side[i - 1];
|
||||
Point2f finish_point = opposite_curved_side[i];
|
||||
Point2f prev_finish_point = opposite_curved_side[i - 1];
|
||||
|
||||
for (size_t j = 0; j < qrcode_locations.size(); j++)
|
||||
{
|
||||
if ((pointPosition(start_point, finish_point, qrcode_locations[j]) >= 0) &&
|
||||
(pointPosition(prev_start_point, prev_finish_point, qrcode_locations[j]) <= 0))
|
||||
{
|
||||
test_mask.at<uint8_t>(qrcode_locations[j]) = 255;
|
||||
}
|
||||
}
|
||||
|
||||
vector<Point2f> perspective_points;
|
||||
|
||||
perspective_points.push_back(Point2f(0.0, start_cut));
|
||||
perspective_points.push_back(Point2f(perspective_curved_size, start_cut));
|
||||
|
||||
perspective_points.push_back(Point2f(perspective_curved_size, start_cut + dist));
|
||||
perspective_points.push_back(Point2f(0.0, start_cut+dist));
|
||||
|
||||
perspective_points.push_back(Point2f(perspective_curved_size * 0.5f, start_cut + dist * 0.5f));
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
for (size_t j = 0; j < closest_points.size(); j++)
|
||||
{
|
||||
if (arePointsNearest(closest_points[j].second, prev_start_point, 3.0))
|
||||
{
|
||||
temp_closest_points[j] = perspective_points[0];
|
||||
}
|
||||
else if (arePointsNearest(closest_points[j].second, prev_finish_point, 3.0))
|
||||
{
|
||||
temp_closest_points[j] = perspective_points[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == number_pnts_to_cut - 1)
|
||||
{
|
||||
for (size_t j = 0; j < closest_points.size(); j++)
|
||||
{
|
||||
if (arePointsNearest(closest_points[j].second, finish_point, 3.0))
|
||||
{
|
||||
temp_closest_points[j] = perspective_points[2];
|
||||
}
|
||||
else if (arePointsNearest(closest_points[j].second, start_point, 3.0))
|
||||
{
|
||||
temp_closest_points[j] = perspective_points[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
start_cut += dist;
|
||||
|
||||
curved_parts_points.push_back(prev_start_point);
|
||||
curved_parts_points.push_back(prev_finish_point);
|
||||
curved_parts_points.push_back(finish_point);
|
||||
curved_parts_points.push_back(start_point);
|
||||
|
||||
Point2f center_point = intersectionLines(curved_parts_points[0], curved_parts_points[2],
|
||||
curved_parts_points[1], curved_parts_points[3]);
|
||||
if (cvIsNaN(center_point.x) || cvIsNaN(center_point.y))
|
||||
return false;
|
||||
|
||||
vector<Point2f> pts = curved_parts_points;
|
||||
pts.push_back(center_point);
|
||||
|
||||
Mat H = findHomography(pts, perspective_points);
|
||||
Mat temp_intermediate(temporary_size, CV_8UC1);
|
||||
warpPerspective(test_mask, temp_intermediate, H, temporary_size, INTER_NEAREST);
|
||||
perspective_result += temp_intermediate;
|
||||
|
||||
}
|
||||
Mat white_mask = Mat(temporary_size, CV_8UC1, Scalar(255));
|
||||
Mat inversion = white_mask - perspective_result;
|
||||
Mat temp_result;
|
||||
|
||||
original_curved_points = temp_closest_points;
|
||||
|
||||
Point2f original_center_point = intersectionLines(original_curved_points[0], original_curved_points[2],
|
||||
original_curved_points[1], original_curved_points[3]);
|
||||
|
||||
original_curved_points.push_back(original_center_point);
|
||||
|
||||
for (size_t i = 0; i < original_curved_points.size(); i++)
|
||||
{
|
||||
if (cvIsNaN(original_curved_points[i].x) || cvIsNaN(original_curved_points[i].y))
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<Point2f> perspective_straight_points;
|
||||
perspective_straight_points.push_back(Point2f(0.f, 0.f));
|
||||
perspective_straight_points.push_back(Point2f(perspective_curved_size, 0.f));
|
||||
|
||||
perspective_straight_points.push_back(Point2f(perspective_curved_size, perspective_curved_size));
|
||||
perspective_straight_points.push_back(Point2f(0.f, perspective_curved_size));
|
||||
|
||||
perspective_straight_points.push_back(Point2f(perspective_curved_size * 0.5f, perspective_curved_size * 0.5f));
|
||||
|
||||
Mat H = findHomography(original_curved_points, perspective_straight_points);
|
||||
warpPerspective(inversion, temp_result, H, temporary_size, INTER_NEAREST, BORDER_REPLICATE);
|
||||
|
||||
no_border_intermediate = temp_result(Range(1, temp_result.rows), Range(1, temp_result.cols));
|
||||
const int border = cvRound(0.1 * perspective_curved_size);
|
||||
const int borderType = BORDER_CONSTANT;
|
||||
copyMakeBorder(no_border_intermediate, curved_to_straight, border, border, border, border, borderType, Scalar(255));
|
||||
intermediate = curved_to_straight;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::preparingCurvedQRCodes()
|
||||
{
|
||||
vector<Point> result_integer_hull;
|
||||
getPointsInsideQRCode(original_points);
|
||||
if (qrcode_locations.size() == 0)
|
||||
return false;
|
||||
convexHull(qrcode_locations, result_integer_hull);
|
||||
if (!computeClosestPoints(result_integer_hull))
|
||||
return false;
|
||||
if (!computeSidesPoints(result_integer_hull))
|
||||
return false;
|
||||
if (!findAndAddStablePoint(result_integer_hull))
|
||||
return false;
|
||||
if (!findIndexesCurvedSides())
|
||||
return false;
|
||||
if (findIncompleteIndexesCurvedSides())
|
||||
{
|
||||
if(!addPointsToSides())
|
||||
return false;
|
||||
}
|
||||
completeAndSortSides();
|
||||
if (!straightenQRCodeInParts())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::updatePerspective()
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
const Point2f centerPt = QRDetect::intersectionLines(original_points[0], original_points[2],
|
||||
original_points[1], original_points[3]);
|
||||
const Point2f centerPt = intersectionLines(original_points[0], original_points[2],
|
||||
original_points[1], original_points[3]);
|
||||
if (cvIsNaN(centerPt.x) || cvIsNaN(centerPt.y))
|
||||
return false;
|
||||
|
||||
@@ -1112,7 +2338,7 @@ bool QRDecode::samplingForVersion()
|
||||
CV_TRACE_FUNCTION();
|
||||
const double multiplyingFactor = (version < 3) ? 1 :
|
||||
(version == 3) ? 1.5 :
|
||||
version * (5 + version - 4);
|
||||
version * (version + 1);
|
||||
const Size newFactorSize(
|
||||
cvRound(no_border_intermediate.size().width * multiplyingFactor),
|
||||
cvRound(no_border_intermediate.size().height * multiplyingFactor));
|
||||
@@ -1197,7 +2423,7 @@ bool QRDecode::decodingProcess()
|
||||
|
||||
}
|
||||
|
||||
bool QRDecode::fullDecodingProcess()
|
||||
bool QRDecode::straightDecodingProcess()
|
||||
{
|
||||
#ifdef HAVE_QUIRC
|
||||
if (!updatePerspective()) { return false; }
|
||||
@@ -1211,6 +2437,20 @@ bool QRDecode::fullDecodingProcess()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QRDecode::curvedDecodingProcess()
|
||||
{
|
||||
#ifdef HAVE_QUIRC
|
||||
if (!preparingCurvedQRCodes()) { return false; }
|
||||
if (!versionDefinition()) { return false; }
|
||||
if (!samplingForVersion()) { return false; }
|
||||
if (!decodingProcess()) { return false; }
|
||||
return true;
|
||||
#else
|
||||
std::cout << "Library QUIRC is not linked. No decoding is performed. Take it to the OpenCV repository." << std::endl;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string QRCodeDetector::decode(InputArray in, InputArray points,
|
||||
OutputArray straight_qrcode)
|
||||
{
|
||||
@@ -1225,7 +2465,35 @@ std::string QRCodeDetector::decode(InputArray in, InputArray points,
|
||||
|
||||
QRDecode qrdec;
|
||||
qrdec.init(inarr, src_points);
|
||||
bool ok = qrdec.fullDecodingProcess();
|
||||
bool ok = qrdec.straightDecodingProcess();
|
||||
|
||||
std::string decoded_info = qrdec.getDecodeInformation();
|
||||
|
||||
if (ok && straight_qrcode.needed())
|
||||
{
|
||||
qrdec.getStraightBarcode().convertTo(straight_qrcode,
|
||||
straight_qrcode.fixedType() ?
|
||||
straight_qrcode.type() : CV_32FC2);
|
||||
}
|
||||
|
||||
return ok ? decoded_info : std::string();
|
||||
}
|
||||
|
||||
cv::String QRCodeDetector::decodeCurved(InputArray in, InputArray points,
|
||||
OutputArray straight_qrcode)
|
||||
{
|
||||
Mat inarr;
|
||||
if (!checkQRInputImage(in, inarr))
|
||||
return std::string();
|
||||
|
||||
vector<Point2f> src_points;
|
||||
points.copyTo(src_points);
|
||||
CV_Assert(src_points.size() == 4);
|
||||
CV_CheckGT(contourArea(src_points), 0.0, "Invalid QR code source points");
|
||||
|
||||
QRDecode qrdec;
|
||||
qrdec.init(inarr, src_points);
|
||||
bool ok = qrdec.curvedDecodingProcess();
|
||||
|
||||
std::string decoded_info = qrdec.getDecodeInformation();
|
||||
|
||||
@@ -1262,6 +2530,28 @@ std::string QRCodeDetector::detectAndDecode(InputArray in,
|
||||
return decoded_info;
|
||||
}
|
||||
|
||||
std::string QRCodeDetector::detectAndDecodeCurved(InputArray in,
|
||||
OutputArray points_,
|
||||
OutputArray straight_qrcode)
|
||||
{
|
||||
Mat inarr;
|
||||
if (!checkQRInputImage(in, inarr))
|
||||
{
|
||||
points_.release();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
vector<Point2f> points;
|
||||
bool ok = detect(inarr, points);
|
||||
if (!ok)
|
||||
{
|
||||
points_.release();
|
||||
return std::string();
|
||||
}
|
||||
updatePointsResult(points_, points);
|
||||
std::string decoded_info = decodeCurved(inarr, points, straight_qrcode);
|
||||
return decoded_info;
|
||||
}
|
||||
|
||||
class QRDetectMulti : public QRDetect
|
||||
{
|
||||
@@ -1495,7 +2785,6 @@ void QRDetectMulti::fixationPoints(vector<Point2f> &local_point)
|
||||
Point2f(static_cast<float>(bin_barcode_temp.cols - 1),
|
||||
static_cast<float>(bin_barcode_temp.rows - 1))));
|
||||
|
||||
|
||||
vector<Point2f> list_area_pnt;
|
||||
list_area_pnt.push_back(current_point);
|
||||
|
||||
@@ -2226,7 +3515,7 @@ public:
|
||||
for (int i = range.start; i < range.end; i++)
|
||||
{
|
||||
qrdec[i].init(inarr, src_points[i]);
|
||||
bool ok = qrdec[i].fullDecodingProcess();
|
||||
bool ok = qrdec[i].straightDecodingProcess();
|
||||
if (ok)
|
||||
{
|
||||
decoded_info[i] = qrdec[i].getDecodeInformation();
|
||||
@@ -2246,7 +3535,7 @@ public:
|
||||
src_points[i][j] /= static_cast<float>(coeff_expansion);
|
||||
}
|
||||
qrdec[i].init(inarr2, src_points[i]);
|
||||
ok = qrdec[i].fullDecodingProcess();
|
||||
ok = qrdec[i].straightDecodingProcess();
|
||||
if (ok)
|
||||
{
|
||||
decoded_info[i] = qrdec[i].getDecodeInformation();
|
||||
|
||||
@@ -21,6 +21,9 @@ std::string qrcode_images_close[] = {
|
||||
std::string qrcode_images_monitor[] = {
|
||||
"monitor_1.png", "monitor_2.png", "monitor_3.png", "monitor_4.png", "monitor_5.png"
|
||||
};
|
||||
std::string qrcode_images_curved[] = {
|
||||
"curved_1.jpg", "curved_2.jpg", "curved_3.jpg", "curved_4.jpg", "curved_5.jpg", "curved_6.jpg", "curved_7.jpg", "curved_8.jpg"
|
||||
};
|
||||
std::string qrcode_images_multiple[] = {
|
||||
"2_qrcodes.png", "3_close_qrcodes.png", "3_qrcodes.png", "4_qrcodes.png",
|
||||
"5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png"
|
||||
@@ -137,7 +140,38 @@ TEST(Objdetect_QRCode_Monitor, generate_test_data)
|
||||
file_config << "]";
|
||||
file_config.release();
|
||||
}
|
||||
TEST(Objdetect_QRCode_Curved, generate_test_data)
|
||||
{
|
||||
const std::string root = "qrcode/curved/";
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::WRITE);
|
||||
|
||||
file_config << "test_images" << "[";
|
||||
size_t images_count = sizeof(qrcode_images_curved) / sizeof(qrcode_images_curved[0]);
|
||||
for (size_t i = 0; i < images_count; i++)
|
||||
{
|
||||
file_config << "{:" << "image_name" << qrcode_images_curved[i];
|
||||
std::string image_path = findDataFile(root + qrcode_images_curved[i]);
|
||||
std::vector<Point> corners;
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
std::string decoded_info;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
EXPECT_TRUE(detectQRCode(src, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
EXPECT_TRUE(decodeCurvedQRCode(src, corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
file_config << "x" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].x; }
|
||||
file_config << "]";
|
||||
file_config << "y" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].y; }
|
||||
file_config << "]";
|
||||
file_config << "info" << decoded_info;
|
||||
file_config << "}";
|
||||
}
|
||||
file_config << "]";
|
||||
file_config.release();
|
||||
}
|
||||
TEST(Objdetect_QRCode_Multi, generate_test_data)
|
||||
{
|
||||
const std::string root = "qrcode/multiple/";
|
||||
@@ -390,6 +424,66 @@ TEST_P(Objdetect_QRCode_Monitor, regression)
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam< std::string > Objdetect_QRCode_Curved;
|
||||
TEST_P(Objdetect_QRCode_Curved, regression)
|
||||
{
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "qrcode/curved/";
|
||||
const int pixels_error = 3;
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
std::vector<Point> corners;
|
||||
std::string decoded_info;
|
||||
QRCodeDetector qrcode;
|
||||
#ifdef HAVE_QUIRC
|
||||
decoded_info = qrcode.detectAndDecodeCurved(src, corners, straight_barcode);
|
||||
ASSERT_FALSE(corners.empty());
|
||||
ASSERT_FALSE(decoded_info.empty());
|
||||
#else
|
||||
ASSERT_TRUE(qrcode.detect(src, corners));
|
||||
#endif
|
||||
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
{
|
||||
FileNode images_list = file_config["test_images"];
|
||||
size_t images_count = static_cast<size_t>(images_list.size());
|
||||
ASSERT_GT(images_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
|
||||
for (size_t index = 0; index < images_count; index++)
|
||||
{
|
||||
FileNode config = images_list[(int)index];
|
||||
std::string name_test_image = config["image_name"];
|
||||
if (name_test_image == name_current_image)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int x = config["x"][i];
|
||||
int y = config["y"][i];
|
||||
EXPECT_NEAR(x, corners[i].x, pixels_error);
|
||||
EXPECT_NEAR(y, corners[i].y, pixels_error);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
std::string original_info = config["info"];
|
||||
EXPECT_EQ(decoded_info, original_info);
|
||||
#endif
|
||||
|
||||
return; // done
|
||||
}
|
||||
}
|
||||
std::cerr
|
||||
<< "Not found results for '" << name_current_image
|
||||
<< "' image in config file:" << dataset_config << std::endl
|
||||
<< "Re-run tests with enabled UPDATE_QRCODE_TEST_DATA macro to update test data."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam < std::string > Objdetect_QRCode_Multi;
|
||||
TEST_P(Objdetect_QRCode_Multi, regression)
|
||||
{
|
||||
@@ -478,6 +572,7 @@ TEST_P(Objdetect_QRCode_Multi, regression)
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode, testing::ValuesIn(qrcode_images_name));
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Close, testing::ValuesIn(qrcode_images_close));
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Monitor, testing::ValuesIn(qrcode_images_monitor));
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Curved, testing::ValuesIn(qrcode_images_curved));
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Multi, testing::ValuesIn(qrcode_images_multiple));
|
||||
|
||||
TEST(Objdetect_QRCode_decodeMulti, decode_regression_16491)
|
||||
|
||||
@@ -218,7 +218,7 @@ MultiBandBlender::MultiBandBlender(int try_gpu, int num_bands, int weight_type)
|
||||
num_bands_ = 0;
|
||||
setNumBands(num_bands);
|
||||
|
||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
#if defined(HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
can_use_gpu_ = try_gpu && cuda::getCudaEnabledDeviceCount();
|
||||
gpu_feed_idx_ = 0;
|
||||
#else
|
||||
@@ -244,7 +244,7 @@ void MultiBandBlender::prepare(Rect dst_roi)
|
||||
|
||||
Blender::prepare(dst_roi);
|
||||
|
||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
#if defined(HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
if (can_use_gpu_)
|
||||
{
|
||||
gpu_initialized_ = false;
|
||||
@@ -330,7 +330,7 @@ void MultiBandBlender::feed(InputArray _img, InputArray mask, Point tl)
|
||||
|
||||
UMat img;
|
||||
|
||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
#if defined(HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
// If using gpu save the top left coordinate when running first time after prepare
|
||||
if (can_use_gpu_)
|
||||
{
|
||||
@@ -351,7 +351,7 @@ void MultiBandBlender::feed(InputArray _img, InputArray mask, Point tl)
|
||||
{
|
||||
img = _img.getUMat();
|
||||
}
|
||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
#if defined(HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
else
|
||||
{
|
||||
gpu_img_ = _img.getGpuMat();
|
||||
@@ -392,7 +392,7 @@ void MultiBandBlender::feed(InputArray _img, InputArray mask, Point tl)
|
||||
int bottom = br_new.y - tl.y - img.rows;
|
||||
int right = br_new.x - tl.x - img.cols;
|
||||
|
||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
#if defined(HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
if (can_use_gpu_)
|
||||
{
|
||||
if (!gpu_initialized_)
|
||||
@@ -601,7 +601,7 @@ void MultiBandBlender::feed(InputArray _img, InputArray mask, Point tl)
|
||||
void MultiBandBlender::blend(InputOutputArray dst, InputOutputArray dst_mask)
|
||||
{
|
||||
Rect dst_rc(0, 0, dst_roi_final_.width, dst_roi_final_.height);
|
||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
#if defined(HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
if (can_use_gpu_)
|
||||
{
|
||||
if (!gpu_initialized_)
|
||||
@@ -836,7 +836,7 @@ void createLaplacePyr(InputArray img, int num_levels, std::vector<UMat> &pyr)
|
||||
|
||||
void createLaplacePyrGpu(InputArray img, int num_levels, std::vector<UMat> &pyr)
|
||||
{
|
||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
#if defined(HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
pyr.resize(num_levels + 1);
|
||||
|
||||
std::vector<cuda::GpuMat> gpu_pyr(num_levels + 1);
|
||||
@@ -877,7 +877,7 @@ void restoreImageFromLaplacePyr(std::vector<UMat> &pyr)
|
||||
|
||||
void restoreImageFromLaplacePyrGpu(std::vector<UMat> &pyr)
|
||||
{
|
||||
#if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
#if defined(HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
|
||||
if (pyr.empty())
|
||||
return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user