mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
889 lines
24 KiB
889 lines
24 KiB
// This file is part of OpenCV project. |
|
// It is subject to the license terms in the LICENSE file found in the top-level directory |
|
// of this distribution and at http://opencv.org/license.html |
|
|
|
#include "precomp.hpp" |
|
#include "opencv2/core/mat.hpp" |
|
#include "opencv2/core/types_c.h" |
|
|
|
namespace cv { |
|
|
|
template<typename T1, typename T2> void |
|
convertData_(const void* _from, void* _to, int cn) |
|
{ |
|
const T1* from = (const T1*)_from; |
|
T2* to = (T2*)_to; |
|
if( cn == 1 ) |
|
*to = saturate_cast<T2>(*from); |
|
else |
|
for( int i = 0; i < cn; i++ ) |
|
to[i] = saturate_cast<T2>(from[i]); |
|
} |
|
|
|
template<typename T1, typename T2> void |
|
convertScaleData_(const void* _from, void* _to, int cn, double alpha, double beta) |
|
{ |
|
const T1* from = (const T1*)_from; |
|
T2* to = (T2*)_to; |
|
if( cn == 1 ) |
|
*to = saturate_cast<T2>(*from*alpha + beta); |
|
else |
|
for( int i = 0; i < cn; i++ ) |
|
to[i] = saturate_cast<T2>(from[i]*alpha + beta); |
|
} |
|
|
|
typedef void (*ConvertData)(const void* from, void* to, int cn); |
|
typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta); |
|
|
|
static ConvertData getConvertElem(int fromType, int toType) |
|
{ |
|
static ConvertData tab[][8] = |
|
{{ convertData_<uchar, uchar>, convertData_<uchar, schar>, |
|
convertData_<uchar, ushort>, convertData_<uchar, short>, |
|
convertData_<uchar, int>, convertData_<uchar, float>, |
|
convertData_<uchar, double>, 0 }, |
|
|
|
{ convertData_<schar, uchar>, convertData_<schar, schar>, |
|
convertData_<schar, ushort>, convertData_<schar, short>, |
|
convertData_<schar, int>, convertData_<schar, float>, |
|
convertData_<schar, double>, 0 }, |
|
|
|
{ convertData_<ushort, uchar>, convertData_<ushort, schar>, |
|
convertData_<ushort, ushort>, convertData_<ushort, short>, |
|
convertData_<ushort, int>, convertData_<ushort, float>, |
|
convertData_<ushort, double>, 0 }, |
|
|
|
{ convertData_<short, uchar>, convertData_<short, schar>, |
|
convertData_<short, ushort>, convertData_<short, short>, |
|
convertData_<short, int>, convertData_<short, float>, |
|
convertData_<short, double>, 0 }, |
|
|
|
{ convertData_<int, uchar>, convertData_<int, schar>, |
|
convertData_<int, ushort>, convertData_<int, short>, |
|
convertData_<int, int>, convertData_<int, float>, |
|
convertData_<int, double>, 0 }, |
|
|
|
{ convertData_<float, uchar>, convertData_<float, schar>, |
|
convertData_<float, ushort>, convertData_<float, short>, |
|
convertData_<float, int>, convertData_<float, float>, |
|
convertData_<float, double>, 0 }, |
|
|
|
{ convertData_<double, uchar>, convertData_<double, schar>, |
|
convertData_<double, ushort>, convertData_<double, short>, |
|
convertData_<double, int>, convertData_<double, float>, |
|
convertData_<double, double>, 0 }, |
|
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }}; |
|
|
|
ConvertData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)]; |
|
CV_Assert( func != 0 ); |
|
return func; |
|
} |
|
|
|
static ConvertScaleData getConvertScaleElem(int fromType, int toType) |
|
{ |
|
static ConvertScaleData tab[][8] = |
|
{{ convertScaleData_<uchar, uchar>, convertScaleData_<uchar, schar>, |
|
convertScaleData_<uchar, ushort>, convertScaleData_<uchar, short>, |
|
convertScaleData_<uchar, int>, convertScaleData_<uchar, float>, |
|
convertScaleData_<uchar, double>, 0 }, |
|
|
|
{ convertScaleData_<schar, uchar>, convertScaleData_<schar, schar>, |
|
convertScaleData_<schar, ushort>, convertScaleData_<schar, short>, |
|
convertScaleData_<schar, int>, convertScaleData_<schar, float>, |
|
convertScaleData_<schar, double>, 0 }, |
|
|
|
{ convertScaleData_<ushort, uchar>, convertScaleData_<ushort, schar>, |
|
convertScaleData_<ushort, ushort>, convertScaleData_<ushort, short>, |
|
convertScaleData_<ushort, int>, convertScaleData_<ushort, float>, |
|
convertScaleData_<ushort, double>, 0 }, |
|
|
|
{ convertScaleData_<short, uchar>, convertScaleData_<short, schar>, |
|
convertScaleData_<short, ushort>, convertScaleData_<short, short>, |
|
convertScaleData_<short, int>, convertScaleData_<short, float>, |
|
convertScaleData_<short, double>, 0 }, |
|
|
|
{ convertScaleData_<int, uchar>, convertScaleData_<int, schar>, |
|
convertScaleData_<int, ushort>, convertScaleData_<int, short>, |
|
convertScaleData_<int, int>, convertScaleData_<int, float>, |
|
convertScaleData_<int, double>, 0 }, |
|
|
|
{ convertScaleData_<float, uchar>, convertScaleData_<float, schar>, |
|
convertScaleData_<float, ushort>, convertScaleData_<float, short>, |
|
convertScaleData_<float, int>, convertScaleData_<float, float>, |
|
convertScaleData_<float, double>, 0 }, |
|
|
|
{ convertScaleData_<double, uchar>, convertScaleData_<double, schar>, |
|
convertScaleData_<double, ushort>, convertScaleData_<double, short>, |
|
convertScaleData_<double, int>, convertScaleData_<double, float>, |
|
convertScaleData_<double, double>, 0 }, |
|
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }}; |
|
|
|
ConvertScaleData func = tab[CV_MAT_DEPTH(fromType)][CV_MAT_DEPTH(toType)]; |
|
CV_Assert( func != 0 ); |
|
return func; |
|
} |
|
|
|
enum { HASH_SIZE0 = 8 }; |
|
|
|
static inline void copyElem(const uchar* from, uchar* to, size_t elemSize) |
|
{ |
|
size_t i; |
|
for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) ) |
|
*(int*)(to + i) = *(const int*)(from + i); |
|
for( ; i < elemSize; i++ ) |
|
to[i] = from[i]; |
|
} |
|
|
|
static inline bool isZeroElem(const uchar* data, size_t elemSize) |
|
{ |
|
size_t i; |
|
for( i = 0; i + sizeof(int) <= elemSize; i += sizeof(int) ) |
|
if( *(int*)(data + i) != 0 ) |
|
return false; |
|
for( ; i < elemSize; i++ ) |
|
if( data[i] != 0 ) |
|
return false; |
|
return true; |
|
} |
|
|
|
SparseMat::Hdr::Hdr( int _dims, const int* _sizes, int _type ) |
|
{ |
|
refcount = 1; |
|
|
|
dims = _dims; |
|
valueOffset = (int)alignSize(sizeof(SparseMat::Node) - MAX_DIM*sizeof(int) + |
|
dims*sizeof(int), CV_ELEM_SIZE1(_type)); |
|
nodeSize = alignSize(valueOffset + |
|
CV_ELEM_SIZE(_type), (int)sizeof(size_t)); |
|
|
|
int i; |
|
for( i = 0; i < dims; i++ ) |
|
size[i] = _sizes[i]; |
|
for( ; i < CV_MAX_DIM; i++ ) |
|
size[i] = 0; |
|
clear(); |
|
} |
|
|
|
void SparseMat::Hdr::clear() |
|
{ |
|
hashtab.clear(); |
|
hashtab.resize(HASH_SIZE0); |
|
pool.clear(); |
|
pool.resize(nodeSize); |
|
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) |
|
{ |
|
create( m.dims, m.size, m.type() ); |
|
|
|
int i, idx[CV_MAX_DIM] = {0}, d = m.dims, lastSize = m.size[d - 1]; |
|
size_t esz = m.elemSize(); |
|
const uchar* dptr = m.ptr(); |
|
|
|
for(;;) |
|
{ |
|
for( i = 0; i < lastSize; i++, dptr += esz ) |
|
{ |
|
if( isZeroElem(dptr, esz) ) |
|
continue; |
|
idx[d-1] = i; |
|
uchar* to = newNode(idx, hash(idx)); |
|
copyElem( dptr, to, esz ); |
|
} |
|
|
|
for( i = d - 2; i >= 0; i-- ) |
|
{ |
|
dptr += m.step[i] - m.size[i+1]*m.step[i+1]; |
|
if( ++idx[i] < m.size[i] ) |
|
break; |
|
idx[i] = 0; |
|
} |
|
if( i < 0 ) |
|
break; |
|
} |
|
} |
|
|
|
void SparseMat::create(int d, const int* _sizes, int _type) |
|
{ |
|
CV_Assert( _sizes && 0 < d && d <= CV_MAX_DIM ); |
|
for( int i = 0; i < d; i++ ) |
|
CV_Assert( _sizes[i] > 0 ); |
|
_type = CV_MAT_TYPE(_type); |
|
if( hdr && _type == type() && hdr->dims == d && hdr->refcount == 1 ) |
|
{ |
|
int i; |
|
for( i = 0; i < d; i++ ) |
|
if( _sizes[i] != hdr->size[i] ) |
|
break; |
|
if( i == d ) |
|
{ |
|
clear(); |
|
return; |
|
} |
|
} |
|
int _sizes_backup[CV_MAX_DIM]; // #5991 |
|
if (hdr && _sizes == hdr->size) |
|
{ |
|
for(int i = 0; i < d; i++ ) |
|
_sizes_backup[i] = _sizes[i]; |
|
_sizes = _sizes_backup; |
|
} |
|
release(); |
|
flags = MAGIC_VAL | _type; |
|
hdr = new Hdr(d, _sizes, _type); |
|
} |
|
|
|
void SparseMat::copyTo( SparseMat& m ) const |
|
{ |
|
if( hdr == m.hdr ) |
|
return; |
|
if( !hdr ) |
|
{ |
|
m.release(); |
|
return; |
|
} |
|
m.create( hdr->dims, hdr->size, type() ); |
|
SparseMatConstIterator from = begin(); |
|
size_t N = nzcount(), esz = elemSize(); |
|
|
|
for( size_t i = 0; i < N; i++, ++from ) |
|
{ |
|
const Node* n = from.node(); |
|
uchar* to = m.newNode(n->idx, n->hashval); |
|
copyElem( from.ptr, to, esz ); |
|
} |
|
} |
|
|
|
void SparseMat::copyTo( Mat& m ) const |
|
{ |
|
CV_Assert( hdr ); |
|
int ndims = dims(); |
|
m.create( ndims, hdr->size, type() ); |
|
m = Scalar(0); |
|
|
|
SparseMatConstIterator from = begin(); |
|
size_t N = nzcount(), esz = elemSize(); |
|
|
|
for( size_t i = 0; i < N; i++, ++from ) |
|
{ |
|
const Node* n = from.node(); |
|
copyElem( from.ptr, (ndims > 1 ? m.ptr(n->idx) : m.ptr(n->idx[0])), esz); |
|
} |
|
} |
|
|
|
|
|
void SparseMat::convertTo( SparseMat& m, int rtype, double alpha ) const |
|
{ |
|
int cn = channels(); |
|
if( rtype < 0 ) |
|
rtype = type(); |
|
rtype = CV_MAKETYPE(rtype, cn); |
|
if( hdr == m.hdr && rtype != type() ) |
|
{ |
|
SparseMat temp; |
|
convertTo(temp, rtype, alpha); |
|
m = temp; |
|
return; |
|
} |
|
|
|
CV_Assert(hdr != 0); |
|
if( hdr != m.hdr ) |
|
m.create( hdr->dims, hdr->size, rtype ); |
|
|
|
SparseMatConstIterator from = begin(); |
|
size_t N = nzcount(); |
|
|
|
if( alpha == 1 ) |
|
{ |
|
ConvertData cvtfunc = getConvertElem(type(), rtype); |
|
for( size_t i = 0; i < N; i++, ++from ) |
|
{ |
|
const Node* n = from.node(); |
|
uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval); |
|
cvtfunc( from.ptr, to, cn ); |
|
} |
|
} |
|
else |
|
{ |
|
ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype); |
|
for( size_t i = 0; i < N; i++, ++from ) |
|
{ |
|
const Node* n = from.node(); |
|
uchar* to = hdr == m.hdr ? from.ptr : m.newNode(n->idx, n->hashval); |
|
cvtfunc( from.ptr, to, cn, alpha, 0 ); |
|
} |
|
} |
|
} |
|
|
|
|
|
void SparseMat::convertTo( Mat& m, int rtype, double alpha, double beta ) const |
|
{ |
|
int cn = channels(); |
|
if( rtype < 0 ) |
|
rtype = type(); |
|
rtype = CV_MAKETYPE(rtype, cn); |
|
|
|
CV_Assert( hdr ); |
|
m.create( dims(), hdr->size, rtype ); |
|
m = Scalar(beta); |
|
|
|
SparseMatConstIterator from = begin(); |
|
size_t N = nzcount(); |
|
|
|
if( alpha == 1 && beta == 0 ) |
|
{ |
|
ConvertData cvtfunc = getConvertElem(type(), rtype); |
|
for( size_t i = 0; i < N; i++, ++from ) |
|
{ |
|
const Node* n = from.node(); |
|
uchar* to = m.ptr(n->idx); |
|
cvtfunc( from.ptr, to, cn ); |
|
} |
|
} |
|
else |
|
{ |
|
ConvertScaleData cvtfunc = getConvertScaleElem(type(), rtype); |
|
for( size_t i = 0; i < N; i++, ++from ) |
|
{ |
|
const Node* n = from.node(); |
|
uchar* to = m.ptr(n->idx); |
|
cvtfunc( from.ptr, to, cn, alpha, beta ); |
|
} |
|
} |
|
} |
|
|
|
void SparseMat::clear() |
|
{ |
|
if( hdr ) |
|
hdr->clear(); |
|
} |
|
|
|
uchar* SparseMat::ptr(int i0, bool createMissing, size_t* hashval) |
|
{ |
|
CV_Assert( hdr && hdr->dims == 1 ); |
|
size_t h = hashval ? *hashval : hash(i0); |
|
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; |
|
uchar* pool = &hdr->pool[0]; |
|
while( nidx != 0 ) |
|
{ |
|
Node* elem = (Node*)(pool + nidx); |
|
if( elem->hashval == h && elem->idx[0] == i0 ) |
|
return &value<uchar>(elem); |
|
nidx = elem->next; |
|
} |
|
|
|
if( createMissing ) |
|
{ |
|
int idx[] = { i0 }; |
|
return newNode( idx, h ); |
|
} |
|
return NULL; |
|
} |
|
|
|
uchar* SparseMat::ptr(int i0, int i1, bool createMissing, size_t* hashval) |
|
{ |
|
CV_Assert( hdr && hdr->dims == 2 ); |
|
size_t h = hashval ? *hashval : hash(i0, i1); |
|
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; |
|
uchar* pool = &hdr->pool[0]; |
|
while( nidx != 0 ) |
|
{ |
|
Node* elem = (Node*)(pool + nidx); |
|
if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 ) |
|
return &value<uchar>(elem); |
|
nidx = elem->next; |
|
} |
|
|
|
if( createMissing ) |
|
{ |
|
int idx[] = { i0, i1 }; |
|
return newNode( idx, h ); |
|
} |
|
return NULL; |
|
} |
|
|
|
uchar* SparseMat::ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval) |
|
{ |
|
CV_Assert( hdr && hdr->dims == 3 ); |
|
size_t h = hashval ? *hashval : hash(i0, i1, i2); |
|
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; |
|
uchar* pool = &hdr->pool[0]; |
|
while( nidx != 0 ) |
|
{ |
|
Node* elem = (Node*)(pool + nidx); |
|
if( elem->hashval == h && elem->idx[0] == i0 && |
|
elem->idx[1] == i1 && elem->idx[2] == i2 ) |
|
return &value<uchar>(elem); |
|
nidx = elem->next; |
|
} |
|
|
|
if( createMissing ) |
|
{ |
|
int idx[] = { i0, i1, i2 }; |
|
return newNode( idx, h ); |
|
} |
|
return NULL; |
|
} |
|
|
|
uchar* SparseMat::ptr(const int* idx, bool createMissing, size_t* hashval) |
|
{ |
|
CV_Assert( hdr ); |
|
int i, d = hdr->dims; |
|
size_t h = hashval ? *hashval : hash(idx); |
|
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx]; |
|
uchar* pool = &hdr->pool[0]; |
|
while( nidx != 0 ) |
|
{ |
|
Node* elem = (Node*)(pool + nidx); |
|
if( elem->hashval == h ) |
|
{ |
|
for( i = 0; i < d; i++ ) |
|
if( elem->idx[i] != idx[i] ) |
|
break; |
|
if( i == d ) |
|
return &value<uchar>(elem); |
|
} |
|
nidx = elem->next; |
|
} |
|
|
|
return createMissing ? newNode(idx, h) : NULL; |
|
} |
|
|
|
void SparseMat::erase(int i0, int i1, size_t* hashval) |
|
{ |
|
CV_Assert( hdr && hdr->dims == 2 ); |
|
size_t h = hashval ? *hashval : hash(i0, i1); |
|
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0; |
|
uchar* pool = &hdr->pool[0]; |
|
while( nidx != 0 ) |
|
{ |
|
Node* elem = (Node*)(pool + nidx); |
|
if( elem->hashval == h && elem->idx[0] == i0 && elem->idx[1] == i1 ) |
|
break; |
|
previdx = nidx; |
|
nidx = elem->next; |
|
} |
|
|
|
if( nidx ) |
|
removeNode(hidx, nidx, previdx); |
|
} |
|
|
|
void SparseMat::erase(int i0, int i1, int i2, size_t* hashval) |
|
{ |
|
CV_Assert( hdr && hdr->dims == 3 ); |
|
size_t h = hashval ? *hashval : hash(i0, i1, i2); |
|
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0; |
|
uchar* pool = &hdr->pool[0]; |
|
while( nidx != 0 ) |
|
{ |
|
Node* elem = (Node*)(pool + nidx); |
|
if( elem->hashval == h && elem->idx[0] == i0 && |
|
elem->idx[1] == i1 && elem->idx[2] == i2 ) |
|
break; |
|
previdx = nidx; |
|
nidx = elem->next; |
|
} |
|
|
|
if( nidx ) |
|
removeNode(hidx, nidx, previdx); |
|
} |
|
|
|
void SparseMat::erase(const int* idx, size_t* hashval) |
|
{ |
|
CV_Assert( hdr ); |
|
int i, d = hdr->dims; |
|
size_t h = hashval ? *hashval : hash(idx); |
|
size_t hidx = h & (hdr->hashtab.size() - 1), nidx = hdr->hashtab[hidx], previdx=0; |
|
uchar* pool = &hdr->pool[0]; |
|
while( nidx != 0 ) |
|
{ |
|
Node* elem = (Node*)(pool + nidx); |
|
if( elem->hashval == h ) |
|
{ |
|
for( i = 0; i < d; i++ ) |
|
if( elem->idx[i] != idx[i] ) |
|
break; |
|
if( i == d ) |
|
break; |
|
} |
|
previdx = nidx; |
|
nidx = elem->next; |
|
} |
|
|
|
if( nidx ) |
|
removeNode(hidx, nidx, previdx); |
|
} |
|
|
|
void SparseMat::resizeHashTab(size_t newsize) |
|
{ |
|
newsize = std::max(newsize, (size_t)8); |
|
if((newsize & (newsize-1)) != 0) |
|
newsize = (size_t)1 << cvCeil(std::log((double)newsize)/CV_LOG2); |
|
|
|
size_t hsize = hdr->hashtab.size(); |
|
std::vector<size_t> _newh(newsize); |
|
size_t* newh = &_newh[0]; |
|
for( size_t i = 0; i < newsize; i++ ) |
|
newh[i] = 0; |
|
uchar* pool = &hdr->pool[0]; |
|
for( size_t i = 0; i < hsize; i++ ) |
|
{ |
|
size_t nidx = hdr->hashtab[i]; |
|
while( nidx ) |
|
{ |
|
Node* elem = (Node*)(pool + nidx); |
|
size_t next = elem->next; |
|
size_t newhidx = elem->hashval & (newsize - 1); |
|
elem->next = newh[newhidx]; |
|
newh[newhidx] = nidx; |
|
nidx = next; |
|
} |
|
} |
|
hdr->hashtab = _newh; |
|
} |
|
|
|
uchar* SparseMat::newNode(const int* idx, size_t hashval) |
|
{ |
|
const int HASH_MAX_FILL_FACTOR=3; |
|
CV_Assert(hdr); |
|
size_t hsize = hdr->hashtab.size(); |
|
if( ++hdr->nodeCount > hsize*HASH_MAX_FILL_FACTOR ) |
|
{ |
|
resizeHashTab(std::max(hsize*2, (size_t)8)); |
|
hsize = hdr->hashtab.size(); |
|
} |
|
|
|
if( !hdr->freeList ) |
|
{ |
|
size_t i, nsz = hdr->nodeSize, psize = hdr->pool.size(), |
|
newpsize = std::max(psize*3/2, 8*nsz); |
|
newpsize = (newpsize/nsz)*nsz; |
|
hdr->pool.resize(newpsize); |
|
uchar* pool = &hdr->pool[0]; |
|
hdr->freeList = std::max(psize, nsz); |
|
for( i = hdr->freeList; i < newpsize - nsz; i += nsz ) |
|
((Node*)(pool + i))->next = i + nsz; |
|
((Node*)(pool + i))->next = 0; |
|
} |
|
size_t nidx = hdr->freeList; |
|
Node* elem = (Node*)&hdr->pool[nidx]; |
|
hdr->freeList = elem->next; |
|
elem->hashval = hashval; |
|
size_t hidx = hashval & (hsize - 1); |
|
elem->next = hdr->hashtab[hidx]; |
|
hdr->hashtab[hidx] = nidx; |
|
|
|
int i, d = hdr->dims; |
|
for( i = 0; i < d; i++ ) |
|
elem->idx[i] = idx[i]; |
|
size_t esz = elemSize(); |
|
uchar* p = &value<uchar>(elem); |
|
if( esz == sizeof(float) ) |
|
*((float*)p) = 0.f; |
|
else if( esz == sizeof(double) ) |
|
*((double*)p) = 0.; |
|
else |
|
memset(p, 0, esz); |
|
|
|
return p; |
|
} |
|
|
|
|
|
void SparseMat::removeNode(size_t hidx, size_t nidx, size_t previdx) |
|
{ |
|
Node* n = node(nidx); |
|
if( previdx ) |
|
{ |
|
Node* prev = node(previdx); |
|
prev->next = n->next; |
|
} |
|
else |
|
hdr->hashtab[hidx] = n->next; |
|
n->next = hdr->freeList; |
|
hdr->freeList = nidx; |
|
--hdr->nodeCount; |
|
} |
|
|
|
// |
|
// Operations |
|
// |
|
double norm( const SparseMat& src, int normType ) |
|
{ |
|
CV_INSTRUMENT_REGION(); |
|
|
|
SparseMatConstIterator it = src.begin(); |
|
|
|
size_t i, N = src.nzcount(); |
|
normType &= NORM_TYPE_MASK; |
|
int type = src.type(); |
|
double result = 0; |
|
|
|
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 ); |
|
|
|
if( type == CV_32F ) |
|
{ |
|
if( normType == NORM_INF ) |
|
for( i = 0; i < N; i++, ++it ) |
|
{ |
|
CV_Assert(it.ptr); |
|
result = std::max(result, std::abs((double)it.value<float>())); |
|
} |
|
else if( normType == NORM_L1 ) |
|
for( i = 0; i < N; i++, ++it ) |
|
{ |
|
CV_Assert(it.ptr); |
|
result += std::abs(it.value<float>()); |
|
} |
|
else |
|
for( i = 0; i < N; i++, ++it ) |
|
{ |
|
CV_Assert(it.ptr); |
|
double v = it.value<float>(); |
|
result += v*v; |
|
} |
|
} |
|
else if( type == CV_64F ) |
|
{ |
|
if( normType == NORM_INF ) |
|
for( i = 0; i < N; i++, ++it ) |
|
{ |
|
CV_Assert(it.ptr); |
|
result = std::max(result, std::abs(it.value<double>())); |
|
} |
|
else if( normType == NORM_L1 ) |
|
for( i = 0; i < N; i++, ++it ) |
|
{ |
|
CV_Assert(it.ptr); |
|
result += std::abs(it.value<double>()); |
|
} |
|
else |
|
for( i = 0; i < N; i++, ++it ) |
|
{ |
|
CV_Assert(it.ptr); |
|
double v = it.value<double>(); |
|
result += v*v; |
|
} |
|
} |
|
else |
|
CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" ); |
|
|
|
if( normType == NORM_L2 ) |
|
result = std::sqrt(result); |
|
return result; |
|
} |
|
|
|
void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _minidx, int* _maxidx ) |
|
{ |
|
CV_INSTRUMENT_REGION(); |
|
|
|
SparseMatConstIterator it = src.begin(); |
|
size_t i, N = src.nzcount(), d = src.hdr ? src.hdr->dims : 0; |
|
int type = src.type(); |
|
const int *minidx = 0, *maxidx = 0; |
|
|
|
if( type == CV_32F ) |
|
{ |
|
float minval = FLT_MAX, maxval = -FLT_MAX; |
|
for( i = 0; i < N; i++, ++it ) |
|
{ |
|
CV_Assert(it.ptr); |
|
float v = it.value<float>(); |
|
if( v < minval ) |
|
{ |
|
minval = v; |
|
minidx = it.node()->idx; |
|
} |
|
if( v > maxval ) |
|
{ |
|
maxval = v; |
|
maxidx = it.node()->idx; |
|
} |
|
} |
|
if( _minval ) |
|
*_minval = minval; |
|
if( _maxval ) |
|
*_maxval = maxval; |
|
} |
|
else if( type == CV_64F ) |
|
{ |
|
double minval = DBL_MAX, maxval = -DBL_MAX; |
|
for( i = 0; i < N; i++, ++it ) |
|
{ |
|
CV_Assert(it.ptr); |
|
double v = it.value<double>(); |
|
if( v < minval ) |
|
{ |
|
minval = v; |
|
minidx = it.node()->idx; |
|
} |
|
if( v > maxval ) |
|
{ |
|
maxval = v; |
|
maxidx = it.node()->idx; |
|
} |
|
} |
|
if( _minval ) |
|
*_minval = minval; |
|
if( _maxval ) |
|
*_maxval = maxval; |
|
} |
|
else |
|
CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" ); |
|
|
|
if( _minidx && minidx ) |
|
for( i = 0; i < d; i++ ) |
|
_minidx[i] = minidx[i]; |
|
if( _maxidx && maxidx ) |
|
for( i = 0; i < d; i++ ) |
|
_maxidx[i] = maxidx[i]; |
|
} |
|
|
|
|
|
void normalize( const SparseMat& src, SparseMat& dst, double a, int norm_type ) |
|
{ |
|
CV_INSTRUMENT_REGION(); |
|
|
|
double scale = 1; |
|
if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C ) |
|
{ |
|
scale = norm( src, norm_type ); |
|
scale = scale > DBL_EPSILON ? a/scale : 0.; |
|
} |
|
else |
|
CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" ); |
|
|
|
src.convertTo( dst, -1, scale ); |
|
} |
|
|
|
} // cv:: |
|
|
|
// |
|
// C-API glue |
|
// |
|
CvSparseMat* cvCreateSparseMat(const cv::SparseMat& sm) |
|
{ |
|
if( !sm.hdr || sm.hdr->dims > (int)cv::SparseMat::MAX_DIM) |
|
return 0; |
|
|
|
CvSparseMat* m = cvCreateSparseMat(sm.hdr->dims, sm.hdr->size, sm.type()); |
|
|
|
cv::SparseMatConstIterator from = sm.begin(); |
|
size_t i, N = sm.nzcount(), esz = sm.elemSize(); |
|
|
|
for( i = 0; i < N; i++, ++from ) |
|
{ |
|
const cv::SparseMat::Node* n = from.node(); |
|
uchar* to = cvPtrND(m, n->idx, 0, -2, 0); |
|
cv::copyElem(from.ptr, to, esz); |
|
} |
|
return m; |
|
} |
|
|
|
void CvSparseMat::copyToSparseMat(cv::SparseMat& m) const |
|
{ |
|
m.create( dims, &size[0], type ); |
|
|
|
CvSparseMatIterator it; |
|
CvSparseNode* n = cvInitSparseMatIterator(this, &it); |
|
size_t esz = m.elemSize(); |
|
|
|
for( ; n != 0; n = cvGetNextSparseNode(&it) ) |
|
{ |
|
const int* idx = CV_NODE_IDX(this, n); |
|
uchar* to = m.newNode(idx, m.hash(idx)); |
|
cv::copyElem((const uchar*)CV_NODE_VAL(this, n), to, esz); |
|
} |
|
}
|
|
|