Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting the squama of lizards

A biologist friend of mine asked me if I could help him make a program to count the squama (is this the right translation?) of lizards.

He sent me some images and I tried some things on Matlab. For some images it's much harder than other, for example when there are darker(black) regions. At least with my method. I'm sure I can get some useful help here. How should I improve this? Have I taken the right approach?

These are some of the images.

pic1

pic2

I got the best results by following Image Processing and Counting using MATLAB. It's basically turning the image into Black and white and then threshold it. But I did add a bit of erosion.

Here's the 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);

And these are some of the results. One the top-left corner you can see how many were counted.

Also, I think it's useful to have the counted elements marked in green so at least the user can know which ones have to be counted manually.

enter image description here

like image 625
fersarr Avatar asked Apr 02 '14 07:04

fersarr


1 Answers

There is one route you should consider: watershed segmentation. Here is a quick and dirty example with your first image (it assumes you have the IP toolbox):

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

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

Result shown with a colormap:

watershed

You can then count the cells as follows:

count = numel(unique(L));

One of the advantages is that it can be directly fed to regionprops and give you all the nice details about the individual 'squama':

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

Which you could use to monitor over/under segmentation: bounding boxes

Note: special thanks to @jucestain for helping with the proper access to the fields in the r structure here

like image 156
Cape Code Avatar answered Sep 18 '22 03:09

Cape Code