2

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 !

Community
  • 1
  • 1
Hyppolite
  • 47
  • 5
  • 2
    For hours?! only *for hours*? So, you want to implement a research level method to automatically segment cells and you searched *hours*? I mean, people do 4 years of a PhD to do this things properly. Your first step should be an image processing book/course. – Ander Biguri Mar 06 '17 at 13:08
  • 2
    The filament seems pretty red, I'd try to exploit this information if I were you. – UJIN Mar 06 '17 at 13:22
  • I understand that is complex, I won't give my personal situation but this project I am working on is a side project part of my PhD (I am physicist, not biologist) and I do not have a lot of time to dedicate to. I am trying to use the fact that the filament are pretty red but it never ends that well... – Hyppolite Mar 06 '17 at 14:00
  • 1
    Now I don't have time to experiment, but if you haven't done it you could try to check the Hue channel after having converted the image from RGB to HSV with `rgb2hsv`. The hue channel is illumination invariant, so the red filament should be pretty much uniform. – UJIN Mar 06 '17 at 14:36

2 Answers2

3

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.

Ozcan
  • 726
  • 4
  • 13
2

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).

UJIN
  • 1,648
  • 13
  • 28
  • It is not precise indeed but since I can repeat the treatment for a large set of image it could be enough. I'll work on this ! Thank you very much ! – Hyppolite Mar 06 '17 at 17:17