caffe_features_multiple_images.m 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. function [ features ] = caffe_features_multiple_images( s_filelist, f_mean, net, settings )
  2. % function [ features ] = caffe_features_multiple_images( s_filelist, f_mean, net, settings )
  3. %
  4. % BRIEF:
  5. % Run a forward pass of a given net on a set of images which are
  6. % listed in an external file and grep features of a specified layer.
  7. % Requires Caffe version from 17-07-2015 (hash: 6d92d8fcfe0eea9495ffbc)
  8. %
  9. % INPUT
  10. % s_filelist -- string, filename to an external list which contains
  11. % image names in each line. Alternatively, the variable is
  12. % given as cell array where each entry contains a loaded
  13. % image.
  14. % f_mean -- The average image of your dataset. This should be the same that was used during training of the CNN model.
  15. % Required to be cropped to the input size of your
  16. % network! See caffe_load_network.m
  17. % net -- a previously loaded network, see caffe_load_network.m
  18. % settings -- optional, (default []), struct with following possible fields
  19. % .s_layer -- optional (default: 'relu7'), string, specifies the layer used for feature exatraction
  20. % .b_apply_bilinear_pooling
  21. % -- optional (default: false),
  22. % .b_skip_normalization_in_bilinear_pooling
  23. % -- optional (default: false),
  24. % .b_apply_log_M
  25. % -- optional (default: false),
  26. % .f_sigma -- optional (default: 1e-5),
  27. % .s_filename_prefix
  28. % -- optional (default: ''), if not empty, this string
  29. % will be appended to the filenames given in the filelist
  30. % (useful if list contains only relative filenames)
  31. %
  32. %% parse inputs
  33. if (nargin<2)
  34. error ( 'no mean passed');
  35. end
  36. if (nargin<3)
  37. error ( 'no network passed');
  38. end
  39. if (nargin<4)
  40. settings = [];
  41. end
  42. s_layer = getFieldWithDefault ( settings, 's_layer', 'relu7');
  43. b_apply_bilinear_pooling = getFieldWithDefault ( settings, 'b_apply_bilinear_pooling', false );
  44. b_skip_normalization_in_bilinear_pooling ...
  45. = getFieldWithDefault ( settings, 'b_skip_normalization_in_bilinear_pooling', false );
  46. b_apply_log_M = getFieldWithDefault ( settings, 'b_apply_log_M', false );
  47. f_sigma = getFieldWithDefault ( settings, 'f_sigma', 1e-5 );
  48. %
  49. s_filename_prefix = getFieldWithDefault ( settings, 's_filename_prefix', '');
  50. %% prepare list of filenames
  51. b_filelistmode = ischar( s_filelist );
  52. if (b_filelistmode)
  53. % load the file list
  54. fid = fopen( s_filelist );
  55. s_filelist_to_use = textscan(fid,'%s');
  56. s_filelist_to_use = s_filelist_to_use{1};
  57. fclose(fid);
  58. if ( ~isempty( s_filename_prefix ) )
  59. s_filelist_to_use = strcat( s_filename_prefix, s_filelist_to_use );
  60. % s_filelist_to_use = cellfun(@(c)[s_filename_prefix, c],s_filelist_to_use, 'uni', false );
  61. end
  62. else
  63. % use the passed filelist
  64. s_filelist_to_use = s_filelist;
  65. end
  66. %% new caffe layout
  67. net_input_shape = net.blobs('data').shape;
  68. i_batch_size = net_input_shape(4);
  69. % create tmp for batch
  70. batch_data = {zeros(net_input_shape(1),... %height
  71. net_input_shape(2),... %width
  72. net_input_shape(3),... %width, ...%RGB
  73. i_batch_size,...
  74. 'single')};
  75. % Calculate the starting indices of every batch
  76. slices = 1:i_batch_size:size(s_filelist_to_use,1);
  77. slices(end+1)=size(s_filelist_to_use,1)+1;
  78. % crop the list of files into batches of adequate size
  79. % then run over every batch
  80. for i=1:numel(slices)-1
  81. % debug information for progress
  82. if ( ( i > 1 ) && ( mod(i,10) == 0 ) )
  83. fprintf('Running batch number %i of %i\n',i, numel(slices)-1);
  84. end
  85. % load the images of the next slice
  86. for j=slices(i):slices(i+1)-1;
  87. if (b_filelistmode)
  88. batch_data{1}(:,:,:,j-slices(i)+1) = caffe_prepare_image(imread( s_filelist_to_use{j} ), f_mean );
  89. else
  90. batch_data{1}(:,:,:,j-slices(i)+1) = caffe_prepare_image(s_filelist_to_use{j}, f_mean );
  91. end
  92. end
  93. % run a single forward pass
  94. [~] = net.forward( batch_data );
  95. % fetch activations from specified layer
  96. tmp_feat = net.blobs( s_layer ).get_data();
  97. %% optional: bilinear pooling
  98. if ( b_apply_bilinear_pooling )
  99. %% efficient version: reshape and sum
  100. %
  101. % compute outer product with sum pooling
  102. % this is consistent with the matlab code of liu et al. iccv 2015
  103. for i_img = 1:i_batch_size
  104. if ( i_batch_size ==1 )
  105. b_has_spatial_support = ( ndims ( tmp_feat ) == 3 );
  106. else
  107. b_has_spatial_support = ( ndims ( tmp_feat ) == 4 );
  108. end
  109. if ( b_has_spatial_support )
  110. i_channelCount = size ( tmp_feat, 3);
  111. % reshape with [] automatically resizes to correct number of examples,
  112. % this is equivalent to ...size(features,1)*size(features,2),size(features,3) );
  113. featImg = reshape ( tmp_feat(:,:,:,i_img), [],i_channelCount );% size(features,1)*size(features,2),size(features,3) , 'forder');
  114. % response normalization to increase comparability of features
  115. % this improves the condition of the bilinear matrix
  116. %
  117. if ( ~b_skip_normalization_in_bilinear_pooling )
  118. %this equals 1/abs(sum(features,2))...
  119. %
  120. % note: the max... is just for security reasons to
  121. % prevent division by zero in case that *all*
  122. % values should be zero or the signed sum equals zero
  123. %
  124. featImg = bsxfun(@times, featImg, 1./( max( 10e-8, sqrt(sum(featImg,2).^2) ) ) );
  125. end
  126. % compute outer product
  127. featImg = featImg'*featImg;
  128. else
  129. featImg = tmp_feat(:,i_img)*tmp_feat(:,i_img)';
  130. end
  131. if ( b_apply_log_M )
  132. %channel_count = size(b(ismember(b_struct(3,:)',layer_image)).data,3);
  133. %selection_matrix = logical(tril(ones(channel_count)));
  134. %
  135. %features = logm(features'*features+1e-5*eye(channel_count));
  136. featImg = logm( featImg + f_sigma*eye( size(featImg) ) );
  137. end
  138. % take lower tri-angle only to remove redundant information
  139. % -> logical automatically reshapes into vector
  140. featImg = featImg ( logical(tril(ones(size(featImg)))));
  141. % pass through signed square root step (see Lin et al 2015 ICCV)
  142. featImg = sign(featImg).*sqrt(abs(featImg));
  143. % apply L2 normalization (see Lin et al 2015 ICCV)
  144. featImg = featImg / sqrt(sum(featImg.^2));
  145. % allocate enough space in first run
  146. if ( ~exist('features','var') )
  147. features = zeros( size(featImg,1), size(s_filelist_to_use,1), 'single');
  148. end
  149. % store computed feature accordingly
  150. features( :, slices(i)+i_img-1 ) = featImg;
  151. end
  152. else
  153. % vectorize and concatenate activation maps
  154. if ( ndims( tmp_feat ) > 2 )
  155. tmp_feat = reshape( tmp_feat, ...
  156. size(tmp_feat,1)*size(tmp_feat,2)*size(tmp_feat,3), ...
  157. size(tmp_feat,4)...
  158. );
  159. end
  160. % allocate enough space in first run
  161. if ( ~exist('features','var') )
  162. features = zeros( size(tmp_feat,1), size(s_filelist_to_use,1), 'single');
  163. end
  164. % store computed feature accordingly
  165. features( :, slices(i):(slices(i+1)-1) ) = tmp_feat( :, 1:(slices(i+1)-slices(i)) );
  166. end
  167. end
  168. % convert output to double precision
  169. features = double(features);
  170. end