Segment unfocused background pixels from foreground - Active contours

2 views (last 30 days)
Hi - I have attached an image of some particles taken from a microscope. It is quite clear what is foreground and what is below the surface and makes up the blurry background. I would like to remove the background, or just isolate the foreground particles for further analysis. I have attempted active contour method (Chan-Vese), however this seems too sensitive and included the background areas as well as my desire particles. Is there a way to implement a less sensitive version of this?
Any advice would be greatly appreciated.
Thanks, Joe
Usage of varibles:
% input:
% I = any gray/double/RGB input image
% mask = initial mask, either customerlized or built-in
% num_iter = total number of iterations
% mu = weight of length term
% method = submethods pick from ('chen','vector','multiphase')
%
% Types of built-in mask functions
% 'small' = create a small circular mask
% 'medium' = create a medium circular mask
% 'large' = create a large circular mask
% 'whole' = create a mask with holes around
% 'whole+small' = create a two layer mask with one layer small
% circular mask and the other layer with holes around
% (only work for method 'multiphase')
% Types of methods
% 'chen' = general CV method
% 'vector' = CV method for vector image
% 'multiphase'= CV method for multiphase (2 phases applied here)
%
% output:
% phi0 = updated level set function
function seg = chenvese(I,mask,num_iter,mu,method)
if true
% code
end
%-- Default settings
% length term mu = 0.2 and default method = 'chan'
if(~exist('mu','var'))
mu=0.2;
end
if(~exist('method','var'))
method = 'chan';
end
%-- End default settings
%-- Initializations on input image I and mask
% resize original image
s = 200./min(size(I,1),size(I,2)); % resize scale
if s<1
I = imresize(I,s);
end
% auto mask settings
if ischar(mask)
switch lower (mask)
case 'small'
mask = maskcircle2(I,'small');
case 'medium'
mask = maskcircle2(I,'medium');
case 'large'
mask = maskcircle2(I,'large');
case 'whole'
mask = maskcircle2(I,'whole');
%mask = init_mask(I,30);
case 'whole+small'
m1 = maskcircle2(I,'whole');
m2 = maskcircle2(I,'small');
mask = zeros(size(I,1),size(I,2),2);
mask(:,:,1) = m1(:,:,1);
mask(:,:,2) = m2(:,:,2);
otherwise
error('unrecognized mask shape name (MASK).');
end
else
if s<1
mask = imresize(mask,s);
end
if size(mask,1)>size(I,1) || size(mask,2)>size(I,2)
error('dimensions of mask unmathch those of the image.')
end
switch lower(method)
case 'multiphase'
if (size(mask,3) == 1)
error('multiphase requires two masks but only gets one.')
end
end
end
switch lower(method)
case 'chan'
if size(I,3)== 3
P = rgb2gray(uint8(I));
P = double(P);
elseif size(I,3) == 2
P = 0.5.*(double(I(:,:,1))+double(I(:,:,2)));
else
P = double(I);
end
layer = 1;
case 'vector'
s = 200./min(size(I,1),size(I,2)); % resize scale
I = imresize(I,s);
mask = imresize(mask,s);
layer = size(I,3);
if layer == 1
display('only one image component for vector image')
end
P = double(I);
case 'multiphase'
layer = size(I,3);
if size(I,1)*size(I,2)>200^2
s = 200./min(size(I,1),size(I,2)); % resize scale
I = imresize(I,s);
mask = imresize(mask,s);
end
P = double(I); %P store the original image
otherwise
error('!invalid method')
end
%-- End Initializations on input image I and mask
%-- Core function
switch lower(method)
case {'chan','vector'}
%-- SDF
% Get the distance map of the initial mask
mask = mask(:,:,1);
phi0 = bwdist(mask)-bwdist(1-mask)+im2double(mask)-.5;
% initial force, set to eps to avoid division by zeros
force = eps;
%-- End Initialization
%-- Display settings
figure();
subplot(2,2,1); imshow(I); title('Input Image');
subplot(2,2,2); contour(flipud(phi0), [0 0], 'r','LineWidth',1); title('initial contour');
subplot(2,2,3); title('Segmentation');
%-- End Display original image and mask
%-- Main loop
for n=1:num_iter
inidx = find(phi0>=0); % frontground index
outidx = find(phi0<0); % background index
force_image = 0; % initial image force for each layer
for i=1:layer
L = im2double(P(:,:,i)); % get one image component
c1 = sum(sum(L.*Heaviside(phi0)))/(length(inidx)+eps); % average inside of Phi0
c2 = sum(sum(L.*(1-Heaviside(phi0))))/(length(outidx)+eps); % verage outside of Phi0
force_image=-(L-c1).^2+(L-c2).^2+force_image;
% sum Image Force on all components (used for vector image)
% if 'chan' is applied, this loop become one sigle code as a
% result of layer = 1
end
% calculate the external force of the image
force = mu*kappa(phi0)./max(max(abs(kappa(phi0))))+1/layer.*force_image;
% normalized the force
force = force./(max(max(abs(force))));
% get stepsize dt
dt=0.5;
% get parameters for checking whether to stop
old = phi0;
phi0 = phi0+dt.*force;
new = phi0;
indicator = checkstop(old,new,dt);
% intermediate output
if(mod(n,20) == 0)
showphi(I,phi0,n);
end;
if indicator % decide to stop or continue
showphi(I,phi0,n);
%make mask from SDF
seg = phi0<=0; %-- Get mask from levelset
subplot(2,2,4); imshow(seg); title('Global Region-Based Segmentation');
return;
end
end;
showphi(I,phi0,n);
%make mask from SDF
seg = phi0<=0; %-- Get mask from levelset
subplot(2,2,4); imshow(seg); title('Global Region-Based Segmentation');
case 'multiphase'
%-- Initializations
% Get the distance map of the initial masks
mask1 = mask(:,:,1);
mask2 = mask(:,:,2);
phi1=bwdist(mask1)-bwdist(1-mask1)+im2double(mask1)-.5;%Get phi1 from the initial mask 1
phi2=bwdist(mask2)-bwdist(1-mask2)+im2double(mask2)-.5;%Get phi1 from the initial mask 2
%-- Display settings
figure();
subplot(2,2,1);
if layer ~= 1
imshow(I); title('Input Image');
else
imagesc(P); axis image; colormap(gray);title('Input Image');
end
subplot(2,2,2);
hold on
contour(flipud(mask1),[0,0],'r','LineWidth',2.5);
contour(flipud(mask1),[0,0],'x','LineWidth',1);
contour(flipud(mask2),[0,0],'g','LineWidth',2.5);
contour(flipud(mask2),[0,0],'x','LineWidth',1);
title('initial contour');
hold off
subplot(2,2,3); title('Segmentation');
%-- End display settings
%Main loop
for n=1:num_iter
%-- Narrow band for each phase
nb1 = find(phi1<1.2 & phi1>=-1.2); %narrow band of phi1
inidx1 = find(phi1>=0); %phi1 frontground index
outidx1 = find(phi1<0); %phi1 background index
nb2 = find(phi2<1.2 & phi2>=-1.2); %narrow band of phi2
inidx2 = find(phi2>=0); %phi2 frontground index
outidx2 = find(phi2<0); %phi2 background index
%-- End initiliazaions on narrow band
%-- Mean calculations for different partitions
%c11 = mean (phi1>0 & phi2>0)
%c12 = mean (phi1>0 & phi2<0)
%c21 = mean (phi1<0 & phi2>0)
%c22 = mean (phi1<0 & phi2<0)
cc11 = intersect(inidx1,inidx2); %index belong to (phi1>0 & phi2>0)
cc12 = intersect(inidx1,outidx2); %index belong to (phi1>0 & phi2<0)
cc21 = intersect(outidx1,inidx2); %index belong to (phi1<0 & phi2>0)
cc22 = intersect(outidx1,outidx2); %index belong to (phi1<0 & phi2<0)
f_image11 = 0;
f_image12 = 0;
f_image21 = 0;
f_image22 = 0; % initial image force for each layer
for i=1:layer
L = im2double(P(:,:,i)); % get one image component
if isempty(cc11)
c11 = eps;
else
c11 = mean(L(cc11));
end
if isempty(cc12)
c12 = eps;
else
c12 = mean(L(cc12));
end
if isempty(cc21)
c21 = eps;
else
c21 = mean(L(cc21));
end
if isempty(cc22)
c22 = eps;
else
c22 = mean(L(cc22));
end
%-- End mean calculation
%-- Force calculation and normalization
% force on each partition
f_image11=(L-c11).^2.*Heaviside(phi1).*Heaviside(phi2)+f_image11;
f_image12=(L-c12).^2.*Heaviside(phi1).*(1-Heaviside(phi2))+f_image12;
f_image21=(L-c21).^2.*(1-Heaviside(phi1)).*Heaviside(phi2)+f_image21;
f_image22=(L-c22).^2.*(1-Heaviside(phi1)).*(1-Heaviside(phi2))+f_image22;
end
% sum Image Force on all components (used for vector image)
% if 'chan' is applied, this loop become one sigle code as a
% result of layer = 1
% calculate the external force of the image
% curvature on phi1
curvature1 = mu*kappa(phi1);
curvature1 = curvature1(nb1);
% image force on phi1
fim1 = 1/layer.*(-f_image11(nb1)+f_image21(nb1)-f_image12(nb1)+f_image22(nb1));
fim1 = fim1./max(abs(fim1)+eps);
% curvature on phi2
curvature2 = mu*kappa(phi2);
curvature2 = curvature2(nb2);
% image force on phi2
fim2 = 1/layer.*(-f_image11(nb2)+f_image12(nb2)-f_image21(nb2)+f_image22(nb2));
fim2 = fim2./max(abs(fim2)+eps);
% force on phi1 and phi2
force1 = curvature1+fim1;
force2 = curvature2+fim2;
%-- End force calculation
% detal t
dt = 1.5;
old(:,:,1) = phi1;
old(:,:,2) = phi2;
%update of phi1 and phi2
phi1(nb1) = phi1(nb1)+dt.*force1;
phi2(nb2) = phi2(nb2)+dt.*force2;
new(:,:,1) = phi1;
new(:,:,2) = phi2;
indicator = checkstop(old,new,dt);
if indicator
showphi(I, new, n);
%make mask from SDF
seg11 = (phi1>0 & phi2>0); %-- Get mask from levelset
seg12 = (phi1>0 & phi2<0);
seg21 = (phi1<0 & phi2>0);
seg22 = (phi1<0 & phi2<0);
se = strel('disk',1);
aa1 = imerode(seg11,se);
aa2 = imerode(seg12,se);
aa3 = imerode(seg21,se);
aa4 = imerode(seg22,se);
seg = aa1+2*aa2+3*aa3+4*aa4;
subplot(2,2,4); imagesc(seg);axis image;title('Global Region-Based Segmentation');
return
end
% re-initializations
phi1 = reinitialization(phi1, 0.6);%sussman(phi1, 0.6);%
phi2 = reinitialization(phi2, 0.6);%sussman(phi2,0.6);
%intermediate output
if(mod(n,20) == 0)
phi(:,:,1) = phi1;
phi(:,:,2) = phi2;
showphi(I, phi, n);
end;
end;
phi(:,:,1) = phi1;
phi(:,:,2) = phi2;
showphi(I, phi, n);
%make mask from SDF
seg11 = (phi1>0 & phi2>0); %-- Get mask from levelset
seg12 = (phi1>0 & phi2<0);
seg21 = (phi1<0 & phi2>0);
seg22 = (phi1<0 & phi2<0);
se = strel('disk',1);
aa1 = imerode(seg11,se);
aa2 = imerode(seg12,se);
aa3 = imerode(seg21,se);
aa4 = imerode(seg22,se);
seg = aa1+2*aa2+3*aa3+4*aa4;
%seg = bwlabel(seg);
subplot(2,2,4); imagesc(seg);axis image;title('Global Region-Based Segmentation');
end

Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!