1 Star 0 Fork 0

郭志杰/DBow3

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
Database.cpp 24.12 KB
一键复制 编辑 原始数据 按行查看 历史
yangkui 提交于 2017-02-22 15:41 +08:00 . fix an error: miss return value in Database::add
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
#include "Database.h"
namespace DBoW3{
// --------------------------------------------------------------------------
Database::Database
(bool use_di, int di_levels)
: m_voc(NULL), m_use_di(use_di), m_dilevels(di_levels), m_nentries(0)
{
}
// --------------------------------------------------------------------------
Database::Database
(const Vocabulary &voc, bool use_di, int di_levels)
: m_voc(NULL), m_use_di(use_di), m_dilevels(di_levels)
{
setVocabulary(voc);
clear();
}
// --------------------------------------------------------------------------
Database::Database
(const Database &db)
: m_voc(NULL)
{
*this = db;
}
// --------------------------------------------------------------------------
Database::Database
(const std::string &filename)
: m_voc(NULL)
{
load(filename);
}
// --------------------------------------------------------------------------
Database::Database
(const char *filename)
: m_voc(NULL)
{
load(filename);
}
// --------------------------------------------------------------------------
Database::~Database(void)
{
delete m_voc;
}
// --------------------------------------------------------------------------
Database& Database::operator=
(const Database &db)
{
if(this != &db)
{
m_dfile = db.m_dfile;
m_dilevels = db.m_dilevels;
m_ifile = db.m_ifile;
m_nentries = db.m_nentries;
m_use_di = db.m_use_di;
if (db.m_voc!=0) setVocabulary(*db.m_voc);
}
return *this;
}
// --------------------------------------------------------------------------
EntryId Database::add(
const cv::Mat &features,
BowVector *bowvec, FeatureVector *fvec)
{
std::vector<cv::Mat> vf(features.rows);
for(int r=0;r<features.rows;r++) vf[r]=features.rowRange(r,r+1);
return add(vf,bowvec,fvec);
}
EntryId Database::add(
const std::vector<cv::Mat> &features,
BowVector *bowvec, FeatureVector *fvec)
{
BowVector aux;
BowVector& v = (bowvec ? *bowvec : aux);
if(m_use_di && fvec != NULL)
{
m_voc->transform(features, v, *fvec, m_dilevels); // with features
return add(v, *fvec);
}
else if(m_use_di)
{
FeatureVector fv;
m_voc->transform(features, v, fv, m_dilevels); // with features
return add(v, fv);
}
else if(fvec != NULL)
{
m_voc->transform(features, v, *fvec, m_dilevels); // with features
return add(v);
}
else
{
m_voc->transform(features, v); // with features
return add(v);
}
}
// ---------------------------------------------------------------------------
EntryId Database::add(const BowVector &v,
const FeatureVector &fv)
{
EntryId entry_id = m_nentries++;
BowVector::const_iterator vit;
std::vector<unsigned int>::const_iterator iit;
if(m_use_di)
{
// update direct file
if(entry_id == m_dfile.size())
{
m_dfile.push_back(fv);
}
else
{
m_dfile[entry_id] = fv;
}
}
// update inverted file
for(vit = v.begin(); vit != v.end(); ++vit)
{
const WordId& word_id = vit->first;
const WordValue& word_weight = vit->second;
IFRow& ifrow = m_ifile[word_id];
ifrow.push_back(IFPair(entry_id, word_weight));
}
return entry_id;
}
// --------------------------------------------------------------------------
void Database::setVocabulary
(const Vocabulary& voc)
{
delete m_voc;
m_voc = new Vocabulary(voc);
clear();
}
// --------------------------------------------------------------------------
void Database::setVocabulary
(const Vocabulary& voc, bool use_di, int di_levels)
{
m_use_di = use_di;
m_dilevels = di_levels;
delete m_voc;
m_voc = new Vocabulary(voc);
clear();
}
// --------------------------------------------------------------------------
const Vocabulary*
Database::getVocabulary() const
{
return m_voc;
}
// --------------------------------------------------------------------------
void Database::clear()
{
// resize vectors
m_ifile.resize(0);
m_ifile.resize(m_voc->size());
m_dfile.resize(0);
m_nentries = 0;
}
// --------------------------------------------------------------------------
void Database::allocate(int nd, int ni)
{
// m_ifile already contains |words| items
if(ni > 0)
{
for(auto rit = m_ifile.begin(); rit != m_ifile.end(); ++rit)
{
int n = (int)rit->size();
if(ni > n)
{
rit->resize(ni);
rit->resize(n);
}
}
}
if(m_use_di && (int)m_dfile.size() < nd)
{
m_dfile.resize(nd);
}
}
// --------------------------------------------------------------------------
void Database::query(
const cv::Mat &features,
QueryResults &ret, int max_results, int max_id) const
{
std::vector<cv::Mat> vf(features.rows);
for(int r=0;r<features.rows;r++) vf[r]=features.rowRange(r,r+1);
query(vf, ret, max_results, max_id);
}
void Database::query(
const std::vector<cv::Mat> &features,
QueryResults &ret, int max_results, int max_id) const
{
BowVector vec;
m_voc->transform(features, vec);
query(vec, ret, max_results, max_id);
}
// --------------------------------------------------------------------------
void Database::query(
const BowVector &vec,
QueryResults &ret, int max_results, int max_id) const
{
ret.resize(0);
switch(m_voc->getScoringType())
{
case L1_NORM:
queryL1(vec, ret, max_results, max_id);
break;
case L2_NORM:
queryL2(vec, ret, max_results, max_id);
break;
case CHI_SQUARE:
queryChiSquare(vec, ret, max_results, max_id);
break;
case KL:
queryKL(vec, ret, max_results, max_id);
break;
case BHATTACHARYYA:
queryBhattacharyya(vec, ret, max_results, max_id);
break;
case DOT_PRODUCT:
queryDotProduct(vec, ret, max_results, max_id);
break;
}
}
// --------------------------------------------------------------------------
void Database::queryL1(const BowVector &vec,
QueryResults &ret, int max_results, int max_id) const
{
BowVector::const_iterator vit;
std::map<EntryId, double> pairs;
std::map<EntryId, double>::iterator pit;
for(vit = vec.begin(); vit != vec.end(); ++vit)
{
const WordId word_id = vit->first;
const WordValue& qvalue = vit->second;
const IFRow& row = m_ifile[word_id];
// IFRows are sorted in ascending entry_id order
for(auto rit = row.begin(); rit != row.end(); ++rit)
{
const EntryId entry_id = rit->entry_id;
const WordValue& dvalue = rit->word_weight;
if((int)entry_id < max_id || max_id == -1)
{
double value = fabs(qvalue - dvalue) - fabs(qvalue) - fabs(dvalue);
pit = pairs.lower_bound(entry_id);
if(pit != pairs.end() && !(pairs.key_comp()(entry_id, pit->first)))
{
pit->second += value;
}
else
{
pairs.insert(pit,
std::map<EntryId, double>::value_type(entry_id, value));
}
}
} // for each inverted row
} // for each query word
// move to vector
ret.reserve(pairs.size());
for(pit = pairs.begin(); pit != pairs.end(); ++pit)
{
ret.push_back(Result(pit->first, pit->second));
}
// resulting "scores" are now in [-2 best .. 0 worst]
// sort vector in ascending order of score
std::sort(ret.begin(), ret.end());
// (ret is inverted now --the lower the better--)
// cut vector
if(max_results > 0 && (int)ret.size() > max_results)
ret.resize(max_results);
// complete and scale score to [0 worst .. 1 best]
// ||v - w||_{L1} = 2 + Sum(|v_i - w_i| - |v_i| - |w_i|)
// for all i | v_i != 0 and w_i != 0
// (Nister, 2006)
// scaled_||v - w||_{L1} = 1 - 0.5 * ||v - w||_{L1}
QueryResults::iterator qit;
for(qit = ret.begin(); qit != ret.end(); qit++)
qit->Score = -qit->Score/2.0;
}
// --------------------------------------------------------------------------
void Database::queryL2(const BowVector &vec,
QueryResults &ret, int max_results, int max_id) const
{
BowVector::const_iterator vit;
std::map<EntryId, double> pairs;
std::map<EntryId, double>::iterator pit;
//map<EntryId, int> counters;
//map<EntryId, int>::iterator cit;
for(vit = vec.begin(); vit != vec.end(); ++vit)
{
const WordId word_id = vit->first;
const WordValue& qvalue = vit->second;
const IFRow& row = m_ifile[word_id];
// IFRows are sorted in ascending entry_id order
for(auto rit = row.begin(); rit != row.end(); ++rit)
{
const EntryId entry_id = rit->entry_id;
const WordValue& dvalue = rit->word_weight;
if((int)entry_id < max_id || max_id == -1)
{
double value = - qvalue * dvalue; // minus sign for sorting trick
pit = pairs.lower_bound(entry_id);
//cit = counters.lower_bound(entry_id);
if(pit != pairs.end() && !(pairs.key_comp()(entry_id, pit->first)))
{
pit->second += value;
//cit->second += 1;
}
else
{
pairs.insert(pit,
std::map<EntryId, double>::value_type(entry_id, value));
//counters.insert(cit,
// map<EntryId, int>::value_type(entry_id, 1));
}
}
} // for each inverted row
} // for each query word
// move to vector
ret.reserve(pairs.size());
//cit = counters.begin();
for(pit = pairs.begin(); pit != pairs.end(); ++pit)//, ++cit)
{
ret.push_back(Result(pit->first, pit->second));// / cit->second));
}
// resulting "scores" are now in [-1 best .. 0 worst]
// sort vector in ascending order of score
std::sort(ret.begin(), ret.end());
// (ret is inverted now --the lower the better--)
// cut vector
if(max_results > 0 && (int)ret.size() > max_results)
ret.resize(max_results);
// complete and scale score to [0 worst .. 1 best]
// ||v - w||_{L2} = sqrt( 2 - 2 * Sum(v_i * w_i)
// for all i | v_i != 0 and w_i != 0 )
// (Nister, 2006)
QueryResults::iterator qit;
for(qit = ret.begin(); qit != ret.end(); qit++)
{
if(qit->Score <= -1.0) // rounding error
qit->Score = 1.0;
else
qit->Score = 1.0 - sqrt(1.0 + qit->Score); // [0..1]
// the + sign is ok, it is due to - sign in
// value = - qvalue * dvalue
}
}
// --------------------------------------------------------------------------
void Database::queryChiSquare(const BowVector &vec,
QueryResults &ret, int max_results, int max_id) const
{
BowVector::const_iterator vit;
std::map<EntryId, std::pair<double, int> > pairs;
std::map<EntryId, std::pair<double, int> >::iterator pit;
std::map<EntryId, std::pair<double, double> > sums; // < sum vi, sum wi >
std::map<EntryId, std::pair<double, double> >::iterator sit;
// In the current implementation, we suppose vec is not normalized
//map<EntryId, double> expected;
//map<EntryId, double>::iterator eit;
for(vit = vec.begin(); vit != vec.end(); ++vit)
{
const WordId word_id = vit->first;
const WordValue& qvalue = vit->second;
const IFRow& row = m_ifile[word_id];
// IFRows are sorted in ascending entry_id order
for(auto rit = row.begin(); rit != row.end(); ++rit)
{
const EntryId entry_id = rit->entry_id;
const WordValue& dvalue = rit->word_weight;
if((int)entry_id < max_id || max_id == -1)
{
// (v-w)^2/(v+w) - v - w = -4 vw/(v+w)
// we move the 4 out
double value = 0;
if(qvalue + dvalue != 0.0) // words may have weight zero
value = - qvalue * dvalue / (qvalue + dvalue);
pit = pairs.lower_bound(entry_id);
sit = sums.lower_bound(entry_id);
//eit = expected.lower_bound(entry_id);
if(pit != pairs.end() && !(pairs.key_comp()(entry_id, pit->first)))
{
pit->second.first += value;
pit->second.second += 1;
//eit->second += dvalue;
sit->second.first += qvalue;
sit->second.second += dvalue;
}
else
{
pairs.insert(pit,
std::map<EntryId, std::pair<double, int> >::value_type(entry_id,
std::make_pair(value, 1) ));
//expected.insert(eit,
// map<EntryId, double>::value_type(entry_id, dvalue));
sums.insert(sit,
std::map<EntryId, std::pair<double, double> >::value_type(entry_id,
std::make_pair(qvalue, dvalue) ));
}
}
} // for each inverted row
} // for each query word
// move to vector
ret.reserve(pairs.size());
sit = sums.begin();
for(pit = pairs.begin(); pit != pairs.end(); ++pit, ++sit)
{
if(pit->second.second >= MIN_COMMON_WORDS)
{
ret.push_back(Result(pit->first, pit->second.first));
ret.back().nWords = pit->second.second;
ret.back().sumCommonVi = sit->second.first;
ret.back().sumCommonWi = sit->second.second;
ret.back().expectedChiScore =
2 * sit->second.second / (1 + sit->second.second);
}
//ret.push_back(Result(pit->first, pit->second));
}
// resulting "scores" are now in [-2 best .. 0 worst]
// we have to add +2 to the scores to obtain the chi square score
// sort vector in ascending order of score
std::sort(ret.begin(), ret.end());
// (ret is inverted now --the lower the better--)
// cut vector
if(max_results > 0 && (int)ret.size() > max_results)
ret.resize(max_results);
// complete and scale score to [0 worst .. 1 best]
QueryResults::iterator qit;
for(qit = ret.begin(); qit != ret.end(); qit++)
{
// this takes the 4 into account
qit->Score = - 2. * qit->Score; // [0..1]
qit->chiScore = qit->Score;
}
}
// --------------------------------------------------------------------------
void Database::queryKL(const BowVector &vec,
QueryResults &ret, int max_results, int max_id) const
{
BowVector::const_iterator vit;
std::map<EntryId, double> pairs;
std::map<EntryId, double>::iterator pit;
for(vit = vec.begin(); vit != vec.end(); ++vit)
{
const WordId word_id = vit->first;
const WordValue& vi = vit->second;
const IFRow& row = m_ifile[word_id];
// IFRows are sorted in ascending entry_id order
for(auto rit = row.begin(); rit != row.end(); ++rit)
{
const EntryId entry_id = rit->entry_id;
const WordValue& wi = rit->word_weight;
if((int)entry_id < max_id || max_id == -1)
{
double value = 0;
if(vi != 0 && wi != 0) value = vi * log(vi/wi);
pit = pairs.lower_bound(entry_id);
if(pit != pairs.end() && !(pairs.key_comp()(entry_id, pit->first)))
{
pit->second += value;
}
else
{
pairs.insert(pit,
std::map<EntryId, double>::value_type(entry_id, value));
}
}
} // for each inverted row
} // for each query word
// resulting "scores" are now in [-X worst .. 0 best .. X worst]
// but we cannot make sure which ones are better without calculating
// the complete score
// complete scores and move to vector
ret.reserve(pairs.size());
for(pit = pairs.begin(); pit != pairs.end(); ++pit)
{
EntryId eid = pit->first;
double value = 0.0;
for(vit = vec.begin(); vit != vec.end(); ++vit)
{
const WordValue &vi = vit->second;
const IFRow& row = m_ifile[vit->first];
if(vi != 0)
{
if(row.end() == find(row.begin(), row.end(), eid ))
{
value += vi * (log(vi) - GeneralScoring::LOG_EPS);
}
}
}
pit->second += value;
// to vector
ret.push_back(Result(pit->first, pit->second));
}
// real scores are now in [0 best .. X worst]
// sort vector in ascending order
// (scores are inverted now --the lower the better--)
std::sort(ret.begin(), ret.end());
// cut vector
if(max_results > 0 && (int)ret.size() > max_results)
ret.resize(max_results);
// cannot scale scores
}
// --------------------------------------------------------------------------
void Database::queryBhattacharyya(
const BowVector &vec, QueryResults &ret, int max_results, int max_id) const
{
BowVector::const_iterator vit;
//map<EntryId, double> pairs;
//map<EntryId, double>::iterator pit;
std::map<EntryId, std::pair<double, int> > pairs; // <eid, <score, counter> >
std::map<EntryId, std::pair<double, int> >::iterator pit;
for(vit = vec.begin(); vit != vec.end(); ++vit)
{
const WordId word_id = vit->first;
const WordValue& qvalue = vit->second;
const IFRow& row = m_ifile[word_id];
// IFRows are sorted in ascending entry_id order
for(auto rit = row.begin(); rit != row.end(); ++rit)
{
const EntryId entry_id = rit->entry_id;
const WordValue& dvalue = rit->word_weight;
if((int)entry_id < max_id || max_id == -1)
{
double value = sqrt(qvalue * dvalue);
pit = pairs.lower_bound(entry_id);
if(pit != pairs.end() && !(pairs.key_comp()(entry_id, pit->first)))
{
pit->second.first += value;
pit->second.second += 1;
}
else
{
pairs.insert(pit,
std::map<EntryId, std::pair<double, int> >::value_type(entry_id,
std::make_pair(value, 1)));
}
}
} // for each inverted row
} // for each query word
// move to vector
ret.reserve(pairs.size());
for(pit = pairs.begin(); pit != pairs.end(); ++pit)
{
if(pit->second.second >= MIN_COMMON_WORDS)
{
ret.push_back(Result(pit->first, pit->second.first));
ret.back().nWords = pit->second.second;
ret.back().bhatScore = pit->second.first;
}
}
// scores are already in [0..1]
// sort vector in descending order
std::sort(ret.begin(), ret.end(), Result::gt);
// cut vector
if(max_results > 0 && (int)ret.size() > max_results)
ret.resize(max_results);
}
// ---------------------------------------------------------------------------
void Database::queryDotProduct(
const BowVector &vec, QueryResults &ret, int max_results, int max_id) const
{
BowVector::const_iterator vit;
std::map<EntryId, double> pairs;
std::map<EntryId, double>::iterator pit;
for(vit = vec.begin(); vit != vec.end(); ++vit)
{
const WordId word_id = vit->first;
const WordValue& qvalue = vit->second;
const IFRow& row = m_ifile[word_id];
// IFRows are sorted in ascending entry_id order
for(auto rit = row.begin(); rit != row.end(); ++rit)
{
const EntryId entry_id = rit->entry_id;
const WordValue& dvalue = rit->word_weight;
if((int)entry_id < max_id || max_id == -1)
{
double value;
if(this->m_voc->getWeightingType() == BINARY)
value = 1;
else
value = qvalue * dvalue;
pit = pairs.lower_bound(entry_id);
if(pit != pairs.end() && !(pairs.key_comp()(entry_id, pit->first)))
{
pit->second += value;
}
else
{
pairs.insert(pit,
std::map<EntryId, double>::value_type(entry_id, value));
}
}
} // for each inverted row
} // for each query word
// move to vector
ret.reserve(pairs.size());
for(pit = pairs.begin(); pit != pairs.end(); ++pit)
{
ret.push_back(Result(pit->first, pit->second));
}
// scores are the greater the better
// sort vector in descending order
std::sort(ret.begin(), ret.end(), Result::gt);
// cut vector
if(max_results > 0 && (int)ret.size() > max_results)
ret.resize(max_results);
// these scores cannot be scaled
}
// ---------------------------------------------------------------------------
const FeatureVector& Database::retrieveFeatures
(EntryId id) const
{
assert(id < size());
return m_dfile[id];
}
// --------------------------------------------------------------------------
void Database::save(const std::string &filename) const
{
cv::FileStorage fs(filename.c_str(), cv::FileStorage::WRITE);
if(!fs.isOpened()) throw std::string("Could not open file ") + filename;
save(fs);
}
// --------------------------------------------------------------------------
void Database::save(cv::FileStorage &fs,
const std::string &name) const
{
// Format YAML:
// vocabulary { ... see TemplatedVocabulary::save }
// database
// {
// nEntries:
// usingDI:
// diLevels:
// invertedIndex
// [
// [
// {
// imageId:
// weight:
// }
// ]
// ]
// directIndex
// [
// [
// {
// nodeId:
// features: [ ]
// }
// ]
// ]
// invertedIndex[i] is for the i-th word
// directIndex[i] is for the i-th entry
// directIndex may be empty if not using direct index
//
// imageId's and nodeId's must be stored in ascending order
// (according to the construction of the indexes)
m_voc->save(fs);
fs << name << "{";
fs << "nEntries" << m_nentries;
fs << "usingDI" << (m_use_di ? 1 : 0);
fs << "diLevels" << m_dilevels;
fs << "invertedIndex" << "[";
for(auto iit = m_ifile.begin(); iit != m_ifile.end(); ++iit)
{
fs << "["; // word of IF
for(auto irit = iit->begin(); irit != iit->end(); ++irit)
{
fs << "{:"
<< "imageId" << (int)irit->entry_id
<< "weight" << irit->word_weight
<< "}";
}
fs << "]"; // word of IF
}
fs << "]"; // invertedIndex
fs << "directIndex" << "[";
for(auto dit = m_dfile.begin(); dit != m_dfile.end(); ++dit)
{
fs << "["; // entry of DF
for(auto drit = dit->begin(); drit != dit->end(); ++drit)
{
NodeId nid = drit->first;
const std::vector<unsigned int>& features = drit->second;
// save info of last_nid
fs << "{";
fs << "nodeId" << (int)nid;
// msvc++ 2010 with opencv 2.3.1 does not allow FileStorage::operator<<
// with vectors of unsigned int
fs << "features" << "["
<< *(const std::vector<int>*)(&features) << "]";
fs << "}";
}
fs << "]"; // entry of DF
}
fs << "]"; // directIndex
fs << "}"; // database
}
// --------------------------------------------------------------------------
void Database::load(const std::string &filename)
{
cv::FileStorage fs(filename.c_str(), cv::FileStorage::READ);
if(!fs.isOpened()) throw std::string("Could not open file ") + filename;
load(fs);
}
// --------------------------------------------------------------------------
void Database::load(const cv::FileStorage &fs,
const std::string &name)
{
// load voc first
// subclasses must instantiate m_voc before calling this ::load
if(!m_voc) m_voc = new Vocabulary;
m_voc->load(fs);
// load database now
clear(); // resizes inverted file
cv::FileNode fdb = fs[name];
m_nentries = (int)fdb["nEntries"];
m_use_di = (int)fdb["usingDI"] != 0;
m_dilevels = (int)fdb["diLevels"];
cv::FileNode fn = fdb["invertedIndex"];
for(WordId wid = 0; wid < fn.size(); ++wid)
{
cv::FileNode fw = fn[wid];
for(unsigned int i = 0; i < fw.size(); ++i)
{
EntryId eid = (int)fw[i]["imageId"];
WordValue v = fw[i]["weight"];
m_ifile[wid].push_back(IFPair(eid, v));
}
}
if(m_use_di)
{
fn = fdb["directIndex"];
m_dfile.resize(fn.size());
assert(m_nentries == (int)fn.size());
FeatureVector::iterator dit;
for(EntryId eid = 0; eid < fn.size(); ++eid)
{
cv::FileNode fe = fn[eid];
m_dfile[eid].clear();
for(unsigned int i = 0; i < fe.size(); ++i)
{
NodeId nid = (int)fe[i]["nodeId"];
dit = m_dfile[eid].insert(m_dfile[eid].end(),
make_pair(nid, std::vector<unsigned int>() ));
// this failed to compile with some opencv versions (2.3.1)
//fe[i]["features"] >> dit->second;
// this was ok until OpenCV 2.4.1
//std::vector<int> aux;
//fe[i]["features"] >> aux; // OpenCV < 2.4.1
//dit->second.resize(aux.size());
//std::copy(aux.begin(), aux.end(), dit->second.begin());
cv::FileNode ff = fe[i]["features"][0];
dit->second.reserve(ff.size());
cv::FileNodeIterator ffit;
for(ffit = ff.begin(); ffit != ff.end(); ++ffit)
{
dit->second.push_back((int)*ffit);
}
}
} // for each entry
} // if use_id
}
std::ostream& operator<<(std::ostream &os,
const Database &db)
{
os << "Database: Entries = " << db.size() << ", "
"Using direct index = " << (db.usingDirectIndex() ? "yes" : "no");
if(db.usingDirectIndex())
os << ", Direct index levels = " << db.getDirectIndexLevels();
os << ". " << *db.getVocabulary();
return os;
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/kbytes/DBow3.git
git@gitee.com:kbytes/DBow3.git
kbytes
DBow3
DBow3
master

搜索帮助