How to properly tesselate a image of cells using matlab?

802 Views Asked by At

I have the following picture which is a photo of pancreatic cells enter image description here

What I would like to do is being able to get the membrane of each cell (red filament) and then do a tessellation in order to get an idea of the length of a filament. So far I have tried to use the example given on the matlab website but the result is not really good...

 I = imread('picture.tiff');
 I_gray = rgb2gray(I);
 [~, threshold] = edge(I_gray, 'sobel');
 fudgeFactor = .5;
 BWs = edge(I_gray,'sobel', threshold * fudgeFactor);
 se90 = strel('line', 3, 90);
 se0 = strel('line', 3, 0);
 BWsdil = imdilate(BWs, [se90 se0]);

enter image description here

I have been searching for hours other way to do it but without any satisfying result... Is there a way to do so ? Maybe an other software than matlab could be more efficient. Thank you by advance !

2

There are 2 best solutions below

0
Ozcan On BEST ANSWER

I don't know anything about cells or tessellation or whatever. But if you want to detect those blobs in a non uniform background, then I might help. You need to analyse the blobs individually because of the non uniform background. You can't just set a fixed threshold to detect all blobs at once. First, you will detect each blob individually and then use individual threshold. Here is the example

The original image

im=imread('gxGkH.jpg');
figure,imagesc(im);axis image;

enter image description here

I am choosing only the blue colour to analyse

imb=im(:,:,3);
figure,imagesc(imb);axis image;

enter image description here

1) Blur the image, since after blurring the blobs will have local maxima/minima at their centres

sigma=7;
kernel = fspecial('gaussian',4*sigma+1,sigma);
im2=imfilter(imb,kernel,'symmetric');

figure,imagesc(im2);axis image;

enter image description here

2) Use watershed transform to separate each blob region

% L = watershed(im2);
L = watershed(max(im2(:))-im2);
[x,y]=find(L==0);

Draw the boundaries

figure,imagesc(im2),axis image
hold on, plot(y,x,'r.')

enter image description here

3) Here I analyse each blob individually and find an otsu threshold for each blob, then I detect the blobs and combine all detections

tmp=zeros(size(imb));

for i=1:max(L(:))
  ind=find(L==i);
  mask=L==i;
  [thr,metric] =multithresh(imb(ind),1);
  if metric>0.7
    tmp(ind)=imb(ind)>thr;
  end
end

Remove some noise

tmp=imopen(tmp,strel('disk',1));
figure,imagesc(tmp),axis image

enter image description here

If the background has higher contrast then the blobs, then you won't need to invert the image in watershed transform.

1
UJIN On

I am not sure if this may get you closer to the solution of your problem, but what I would do would be something like this. Mind you, it's a really simple and naive approach:

image = imread('picture.tiff'); % load image
image = rgb2hsv(image); % convert to hsv colorspace
image = image(:,:,1); % take the hue channel

binary_im = imbinarize(image); % make binary image

The binary image should look like this:

enter image description here

Now you can use Mathematical Morphology to eliminate the noise. You first create a structuring element and then you convolve it with the binary image:

str_el = strel('disk', 5, 0); % create a round, 5px radius, str_el
closed_im = imclose(binary_im, str_el); % close image with str_el

Now your new image should look like this:

enter image description here

At this point you can use another morphological operation that finds the skeleton:

skeleton = bwmorph(closed_im, 'skel', Inf); % Find skeleton image

The skeleton image would look like this:

enter image description here

Of course this method is far from being precise, but may give you an overall information on the length of the filament, especially if you could get rid of the final noise (those appendices of the skeleton).