Question Compter le squama des lézards


Un ami biologiste m'a demandé si je pouvais l'aider à faire un programme pour compter le squama (est-ce la bonne traduction?) des lézards.

Il m'a envoyé des images et j'ai essayé certaines choses sur Matlab. Pour certaines images, c'est beaucoup plus difficile que d'autres, par exemple quand il y a des régions plus sombres (noires). Au moins avec ma méthode. Je suis sûr que je peux obtenir une aide utile ici. Comment devrais-je améliorer cela? Ai-je pris la bonne approche?

Ce sont certaines des images.

pic1

pic2

J'ai obtenu les meilleurs résultats en suivant Traitement et comptage d'images à l'aide de MATLAB. Il s'agit essentiellement de transformer l'image en noir et blanc puis de la définir. Mais j'ai ajouté un peu d'érosion.

Voici le code:

img0=imread('C:...\pic.png');

img1=rgb2gray(img0);

%The output image BW replaces all pixels in the input image with luminance greater than level with the value 1 (white) and replaces all other pixels with the value 0 (black). Specify level in the range [0,1]. 
img2=im2bw(img1,0.65);%(img1,graythresh(img1));

imshow(img2)
figure;

 %erode
 se = strel('line',6,0);     
 img2 = imerode(img2,se);
 se = strel('line',6,90);   
 img2 = imerode(img2,se);
 imshow(img2)
figure;

imshow(img1, 'InitialMag', 'fit')

% Make a truecolor all-green image. I use this later to overlay it on top of the original image to show which elements were counted (with green)
 green = cat(3, zeros(size(img1)),ones(size(img1)), zeros(size(img1)));
 hold on
 h = imshow(green); 
 hold off


%counts the elements now defined by black spots on the image
[B,L,N,A] = bwboundaries(img2);
%imshow(img2); hold on;
set(h, 'AlphaData', img2)
text(10,10,strcat('\color{green}Objects Found:',num2str(length(B))))
figure;



%this produces a new image showing each counted element and its count id on top of it.
imshow(img2); hold on;
colors=['b' 'g' 'r' 'c' 'm' 'y'];
for k=1:length(B),
     boundary = B{k};
     cidx = mod(k,length(colors))+1;
     plot(boundary(:,2), boundary(:,1), colors(cidx),'LineWidth',2);
     %randomize text position for better visibility
     rndRow = ceil(length(boundary)/(mod(rand*k,7)+1));
     col = boundary(rndRow,2); row = boundary(rndRow,1);
     h = text(col+1, row-1, num2str(L(row,col)));
     set(h,'Color',colors(cidx),'FontSize',14,'FontWeight','bold');
end
figure; 
spy(A);

Et ce sont certains des résultats. Dans le coin supérieur gauche, vous pouvez voir combien ont été comptés.

De plus, je pense qu'il est utile que les éléments comptés soient marqués en vert afin que l'utilisateur puisse au moins savoir lesquels doivent être comptés manuellement.

enter image description here


10
2018-04-02 07:52


origine


Réponses:


Il y a une voie à considérer: segmentation du bassin versant. Voici un exemple rapide et sale avec votre première image (cela suppose que vous avez la boîte à outils IP):

raw=rgb2gray(imread('lCeL8.jpg'));

Icomp = imcomplement(raw);
I3 = imhmin(Icomp,20);
L = watershed(I3);
%%
imagesc(L);
axis image

Résultat affiché avec une palette de couleurs:

watershed

Vous pouvez ensuite compter les cellules comme suit:

count = numel(unique(L));

L’un des avantages est qu’il peut être directement utilisé regionprops et vous donner tous les détails sur le squama individuel:

r=regionprops(L, 'All');
imshow(raw);

for k=2:numel(r)
    if r(k).Area>100 % I chose 100 to filter out the objects with a small are.
        rectangle('Position',r(k).BoundingBox, 'LineWidth',1, 'EdgeColor','b', 'Curvature', [1 1]); 
    end
end

Ce que vous pourriez utiliser pour surveiller la sur-segmentation / sous-segmentation: bounding boxes

Remarque: merci à @jucestain d’avoir aidé à accéder correctement aux champs du r structure ici


6
2018-04-02 13:49