Code covered by the BSD License  

Highlights from
Toolbox Wavelets

image thumbnail
from Toolbox Wavelets by Gabriel Peyre
Wavelet transform and coding functions, including other more exotic transforms (laplacian, steerable

perform_segmentation(E,options)
function [B,err] = perform_segmentation(E,options)

% perform_segmentation - perform image segmentation
%
%   B = perform_segmentation(E,options);
%
%   E is an (n,n,k) set of k dimensional features vectors (one per pixel in
%   the image).
%
%   options.segmentation_method can be 
%       'simple': E(:,:,k) should be minimum in area where texture i is
%           present. The algorithm uses a simple filtering.
%       'chan-vese': E(:,:,k) should be minimum in area where texture i is
%          present. The algorithm uses a Chan-Vese active contour. 
%       'kmeans': E(i,j,:) is a feature vector around pixel (i,j).
%           the algorithm compute feature center for each texture using
%           k-means and then perform nearest-neighbors classification.
%
%   Copyright (c) 2007 Gabriel Peyre

n = size(E,1);

ntextures = size(E,3);

segmentation_method = getoptions(options, 'segmentation_method', 'simple');
oracle = getoptions(options, 'oracle', []);
lambda = getoptions(options, 'lambda', 1.2);

% for testing various filtering sizes
if isempty(oracle)
    nmu = 1;
    mu = getoptions(options, 'mu', 4);
    mu_list = mu;
else
    nmu = getoptions(options, 'nmu', 18);
    mumax = getoptions(options, 'mumax', 10);
    mu_list = linspace( 0.1,mumax,nmu );
end

% best dictionary
switch segmentation_method
    case 'simple'
        
        q = size(E,3);
        q1 = min(20,q); % PCA dimension
        err_list = []; B1 = {};
        for i=1:nmu
            progressbar(i,nmu);
            EE = perform_blurring(E,mu_list(i));
            [tmp,B1{i}] = min(EE,[],3);
            if not(isempty(oracle))
                err_list(i) = 1 - sum( B1{i}(:)~=oracle(:) )/n^2;
            else
                err_list(i) = 0;
            end
        end
        [err,i] = max(err_list);
        B = B1{i};
        
    case 'kmeans'
        
        %% perform clustering via Kmeans
        ntextures = getoptions(options, 'ntextures',[],1);
        q = size(E,3);
        q1 = min(20,q); % PCA dimension
        err_list = []; B1 = {};
        for i=1:nmu
            progressbar(i,nmu);
            % apply non-linearity + smoothing
            E1 = perform_blurring(E,mu_list(i));
            E1 = reshape(E1,[n^2 q])';
            % add spacial relationship
            % rescale the features
            E1 = E1 - repmat(min(E1,[],2),[1 n^2]);
            E1 = E1 ./ repmat( median(E1,2),[1 n^2]);
            % dimension reduction
            [Y,E1] = pca(E1,q1);
            % do k-means on a subset
            options.nb_iter = 50;
            options.kmeans_code = 3;
            [B1{i},seeds,rms] = perform_kmeans(E1,ntextures,options);
            B1{i} = reshape(B1{i},n,n);
            [B1{i},err_list(end+1)] = fit_segmentation(B1{i},oracle);            
        end
        [err,i] = max(err_list);
        B = B1{i};
            
    case 'chan-vese'

        % active contours
        En = zeros(n,n,ntextures);
        if ntextures==2
            En = E(:,:,1)-E(:,:,2);
        elseif ntextures==4
            v = {[4 2] [3 1] [4 3] [2 1] };
            for k=1:4
                En(:,:,k) = E(:,:,v{k}(1))-E(:,:,v{k}(2)); a =  En(:,:,k);
                % En(:,:,k) = En(:,:,k)-median(a(:)); a =  En(:,:,k);
                % En(:,:,k) = lambda * En(:,:,k)/std( a(:) );
            end
        else
            error('Works only for 2/4 textures');
        end
        % normalize
        options.E = lambda * En/sqrt( mean(En(:).^2) );
        if not(isfield(options, 'Tmax'))
            options.Tmax = 180;
        end
        options.redistance_freq = 10;
        options.dt = 0.5;
        options.display_freq = 10;
        if not(isfield(options, 'nb_svg'))
            options.nb_svg = 0;
        end
        options.solver = 'grad';
        namec = 'small-disks';  % initial shape
        Dist0 = compute_levelset_shape(namec, n);
        if ntextures==4 % shift this function for the other phase
            sel = mod( (1:n) + 8,n )+1;
            Dist0 = cat(3,Dist0,Dist0(sel,sel));
        end
        fprintf('Active contours:');
        Dist = perform_active_contour(Dist0, 'chan-vese-user', options);
        if ntextures==2
            B = (Dist>0)+1;
        else
            B = zeros(n); D1 = Dist(:,:,1); D2 = Dist(:,:,2);
            B(D1<0 & D2<0) = 1;
            B(D1<0 & D2>=0) = 2;
            B(D1>=0 & D2<0) = 3;
            B(D1>=0 & D2>=0) = 4;
        end
end

err = 0;
if not(isempty(oracle))
    [B,err] = fit_segmentation(B,oracle);
end



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [B,err] = fit_segmentation(B,B0)

if isempty(B0)
    return;
end

n = size(B,1);
% check for optimal permutation to fit B0
ntextures = max(B(:));
P = perms(1:ntextures);
err1 = [];
for k=1:size(P,1)
    pp = P(k,:)';
    err1(k) = sum( P(k,B(:))'==B0(:) )/n^2;
end
[err,k] = max(err1);
B = reshape( P(k,B), size(B) );

Contact us at files@mathworks.com