FeatureLearningClusterBased.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #include "FeatureLearningClusterBased.h"
  2. #include <iostream>
  3. #include <core/image/FilterT.h>
  4. #include <core/image/CircleT.h>
  5. #include <core/image/Convert.h>
  6. #include <core/vector/VectorT.h>
  7. // #include <vislearning/baselib/ICETools.h>
  8. //
  9. #include <vislearning/features/localfeatures/LFonHSG.h>
  10. #include <vislearning/features/localfeatures/LFColorSande.h>
  11. #include <vislearning/features/localfeatures/LFColorWeijer.h>
  12. #include <vislearning/features/localfeatures/LFReadCache.h>
  13. #include <vislearning/features/localfeatures/LFWriteCache.h>
  14. //
  15. #include <vislearning/math/cluster/KMeans.h>
  16. #include <vislearning/math/cluster/GMM.h>
  17. using namespace std;
  18. using namespace NICE;
  19. using namespace OBJREC;
  20. //**********************************************
  21. //
  22. // PROTECTED METHODS
  23. //
  24. //**********************************************
  25. void FeatureLearningClusterBased::setClusterAlgo( const std::string & _clusterAlgoString, const bool & _setForInitialTraining)
  26. {
  27. //be careful with previously allocated memory
  28. if (this->clusterAlgo != NULL)
  29. delete clusterAlgo;
  30. if (_clusterAlgoString.compare("kmeans") == 0)
  31. {
  32. if ( _setForInitialTraining )
  33. this->clusterAlgo = new OBJREC::KMeans(this->initialNumberOfClusters);
  34. else
  35. this->clusterAlgo = new OBJREC::KMeans(this->numberOfClustersForNewImage);
  36. }
  37. else if (_clusterAlgoString.compare("GMM") == 0)
  38. {
  39. if ( _setForInitialTraining )
  40. this->clusterAlgo = new OBJREC::GMM(this->conf, this->initialNumberOfClusters);
  41. else
  42. this->clusterAlgo = new OBJREC::GMM(this->conf, this->numberOfClustersForNewImage);
  43. }
  44. else
  45. {
  46. std::cerr << "Unknown cluster algorithm selected, use k-means instead" << std::endl;
  47. if ( _setForInitialTraining )
  48. this->clusterAlgo = new OBJREC::KMeans(this->initialNumberOfClusters);
  49. else
  50. this->clusterAlgo = new OBJREC::KMeans(this->numberOfClustersForNewImage);
  51. }
  52. }
  53. //**********************************************
  54. //
  55. // PUBLIC METHODS
  56. //
  57. //**********************************************
  58. FeatureLearningClusterBased::FeatureLearningClusterBased ( const Config *_conf,
  59. const MultiDataset *_md, const std::string & _section )
  60. : FeatureLearningPrototypes ( _conf, _md, _section )
  61. {
  62. // define the number of clusters we want to compute for an unseen image
  63. numberOfClustersForNewImage = conf->gI(section, "numberOfClustersForNewImage", 10);
  64. //**********************************************
  65. //
  66. // SET UP VARIABLES AND METHODS
  67. // - FEATURE TYPE
  68. // - CLUSTERING ALGO
  69. // - DISTANCE FUNCTION
  70. // - ...
  71. //
  72. //**********************************************
  73. //run the training to initially compute a codebook and stuff like that
  74. // this->train( _md );
  75. // define the clustering algorithm to be used
  76. std::string clusterAlgoString = conf->gS(section, "clusterAlgo", "kmeans");
  77. this->setClusterAlgo( clusterAlgoString, false /*set cluster algo for feature learning*/ );
  78. }
  79. FeatureLearningClusterBased::~FeatureLearningClusterBased()
  80. {
  81. // clean-up
  82. }
  83. void FeatureLearningClusterBased::learnNewFeatures ( const std::string & _filename )
  84. {
  85. NICE::ColorImage img( _filename );
  86. int xsize ( img.width() );
  87. int ysize ( img.height() );
  88. //variables to store feature information
  89. NICE::VVector newFeatures;
  90. NICE::VVector cfeatures;
  91. NICE::VVector positions;
  92. //compute features
  93. std::cerr << " EXTRACT FEATURES FROM UNSEEN IMAGE" << std::endl;
  94. Globals::setCurrentImgFN ( _filename );
  95. featureExtractor->extractFeatures ( img, newFeatures, positions );
  96. //store feature information in larger data structure
  97. for ( NICE::VVector::iterator i = newFeatures.begin();
  98. i != newFeatures.end();
  99. i++)
  100. {
  101. //normalization :)
  102. i->normalizeL1();
  103. }
  104. //cluster features
  105. std::cerr << " CLUSTER FEATURES FROM UNSEEN IMAGE" << std::endl;
  106. NICE::VVector prototypesForNewImage;
  107. std::vector< double > weights;
  108. std::vector< int > assignment;
  109. clusterAlgo->cluster ( newFeatures, prototypesForNewImage, weights, assignment);
  110. if ( b_evaluationWhileFeatureLearning )
  111. {
  112. //visualize new clusters
  113. int tmpProtCnt ( 0 );
  114. for (NICE::VVector::const_iterator protIt = prototypesForNewImage.begin(); protIt != prototypesForNewImage.end(); protIt++, tmpProtCnt++)
  115. {
  116. double distToNewCluster ( std::numeric_limits<double>::max() );
  117. int indexOfMostSimFeat( 0 );
  118. double tmpDist;
  119. int tmpCnt ( 0 );
  120. for ( NICE::VVector::iterator i = newFeatures.begin();
  121. i != newFeatures.end();
  122. i++, tmpCnt++)
  123. {
  124. tmpDist = this->distFunction->calculate( *i, *protIt );
  125. if ( tmpDist < distToNewCluster )
  126. {
  127. distToNewCluster = tmpDist;
  128. indexOfMostSimFeat = tmpCnt;
  129. }
  130. }
  131. int posX ( ( positions[indexOfMostSimFeat] ) [0] );
  132. int posY ( ( positions[indexOfMostSimFeat] ) [1] );
  133. NICE::Circle circ ( Coord( posX, posY), 10 /* radius*/, Color(200,0,255) );
  134. img.draw(circ);
  135. }
  136. //draw features most similar to old clusters
  137. tmpProtCnt = 0;
  138. for (NICE::VVector::const_iterator protIt = prototypes.begin(); protIt != prototypes.end(); protIt++, tmpProtCnt++)
  139. {
  140. double distToNewCluster ( std::numeric_limits<double>::max() );
  141. int indexOfMostSimFeat( 0 );
  142. double tmpDist;
  143. int tmpCnt ( 0 );
  144. for ( NICE::VVector::iterator i = newFeatures.begin();
  145. i != newFeatures.end();
  146. i++, tmpCnt++)
  147. {
  148. tmpDist = this->distFunction->calculate( *i, *protIt );
  149. if ( tmpDist < distToNewCluster )
  150. {
  151. distToNewCluster = tmpDist;
  152. indexOfMostSimFeat = tmpCnt;
  153. }
  154. }
  155. int posX ( ( positions[indexOfMostSimFeat] ) [0] );
  156. int posY ( ( positions[indexOfMostSimFeat] ) [1] );
  157. NICE::Circle circ ( Coord( posX, posY), 5 /* radius*/, Color(200,255,0 ) );
  158. img.draw(circ);
  159. }
  160. if ( b_showResults )
  161. showImage(img, "Current (new) image and most similar feature for new cluster");
  162. else
  163. {
  164. std::vector< std::string > list2;
  165. StringTools::split ( _filename, '/', list2 );
  166. std::string destination ( s_resultdir + NICE::intToString(this->newImageCounter) + "_" + list2.back() + "_1_oldAndNewClusters.ppm");
  167. img.writePPM( destination );
  168. }
  169. }
  170. //compute score for every cluster: #assigned features * distance to current cluster centers
  171. NICE::Vector distancesToCurrentClusters ( numberOfClustersForNewImage, 0.0 );
  172. NICE::Vector clusterSizes ( numberOfClustersForNewImage, 0.0 ); //i.e., the number of assignments, or a derived number
  173. //compute "relevance" of every new cluster
  174. std::cerr << " COMPUTE SIZES OF NEW CLUSTERS" << std::endl;
  175. for (std::vector<int>::const_iterator assignIt = assignment.begin(); assignIt != assignment.end(); assignIt++)
  176. {
  177. clusterSizes[*assignIt]++;
  178. }
  179. clusterSizes.normalizeL1();
  180. std::cerr << "cluster Sizes: " << clusterSizes << std::endl;
  181. //compute distances of new cluster centers to old cluster centers
  182. std::cerr << " COMPUTE DISTANCES BETWEEN NEW AND OLD CLUSTERS" << std::endl;
  183. NICE::Vector::iterator distanceIt = distancesToCurrentClusters.begin();
  184. for ( NICE::VVector::const_iterator newProtIt = prototypesForNewImage.begin(); newProtIt != prototypesForNewImage.end(); newProtIt++, distanceIt++)
  185. {
  186. double minDist ( std::numeric_limits<double>::max() );
  187. double tmpDist;
  188. for ( NICE::VVector::const_iterator protIt = prototypes.begin(); protIt != prototypes.end(); protIt ++)
  189. {
  190. //compute distance
  191. tmpDist = this->distFunction->calculate( *protIt, *newProtIt );
  192. if (tmpDist < minDist)
  193. minDist = tmpDist;
  194. }
  195. *distanceIt = minDist;
  196. }
  197. std::cerr << "distances: " << distancesToCurrentClusters << std::endl;
  198. //compute final scores for the new image
  199. NICE::Vector clusterScores ( numberOfClustersForNewImage, 0.0 );
  200. for (uint i = 0; i < numberOfClustersForNewImage; i++)
  201. {
  202. clusterScores[i] = clusterSizes[i] * distancesToCurrentClusters[i];
  203. }
  204. std::cerr << "final cluster scores for new image: " << clusterScores << std::endl;
  205. NICE::Vector chosenClusterCenter ( prototypesForNewImage[ clusterScores.MaxIndex() ] );
  206. //include the chosen information into the currently used prototypes
  207. prototypes.push_back( chosenClusterCenter );
  208. if ( b_evaluationWhileFeatureLearning )
  209. {
  210. NICE::ColorImage imgTmp( _filename );
  211. double distToNewCluster ( std::numeric_limits<double>::max() );
  212. int indexOfMostSimFeat( 0 );
  213. double tmpDist;
  214. int tmpCnt ( 0 );
  215. for ( NICE::VVector::iterator i = newFeatures.begin();
  216. i != newFeatures.end();
  217. i++, tmpCnt++)
  218. {
  219. tmpDist = this->distFunction->calculate( *i, chosenClusterCenter );
  220. if ( tmpDist < distToNewCluster )
  221. {
  222. distToNewCluster = tmpDist;
  223. indexOfMostSimFeat = tmpCnt;
  224. }
  225. }
  226. int posX ( ( positions[indexOfMostSimFeat] ) [0] );
  227. int posY ( ( positions[indexOfMostSimFeat] ) [1] );
  228. NICE::Circle circ ( Coord( posX, posY), 10 /* radius*/, Color(200,0,255) );
  229. imgTmp.draw(circ);
  230. if ( b_showResults )
  231. showImage(imgTmp, "Current (new) image and most similar feature for new cluster");
  232. else
  233. {
  234. std::vector< std::string > list2;
  235. StringTools::split ( _filename, '/', list2 );
  236. std::string destination ( s_resultdir + NICE::intToString(this->newImageCounter) + "_" + list2.back() + "_2_bestNewCluster.ppm");
  237. imgTmp.writePPM( destination );
  238. }
  239. }
  240. //this was a new image, so we increase our internal counter
  241. (this->newImageCounter)++;
  242. }