Ver Fonte

first commit, supports loading of networks, image preparation, feat extraction for single image

Alexander Freytag há 9 anos atrás
commit
943926a51a
4 ficheiros alterados com 158 adições e 0 exclusões
  1. 1 0
      .gitignore
  2. 66 0
      caffe_features_single_image.m
  3. 48 0
      caffe_load_network.m
  4. 43 0
      caffe_prepare_image.m

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+*~

+ 66 - 0
caffe_features_single_image.m

@@ -0,0 +1,66 @@
+function [ features ] = caffe_features_single_image( i_image, f_mean, net, s_layer)
+% function [ features ] = caffe_features_single_image( i_image, f_mean, net, s_layer)
+% 
+%  BRIEF:
+%   Run a forward pass of a given net on a single image and grep features of a specified layer
+%   Requires Caffe version from 17-07-2015 (hash: 6d92d8fcfe0eea9495ffbc)
+% 
+%  INPUT
+%   i_image     -- 2d or 3d matrix
+%   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    
+    
+
+
+    %% old caffe layout
+%     % prepare image for caffe format
+%     batch_data          = zeros(i_width,i_width,3,1,'single');
+%     batch_data(:,:,:,1) = caffe_prepare_image(i_image,f_mean,i_width);
+%     batch_data          = repmat(batch_data, [1,1,1, batch_size] );
+%     
+% 
+%     %% grep output and adjust desired format
+%     features = caffe_('get_features',{batch_data},layer);
+%     features = reshape(features{1},size(features{1},1)*size(features{1},2)*size(features{1},3),size(features{1},4))';
+%     
+%     features = double(features(1,:)');
+
+    %% new caffe layout
+    % scale, permute dimensions, subtract mean
+    data         = caffe_prepare_image( i_image, f_mean );
+    
+    % check that network was prepared to work on single images
+    tmp_netshape = net.blobs('prob').shape;
+    assert (  tmp_netshape(2) == 1, 'network not reshaped for passing only a single image' );
+    
+    % run a single forward pass
+    [~] = net.forward({data});    
+    
+    % fetch activations from specified layer
+    features = net.blobs( s_layer ).get_data();
+    
+    % vectorize and concatenate activation maps
+    features = reshape( features, ...
+                        size(features,1)*size(features,2)*size(features,3), ...
+                        size(features,4)...
+                      );
+    
+    % convert output to double precision
+    features = double(features);
+end
+

+ 48 - 0
caffe_load_network.m

@@ -0,0 +1,48 @@
+function [net, mean_data] = caffe_load_network ( s_pathtodeployfile, s_pathtomodel, s_phase, s_meanfile, b_reshape_for_single_image_processing)
+% function [net, mean_data] = caffe_load_network ( s_pathtodeployfile, s_pathtomodel, s_phase, s_meanfile, b_reshape_for_single_image_processing)
+% 
+%  BRIEF 
+%   Load a specified network with mean image for train or test. 
+%   Requires Caffe version from 17-07-2015 (hash: 6d92d8fcfe0eea9495ffbc)
+% 
+%  INPUT
+%   s_pathtodeployfile     -- string, path to file describing the network's 
+%                             architecture, e.g., deploy.prototxt
+%   s_pathtomodel          -- string, path to file describing the network's 
+%                             learned parameters, e.g. bvlc_reference_caffenet.caffemodel
+%   s_phase                -- string, 'test' or 'train'. 'test' will de-activate dropout
+%   s_meanfile             -- string, path to file which contains the mean 
+%                             image of a dataset, e.g., imagenet_mean.binaryproto
+%   b_reshape_for_single_image_processing 
+%                           -- bool, true of the network shall
+%                              operate on single images instead of image batches
+
+
+    %% load network
+    net = caffe.Net(s_pathtodeployfile, s_pathtomodel, s_phase); % create net and load weights
+
+    %% reshape network input for batch or single-image processing
+    if ( b_reshape_for_single_image_processing )
+        %
+        % reshape network to run only a single image in a forward pass instead
+        % of 10 (for which it was trained)
+        i_currentNetInputSize = net.blobs('data').shape;
+        net.blobs('data').reshape([i_currentNetInputSize(1) ...
+                                   i_currentNetInputSize(2) ...
+                                   i_currentNetInputSize(3) ...
+                                   1 ...
+                                  ]); % reshape blob 'data'
+        net.reshape();
+    end
+    
+    %% load mean image and adapt to network input size
+    mean_data  = caffe.io.read_mean( s_meanfile );
+    % crop center from mean file according to network size
+    i_sizeMean = size( mean_data );
+    offset_row = floor ( int32( i_sizeMean(1)-i_currentNetInputSize(1) ) / 2 ) + 1;
+    offset_col = floor ( int32( i_sizeMean(2)-i_currentNetInputSize(2) ) / 2 ) + 1;
+    mean_data  = mean_data( offset_row:offset_row+i_currentNetInputSize(1)-1, ...
+                            offset_col:offset_col+i_currentNetInputSize(2)-1, ...
+                            : ...
+                          );       
+end

+ 43 - 0
caffe_prepare_image.m

@@ -0,0 +1,43 @@
+function im_data = caffe_prepare_image( i_img, f_mean )
+% function crops_data = caffe_prepare_image( i_img, f_mean )
+% 
+%  BRIEF:
+%   Bring Image into caffe-format for passing it through a deep neural
+%   network. Assumes f_mean to be of the size of the network input
+%   Based on prepare_image in classification_demo.m
+%   Requires Caffe version from 17-07-2015 (hash: 6d92d8fcfe0eea9495ffbc)
+%   
+% 
+    
+    %% start processing of input image
+    
+    % Convert an image returned by Matlab's imread to im_data in caffe's data
+    % format: W x H x C with BGR channels
+    
+    % produce correct ordering of three-channel image
+    if (size(i_img,3)==1)
+        % adapt gray scale images
+        im_data = repmat(i_img,1,1,3);
+    else
+        % permute channels from RGB to BGR
+        im_data = i_img(:, :, [3, 2, 1]);  
+    end    
+    
+    % flip width and height
+    im_data    = permute(im_data, [2, 1, 3]);  
+    
+    % make sure it's single type
+    im_data    = single(im_data); % convert from uint8 to single
+    
+    % resize image to fit the network's input
+    i_sizeMean = size( f_mean );
+    im_data    = imresize(im_data, [i_sizeMean(1) i_sizeMean(2)], 'bilinear');  % resize im_data
+    
+    % caffe/matlab/+caffe/imagenet/ilsvrc_2012_mean.mat contains mean_data that
+    % is already in W x H x C with BGR channels          
+    
+    % subtract mean_data (already in W x H x C, BGR)
+    im_data = im_data - f_mean;   
+    
+end
+