featPyramidGeneric.m 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. function pyra = featPyramidGeneric(im, model, settings )
  2. % function pyra = featPyramidGeneric(im, model, settings )
  3. %
  4. % author: Alexander Freytag
  5. % date: 26-02-2014 ( dd-mm-yyyy )
  6. %
  7. % BRIEF:
  8. % Computes a feature pyramid from an image. Features are padded such
  9. % that at least a single cell is visible. For every scale factor, the
  10. % resized image is as often downsampled by factor 2 until less than
  11. % i_numCells *i_binSize pixel are available.
  12. %
  13. % INPUT:
  14. % im -- image to extract feature pyramid from, gray scale and
  15. % RGB images are supported right now
  16. %
  17. % model -- struct, with at least the following fields
  18. % .interval -- scalar, number of octaves for rescaling the img
  19. % .i_numCells -- 2x1, number of cells in y and x direction
  20. % .i_binSize -- scalar, number of pixel of every cell in x and y direction
  21. %
  22. % settings -- (optional) struct, with possible fields
  23. % .fh_featureExtractor -- (struct), contains name and mfunction for
  24. % feature extraction
  25. % .d_maxRelBoxExtent -- what shall be the max extent of a box
  26. % features are extracted from? (1.0 allows
  27. % for responses covering the whole image)
  28. %
  29. % OUTPUT:
  30. % pyra.feat{i} is the i-th level of the feature pyramid.
  31. % pyra.scales{i} is the scaling factor used for the i-th level.
  32. % pyra.feat{i+interval} is computed at exactly half the resolution of feat{i}.
  33. %
  34. %% (1) check input
  35. if ( nargin < 3 )
  36. settings = [];
  37. end
  38. %check for feature extractor, if not existing, set to default
  39. fh_featureExtractor = struct('name','Compute patch means', 'mfunction',@computePatchMeans);
  40. settings = addDefaultVariableSetting( settings, 'fh_featureExtractor', fh_featureExtractor, settings );
  41. %check for feature extractor, if not existing, set to []
  42. settingsFeatureExtractorDefault = [];
  43. settings = addDefaultVariableSetting( settings, 'settingsFeatureExtractor', settingsFeatureExtractorDefault, settings );
  44. %% (2) compute features
  45. interval = model.interval;
  46. i_numCells = model.i_numCells;
  47. i_binSize = model.i_binSize;
  48. % Select padding, allowing for at least one cell in model to be visible
  49. if (getFieldWithDefault ( settings, 'b_padFeatPyramid', true ) )
  50. padx = max(model.i_numCells(2)-1,0);
  51. pady = max(model.i_numCells(1)-1,0);
  52. else
  53. padx = 0;
  54. pady = 0;
  55. end
  56. % Even padding allows for consistent spatial relations across 2X scales
  57. padx = floor(padx/2)*2;
  58. pady = floor(pady/2)*2;
  59. sc = 2 ^(1/interval);
  60. imsize = [size(im, 1) size(im, 2)];
  61. % a value of 1.0 allows responses covering the whole image, whereas 0.5
  62. % results on boxes covering 25% at most
  63. d_maxRelBoxExtent = getFieldWithDefault ( settings, 'd_maxRelBoxExtent', 1.0 );
  64. imsizeMaxAcceptable = d_maxRelBoxExtent*imsize;
  65. % determine maximum scale such that at least i_numCells *i_binSize px
  66. % are visible in the scaled image
  67. maxScalesProLevel = zeros( interval, 1);
  68. for i = 1:interval
  69. maxScalesProLevel(i) = ...
  70. 1 + floor( log2( 1/sc^(i-1).*min( double(imsizeMaxAcceptable) ...
  71. ./ ...
  72. (i_numCells *i_binSize) ...
  73. ) ...
  74. ) ...
  75. );
  76. end
  77. %pre-allocate memory
  78. pyra.feat = cell( sum( maxScalesProLevel), 1);
  79. pyra.scale = zeros( sum( maxScalesProLevel), 1);
  80. % our resize function wants floating point values
  81. im = double(im);
  82. %%TODO check whether double<-> uint8 is still needed for meanPatch features
  83. if ( length(size(im)) == 2)
  84. resizeFct = @resizeGrayScale;
  85. reduceFct = @reduceGrayScale;
  86. else
  87. resizeFct = @resizeColor;
  88. reduceFct = @reduceColor;
  89. end
  90. settings.settingsFeatureExtractor.i_binSize = i_binSize;
  91. % every iteration rescales the image with exponentially decreasing
  92. % factors, corresponds to the scale space of Lowes SIFT paper
  93. for i = 1:interval
  94. %rescale image according to current scaling factor
  95. scaledImg = resizeFct(im, 1/sc^(i-1));
  96. %initial scaling factor for this iteration
  97. pyra.scale( i ) = 1/sc^(i-1);
  98. % always doubles support of cells by shrinking the image by a factor of
  99. % 2 in every iteration, corresponds to octaves of Lowes SIFT paper
  100. for j = 1:maxScalesProLevel(i)
  101. %extracat features for current level
  102. pyra.feat{ i+(j-1)*interval } = settings.fh_featureExtractor.mfunction ( scaledImg, settings.settingsFeatureExtractor );
  103. % the scale is exactly have the scale of the previous level
  104. pyra.scale( i+(j-1)*interval ) = 0.5^(j-1) * pyra.scale(i);
  105. % shrink image by factor of 2 for next iteration in inner round
  106. scaledImg = reduceFct(scaledImg);
  107. end
  108. end
  109. %% write results to output object
  110. % write boundary occlusion feature
  111. %Ricks code: td = model.features.truncation_dim;
  112. if ( strcmp ( settings.fh_featureExtractor.name, 'Compute HOG features using WHO code' ) || ...
  113. strcmp ( settings.fh_featureExtractor.name, 'HOG and Patch Means concatenated' ) ...
  114. )
  115. td = 32;
  116. else
  117. % no truncation for all other known feature types
  118. td = 0;
  119. end
  120. if ( strcmp ( settings.fh_featureExtractor.name, 'Compute HOG features using WHO code' ) )
  121. % add 1 to padding because feature generation deletes a 1-cell
  122. % wide border around the feature map
  123. padAdd = 1;
  124. else
  125. % nothing to change for padding
  126. padAdd = 0;
  127. end
  128. for i = 1:length(pyra.feat)
  129. if ( ndims ( pyra.feat{i} ) > 2 )
  130. pyra.feat{i} = myPadArray(pyra.feat{i}, [pady+padAdd padx+padAdd 0], 0);
  131. else
  132. pyra.feat{i} = myPadArray(pyra.feat{i}, [pady+padAdd padx+padAdd], 0);
  133. end
  134. % possibly correct the truncation feature
  135. if ( td > 0 )
  136. pyra.feat{i}(1:pady, :, td) = 1;
  137. pyra.feat{i}(end-pady:end, :, td) = 1;
  138. pyra.feat{i}(:, 1:padx, td) = 1;
  139. pyra.feat{i}(:, end-padx:end, td) = 1;
  140. end
  141. end
  142. %% add further settings to output object
  143. pyra.scale = model.i_binSize./pyra.scale;
  144. pyra.interval = interval;
  145. pyra.imy = imsize(1);
  146. pyra.imx = imsize(2);
  147. pyra.pady = pady;
  148. pyra.padx = padx;
  149. end