17 #ifndef __D_T_TEMPLATED_VOCABULARY__ 18 #define __D_T_TEMPLATED_VOCABULARY__ 27 #include <opencv2/core/core.hpp> 34 #include "../DUtils/Random.h" 42 template<
class TDescriptor,
class F>
96 (
const std::vector<std::vector<TDescriptor> > &training_features);
106 (
const std::vector<std::vector<TDescriptor> > &training_features,
115 (
const std::vector<std::vector<TDescriptor> > &training_features,
122 virtual inline unsigned int size()
const;
128 virtual inline bool empty()
const;
135 virtual void transform(
const std::vector<TDescriptor>& features,
BowVector &v)
145 virtual void transform(
const std::vector<TDescriptor>& features,
153 virtual WordId transform(
const TDescriptor& feature)
const;
171 virtual NodeId getParentNode(
WordId wid,
int levelsup)
const;
179 void getWordsFromNode(
NodeId nid, std::vector<WordId> &words)
const;
197 float getEffectiveLevels()
const;
204 virtual inline TDescriptor getWord(
WordId wid)
const;
241 bool loadFromTextFile(
const std::string &filename);
247 void saveToTextFile(
const std::string &filename)
const;
253 bool loadFromBinFile(
const std::string &filename);
260 void saveToBinFile(
const std::string &filename)
const;
266 void save(
const std::string &filename)
const;
272 void load(
const std::string &filename);
278 virtual void save(cv::FileStorage &fs,
279 const std::string &name =
"vocabulary")
const;
287 virtual void load(
const cv::FileStorage &fs,
288 const std::string &name =
"vocabulary");
302 virtual int stopWords(
double minWeight);
329 Node(): id(0), weight(0), parent(0), word_id(0){}
335 Node(
NodeId _id): id(_id), weight(0), parent(0), word_id(0){}
341 inline bool isLeaf()
const {
return children.empty(); }
349 void createScoringObject();
357 const vector<vector<TDescriptor> > &training_features,
358 vector<pDescriptor> &features)
const;
368 virtual void transform(
const TDescriptor &feature,
376 virtual void transform(
const TDescriptor &feature,
WordId &
id)
const;
385 void HKmeansStep(
NodeId parent_id,
const vector<pDescriptor> &descriptors,
393 virtual void initiateClusters(
const vector<pDescriptor> &descriptors,
394 vector<TDescriptor> &clusters)
const;
402 void initiateClustersKMpp(
const vector<pDescriptor> &descriptors,
403 vector<TDescriptor> &clusters)
const;
416 void setNodeWeights(
const vector<vector<TDescriptor> > &features);
446 template<
class TDescriptor,
class F>
449 : m_k(k), m_L(L), m_weighting(weighting), m_scoring(scoring),
450 m_scoring_object(NULL)
452 createScoringObject();
457 template<
class TDescriptor,
class F>
459 (
const std::string &filename): m_scoring_object(NULL)
466 template<
class TDescriptor,
class F>
468 (
const char *filename): m_scoring_object(NULL)
475 template<
class TDescriptor,
class F>
478 delete m_scoring_object;
479 m_scoring_object = NULL;
484 m_scoring_object =
new L1Scoring;
488 m_scoring_object =
new L2Scoring;
492 m_scoring_object =
new ChiSquareScoring;
496 m_scoring_object =
new KLScoring;
500 m_scoring_object =
new BhattacharyyaScoring;
504 m_scoring_object =
new DotProductScoring;
512 template<
class TDescriptor,
class F>
516 createScoringObject();
521 template<
class TDescriptor,
class F>
524 this->m_weighting = type;
529 template<
class TDescriptor,
class F>
532 : m_scoring_object(NULL)
539 template<
class TDescriptor,
class F>
547 template<
class TDescriptor,
class F>
570 template<
class TDescriptor,
class F>
572 const std::vector<std::vector<TDescriptor> > &training_features)
579 (int)((pow((
double)
m_k, (
double)
m_L + 1) - 1)/(m_k - 1));
581 m_nodes.reserve(expected_nodes);
584 vector<pDescriptor> features;
604 template<
class TDescriptor,
class F>
606 const std::vector<std::vector<TDescriptor> > &training_features,
612 create(training_features);
617 template<
class TDescriptor,
class F>
619 const std::vector<std::vector<TDescriptor> > &training_features,
628 create(training_features);
633 template<
class TDescriptor,
class F>
635 const vector<vector<TDescriptor> > &training_features,
636 vector<pDescriptor> &features)
const 640 typename vector<vector<TDescriptor> >::const_iterator vvit;
641 typename vector<TDescriptor>::const_iterator vit;
642 for(vvit = training_features.begin(); vvit != training_features.end(); ++vvit)
644 features.reserve(features.size() + vvit->size());
645 for(vit = vvit->begin(); vit != vvit->end(); ++vit)
647 features.push_back(&(*vit));
654 template<
class TDescriptor,
class F>
656 const vector<pDescriptor> &descriptors,
int current_level)
658 if(descriptors.empty())
return;
661 vector<TDescriptor> clusters;
662 vector<vector<unsigned int> > groups;
665 clusters.reserve(
m_k);
673 if((
int)descriptors.size() <=
m_k)
676 groups.resize(descriptors.size());
678 for(
unsigned int i = 0; i < descriptors.size(); i++)
680 groups[i].push_back(i);
681 clusters.push_back(*descriptors[i]);
688 bool first_time =
true;
692 vector<int> last_association, current_association;
707 for(
unsigned int c = 0; c < clusters.size(); ++c)
709 vector<pDescriptor> cluster_descriptors;
710 cluster_descriptors.reserve(groups[c].
size());
722 vector<unsigned int>::const_iterator vit;
723 for(vit = groups[c].begin(); vit != groups[c].end(); ++vit)
725 cluster_descriptors.push_back(descriptors[*vit]);
729 F::meanValue(cluster_descriptors, clusters[c]);
738 groups.resize(clusters.size(), vector<unsigned int>());
739 current_association.resize(descriptors.size());
743 typename vector<pDescriptor>::const_iterator fit;
745 for(fit = descriptors.begin(); fit != descriptors.end(); ++fit)
747 double best_dist = F::distance(*(*fit), clusters[0]);
748 unsigned int icluster = 0;
750 for(
unsigned int c = 1; c < clusters.size(); ++c)
752 double dist = F::distance(*(*fit), clusters[c]);
762 groups[icluster].push_back(fit - descriptors.begin());
763 current_association[ fit - descriptors.begin() ] = icluster;
778 for(
unsigned int i = 0; i < current_association.size(); i++)
780 if(current_association[i] != last_association[i]){
790 last_association = current_association;
799 for(
unsigned int i = 0; i < clusters.size(); ++i)
803 m_nodes.back().descriptor = clusters[i];
804 m_nodes.back().parent = parent_id;
805 m_nodes[parent_id].children.push_back(
id);
809 if(current_level <
m_L)
812 const vector<NodeId> &children_ids =
m_nodes[parent_id].children;
813 for(
unsigned int i = 0; i < clusters.size(); ++i)
815 NodeId id = children_ids[i];
817 vector<pDescriptor> child_features;
818 child_features.reserve(groups[i].
size());
820 vector<unsigned int>::const_iterator vit;
821 for(vit = groups[i].begin(); vit != groups[i].end(); ++vit)
823 child_features.push_back(descriptors[*vit]);
826 if(child_features.size() > 1)
828 HKmeansStep(
id, child_features, current_level + 1);
836 template<
class TDescriptor,
class F>
838 (
const vector<pDescriptor> &descriptors, vector<TDescriptor> &clusters)
const 845 template<
class TDescriptor,
class F>
847 const vector<pDescriptor> &pfeatures, vector<TDescriptor> &clusters)
const 863 clusters.reserve(
m_k);
864 vector<double> min_dists(pfeatures.size(), std::numeric_limits<double>::max());
871 clusters.push_back(*pfeatures[ifeature]);
874 typename vector<pDescriptor>::const_iterator fit;
875 vector<double>::iterator dit;
876 dit = min_dists.begin();
877 for(fit = pfeatures.begin(); fit != pfeatures.end(); ++fit, ++dit)
879 *dit = F::distance(*(*fit), clusters.back());
882 while((
int)clusters.size() <
m_k)
885 dit = min_dists.begin();
886 for(fit = pfeatures.begin(); fit != pfeatures.end(); ++fit, ++dit)
890 double dist = F::distance(*(*fit), clusters.back());
891 if(dist < *dit) *dit = dist;
896 double dist_sum = std::accumulate(min_dists.begin(), min_dists.end(), 0.0);
903 cut_d = DUtils::Random::RandomValue<double>(0, dist_sum);
904 }
while(cut_d == 0.0);
907 for(dit = min_dists.begin(); dit != min_dists.end(); ++dit)
910 if(d_up_now >= cut_d)
break;
913 if(dit == min_dists.end())
914 ifeature = pfeatures.size()-1;
916 ifeature = dit - min_dists.begin();
918 clusters.push_back(*pfeatures[ifeature]);
930 template<
class TDescriptor,
class F>
939 typename vector<Node>::iterator nit;
942 for(++nit; nit !=
m_nodes.end(); ++nit)
955 template<
class TDescriptor,
class F>
957 (
const vector<vector<TDescriptor> > &training_features)
959 const unsigned int NWords =
m_words.size();
960 const unsigned int NDocs = training_features.size();
965 for(
unsigned int i = 0; i < NWords; i++)
975 vector<unsigned int> Ni(NWords, 0);
976 vector<bool> counted(NWords,
false);
978 typename vector<vector<TDescriptor> >::const_iterator mit;
979 typename vector<TDescriptor>::const_iterator fit;
981 for(mit = training_features.begin(); mit != training_features.end(); ++mit)
983 fill(counted.begin(), counted.end(),
false);
985 for(fit = mit->begin(); fit < mit->end(); ++fit)
990 if(!counted[word_id])
993 counted[word_id] =
true;
999 for(
unsigned int i = 0; i < NWords; i++)
1003 m_words[i]->weight = log((
double)NDocs / (
double)Ni[i]);
1013 template<
class TDescriptor,
class F>
1021 template<
class TDescriptor,
class F>
1029 template<
class TDescriptor,
class F>
1033 typename std::vector<Node*>::const_iterator wit;
1036 const Node *p = *wit;
1041 return (
float)((double)sum / (
double)
m_words.size());
1046 template<
class TDescriptor,
class F>
1049 return m_words[wid]->descriptor;
1054 template<
class TDescriptor,
class F>
1062 template<
class TDescriptor,
class F>
1064 (
const TDescriptor& feature)
const 1078 template<
class TDescriptor,
class F>
1080 const std::vector<TDescriptor>& features,
BowVector &v)
const 1093 typename vector<TDescriptor>::const_iterator fit;
1097 for(fit = features.begin(); fit < features.end(); ++fit)
1109 if(!v.empty() && !must)
1112 const double nd = v.size();
1113 for(BowVector::iterator vit = v.begin(); vit != v.end(); vit++)
1120 for(fit = features.begin(); fit < features.end(); ++fit)
1139 template<
class TDescriptor,
class F>
1141 const std::vector<TDescriptor>& features,
1156 typename vector<TDescriptor>::const_iterator fit;
1160 unsigned int i_feature = 0;
1161 for(fit = features.begin(); fit < features.end(); ++fit, ++i_feature)
1177 if(!v.empty() && !must)
1180 const double nd = v.size();
1181 for(BowVector::iterator vit = v.begin(); vit != v.end(); vit++)
1188 unsigned int i_feature = 0;
1189 for(fit = features.begin(); fit < features.end(); ++fit, ++i_feature)
1211 template<
class TDescriptor,
class F>
1220 template<
class TDescriptor,
class F>
1222 (
const TDescriptor &feature,
WordId &
id)
const 1230 template<
class TDescriptor,
class F>
1235 vector<NodeId> nodes;
1236 typename vector<NodeId>::const_iterator nit;
1239 const int nid_level =
m_L - levelsup;
1240 if(nid_level <= 0 && nid != NULL) *nid = 0;
1243 int current_level = 0;
1248 nodes =
m_nodes[final_id].children;
1249 final_id = nodes[0];
1251 double best_d = F::distance(feature,
m_nodes[final_id].descriptor);
1253 for(nit = nodes.begin() + 1; nit != nodes.end(); ++nit)
1256 double d = F::distance(feature,
m_nodes[
id].descriptor);
1264 if(nid != NULL && current_level == nid_level)
1267 }
while( !
m_nodes[final_id].isLeaf() );
1270 word_id =
m_nodes[final_id].word_id;
1271 weight =
m_nodes[final_id].weight;
1276 template<
class TDescriptor,
class F>
1281 while(levelsup > 0 && ret != 0)
1291 template<
class TDescriptor,
class F>
1293 (
NodeId nid, std::vector<WordId> &words)
const 1299 words.push_back(
m_nodes[nid].word_id);
1305 vector<NodeId> parents;
1306 parents.push_back(nid);
1308 while(!parents.empty())
1310 NodeId parentid = parents.back();
1313 const vector<NodeId> &child_ids =
m_nodes[parentid].children;
1314 vector<NodeId>::const_iterator cit;
1316 for(cit = child_ids.begin(); cit != child_ids.end(); ++cit)
1321 words.push_back(child_node.
word_id);
1323 parents.push_back(*cit);
1332 template<
class TDescriptor,
class F>
1336 typename vector<Node*>::iterator wit;
1339 if((*wit)->weight < minWeight)
1350 template<
class TDescriptor,
class F>
1354 f.open(filename.c_str());
1361 std::cerr <<
"An error occured while opening the input stream." << endl;
1378 if(m_k<0 || m_k>20 || m_L<1 || m_L>10 || n1<0 || n1>5 || n2<0 || n2>3)
1380 std::cerr <<
"Vocabulary loading failure: This is not a correct text file!" << endl;
1389 int expected_nodes =
1390 (int)((pow((
double)m_k, (
double)m_L + 1) - 1)/(m_k - 1));
1391 m_nodes.reserve(expected_nodes);
1393 m_words.reserve(pow((
double)m_k, (
double)m_L + 1));
1401 stringstream ssnode;
1411 m_nodes[pid].children.push_back(nid);
1417 for(
int iD=0;iD<F::L;iD++)
1421 ssd << sElement <<
" ";
1423 F::fromString(
m_nodes[nid].descriptor, ssd.str());
1425 ssnode >>
m_nodes[nid].weight;
1437 m_nodes[nid].children.reserve(m_k);
1447 template<
class TDescriptor,
class F>
1451 f.open(filename.c_str(),ios_base::out);
1453 for(
size_t i=1; i<
m_nodes.size()-1;i++)
1472 template<
class TDescriptor,
class F>
1476 f.open(filename.c_str());
1483 std::cerr <<
"An error occured while opening the input stream." << endl;
1490 f.read((
char*)&
m_k,
sizeof(
m_k));
1491 f.read((
char*)&
m_L,
sizeof(
m_L));
1493 f.read((
char*)&n1,
sizeof(n1));
1494 f.read((
char*)&n2,
sizeof(n2));
1496 if(m_k<0 || m_k>20 || m_L<1 || m_L>10 || n1<0 || n1>5 || n2<0 || n2>3)
1498 std::cerr <<
"Vocabulary loading failure: This is not a correct Binary file!" << endl;
1507 int expected_nodes =
1508 (int)((pow((
double)
m_k, (
double)
m_L + 1) - 1)/(m_k - 1));
1509 m_nodes.reserve(expected_nodes);
1510 m_words.reserve(pow((
double)m_k, (
double)
m_L + 1));
1514 while((!f.eof()) && (
m_nodes.size()<(
unsigned int)expected_nodes) )
1520 f.read((
char*)&pid,
sizeof(pid));
1522 m_nodes[pid].children.push_back(nid);
1524 unsigned char nIsLeafuc;
1525 f.read((
char*)&nIsLeafuc,
sizeof(nIsLeafuc));
1527 unsigned char array[F::L];
1528 f.read((
char*)array,(
long)F::L);
1529 m_nodes[nid].descriptor.create(1, F::L, CV_8U);
1530 F::fromArray8U(
m_nodes[nid].descriptor,(
unsigned char *)array);
1541 m_nodes[nid].children.reserve(m_k);
1550 template<
class TDescriptor,
class F>
1554 f.open(filename.c_str(),ios_base::out);
1555 f.write((
const char*)&
m_k,
sizeof(
m_k));
1556 f.write((
const char*)&
m_L,
sizeof(
m_L));
1559 unsigned int nbiter=
m_nodes.size();
1561 unsigned char one=1;
1562 unsigned char zero=0;
1564 for(
size_t i=1; i<nbiter-1;i++)
1567 f.write((
const char*)& node.
parent ,
sizeof( node.
parent ));
1569 f.write((
const char*)& one ,
sizeof( one ));
1571 f.write((
const char*)& zero ,
sizeof( zero ));
1572 unsigned char array[F::L];
1573 F::toArray8U(node.
descriptor,(
unsigned char *)array);
1574 f.write((
char*)array,(
long)F::L);
1575 f.write((
const char*)& node.
weight ,
sizeof( node.
weight ));
1582 template<
class TDescriptor,
class F>
1585 cv::FileStorage fs(filename.c_str(), cv::FileStorage::WRITE);
1586 if(!fs.isOpened())
throw string(
"Could not open file ") + filename;
1593 template<
class TDescriptor,
class F>
1596 cv::FileStorage fs(filename.c_str(), cv::FileStorage::READ);
1597 if(!fs.isOpened())
throw string(
"Could not open file ") + filename;
1604 template<
class TDescriptor,
class F>
1606 const std::string &name)
const 1644 f <<
"nodes" <<
"[";
1645 vector<NodeId> parents, children;
1646 vector<NodeId>::const_iterator pit;
1648 parents.push_back(0);
1650 while(!parents.empty())
1652 NodeId pid = parents.back();
1658 for(pit = children.begin(); pit != children.end(); pit++)
1664 f <<
"nodeId" << (int)child.
id;
1665 f <<
"parentId" << (
int)pid;
1666 f <<
"weight" << (double)child.
weight;
1667 f <<
"descriptor" << F::toString(child.
descriptor);
1673 parents.push_back(*pit);
1681 f <<
"words" <<
"[";
1683 typename vector<Node*>::const_iterator wit;
1688 f <<
"wordId" << (int)
id;
1689 f <<
"nodeId" << (int)(*wit)->id;
1701 template<
class TDescriptor,
class F>
1703 const std::string &name)
1708 cv::FileNode fvoc = fs[name];
1710 m_k = (int)fvoc[
"k"];
1711 m_L = (int)fvoc[
"L"];
1718 cv::FileNode fn = fvoc[
"nodes"];
1720 m_nodes.resize(fn.size() + 1);
1723 for(
unsigned int i = 0; i < fn.size(); ++i)
1725 NodeId nid = (int)fn[i][
"nodeId"];
1726 NodeId pid = (int)fn[i][
"parentId"];
1728 string d = (string)fn[i][
"descriptor"];
1733 m_nodes[pid].children.push_back(nid);
1735 F::fromString(
m_nodes[nid].descriptor, d);
1743 for(
unsigned int i = 0; i < fn.size(); ++i)
1745 NodeId wid = (int)fn[i][
"wordId"];
1746 NodeId nid = (int)fn[i][
"nodeId"];
1760 template<
class TDescriptor,
class F>
1766 <<
", Weighting = ";
1770 case TF_IDF: os <<
"tf-idf";
break;
1771 case TF: os <<
"tf";
break;
1772 case IDF: os <<
"idf";
break;
1773 case BINARY: os <<
"binary";
break;
1776 os <<
", Scoring = ";
1779 case L1_NORM: os <<
"L1-norm";
break;
1780 case L2_NORM: os <<
"L2-norm";
break;
1781 case CHI_SQUARE: os <<
"Chi square distance";
break;
1782 case KL: os <<
"KL-divergence";
break;
1783 case BHATTACHARYYA: os <<
"Bhattacharyya coefficient";
break;
1787 os <<
", Number of words = " << voc.
size();
double score(const BowVector &a, const BowVector &b) const
virtual void initiateClusters(const vector< pDescriptor > &descriptors, vector< TDescriptor > &clusters) const
std::vector< Node > m_nodes
Tree nodes.
ScoringType getScoringType() const
void getFeatures(const vector< vector< TDescriptor > > &training_features, vector< pDescriptor > &features) const
void saveToBinFile(const std::string &filename) const
WeightingType
Weighting type.
virtual TDescriptor getWord(WordId wid) const
WeightingType m_weighting
Weighting method.
static void SeedRandOnce()
void load(const std::string &filename)
TDescriptor descriptor
Node descriptor.
void load(Archive &ar,::cv::Mat &m, const unsigned int version)
float getEffectiveLevels() const
WordValue weight
Weight if the node is a word.
int getDepthLevels() const
void saveToTextFile(const std::string &filename) const
void getWordsFromNode(NodeId nid, std::vector< WordId > &words) const
virtual NodeId getParentNode(WordId wid, int levelsup) const
void addWeight(WordId id, WordValue v)
void initiateClustersKMpp(const vector< pDescriptor > &descriptors, vector< TDescriptor > &clusters) const
GeneralScoring * m_scoring_object
Object for computing scores.
virtual double score(const BowVector &v, const BowVector &w) const =0
void HKmeansStep(NodeId parent_id, const vector< pDescriptor > &descriptors, int current_level)
virtual bool mustNormalize(LNorm &norm) const =0
void normalize(LNorm norm_type)
vector< NodeId > children
Children.
virtual void transform(const std::vector< TDescriptor > &features, BowVector &v) const
Base class of scoring functions.
NodeId parent
Parent node (undefined in case of root)
virtual unsigned int size() const
WeightingType getWeightingType() const
ScoringType m_scoring
Scoring method.
LNorm
L-norms for normalization.
std::vector< Node * > m_words
bool loadFromTextFile(const std::string &filename)
Vector of words to represent images.
int getBranchingFactor() const
double WordValue
Value of a word.
Vector of nodes with indexes of local features.
void createScoringObject()
static int RandomInt(int min, int max)
virtual bool empty() const
unsigned int WordId
Id of words.
std::ostream & operator<<(std::ostream &out, const BowVector &v)
TFSIMD_FORCE_INLINE const tfScalar & w() const
void addIfNotExist(WordId id, WordValue v)
const TDescriptor * pDescriptor
Pointer to descriptor.
void save(const std::string &filename) const
bool loadFromBinFile(const std::string &filename)
void save(Archive &ar, const ::cv::Mat &m, const unsigned int file_version)
WordId word_id
Word id if the node is a word.
virtual int stopWords(double minWeight)
virtual void create(const std::vector< std::vector< TDescriptor > > &training_features)
virtual WordValue getWordWeight(WordId wid) const
virtual ~TemplatedVocabulary()
void setNodeWeights(const vector< vector< TDescriptor > > &features)
void addFeature(NodeId id, unsigned int i_feature)
unsigned int NodeId
Id of nodes in the vocabulary treee.