www.pudn.com > ms.rar > func_mean_shift_image_segmentation_demo.m, change:2008-07-18,size:4370b


function func_mean_shift_image_segmentation_demo 
% A simple demo for image segmentation using mean-shift. This program is 
% inspired by Bart Finkston's program at 
% http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=10161&objectType=file 
% Note: 
% 1. This program only consider the image's intensity value. 
% 2. This program can only handle gray image only. 
% 
 
close all; clear all; clc; profile on; 
 
infilename = 'test.jpg'; 
 
img_orig = im2double(imread(infilename)); 
img         = img_orig(:)'; 
% user defined parameter 
bandWidth   = 0.2;              % bandwidth parameter 
stopThresh  = 5;                % stopping criterion for iteration 
 
 
numPts          = length(img); 
numClust        = 0; 
bandSq          = bandWidth^2; 
initPtInds      = 1:numPts; 
 
 
clustCent       = [];                                   %center of clust 
beenVisitedFlag = zeros(1,numPts,'uint8');              %track if a points been seen already 
numInitPts      = numPts;                               %number of points to posibaly use as initilization points 
clusterVotes    = zeros(1,numPts,'uint16');             %used to resolve conflicts on cluster membership 
 
while numInitPts 
    rand('state', sum(100*clock));                      %set the random seed as the clock 
    tempInd         = ceil((numInitPts-1e-6)*rand);     %pick a random seed point 
    stInd           = initPtInds(tempInd);              %use this point as start of mean 
    myMean          = img(stInd);                       %intilize mean to this points location 
    myMembers       = [];                               %points that will get added to this cluster                           
    thisClusterVotes    = zeros(1,numPts,'uint16');     %used to resolve conflicts on cluster membership 
 
    while 1     %loop untill convergence 
         
        sqDistToAll = (repmat(myMean,1,numPts) - img).^2;       %dist squared from mean to all points still active 
        inInds      = find(sqDistToAll < bandSq);               %points within bandWidth 
        thisClusterVotes(inInds) = thisClusterVotes(inInds)+1;  %add a vote for all the in points belonging to this cluster 
         
        myOldMean   = myMean;                                   %save the old mean 
        myMean      = mean(img(inInds));                        %compute the new mean 
        myMembers   = [myMembers inInds];                       %add any point within bandWidth to the cluster 
        beenVisitedFlag(myMembers) = 1;                         %mark that these points have been visited 
         
        %**** if mean doesn't move much stop this cluster *** 
        if norm(myMean-myOldMean) < stopThresh 
             
            %check for merge posibilities 
            mergeWith = 0; 
            for cN = 1:numClust 
                distToOther = norm(myMean-clustCent(cN));       %distance from posible new clust max to old clust max 
                if distToOther < bandWidth/2                    %if its within bandwidth/2 merge new and old 
                    mergeWith = cN; 
                    break; 
                end 
            end 
             
             
            if mergeWith > 0    % something to merge 
                clustCent(mergeWith)       = 0.5*(myMean+clustCent(mergeWith));                 %record the max as the mean of the two merged (I know biased twoards new ones) 
                clusterVotes(mergeWith,:)    = clusterVotes(mergeWith,:) + thisClusterVotes;    %add these votes to the merged cluster 
            else    %its a new cluster 
                numClust                    = numClust+1;                   %increment clusters 
                clustCent(numClust)       = myMean;                         %record the mean   
                clusterVotes(numClust,:)    = thisClusterVotes; 
            end 
            break; 
        end 
 
    end 
   
    initPtInds      = find(beenVisitedFlag == 0);           %we can initialize with any of the points not yet visited 
    numInitPts      = length(initPtInds);                   %number of active points in set 
end 
 
 
[val,data2cluster] = max(clusterVotes,[],1);                %a point belongs to the cluster with the most votes 
 
img_seg_idx = reshape(data2cluster, size(img_orig,1), size(img_orig,2)); 
 
figure(1); 
imshow(img_seg_idx,[]);