1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| 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,[]); |
Partager