Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
fbreve committed Jan 21, 2019
0 parents commit 79cd3ca
Show file tree
Hide file tree
Showing 15 changed files with 872 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
34 changes: 34 additions & 0 deletions example.asv
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
% This is an usage example of the Interactive Image Segmentation using
% Label Propagation through Complex Networks method.
%
% BREVE, Fabricio Aparecido. Interactive Image Segmentation using Label
% Propagation through Complex Networks. Expert System With Applications,
% v. 123, p.18 � 33, 2019.
%
% by Fabricio Breve - 21/01/2019
%
% Loading example image
img = imread('ralph.jpg');
% Loading scribbles image
imgslab = imread('ralph-scribble.png');
% Loading ground-truth image
gt = imread('ralph-gt.png');
% Calling method to segment the image with default parameters
disp('Running image segmentation...');
tStart = tic;
[owner, pot] = lpcn(img, imgslab);
tElapsed = toc(tStart);
% Converting output to image
imgres = own2img(owner,img,0);
% Calculating error rate
y = imgeval(imgres, gt, imgslab);
% Displaying numerical results
fprintf('Error Rate: %0.4f - Execution Time: %0.4fs\n',y,tElapsed);
% Applying mask to the original image
imgres3 = repmat(imgres,1,1,3)./255;
imgseg = img .* imgres3;
imgseg(imgres3==0)=255;
% Showing segmentation results
subplot(2,2,1), imshow(img),
subplot(2,2,2), imshow(imgslab),
subplot(2,2,3), imshow(imgr
35 changes: 35 additions & 0 deletions example.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
% This is an usage example of the Interactive Image Segmentation using
% Label Propagation through Complex Networks method.
%
% BREVE, Fabricio Aparecido. Interactive Image Segmentation using Label
% Propagation through Complex Networks. Expert System With Applications,
% v. 123, p.18 – 33, 2019.
%
% by Fabricio Breve - 21/01/2019
%
% Loading example image
img = imread('ralph.jpg');
% Loading scribbles image
imgslab = imread('ralph-scribble.png');
% Loading ground-truth image
gt = imread('ralph-gt.png');
% Calling method to segment the image with default parameters
disp('Running image segmentation...');
tStart = tic;
[owner, pot] = lpcn(img, imgslab);
tElapsed = toc(tStart);
% Converting output to image
imgres = own2img(owner,img,0);
% Calculating error rate
y = imgeval(imgres, gt, imgslab);
% Displaying numerical results
fprintf('Error Rate: %0.4f - Execution Time: %0.4fs\n',y,tElapsed);
% Applying mask to the original image
imgres3 = repmat(imgres,1,1,3)./255;
imgseg = img .* imgres3;
imgseg(imgres3==0)=255;
% Showing segmentation results
subplot(2,2,1), imshow(img),
subplot(2,2,2), imshow(imgslab),
subplot(2,2,3), imshow(imgres),
subplot(2,2,4), imshow(imgseg);
10 changes: 10 additions & 0 deletions imgeval.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
% Avaliação de imagens segmentadas do Microsoft GrabCut dataset
% Uso: error = imgeval(imgres, gt, imgslab)
% imgres - imagem resultante da segmentação
% gt - ground truth
% imgslab - imagem
function error = imgeval(imgres, gt, imgslab)
totunlpix = sum(sum(imgslab==128 & gt~=128));
toterrpix = sum(sum(abs(double(imgres)-double(gt))>1 & imgslab==128 & gt~=128));
error = toterrpix/totunlpix;
end
262 changes: 262 additions & 0 deletions lpcn.asv
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
% Interactive Image Segmentation using Label Propagation through Complex Networks
% by Fabricio Breve - 21/01/2019
%
% If you use this algorithm, please cite:
%
% BREVE, Fabricio Aparecido. Interactive Image Segmentation using Label
% Propagation through Complex Networks. Expert System With Applications,
% v. 123, p.18 � 33, 2019.
%
% Usage: [owner, pot, ti1, ti2] = cnsslis9(img, imgslab, fw, k, sigma, disttype, omega, maxiter)
%
% INPUT:
% img - Image to be segmented (24 bits, 3 channels - RGB)
% imgslab - Image with labeled/unlabeled pixel information (0 is reserved
% for ignored background, 64 - background class, 128 -
% unlabeled pixels, 255 - foreground class. For multiclass use
% [1~63; 65~127; 129~254] for other classes. (Obs: use only grayscale 8-bit indexed image)
% fw - vector of feature weights
% k - each node is connected to its k-neirest neighbors
% disttype - use 'euclidean', etc.
% omega - Default: 0.001 (lower it to stop earlier, accuracy may be lower; increase to increase accuracy)
% maxiter - maximum amount of iterations
%
% OUTPUT:
% owner - vector of classes assigned to each data item
% pot - continuos-output with pertinence of each data item to each
% class
% ti1 - total iterations executed on phase 1
% ti2 - total iterations executed on phase 2

function [owner, pot, ti1, ti2] = lpcn(img, imgslab, fw, k, sigma, disttype, omega, maxiter)
if (nargin < 8) || isempty(maxiter)
maxiter = 500000; % n�mero de itera��es
end
if (nargin < 7) || isempty(omega)
omega = 0.0001;
end
if (nargin < 6) || isempty(disttype)
disttype = 'euclidean'; % dist�ncia euclidiana n�o normalizada
end
if (nargin < 5) || isempty(sigma)
sigma = 0.5;
end
if (nargin < 4) || isempty(k)
k = 10; % quantidade de vizinhos mais pr�ximos
end
if (nargin < 3) || isempty(fw)
fw = ones(1,9);
%fw = [1 1 0.5 0.5 0.5 0.5 0.5 0.5 0.5];
end
% tratamento da entrada
k = uint16(k);
ti1 = 0;
ti2 = 0;

if k>0
% reduzindo imagem
rs_img = imresize(img,1/3,'bicubic');
otherlabels = [1:63 65:127 129:254];
if isempty(intersect(unique(imgslab),otherlabels)) % se h� apenas duas classes
rs_imgslab = imresize(imgslab,1/3,'bilinear');
rs_imgslab(rs_imgslab<64 & rs_imgslab>0) = 64;
rs_imgslab(rs_imgslab<128 & rs_imgslab>64) = 64;
rs_imgslab(rs_imgslab>128) = 255;
else % mais de duas classes
rs_imgslab = imresize(imgslab,1/3,'nearest');
end

[rs_dim,qtnode,X,slabel,nodeval,nclass] = getFeatures(rs_img,rs_imgslab,fw);

% j� estamos normalizando de qualquer forma
if strcmp(disttype,'seuclidean')==1
disttype='euclidean';
end

indval = find(nodeval); % pega s� os �ndices dos pixels que n�o s�o do fundo ignorado
Xval = X(indval,:); % cria lista de pixels v�lidos (que n�o s�o do fundo ignorado)
qtnodeval = size(indval,1); % quantidade de n�s v�lidos (pixels v�lidos)
slabelval = slabel(indval); % r�tulos dos pixels v�lidos (n�o s�o do fundo ignorado)

nnonlabeled = sum(slabelval==0); % quantidade de n�s n�o rotulados

% lista de n�s n�o rotulados
indnonlabeled = uint32(find(slabelval==0));
% lista de n�s rotulados
labelednodes = uint32(find(slabelval>0));

% encontrando k-vizinhos mais pr�ximos
[KNN,KNND] = knnsearch(Xval,Xval(indnonlabeled,:),'K',k+1,'NSMethod','kdtree','Distance',disttype);
KNN = uint32(KNN);
clear XVal;
KNN = KNN(:,2:end); % eliminando o elemento como vizinho de si mesmo
KNND = KNND(:,2:end);
KNND = exp((-KNND.^2)./(2*sigma^2));
% ajustando todas as dist�ncias na m�xima poss�vel
potval = repmat(1/nclass,qtnodeval,nclass);
% zerando potenciais dos n�s rotulados
potval(labelednodes,:) = 0;
% ajustando potencial da classe respectiva do n� rotulado para m�ximo
potval(sub2ind(size(potval),labelednodes,slabelval(labelednodes))) = 1;
% calling the mex function
ti1 = lpcnloop(maxiter,nnonlabeled,indnonlabeled,omega,potval,k,KNN,KNND);

clear KNN slabelval KNNND;

pot = zeros(qtnode,nclass);
pot(:,1) = 1; % n�s de fundo ser�o associados � mesma classe da cor de �ndice 64.
pot(indval,:)=potval;

clear potval;
end

[dim,qtnode,X,slabel,nodeval,nclass] = getFeatures(img,imgslab,fw);
% Redimensionar matriz de potenciais
% (antes de redimensionar � preciso passar para matriz de 3 dimens�es e
% depois voltar para o formato anterior)
if k>0
pot = reshape(imresize(reshape(pot,rs_dim(1),rs_dim(2),nclass),[dim(1) dim(2)],'bilinear'),qtnode,nclass);
else
pot = repmat(1/nclass,qtnode,nclass);
end

% encontrando nos rotulados
labelednodes = find(slabel>0);
% zerando potenciais dos n�s rotulados
pot(labelednodes,:) = 0;
% ajustando potencial da classe respectiva do n� rotulado para 1
pot(sub2ind(size(pot),labelednodes,slabel(labelednodes))) = 1;

% PARTE 2!
%disp('Parte 2: Encontrando vizinhos...');
if k>0
indefnodesb = max(pot,[],2) < 1; % vetor onde 1 � n� indefinido e 0 � definido
else
indefnodesb = nodeval; % dessa forma todos os vetores de domin�ncia ficam vari�veis e a propaga��o ocorre entre todos os pixels. Por algum motivo isso funciona melhor na base da Microsoft.
end
indefnodes = uint32(find(indefnodesb)); % lista de n�s indefinidos
indefnodesc = size(indefnodes,1); % contagem de n�s indefinidos

if indefnodesc>0

%fprintf('Parte 2: %i n�s indefinidos. Pegando colabora��o de pixels vizinhos\n',size(indefnodes,1))

Ndist = zeros(size(X,1),8);
Nlist = zeros(size(X,1),8,'uint32');
Nsize = zeros(size(X,1),1,'uint8');
% Pesos das liga��es horizontais
for i=1:dim(1)
for j=1:dim(2)-1
ind1 = i+(j-1)*dim(1);
ind2 = ind1 + dim(1);
if indefnodesb(ind1) || indefnodesb(ind2)
p2addNeighbor;
end
end
end
% Peso das liga��es diagonais (\)
for i=1:dim(1)-1
for j=1:dim(2)-1
ind1 = i+(j-1)*dim(1);
ind2 = ind1+dim(1)+1;
if indefnodesb(ind1) || indefnodesb(ind2)
p2addNeighbor;
end
end
end
% Peso das liga��es verticais
for i=1:dim(1)-1
for j=1:dim(2)
ind1 = i+(j-1)*dim(1);
ind2 = ind1+1;
if indefnodesb(ind1) || indefnodesb(ind2)
p2addNeighbor;
end
end
end
% Peso das liga��es diagonais (/)
for i=1:dim(1)-1
for j=2:dim(2)
ind1 = i+(j-1)*dim(1);
ind2 = ind1-dim(1)+1;
if indefnodesb(ind1) || indefnodesb(ind2)
p2addNeighbor;
end
end
end
clear X;
% aplicando Gaussiana nas dist�ncias
Ndist = exp((-Ndist.^2)./(2*sigma^2));
% constantes
npart = indefnodesc; % quantidade de n�s ainda n�o rotulados
% vari�vel para guardar m�ximo potencial mais alto m�dio
% chamando o arquivo mex do strwalk25
%disp('Parte 2: Propaga��o de r�tulos...');
ti2 = lpccnsslis9loop2(maxiter, npart, nclass, omega, indefnodes, slabel, Nsize, Nlist, Ndist, pot);

if k==0
% zerando potenciais dos n�s rotulados
pot(labelednodes,:) = 0;
% ajustando potencial da classe respectiva do n� rotulado para 1
pot(sub2ind(size(pot),labelednodes,slabel(labelednodes))) = 1;
end

end
[~,owner] = max(pot,[],2);

function p2addNeighbor
Nsize(ind1) = Nsize(ind1) + 1;
Nsize(ind2) = Nsize(ind2) + 1;
Ndist(ind1,Nsize(ind1)) = norm(X(ind1,:)-X(ind2,:));
Ndist(ind2,Nsize(ind2)) = Ndist(ind1,Nsize(ind1));
Nlist(ind1,Nsize(ind1)) = ind2;
Nlist(ind2,Nsize(ind2)) = ind1;
end

end

function [dim,qtnode,X,slabel,nodeval,nclass] = getFeatures(img,imgslab,fw)

% Aten��o: Atributo Linha e HSV est�o errados em todas as vers�es anteriores deste algoritmo!

% Dimens�es da imagem
dim = size(img);
qtnode = dim(1)*dim(2);
X = zeros(qtnode,9);
% primeiro e segundo elementos s�o linha e coluna normalizadas no intervalo 0:1
X(:,1:2) = [repmat(((1:dim(1))/dim(1))',dim(2),1), reshape(repmat((1:dim(1))/dim(1),dim(2),1),dim(1)*dim(2),1)];
% depois vem os 3 elementos RGB normalizados em 0:1
imgvec = double(squeeze(reshape(img,dim(1)*dim(2),1,3)))/255;
X(:,3:5) = imgvec;
% depois vem os 3 elementos HSV
imghsv = rgb2hsv(double(img)/255);
X(:,6) = squeeze(reshape(imghsv(:,:,3),dim(1)*dim(2),1,1));
% em seguida ExR, ExG, e ExB
exr = 2.*double(img(:,:,1)) - double(img(:,:,2)) - double(img(:,:,3));
exg = 2.*double(img(:,:,2)) - double(img(:,:,1)) - double(img(:,:,3));
exb = 2.*double(img(:,:,3)) - double(img(:,:,1)) - double(img(:,:,2));
imgex = cat(3, exr, exg, exb);
clear exr exg exb;
X(:,7:9) = squeeze(reshape(imgex,dim(1)*dim(2),1,3));
X = zscore(X) .* repmat(fw,qtnode,1);
% Converter imagem com r�tulos em vetor de r�tulos
slabelraw = reshape(imgslab,dim(1)*dim(2),1);
% montar vetor onde 0 � n� do fundo n�o considerado e 1 � n� v�lido
nodeval = zeros(qtnode,1);
nodeval(slabelraw~=0)=1;
% ajustar vetor de r�tulos
slabel = zeros(qtnode,1,'uint16');
slabel(slabelraw==0)=1; % fundo n�o considerado
slabel(slabelraw==64)=1; % c/ r�tulo - fundo
otherlabels = [1:63 65:127 129:254];
olfound = intersect(unique(slabelraw),otherlabels);
if isempty(olfound) % se n�o outros r�tulos, i.e., h� apenas duas classes
nclass=2;
else % se h� mais r�tulos
nclass=size(olfound,1)+2;
for i=1:nclass-2
slabel(slabelraw==olfound(i)) = i+1;
end
end
slabel(slabelraw==255)=nclass; % c/ r�tulo - objeto
end
Loading

2 comments on commit 79cd3ca

@nasrin3994
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hello.nice too meet you.can you send me matlab code for ralph-gt& ralph-scribble&ralph -scribblemix?

thank you very much

@fbreve
Copy link
Owner Author

@fbreve fbreve commented on 79cd3ca Jul 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no code for that. I didn't build a GUI yet. For now, I build the scribbles and gt files on image editing software.

Please sign in to comment.