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.
715 lines
19 KiB
715 lines
19 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 "persistence.hpp" |
|
|
|
///////////////////////// new C++ interface for CvFileStorage /////////////////////////// |
|
|
|
namespace cv |
|
{ |
|
|
|
FileStorage::FileStorage() |
|
{ |
|
state = UNDEFINED; |
|
} |
|
|
|
FileStorage::FileStorage(const String& filename, int flags, const String& encoding) |
|
{ |
|
state = UNDEFINED; |
|
open( filename, flags, encoding ); |
|
} |
|
|
|
FileStorage::FileStorage(CvFileStorage* _fs, bool owning) |
|
{ |
|
if (owning) fs.reset(_fs); |
|
else fs = Ptr<CvFileStorage>(Ptr<CvFileStorage>(), _fs); |
|
|
|
state = _fs ? NAME_EXPECTED + INSIDE_MAP : UNDEFINED; |
|
} |
|
|
|
FileStorage::~FileStorage() |
|
{ |
|
while( structs.size() > 0 ) |
|
{ |
|
cvEndWriteStruct(fs); |
|
structs.pop_back(); |
|
} |
|
} |
|
|
|
bool FileStorage::open(const String& filename, int flags, const String& encoding) |
|
{ |
|
CV_INSTRUMENT_REGION(); |
|
|
|
release(); |
|
fs.reset(cvOpenFileStorage( filename.c_str(), 0, flags, |
|
!encoding.empty() ? encoding.c_str() : 0)); |
|
bool ok = isOpened(); |
|
state = ok ? NAME_EXPECTED + INSIDE_MAP : UNDEFINED; |
|
return ok; |
|
} |
|
|
|
bool FileStorage::isOpened() const |
|
{ |
|
return fs && fs->is_opened; |
|
} |
|
|
|
void FileStorage::release() |
|
{ |
|
fs.release(); |
|
structs.clear(); |
|
state = UNDEFINED; |
|
} |
|
|
|
String FileStorage::releaseAndGetString() |
|
{ |
|
String buf; |
|
if( fs && fs->outbuf ) |
|
icvClose(fs, &buf); |
|
|
|
release(); |
|
return buf; |
|
} |
|
|
|
FileNode FileStorage::root(int streamidx) const |
|
{ |
|
return isOpened() ? FileNode(fs, cvGetRootFileNode(fs, streamidx)) : FileNode(); |
|
} |
|
|
|
int FileStorage::getFormat() const |
|
{ |
|
CV_Assert(!fs.empty()); |
|
return fs->fmt & FORMAT_MASK; |
|
} |
|
|
|
FileStorage& operator << (FileStorage& fs, const String& str) |
|
{ |
|
CV_TRACE_REGION_VERBOSE(); |
|
|
|
enum { NAME_EXPECTED = FileStorage::NAME_EXPECTED, |
|
VALUE_EXPECTED = FileStorage::VALUE_EXPECTED, |
|
INSIDE_MAP = FileStorage::INSIDE_MAP }; |
|
const char* _str = str.c_str(); |
|
if( !fs.isOpened() || !_str ) |
|
return fs; |
|
if( *_str == '}' || *_str == ']' ) |
|
{ |
|
if( fs.structs.empty() ) |
|
CV_Error_( CV_StsError, ("Extra closing '%c'", *_str) ); |
|
if( (*_str == ']' ? '[' : '{') != fs.structs.back() ) |
|
CV_Error_( CV_StsError, |
|
("The closing '%c' does not match the opening '%c'", *_str, fs.structs.back())); |
|
fs.structs.pop_back(); |
|
fs.state = fs.structs.empty() || fs.structs.back() == '{' ? |
|
INSIDE_MAP + NAME_EXPECTED : VALUE_EXPECTED; |
|
cvEndWriteStruct( *fs ); |
|
fs.elname = String(); |
|
} |
|
else if( fs.state == NAME_EXPECTED + INSIDE_MAP ) |
|
{ |
|
if (!cv_isalpha(*_str) && *_str != '_') |
|
CV_Error_( CV_StsError, ("Incorrect element name %s", _str) ); |
|
fs.elname = str; |
|
fs.state = VALUE_EXPECTED + INSIDE_MAP; |
|
} |
|
else if( (fs.state & 3) == VALUE_EXPECTED ) |
|
{ |
|
if( *_str == '{' || *_str == '[' ) |
|
{ |
|
fs.structs.push_back(*_str); |
|
int flags = *_str++ == '{' ? CV_NODE_MAP : CV_NODE_SEQ; |
|
fs.state = flags == CV_NODE_MAP ? INSIDE_MAP + |
|
NAME_EXPECTED : VALUE_EXPECTED; |
|
if( *_str == ':' ) |
|
{ |
|
flags |= CV_NODE_FLOW; |
|
_str++; |
|
} |
|
cvStartWriteStruct( *fs, fs.elname.size() > 0 ? fs.elname.c_str() : 0, |
|
flags, *_str ? _str : 0 ); |
|
fs.elname = String(); |
|
} |
|
else |
|
{ |
|
write( fs, fs.elname, (_str[0] == '\\' && (_str[1] == '{' || _str[1] == '}' || |
|
_str[1] == '[' || _str[1] == ']')) ? String(_str+1) : str ); |
|
if( fs.state == INSIDE_MAP + VALUE_EXPECTED ) |
|
fs.state = INSIDE_MAP + NAME_EXPECTED; |
|
} |
|
} |
|
else |
|
CV_Error( CV_StsError, "Invalid fs.state" ); |
|
return fs; |
|
} |
|
|
|
|
|
void FileStorage::writeRaw( const String& fmt, const uchar* vec, size_t len ) |
|
{ |
|
if( !isOpened() ) |
|
return; |
|
CV_Assert(!fmt.empty()); |
|
size_t elemSize = ::icvCalcStructSize(fmt.c_str(), 0); |
|
CV_Assert( len % elemSize == 0 ); |
|
cvWriteRawData( fs, vec, (int)(len/elemSize), fmt.c_str()); |
|
} |
|
|
|
|
|
void FileStorage::writeObj( const String& name, const void* obj ) |
|
{ |
|
if( !isOpened() ) |
|
return; |
|
cvWrite( fs, name.size() > 0 ? name.c_str() : 0, obj ); |
|
} |
|
|
|
|
|
void FileStorage::write( const String& name, int val ) |
|
{ |
|
cvWriteInt(fs, name.c_str(), val); |
|
} |
|
|
|
void FileStorage::write( const String& name, double val ) |
|
{ |
|
cvWriteReal(fs, name.c_str(), val); |
|
} |
|
|
|
void FileStorage::write( const String& name, const String& val ) |
|
{ |
|
cvWriteString(fs, name.c_str(), val.c_str()); |
|
} |
|
|
|
void FileStorage::write( const String& name, InputArray val ) |
|
{ |
|
if(state & INSIDE_MAP) |
|
*this << name; |
|
*this << val.getMat(); |
|
} |
|
|
|
void FileStorage::writeComment( const String& comment, bool append ) |
|
{ |
|
cvWriteComment(fs, comment.c_str(), append ? 1 : 0); |
|
} |
|
|
|
void FileStorage::startWriteStruct(const String& name, int flags, const String& typeName) |
|
{ |
|
int struct_type = flags & FileNode::TYPE_MASK; |
|
bool isflow = (flags & FileNode::FLOW) != 0; |
|
CV_Assert(struct_type == FileNode::SEQ || struct_type == FileNode::MAP); |
|
char strbegin_[] = { (struct_type == FileNode::SEQ ? '[' : '{'), (isflow ? ':' : '\0'), '\0' }; |
|
String strbegin = strbegin_; |
|
if (!typeName.empty()) |
|
strbegin += typeName; |
|
*this << name << strbegin; |
|
} |
|
|
|
void FileStorage::endWriteStruct() |
|
{ |
|
if( structs.empty() ) |
|
CV_Error( CV_StsError, "Extra endWriteStruct()" ); |
|
char openparen = structs.back(); |
|
*this << (openparen == '[' ? "]" : "}"); |
|
} |
|
|
|
String FileStorage::getDefaultObjectName(const String& _filename) |
|
{ |
|
static const char* stubname = "unnamed"; |
|
const char* filename = _filename.c_str(); |
|
const char* ptr2 = filename + _filename.size(); |
|
const char* ptr = ptr2 - 1; |
|
cv::AutoBuffer<char> name_buf(_filename.size()+1); |
|
|
|
while( ptr >= filename && *ptr != '\\' && *ptr != '/' && *ptr != ':' ) |
|
{ |
|
if( *ptr == '.' && (!*ptr2 || strncmp(ptr2, ".gz", 3) == 0) ) |
|
ptr2 = ptr; |
|
ptr--; |
|
} |
|
ptr++; |
|
if( ptr == ptr2 ) |
|
CV_Error( CV_StsBadArg, "Invalid filename" ); |
|
|
|
char* name = name_buf.data(); |
|
|
|
// name must start with letter or '_' |
|
if( !cv_isalpha(*ptr) && *ptr!= '_' ){ |
|
*name++ = '_'; |
|
} |
|
|
|
while( ptr < ptr2 ) |
|
{ |
|
char c = *ptr++; |
|
if( !cv_isalnum(c) && c != '-' && c != '_' ) |
|
c = '_'; |
|
*name++ = c; |
|
} |
|
*name = '\0'; |
|
name = name_buf.data(); |
|
if( strcmp( name, "_" ) == 0 ) |
|
strcpy( name, stubname ); |
|
return String(name); |
|
} |
|
|
|
FileNode FileStorage::operator[](const String& nodename) const |
|
{ |
|
return FileNode(fs, cvGetFileNodeByName(fs, 0, nodename.c_str())); |
|
} |
|
|
|
FileNode FileStorage::operator[](const char* nodename) const |
|
{ |
|
return FileNode(fs, cvGetFileNodeByName(fs, 0, nodename)); |
|
} |
|
|
|
FileNode FileNode::operator[](const String& nodename) const |
|
{ |
|
return FileNode(fs, cvGetFileNodeByName(fs, node, nodename.c_str())); |
|
} |
|
|
|
FileNode FileNode::operator[](const char* nodename) const |
|
{ |
|
return FileNode(fs, cvGetFileNodeByName(fs, node, nodename)); |
|
} |
|
|
|
FileNode FileNode::operator[](int i) const |
|
{ |
|
return isSeq() ? FileNode(fs, (CvFileNode*)cvGetSeqElem(node->data.seq, i)) : |
|
i == 0 ? *this : FileNode(); |
|
} |
|
|
|
std::vector<String> FileNode::keys() const |
|
{ |
|
CV_Assert(isMap()); |
|
|
|
std::vector<String> res; |
|
res.reserve(size()); |
|
for (FileNodeIterator it = begin(); it != end(); ++it) |
|
{ |
|
res.push_back((*it).name()); |
|
} |
|
return res; |
|
} |
|
|
|
String FileNode::name() const |
|
{ |
|
const char* str; |
|
return !node || (str = cvGetFileNodeName(node)) == 0 ? String() : String(str); |
|
} |
|
|
|
void* FileNode::readObj() const |
|
{ |
|
if( !fs || !node ) |
|
return 0; |
|
return cvRead( (CvFileStorage*)fs, (CvFileNode*)node ); |
|
} |
|
|
|
static const FileNodeIterator::SeqReader emptyReader = {0, 0, 0, 0, 0, 0, 0, 0}; |
|
|
|
FileNodeIterator::FileNodeIterator() |
|
{ |
|
fs = 0; |
|
container = 0; |
|
reader = emptyReader; |
|
remaining = 0; |
|
} |
|
|
|
FileNodeIterator::FileNodeIterator(const CvFileStorage* _fs, |
|
const CvFileNode* _node, size_t _ofs) |
|
{ |
|
reader = emptyReader; |
|
if( _fs && _node && CV_NODE_TYPE(_node->tag) != CV_NODE_NONE ) |
|
{ |
|
int node_type = _node->tag & FileNode::TYPE_MASK; |
|
fs = _fs; |
|
container = _node; |
|
if( !(_node->tag & FileNode::USER) && (node_type == FileNode::SEQ || node_type == FileNode::MAP) ) |
|
{ |
|
cvStartReadSeq( _node->data.seq, (CvSeqReader*)&reader ); |
|
remaining = FileNode(_fs, _node).size(); |
|
} |
|
else |
|
{ |
|
reader.ptr = (schar*)_node; |
|
reader.seq = 0; |
|
remaining = 1; |
|
} |
|
(*this) += (int)_ofs; |
|
} |
|
else |
|
{ |
|
fs = 0; |
|
container = 0; |
|
remaining = 0; |
|
} |
|
} |
|
|
|
FileNodeIterator::FileNodeIterator(const FileNodeIterator& it) |
|
{ |
|
fs = it.fs; |
|
container = it.container; |
|
reader = it.reader; |
|
remaining = it.remaining; |
|
} |
|
|
|
FileNodeIterator& FileNodeIterator::operator=(const FileNodeIterator& it) |
|
{ |
|
fs = it.fs; |
|
container = it.container; |
|
reader = it.reader; |
|
remaining = it.remaining; |
|
return *this; |
|
} |
|
|
|
FileNodeIterator& FileNodeIterator::operator ++() |
|
{ |
|
if( remaining > 0 ) |
|
{ |
|
if( reader.seq ) |
|
{ |
|
if( ((reader).ptr += (((CvSeq*)reader.seq)->elem_size)) >= (reader).block_max ) |
|
{ |
|
cvChangeSeqBlock( (CvSeqReader*)&(reader), 1 ); |
|
} |
|
} |
|
remaining--; |
|
} |
|
return *this; |
|
} |
|
|
|
FileNodeIterator FileNodeIterator::operator ++(int) |
|
{ |
|
FileNodeIterator it = *this; |
|
++(*this); |
|
return it; |
|
} |
|
|
|
FileNodeIterator& FileNodeIterator::operator --() |
|
{ |
|
if( remaining < FileNode(fs, container).size() ) |
|
{ |
|
if( reader.seq ) |
|
{ |
|
if( ((reader).ptr -= (((CvSeq*)reader.seq)->elem_size)) < (reader).block_min ) |
|
{ |
|
cvChangeSeqBlock( (CvSeqReader*)&(reader), -1 ); |
|
} |
|
} |
|
remaining++; |
|
} |
|
return *this; |
|
} |
|
|
|
FileNodeIterator FileNodeIterator::operator --(int) |
|
{ |
|
FileNodeIterator it = *this; |
|
--(*this); |
|
return it; |
|
} |
|
|
|
FileNodeIterator& FileNodeIterator::operator += (int ofs) |
|
{ |
|
if( ofs == 0 ) |
|
return *this; |
|
if( ofs > 0 ) |
|
ofs = std::min(ofs, (int)remaining); |
|
else |
|
{ |
|
size_t count = FileNode(fs, container).size(); |
|
ofs = (int)(remaining - std::min(remaining - ofs, count)); |
|
} |
|
remaining -= ofs; |
|
if( reader.seq ) |
|
cvSetSeqReaderPos( (CvSeqReader*)&reader, ofs, 1 ); |
|
return *this; |
|
} |
|
|
|
FileNodeIterator& FileNodeIterator::operator -= (int ofs) |
|
{ |
|
return operator += (-ofs); |
|
} |
|
|
|
|
|
FileNodeIterator& FileNodeIterator::readRaw(const String& fmt, uchar* vec, size_t len) |
|
{ |
|
CV_Assert(!fmt.empty()); |
|
if( fs && container && remaining > 0 && len > 0) |
|
{ |
|
if (reader.seq) |
|
{ |
|
size_t step = ::icvCalcStructSize(fmt.c_str(), 0); |
|
if (len % step && len != (size_t)INT_MAX) // TODO remove compatibility hack |
|
{ |
|
CV_PARSE_ERROR("readRaw: total byte size not match elememt size"); |
|
} |
|
size_t maxCount = len / step; |
|
int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2] = {}; |
|
int fmt_pair_count = icvDecodeFormat(fmt.c_str(), fmt_pairs, CV_FS_MAX_FMT_PAIRS); |
|
int vecElems = 0; |
|
for (int k = 0; k < fmt_pair_count; k++) |
|
{ |
|
vecElems += fmt_pairs[k*2]; |
|
} |
|
CV_Assert(vecElems > 0); |
|
size_t count = std::min((size_t)remaining, (size_t)maxCount * vecElems); |
|
cvReadRawDataSlice(fs, (CvSeqReader*)&reader, (int)count, vec, fmt.c_str()); |
|
remaining -= count; |
|
} |
|
else |
|
{ |
|
cvReadRawData( fs, container, vec, fmt.c_str() ); |
|
remaining = 0; |
|
} |
|
} |
|
return *this; |
|
} |
|
|
|
|
|
void write( FileStorage& fs, const String& name, int value ) |
|
{ cvWriteInt( *fs, name.size() ? name.c_str() : 0, value ); } |
|
|
|
void write( FileStorage& fs, const String& name, float value ) |
|
{ cvWriteReal( *fs, name.size() ? name.c_str() : 0, value ); } |
|
|
|
void write( FileStorage& fs, const String& name, double value ) |
|
{ cvWriteReal( *fs, name.size() ? name.c_str() : 0, value ); } |
|
|
|
void write( FileStorage& fs, const String& name, const String& value ) |
|
{ cvWriteString( *fs, name.size() ? name.c_str() : 0, value.c_str() ); } |
|
|
|
void writeScalar(FileStorage& fs, int value ) |
|
{ cvWriteInt( *fs, 0, value ); } |
|
|
|
void writeScalar(FileStorage& fs, float value ) |
|
{ cvWriteReal( *fs, 0, value ); } |
|
|
|
void writeScalar(FileStorage& fs, double value ) |
|
{ cvWriteReal( *fs, 0, value ); } |
|
|
|
void writeScalar(FileStorage& fs, const String& value ) |
|
{ cvWriteString( *fs, 0, value.c_str() ); } |
|
|
|
|
|
void write( FileStorage& fs, const String& name, const Mat& value ) |
|
{ |
|
if( value.dims <= 2 ) |
|
{ |
|
CvMat mat = cvMat(value); |
|
cvWrite( *fs, name.size() ? name.c_str() : 0, &mat ); |
|
} |
|
else |
|
{ |
|
CvMatND mat = cvMatND(value); |
|
cvWrite( *fs, name.size() ? name.c_str() : 0, &mat ); |
|
} |
|
} |
|
|
|
// TODO: the 4 functions below need to be implemented more efficiently |
|
void write( FileStorage& fs, const String& name, const SparseMat& value ) |
|
{ |
|
Ptr<CvSparseMat> mat(cvCreateSparseMat(value)); |
|
cvWrite( *fs, name.size() ? name.c_str() : 0, mat ); |
|
} |
|
|
|
|
|
internal::WriteStructContext::WriteStructContext(FileStorage& _fs, |
|
const String& name, int flags, const String& typeName) : fs(&_fs) |
|
{ |
|
cvStartWriteStruct(**fs, !name.empty() ? name.c_str() : 0, flags, |
|
!typeName.empty() ? typeName.c_str() : 0); |
|
fs->elname = String(); |
|
if ((flags & FileNode::TYPE_MASK) == FileNode::SEQ) |
|
{ |
|
fs->state = FileStorage::VALUE_EXPECTED; |
|
fs->structs.push_back('['); |
|
} |
|
else |
|
{ |
|
fs->state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP; |
|
fs->structs.push_back('{'); |
|
} |
|
} |
|
|
|
internal::WriteStructContext::~WriteStructContext() |
|
{ |
|
cvEndWriteStruct(**fs); |
|
fs->structs.pop_back(); |
|
fs->state = fs->structs.empty() || fs->structs.back() == '{' ? |
|
FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP : |
|
FileStorage::VALUE_EXPECTED; |
|
fs->elname = String(); |
|
} |
|
|
|
|
|
void read( const FileNode& node, Mat& mat, const Mat& default_mat ) |
|
{ |
|
if( node.empty() ) |
|
{ |
|
default_mat.copyTo(mat); |
|
return; |
|
} |
|
void* obj = cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node); |
|
if(CV_IS_MAT_HDR_Z(obj)) |
|
{ |
|
cvarrToMat(obj).copyTo(mat); |
|
cvReleaseMat((CvMat**)&obj); |
|
} |
|
else if(CV_IS_MATND_HDR(obj)) |
|
{ |
|
cvarrToMat(obj).copyTo(mat); |
|
cvReleaseMatND((CvMatND**)&obj); |
|
} |
|
else |
|
{ |
|
cvRelease(&obj); |
|
CV_Error(CV_StsBadArg, "Unknown array type"); |
|
} |
|
} |
|
|
|
void read( const FileNode& node, SparseMat& mat, const SparseMat& default_mat ) |
|
{ |
|
if( node.empty() ) |
|
{ |
|
default_mat.copyTo(mat); |
|
return; |
|
} |
|
Ptr<CvSparseMat> m((CvSparseMat*)cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node)); |
|
CV_Assert(CV_IS_SPARSE_MAT(m)); |
|
m->copyToSparseMat(mat); |
|
} |
|
|
|
CV_EXPORTS void read(const FileNode& node, KeyPoint& value, const KeyPoint& default_value) |
|
{ |
|
if( node.empty() ) |
|
{ |
|
value = default_value; |
|
return; |
|
} |
|
node >> value; |
|
} |
|
|
|
CV_EXPORTS void read(const FileNode& node, DMatch& value, const DMatch& default_value) |
|
{ |
|
if( node.empty() ) |
|
{ |
|
value = default_value; |
|
return; |
|
} |
|
node >> value; |
|
} |
|
|
|
#ifdef CV__LEGACY_PERSISTENCE |
|
void write( FileStorage& fs, const String& name, const std::vector<KeyPoint>& vec) |
|
{ |
|
// from template implementation |
|
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ); |
|
write(fs, vec); |
|
} |
|
|
|
void read(const FileNode& node, std::vector<KeyPoint>& keypoints) |
|
{ |
|
FileNode first_node = *(node.begin()); |
|
if (first_node.isSeq()) |
|
{ |
|
// modern scheme |
|
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED |
|
FileNodeIterator it = node.begin(); |
|
size_t total = (size_t)it.remaining; |
|
keypoints.resize(total); |
|
for (size_t i = 0; i < total; ++i, ++it) |
|
{ |
|
(*it) >> keypoints[i]; |
|
} |
|
#else |
|
FileNodeIterator it = node.begin(); |
|
it >> keypoints; |
|
#endif |
|
return; |
|
} |
|
keypoints.clear(); |
|
FileNodeIterator it = node.begin(), it_end = node.end(); |
|
for( ; it != it_end; ) |
|
{ |
|
KeyPoint kpt; |
|
it >> kpt.pt.x >> kpt.pt.y >> kpt.size >> kpt.angle >> kpt.response >> kpt.octave >> kpt.class_id; |
|
keypoints.push_back(kpt); |
|
} |
|
} |
|
|
|
void write( FileStorage& fs, const String& name, const std::vector<DMatch>& vec) |
|
{ |
|
// from template implementation |
|
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ); |
|
write(fs, vec); |
|
} |
|
|
|
void read(const FileNode& node, std::vector<DMatch>& matches) |
|
{ |
|
FileNode first_node = *(node.begin()); |
|
if (first_node.isSeq()) |
|
{ |
|
// modern scheme |
|
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED |
|
FileNodeIterator it = node.begin(); |
|
size_t total = (size_t)it.remaining; |
|
matches.resize(total); |
|
for (size_t i = 0; i < total; ++i, ++it) |
|
{ |
|
(*it) >> matches[i]; |
|
} |
|
#else |
|
FileNodeIterator it = node.begin(); |
|
it >> matches; |
|
#endif |
|
return; |
|
} |
|
matches.clear(); |
|
FileNodeIterator it = node.begin(), it_end = node.end(); |
|
for( ; it != it_end; ) |
|
{ |
|
DMatch m; |
|
it >> m.queryIdx >> m.trainIdx >> m.imgIdx >> m.distance; |
|
matches.push_back(m); |
|
} |
|
} |
|
#endif |
|
|
|
int FileNode::type() const { return !node ? NONE : (node->tag & TYPE_MASK); } |
|
bool FileNode::isNamed() const { return !node ? false : (node->tag & NAMED) != 0; } |
|
|
|
size_t FileNode::size() const |
|
{ |
|
int t = type(); |
|
return t == MAP ? (size_t)((CvSet*)node->data.map)->active_count : |
|
t == SEQ ? (size_t)node->data.seq->total : (size_t)!isNone(); |
|
} |
|
|
|
void read(const FileNode& node, int& value, int default_value) |
|
{ |
|
value = !node.node ? default_value : |
|
CV_NODE_IS_INT(node.node->tag) ? node.node->data.i : std::numeric_limits<int>::max(); |
|
} |
|
|
|
void read(const FileNode& node, float& value, float default_value) |
|
{ |
|
value = !node.node ? default_value : |
|
CV_NODE_IS_INT(node.node->tag) ? (float)node.node->data.i : |
|
CV_NODE_IS_REAL(node.node->tag) ? saturate_cast<float>(node.node->data.f) : std::numeric_limits<float>::max(); |
|
} |
|
|
|
void read(const FileNode& node, double& value, double default_value) |
|
{ |
|
value = !node.node ? default_value : |
|
CV_NODE_IS_INT(node.node->tag) ? (double)node.node->data.i : |
|
CV_NODE_IS_REAL(node.node->tag) ? node.node->data.f : std::numeric_limits<double>::max(); |
|
} |
|
|
|
void read(const FileNode& node, String& value, const String& default_value) |
|
{ |
|
value = !node.node ? default_value : CV_NODE_IS_STRING(node.node->tag) ? String(node.node->data.str.ptr) : String(); |
|
} |
|
|
|
void read(const FileNode& node, std::string& value, const std::string& default_value) |
|
{ |
|
value = !node.node ? default_value : CV_NODE_IS_STRING(node.node->tag) ? std::string(node.node->data.str.ptr) : default_value; |
|
} |
|
|
|
} // cv::
|
|
|