Ver código fonte

support for feature extraction with image batches

Alexander Freytag 9 anos atrás
pai
commit
e9087399fd
1 arquivos alterados com 106 adições e 0 exclusões
  1. 106 0
      caffe_features_multiple_images.m

+ 106 - 0
caffe_features_multiple_images.m

@@ -0,0 +1,106 @@
+function [ features ] = caffe_features_multiple_images( s_filelist, f_mean, net, s_layer)
+% function [ features ] = caffe_features_multiple_images( s_filelist, f_mean, net, s_layer)
+% 
+%  BRIEF:
+%   Run a forward pass of a given net on a set of images which are 
+%   listed in an external file and grep features of a specified layer.
+%   Requires Caffe version from 17-07-2015 (hash: 6d92d8fcfe0eea9495ffbc)
+% 
+%  INPUT
+%   s_filelist  -- string, filename to an external list which contains
+%                  image names in each line. Alternatively, the variable is
+%                  given as cell array where each entry contains a loaded
+%                  image.
+%   f_mean      -- The average image of your dataset. This should be the same that was used during training of the CNN model.
+%                  Required to be cropped to the input size of your
+%                  network! See caffe_load_network.m
+%   net         -- a previously loaded network, see caffe_load_network.m
+%   s_layer     -- optional (default: 'relu7'), string, specifies the layer used for feature exatraction
+%
+
+
+    %% parse inputs
+    if (nargin<2)
+        error ( 'no mean passed');
+    end
+    if (nargin<3)
+        error ( 'no network passed');
+    end
+    if (nargin<4)
+        s_layer = 'relu7';
+    end 
+    
+    %% prepare list of filenames
+    b_filelistmode = ischar( s_filelist );
+     
+    if (b_filelistmode)
+        % load the file list
+        fid                = fopen( s_filelist );
+        s_filelist_to_use  = textscan(fid,'%s');
+        s_filelist_to_use  = s_filelist_to_use{1};
+        fclose(fid);
+    else
+        % use the passed filelist
+        s_filelist_to_use  = s_filelist;
+    end
+    
+    %% new caffe layout        
+    net_input_shape  = net.blobs('data').shape;    
+    i_batch_size     = net_input_shape(4);
+    
+    % create tmp for batch
+    batch_data = {zeros(net_input_shape(1),... %height
+                        net_input_shape(2),... %width
+                        net_input_shape(3),... %width, ...%RGB
+                        i_batch_size,...
+                        'single')};
+    
+    % Calculate the starting indices of every batch
+    slices = 1:i_batch_size:size(s_filelist_to_use,1);
+    slices(end+1)=size(s_filelist_to_use,1)+1;
+    
+    % crop the list of files into batches of adequate size 
+    % then run over every batch
+    for i=1:numel(slices)-1
+        
+        % debug information for progress
+        if ( ( i > 1 ) && ( mod(i,10) == 0 )  )
+            fprintf('Running batch number %i of %i\n',i, numel(slices)-1);
+        end
+        
+        % load the images of the next slice
+        for j=slices(i):slices(i+1)-1;
+            if (b_filelistmode)
+                batch_data{1}(:,:,:,j-slices(i)+1) = caffe_prepare_image(imread( s_filelist_to_use{j} ), f_mean );
+            else
+                batch_data{1}(:,:,:,j-slices(i)+1) = caffe_prepare_image(s_filelist_to_use{j}, f_mean );
+            end
+        end
+        
+        % run a single forward pass
+        [~] = net.forward( batch_data );
+        
+        % fetch activations from specified layer
+        tmp_feat = net.blobs( s_layer ).get_data();    
+        
+        % vectorize and concatenate activation maps
+        if ( ndims( tmp_feat ) > 2 )
+            tmp_feat = reshape( tmp_feat, ...
+                                size(tmp_feat,1)*size(tmp_feat,2)*size(tmp_feat,3), ...
+                                size(tmp_feat,4)...
+                              );    
+        end
+                      
+        % allocate enough space in first run       
+        if ( ~exist('features','var') )
+            features = zeros( size(tmp_feat,1), size(s_filelist_to_use,1), 'single');
+        end
+        
+        % store computed feature accordingly
+        features( :, slices(i):(slices(i+1)-1) ) = tmp_feat( :, 1:(slices(i+1)-slices(i)) );
+    end
+    
+    % convert output to double precision
+    features = double(features);
+end
+