FeatureLearningRegionBased.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #include "FeatureLearningRegionBased.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. #include <core/vector/VectorT.h>
  9. #include <segmentation/GenericRegionSegmentationMethodSelection.h>
  10. //vislearning
  11. #include <vislearning/baselib/Globals.h>
  12. using namespace std;
  13. using namespace NICE;
  14. using namespace OBJREC;
  15. //**********************************************
  16. //
  17. // PROTECTED METHODS
  18. //
  19. //**********************************************
  20. //**********************************************
  21. //
  22. // PUBLIC METHODS
  23. //
  24. //**********************************************
  25. FeatureLearningRegionBased::FeatureLearningRegionBased ( const Config *_conf,
  26. const MultiDataset *_md, const std::string & _section )
  27. : FeatureLearningPrototypes ( _conf, _md, _section )
  28. {
  29. //save and read segmentation results from files
  30. this->reuseSegmentation = conf->gB ( "FPCPixel", "reuseSegmentation", true );
  31. // select your segmentation method here
  32. // currently, the following options are supported: "MarkovCluster", "GraphBased", "MeanShift", "SLIC"
  33. string rsMethode = conf->gS ( section, "segmentationMethod", "MeanShift" );
  34. OBJREC::RegionSegmentationMethod *tmpRegionSeg = OBJREC::GenericRegionSegmentationMethodSelection::selectRegionSegmentationMethod(conf, rsMethode);
  35. if ( reuseSegmentation )
  36. this->segmentationAlgo = new RSCache ( conf, tmpRegionSeg );
  37. else
  38. this->segmentationAlgo = tmpRegionSeg;
  39. this->i_gridSize = conf->gI( "LFColorSandeTest" , "grid" , 5 );
  40. }
  41. FeatureLearningRegionBased::~FeatureLearningRegionBased()
  42. {
  43. // clean-up
  44. }
  45. void FeatureLearningRegionBased::learnNewFeatures ( const std::string & _filename )
  46. {
  47. NICE::ColorImage img( _filename );
  48. int xsize ( img.width() );
  49. int ysize ( img.height() );
  50. //variables to store feature information
  51. NICE::VVector newFeatures;
  52. NICE::VVector cfeatures;
  53. NICE::VVector positions;
  54. //compute features
  55. std::cerr << " EXTRACT FEATURES FROM UNSEEN IMAGE" << std::endl;
  56. Globals::setCurrentImgFN ( _filename );
  57. featureExtractor->extractFeatures ( img, newFeatures, positions );
  58. //normalization :)
  59. for ( NICE::VVector::iterator i = newFeatures.begin();
  60. i != newFeatures.end();
  61. i++)
  62. {
  63. i->normalizeL1();
  64. }
  65. //compute region segmentation
  66. std::cerr << " COMPUTE REGION SEGMENTATION" << std::endl;
  67. NICE::Matrix mask;
  68. int amountRegions = segmentationAlgo->segRegions ( img, mask );
  69. //compute novelty scores on a feature level
  70. std::cerr << " COMPUTE NOVELTY SCORES ON A FEATURE LEVEL" << std::endl;
  71. FloatImage noveltyImageGaussFiltered ( xsize, ysize );
  72. this->evaluateCurrentCodebookForGivenFeatures( newFeatures, positions, noveltyImageGaussFiltered );
  73. // compute scores for every region
  74. std::cerr << " COMPUTE SCORES FOR EVERY REGION" << std::endl;
  75. std::vector<double> regionNoveltyMeasure (amountRegions, 0.0);
  76. std::vector<int> regionSize (amountRegions, 0);
  77. for ( int y = 0; y < ysize; y += i_gridSize) //y++)
  78. {
  79. for (int x = 0; x < xsize; x += i_gridSize) //x++)
  80. {
  81. int r = mask(x,y);
  82. regionSize[r]++;
  83. //count the amount of "novelty" for the corresponding region
  84. regionNoveltyMeasure[r] += noveltyImageGaussFiltered(x,y);
  85. }
  86. }
  87. //loop over all regions and compute averaged novelty scores
  88. //NOTE this might be unuseful, since lateron we combine novelty score and region size (e.g. by multiplying)
  89. // however, we do not want to settle the combination in adavance
  90. for(int r = 0; r < amountRegions; r++)
  91. {
  92. regionNoveltyMeasure[r] /= regionSize[r];
  93. }
  94. //a new region should cover at least 3% of the image for not being penalized
  95. double d_minimalImageAmountForAcceptableRegions ( 0.03 );
  96. int minimalImageAmountForAcceptableRegions ( round( d_minimalImageAmountForAcceptableRegions * (xsize/i_gridSize) * (ysize/i_gridSize) ) );
  97. std::cerr << "minimalImageAmountForAcceptableRegions: " << minimalImageAmountForAcceptableRegions << std::endl;
  98. //compute final scores for all regions
  99. NICE::Vector regionScores ( amountRegions, 0.0 );
  100. std::cerr << "used region sizes for computation: " << std::endl;
  101. for(int r = 0; r < amountRegions; r++)
  102. {
  103. regionScores[r] = std::min( regionSize[r], minimalImageAmountForAcceptableRegions ) * regionNoveltyMeasure[r];
  104. std::cerr << " " << std::min( regionSize[r], minimalImageAmountForAcceptableRegions );
  105. }
  106. std::cerr << std::endl << std::endl;
  107. int indexOfBestRegion ( regionScores.MaxIndex() );
  108. ////////////////////////////////////
  109. //
  110. // VISUALIZE REGION SCORES
  111. //
  112. ////////////////////////////////////
  113. NICE::FloatImage regionScoreImage ( xsize, ysize );
  114. NICE::FloatImage regionNoveltyImage ( xsize, ysize );
  115. for ( int y = 0; y < ysize; y++)
  116. {
  117. for (int x = 0; x < xsize; x++)
  118. {
  119. int r = mask(x,y);
  120. regionNoveltyImage(x,y) = regionNoveltyMeasure[r];
  121. regionScoreImage(x,y) = regionScores[r];
  122. }
  123. }
  124. std::cerr << "highest region score: " << regionScoreImage.max()<< " -- smallest region score: " << regionScoreImage.min() << std::endl;
  125. std::cerr << "highest region novelty score: " << regionNoveltyImage.max() << " -- smallest region novelty score: " << regionNoveltyImage.min() << std::endl;
  126. NICE::ColorImage regionScoreImageRGB ( xsize, ysize );
  127. //TODO properly specify the maximum value for score visualization here :)
  128. // imageToPseudoColorWithRangeSpecification( regionScoreImage, regionScoreImageRGB, 0 /* min */, 0.5 /* max */ );
  129. imageToPseudoColorWithRangeSpecification( regionScoreImage, regionScoreImageRGB, 0 /* min */, 2.2 /* max */ );
  130. if ( b_showResults )
  131. showImage(regionScoreImageRGB, "Current (new) image with region scores");
  132. else
  133. {
  134. std::vector< std::string > list2;
  135. StringTools::split ( _filename, '/', list2 );
  136. std::string destination ( s_resultdir + NICE::intToString(this->newImageCounter) + "_" + list2.back() + "_1_regionScores.ppm");
  137. regionScoreImageRGB.writePPM( destination );
  138. }
  139. //compute representative for best region
  140. NICE::Vector representative ( newFeatures.begin()->size(), 0.0 );
  141. //first guess: average feature vectors of the "best" region
  142. // NICE::VVector::const_iterator posIt = positions.begin();
  143. // for ( NICE::VVector::const_iterator featIt = newFeatures.begin();
  144. // featIt != newFeatures.end();
  145. // featIt++, posIt++)
  146. // {
  147. //
  148. // //only considere features that actually belong to the best region
  149. // if ( mask( (*posIt)[0], (*posIt)[1] ) != indexOfBestRegion )
  150. // continue;
  151. //
  152. // representative += *featIt;
  153. // }
  154. //
  155. // //simple mean feature vector
  156. // representative /= regionSize[indexOfBestRegion];
  157. // //normalization
  158. // representative.normalizeL1();
  159. //next try: simply take the first feature vector of the "best" region (although this one should lay on the border, and so on...)
  160. NICE::VVector::const_iterator posIt = positions.begin();
  161. for ( NICE::VVector::const_iterator featIt = newFeatures.begin();
  162. featIt != newFeatures.end();
  163. featIt++, posIt++)
  164. {
  165. //only considere features that actually belong to the best region
  166. if ( mask( (*posIt)[0], (*posIt)[1] ) != indexOfBestRegion )
  167. continue;
  168. representative = *featIt;
  169. //break after the first positive feature
  170. break;
  171. }
  172. std::cerr << " New representative: " << std::endl << representative << std::endl;
  173. //include the chosen information into the currently used prototypes
  174. prototypes.push_back( representative );
  175. if ( b_evaluationWhileFeatureLearning )
  176. {
  177. NICE::ColorImage imgTmp( _filename );
  178. double distToNewCluster ( std::numeric_limits<double>::max() );
  179. int indexOfMostSimFeat( 0 );
  180. double tmpDist;
  181. int tmpCnt ( 0 );
  182. for ( NICE::VVector::iterator i = newFeatures.begin();
  183. i != newFeatures.end();
  184. i++, tmpCnt++)
  185. {
  186. tmpDist = this->distFunction->calculate( *i, representative );
  187. if ( tmpDist < distToNewCluster )
  188. {
  189. distToNewCluster = tmpDist;
  190. indexOfMostSimFeat = tmpCnt;
  191. }
  192. }
  193. std::cerr << "** minDist to new cluster: " <<distToNewCluster << std::endl;
  194. int posX ( ( positions[indexOfMostSimFeat] ) [0] );
  195. int posY ( ( positions[indexOfMostSimFeat] ) [1] );
  196. NICE::Circle circ ( Coord( posX, posY), 10 /* radius*/, Color(200,0,255) );
  197. imgTmp.draw(circ);
  198. if ( b_showResults )
  199. showImage(imgTmp, "Current (new) image and most similar feature for new cluster");
  200. else
  201. {
  202. std::vector< std::string > list2;
  203. StringTools::split ( _filename, '/', list2 );
  204. std::string destination ( s_resultdir + NICE::intToString(this->newImageCounter) + "_" + list2.back() + "_2_bestNewCluster.ppm");
  205. imgTmp.writePPM( destination );
  206. }
  207. }
  208. //this was a new image, so we increase our internal counter
  209. (this->newImageCounter)++;
  210. }