123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- function pyra = featPyramidGeneric(im, model, settings )
- % function pyra = featPyramidGeneric(im, model, settings )
- %
- % author: Alexander Freytag
- % date: 26-02-2014 ( dd-mm-yyyy )
- %
- % BRIEF:
- % Computes a feature pyramid from an image. Features are padded such
- % that at least a single cell is visible. For every scale factor, the
- % resized image is as often downsampled by factor 2 until less than
- % i_numCells *i_binSize pixel are available.
- %
- % INPUT:
- % im -- image to extract feature pyramid from, gray scale and
- % RGB images are supported right now
- %
- % model -- struct, with at least the following fields
- % .interval -- scalar, number of octaves for rescaling the img
- % .i_numCells -- 2x1, number of cells in y and x direction
- % .i_binSize -- scalar, number of pixel of every cell in x and y direction
- %
- % settings -- (optional) struct, with possible fields
- % .fh_featureExtractor -- (struct), contains name and mfunction for
- % feature extraction
- % .d_maxRelBoxExtent -- what shall be the max extent of a box
- % features are extracted from? (1.0 allows
- % for responses covering the whole image)
- %
- % OUTPUT:
- % pyra.feat{i} is the i-th level of the feature pyramid.
- % pyra.scales{i} is the scaling factor used for the i-th level.
- % pyra.feat{i+interval} is computed at exactly half the resolution of feat{i}.
- %
- %% (1) check input
- if ( nargin < 3 )
- settings = [];
- end
-
- %check for feature extractor, if not existing, set to default
- fh_featureExtractor = struct('name','Compute patch means', 'mfunction',@computePatchMeans);
- settings = addDefaultVariableSetting( settings, 'fh_featureExtractor', fh_featureExtractor, settings );
-
- %check for feature extractor, if not existing, set to []
- settingsFeatureExtractorDefault = [];
- settings = addDefaultVariableSetting( settings, 'settingsFeatureExtractor', settingsFeatureExtractorDefault, settings );
- %% (2) compute features
- interval = model.interval;
- i_numCells = model.i_numCells;
- i_binSize = model.i_binSize;
- % Select padding, allowing for at least one cell in model to be visible
- if (getFieldWithDefault ( settings, 'b_padFeatPyramid', true ) )
- padx = max(model.i_numCells(2)-1,0);
- pady = max(model.i_numCells(1)-1,0);
- else
- padx = 0;
- pady = 0;
- end
- % Even padding allows for consistent spatial relations across 2X scales
- padx = floor(padx/2)*2;
- pady = floor(pady/2)*2;
-
- sc = 2 ^(1/interval);
- imsize = [size(im, 1) size(im, 2)];
-
- % a value of 1.0 allows responses covering the whole image, whereas 0.5
- % results on boxes covering 25% at most
- d_maxRelBoxExtent = getFieldWithDefault ( settings, 'd_maxRelBoxExtent', 1.0 );
- imsizeMaxAcceptable = d_maxRelBoxExtent*imsize;
-
- % determine maximum scale such that at least i_numCells *i_binSize px
- % are visible in the scaled image
- maxScalesProLevel = zeros( interval, 1);
- for i = 1:interval
- maxScalesProLevel(i) = ...
- 1 + floor( log2( 1/sc^(i-1).*min( double(imsizeMaxAcceptable) ...
- ./ ...
- (i_numCells *i_binSize) ...
- ) ...
- ) ...
- );
- end
- %pre-allocate memory
- pyra.feat = cell( sum( maxScalesProLevel), 1);
- pyra.scale = zeros( sum( maxScalesProLevel), 1);
- % our resize function wants floating point values
- im = double(im);
- %%TODO check whether double<-> uint8 is still needed for meanPatch features
- if ( length(size(im)) == 2)
- resizeFct = @resizeGrayScale;
- reduceFct = @reduceGrayScale;
- else
- resizeFct = @resizeColor;
- reduceFct = @reduceColor;
- end
-
- settings.settingsFeatureExtractor.i_binSize = i_binSize;
-
- % every iteration rescales the image with exponentially decreasing
- % factors, corresponds to the scale space of Lowes SIFT paper
- for i = 1:interval
- %rescale image according to current scaling factor
- scaledImg = resizeFct(im, 1/sc^(i-1));
-
- %initial scaling factor for this iteration
- pyra.scale( i ) = 1/sc^(i-1);
-
- % always doubles support of cells by shrinking the image by a factor of
- % 2 in every iteration, corresponds to octaves of Lowes SIFT paper
- for j = 1:maxScalesProLevel(i)
-
- %extracat features for current level
- pyra.feat{ i+(j-1)*interval } = settings.fh_featureExtractor.mfunction ( scaledImg, settings.settingsFeatureExtractor );
-
- % the scale is exactly have the scale of the previous level
- pyra.scale( i+(j-1)*interval ) = 0.5^(j-1) * pyra.scale(i);
-
- % shrink image by factor of 2 for next iteration in inner round
- scaledImg = reduceFct(scaledImg);
- end
- end
- %% write results to output object
- % write boundary occlusion feature
-
- %Ricks code: td = model.features.truncation_dim;
- if ( strcmp ( settings.fh_featureExtractor.name, 'Compute HOG features using WHO code' ) || ...
- strcmp ( settings.fh_featureExtractor.name, 'HOG and Patch Means concatenated' ) ...
- )
- td = 32;
- else
- % no truncation for all other known feature types
- td = 0;
- end
- if ( strcmp ( settings.fh_featureExtractor.name, 'Compute HOG features using WHO code' ) )
- % add 1 to padding because feature generation deletes a 1-cell
- % wide border around the feature map
- padAdd = 1;
- else
- % nothing to change for padding
- padAdd = 0;
- end
-
- for i = 1:length(pyra.feat)
-
- if ( ndims ( pyra.feat{i} ) > 2 )
- pyra.feat{i} = myPadArray(pyra.feat{i}, [pady+padAdd padx+padAdd 0], 0);
- else
- pyra.feat{i} = myPadArray(pyra.feat{i}, [pady+padAdd padx+padAdd], 0);
- end
- % possibly correct the truncation feature
- if ( td > 0 )
- pyra.feat{i}(1:pady, :, td) = 1;
- pyra.feat{i}(end-pady:end, :, td) = 1;
- pyra.feat{i}(:, 1:padx, td) = 1;
- pyra.feat{i}(:, end-padx:end, td) = 1;
- end
- end
-
- %% add further settings to output object
- pyra.scale = model.i_binSize./pyra.scale;
- pyra.interval = interval;
- pyra.imy = imsize(1);
- pyra.imx = imsize(2);
- pyra.pady = pady;
- pyra.padx = padx;
- end
|