%x = imread('forme.PNG');
x=x(:,:,1);
[M N] = size(x);
%binarisation
level = graythresh(x);
img = im2bw(x,0.1);
%labellisation
CC = bwconncomp(img);
L = labelmatrix(CC);
%affihcage
figure('color',[0.3137 0.3137 0.5098])
subplot(221)
imshow(img)
title('binary image')
subplot(222)
imshow(label2rgb(L));
title('labeling')
The bounding box is the smallest box where an object can be enclosed. We define for each region two coordinates. One for the high left corner and the other for bottom right corner. In the next code, 'param' give for each region: [region number, number of region pixels, left limit, right limit, top limit, botom limit].
%nombre d'objet, number of objects
nbobj = max(max(L));
%parametres des objets, object's parameters
param=zeros(nbobj,6);
for i = 1 : nbobj
param(i,1)=i;
end
%param = [ numero , nb pixel , boite_gauche , boite_droite , boite_haut ,
%boite_bas]
for i = 1 : M
for j = 1 : N
if L(i,j)~=0
numero = L(i,j);
param(numero,2)= param(numero,2) + 1 ;
if param(numero,3)==0 || param(numero,3)>j
param(numero,3)=j;
end
if param(numero,4)==0 || param(numero,4)<j
param(numero,4)=j;
end
if param(numero,5)==0 || param(numero,5)>i
param(numero,5)=i;
end
if param(numero,6)==0 || param(numero,6)<i
param(numero,6)=i;
end
end
end
end
% supression petit objet
var =1;
for i = 1 : nbobj
if param(i,2)>10
parametre(var,:)=param(i,:);
var=var+1;
end
end;
nbobj = size(parametre,1);
At the end of the code, We remove the small regions.
There is the plot of the regions:
For the compute, we use the x and y coordinate of every pixel of a region and the total number of pixel of the region. We compute the sum of coordinates in x for every point and we divide by the total number of pixel of the region. Same operation for y. The coordinates found are the gravity center of the object. We have the next equations:
Where xc and yc are the coordinates of gravity center, I the binary image where I(x,y)=1 if the pixel is a part of the region else I(x,y)=0. M is the number of line and N the number of column. nbpoint is the total pixel number of the region.
for i = 1 : nbobj
poidsx = 0;
poidsy = 0;
nbpoint = 0;
for x = parametre(i,5) : parametre(i,6)
for y = parametre(i,3) : parametre(i,4)
if L(x,y) == parametre(i,1)
poidsx = poidsx + x;
poidsy = poidsy + y;
nbpoint = nbpoint + 1;
end
end
parametre(i,7)=round(poidsx/nbpoint);%centre ligne
parametre(i,8)=round(poidsy/nbpoint);%centre colonne
end
end
% affichage centre de gravité
subplot(223)
imshow(img)
hold on
for i = 1 : nbobj
plot(parametre(i,8),parametre(i,7),'r+','LineWidth',1)
end
title('center of gravity')
It exist alot of algorythm to detect region contour for binary images. I explain one of them.
direction:
Consider a pixel p of coordinate 0,0. We can define 8 possible directions around it.
The object contour will be define following those 8 directions. The same reasoning can be make with the 4 direction of odd indexes.
For every object, we travel its box of M line and N column start by the left top pixel.
We know the first pixel which be a part of the object will be a pixel to the external contour.
Thanks to this assertion, we know that the first contour computed will be the external contour.
accordingly, all the other contour of the same object will be internal contours.
From the first coordinates, we follow the external contour in the clockwise.
How find the next coordinate pixel?
We use the last direction. As we are in the first pixel of the external contour detected, we know that the direction were d1.
we take the 6th direction after in clockwise. It will be d6.
From here we look at the pixel in that direction and we check if it is a part of the object.
If it is a part then we found the next coordinates of the contour. we save the direction that the contour takes.
If it is not a part then we turn the direction of 1 in clockwise (d6->d7) until to find a pixel of the object.
If there is no pixel then the object size is one pixel.
We restart those operations until to find the start pixel of the contour.
Once the external contour find, we continu the treatment to find the internal contours.
we examine the rest of the box from the start pixel of last contour.
We make several hypothesis to find a pixel be owned to an internal contour.
- the pixel is a part of the region.
- the sum of the pixel and its 8 neighbours is different of 9 time the value of the region (if région = 1, different of 9)
- the pixel and its 8 neighbours are not a part of another contour.
then we follow the same method than for the first contour but the first direction to take is not d1, it's d5.
sens=2;
contour = zeros(size(L));
figure(1)
for i = 1 : nbobj
boite = L(parametre(i,5):parametre(i,6),parametre(i,3):parametre(i,4));
boite = wextend(2,'zpd',boite,1);
numerodecontour = 0;
boite_contour = zeros(size(boite));
label = parametre(i,1);
ds = sens;
for m = 2 : size(boite,1)-1
for n = 2 : size(boite,2)-1
if boite(m,n) == label && sum(sum(boite_contour(m-1:m+1,n-1:n+1)))==0 && sum(sum(boite(m-1:m+1,n-1:n+1)))~=9*label
numerodecontour = numerodecontour+1;
xs=[m n];
%label/Lc
%boite/I
%boite_contour/LM
[xt,dnext]= findnextpoint(xs,ds,boite,boite_contour,label);
c{i,numerodecontour}=[xs(1)+parametre(i,5)-1, xs(2)+parametre(i,3)-1 dnext];
xp=xs;
xc=xt;
fin = (xs(1)==xt(1) && xs(2)==xt(2));
while fin==0
boite_contour(xp(1),xp(2))=numerodecontour;
dnext = mod(dnext+5,8)+1;
[xn,dnext]= findnextpoint(xc,dnext,boite,boite_contour,label);
xp=xc;
c{i,numerodecontour}=[c{i,numerodecontour};xp(1)+parametre(i,5)-1, xp(2)+parametre(i,3)-1 dnext];
xc=xn;
fin = (xs(1)==xp(1) && xs(2)==xp(2)) || (xt(1)==xn(1) && xt(2)==xn(2));
end
boite_contour(xn(1),xn(2))=numerodecontour;
c{i,numerodecontour}=[c{i,numerodecontour};xn(1)+parametre(i,5)-1, xn(2)+parametre(i,3)-1 dnext];
ds=7;
end
end
end
i
contour(parametre(i,5):parametre(i,6),parametre(i,3):parametre(i,4))=contour(parametre(i,5):parametre(i,6),parametre(i,3):parametre(i,4))+boite_contour(2:end-1,2:end-1);
end
subplot(224)
imshow(contour)
title('contour')
function [xc,d]= findnextpoint(xc,d,I,LM,label)
direction = [ 0 1
1 1
1 0
1 -1
0 -1
-1 -1
-1 0
-1 1 ];
for i = 0 : 7
xp(1)=xc(1)+ direction(d,1);
xp(2)=xc(2)+ direction(d,2);
if I(xp(1),xp(2))~=label
d=mod(d,8)+1;
else
xc(1)=xp(1);
xc(2)=xp(2);
break
end
end
There is the plot of the contour by region.
Thanks to start coordinates of the contour and all the other directions, It is possible to reconstruct the contour.
We use again the direction table :
We take the next pixel as the pixel which is marked by the direction saved.If, for example, the next direction is d4 then x=x+1 et y=y-1.
This method is used by the RLE compression (Run Length Encoding).
delta/direction | d1 | d2 | d3 | d4 | d5 | d6 | d7 | d8 |
dx | 0 | 1 | 1 | 1 | 0 | -1 | -1 | -1 |
dy | 1 | 1 | 0 | -1 | -1 | -1 | 0 | 1 |
direction = [ 0 1
1 1
1 0
1 -1
0 -1
-1 -1
-1 0
-1 1 ];
figure(4)
[nbregion nbcontour]=size(c);
for i = 1 : nbregion
img=zeros(M,N);
for j = 1:nbcontour
if ~isempty(c{i,j})
contour = c{i,j};
x = contour(1,1);
y = contour(1,2);
img(x,y)=255;
for indice = 1 : size(contour)
x = x + direction(contour(indice,3),1);
y = y + direction(contour(indice,3),2);
img(x,y)=255;
end
end
end
end
Thanks to directions of contours, we can compute their lengths. For every dots of contour, we sum the length with respect to the directions.
If the direction is odd index then the length is
. If the direction is peer index then the length is
The pertimeter of a region is its external contour length. However, this compute overestimate the length. To correct it, we multiply
the length by a factor of 0.95.
[nbregion nbcontour]=size(c);
for i = 1 : nbregion
for j = 1:nbcontour
if ~isempty(c{i,j})
contour = c{i,j};
taille = 0;
for indice = 1 : size(contour)
direction = contour(indice,3) ;
longueurdirection = mod(direction,2);
if longueurdirection == 1
taille = taille + 1;
else
taille = taille + 2^0.5;
end
contour(indice,4)=taille;
end
c{i,j} = contour;
end
end
end
Where aire is the aera of the region, M the number of line of the bounding box and N its number of column. Ir(x,y)=1 if the pixel is a part of the region else Ir(x,y)=0;
for i = 1 : nbobj
boite = L(parametre(i,5):parametre(i,6),parametre(i,3):parametre(i,4));
label = parametre(i,1);
for m = 1 : size(boite,1)
for n = 1 : size(boite,2)
if boite(m,n)==label
aire(i,1)=aire(i,1)+1;
end
end
end
end
The circularity is an index which represente the circle shape of the region.
More an object is circular more its value is close to 1, More it is different of a circle more its value is close to 0.
Where aire is aera of the object and perimeter its perimeter.
circularity = zeros(nbobj,1);
[nbregion nbcontour]=size(c);
for i = 1 : nbregion
contour = c{i,1};
perimeter = contour(end,4);
aera = aire(i);
circularity(i)= 4*pi*(aera / ((0.95*perimeter)^2));
end
Copyright © 2010-2014, all rights reserved, contact: operationpixel@free.fr