function [img_pred, img_rank] = predict_single_image(config, model, feat_types, ...
                                                     parent_dirs, name_root)

% Load the prediction if it already exists.
pred_dir = fullfile(config.paths.pred_results, ...
                    [model.params.model_type '-predictions']);
pred_path = fullfile(pred_dir, [name_root '.mat']);

if exist(pred_path, 'file')
    % fprintf('Loading prediction from %s\n', pred_path);
    preds = load(pred_path);
    img_pred = preds.img_pred;

    if ~isfield(preds, 'img_rank')
        img_rank = rank_img_pred(img_pred);
    else
        img_rank = preds.img_rank;
    end
    return
end

[X, ~, ~, segID] = ...
    aggregate_img_features(parent_dirs, name_root, ...
                           config, feat_types);
X = X';

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

if isfield(model, 'mu')
    X = bsxfun(@minus, X, model.mu);
end

if isfield(model, 'siginv')
    X = bsxfun(@times, X, model.siginv);
end

scores = [];
ranks = [];
n_segs = size(X, 1);
n_lab = length(model.class_name);
switch model.params.model_type
  case 'one-vs-all'
    [~, ~, scores] = test_svm(model.svm, model.params, X);
    scores(:, model.svm.Label) = scores;
  case 'binary'
    scores = zeros(n_segs, n_lab);    
    for ind = 1:length(model.svm)
        [~, ~, svm_scores] = test_svm(model.svm(ind), model.params, X);        
        pos_ind = find(model.svm(ind).Label);
        scores(:, ind) = svm_scores(:, pos_ind);
    end
  case 'rank'
    scores = zeros(n_segs, n_lab^2);    
    for ind = 1:length(model.pair_inds)
        [~, ~, svm_scores] = test_svm(model.svm(ind), model.params, X);        
        pos_ind = find(model.svm(ind).Label);
        scores(:, model.pair_inds(ind)) = svm_scores(:, pos_ind);
    end
    scores = reshape(scores, [n_segs n_lab n_lab]);
    scores = scores + permute((1 - scores).*(scores ~= 0), [1 3 2]);
    [~, ranks] = sort(sum(scores, 3), 2);
    ranks = (ranks - 1)*size(ranks, 1);
    ranks = bsxfun(@plus, ranks, [1:size(ranks, 1)]');
    ranks(ranks(:)) = meshgrid(1:n_lab, 1:size(ranks, 1));
  otherwise
    error('unknown model type');
end

if isempty(ranks)
    img_pred = zeros(prod(size(label_img)), n_lab);
    for seg_i = 1:n_segs
        seg_inds = find(label_img == segID(seg_i));
        img_pred(seg_inds, :) = repmat(scores(seg_i, :), [size(seg_inds, 1) 1]);
    end
    img_pred = reshape(img_pred, [size(label_img) n_lab]);
        
    if size(img_pred, 3) == 8
        img_pred = img_pred(:,:,2:end);
    end

    save(pred_path, 'img_pred');
    img_rank = rank_img_pred(img_pred);
else
    img_pred = [];
    img_rank = zeros(prod(size(label_img)), n_lab);
    for seg_i = 1:n_segs
        seg_inds = find(label_img == segID(seg_i));
        img_rank(seg_inds, :) = repmat(ranks(seg_i, :), [size(seg_inds, 1) 1]);
    end
    img_rank = reshape(img_rank, [size(label_img) n_lab]);
    save(pred_path, 'img_pred', 'img_rank');
end

end

function img_rank = rank_img_pred(img_pred) 
img_size = size(img_pred);
[~, img_rank] = sort(...
    reshape(img_pred, [prod(img_size([1 2])) img_size(3)]), ...
    2, 'descend');
img_rank = (img_rank - 1)*size(img_rank, 1);
img_rank = bsxfun(@plus, img_rank, [1:size(img_rank, 1)]');
img_rank(img_rank(:)) = meshgrid(1:img_size(3), 1:size(img_rank, 1));
img_rank = reshape(img_rank, img_size);
end
