FeatureLearningClusterBased.cpp 9.4 KB

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