function [seg_x, seg_gt, seg_sz, seg_id] = ...
        aggregate_img_features(parent_dirs, name_root, config, feat_types)

% Load the segmentation
seg_path = fullfile(config.paths.seg_data , [name_root '.mat']);
load(seg_path, 'label_img');

% Load the ground truth
gt_label = load_ground_truth(parent_dirs, name_root, config.load_params);
if ~isempty(gt_label) && config.load_params.use_gt_box
    gt_crop = get_gt_box(gt_label, config.load_params);
    seg_map = seg_map(gt_crop(1):gt_crop(2), gt_crop(3):gt_crop(4), :);
    gt_label = gt_label(gt_crop(1):gt_crop(2), gt_crop(3):gt_crop(4), :);
end

[seg_id, seg_sz, seg_gt] = get_seg_info(label_img, gt_label);

% Get relevant segment data
seg_sel = select_segments(seg_id, seg_sz, seg_gt, config.model_params);
seg_gt = seg_gt(seg_sel, :);
seg_sz = seg_sz(seg_sel);
seg_id = seg_id(seg_sel);

% Load each of the features specified
segFeat = cell(size(feat_types, 1), 1);
for feat_i = 1:size(feat_types, 1)
    % Get path to the file where the features are stored
    feat_path = fullfile(config.paths.seg_feats, feat_types{feat_i}, ...
                         [name_root '.mat']);

    % Get the segment features.
    seg_feats = load_seg_feats(feat_path, seg_id);
    if isempty(seg_feats)
        % Load the feature map for the current feature type
        map_path = fullfile(config.paths.img_feats, feat_types{feat_i}, ...
                            [name_root '.mat']);
        load(map_path, 'feature_map', 'map_info');

        % Aggregate region features for each segment
        seg_feats = zeros(size(feature_map, 1), length(seg_id));
        for i = 1:length(seg_id)
            seg_feats(:,i) = pool_region_feats(feature_map, map_info, ...
                                               (label_img == seg_id(i)), ...
                                               config.pool_type);
        end

        save(feat_path, 'seg_feats', 'seg_id');
    end

    % Select the appropriate segments
    segFeat{feat_i} = seg_feats;

    % Normalize each feature (before they are concatenated)
    if isfield(config.model_params, 'norm_each_feat')
        switch config.model_params.norm_each_feat
          case 'L2'
            segFeat{feat_i} = ...
                bsxfun(@rdivide, segFeat{feat_i}, sqrt(sum(segFeat{feat_i}.^2, 1))+eps);
          case 'L1'
            segFeat{feat_i} = ...
                bsxfun(@rdivide, segFeat{feat_i}, sum(segFeat{feat_i}, 1)+eps);
          case 'Linf'
            segFeat{feat_i} = ...
                bsxfun(@rdivide, segFeat{feat_i}, max(segFeat{feat_i}, 1)+eps);
          otherwise
            error('unknown normalization!!!!!');
        end
    end
end

seg_x = sparse(cell2mat(segFeat));

end

function seg_feats = load_seg_feats(feat_path, seg_id)
seg_feats = [];

% Load segment feats if they were saved.
if exist(feat_path, 'file')
    seg_data = load(feat_path, 'seg_feats', 'seg_id');

    if all(seg_id == seg_data.seg_id)
        seg_feats = seg_data.seg_feats;
    else
        id_perm = arrayfun(@(x) find(x == seg_data.seg_id, 1), ...
                           seg_id, 'UniformOutput', false);

        if ~any(cellfun(@isempty, id_perm))
            seg_feats = seg_data.seg_feats(:, id_perm);
        end
    end
end

end
