# Segmentation of a microscopy image with uneven illumination

I am trying to do a little image segmentation on some cells taken from microscopy images that have uneven illumination. I am having trouble getting the background of the image cleaned up after applying LocalAdaptiveBinarize so I can end up with closed white foreground cells on a plain black background.

Here is the original image:

Due to the uneven illumination (darker in the upper left part of image and brighter in the lower right) I couldn't find a simple threshold that worked well across the whole image so I tried to use LocalAdaptiveBinarize by doing LocalAdaptiveBinarize[image, 10]. Here is the result:

The cells aren't bad but there are a couple annoying defects I would like to improve: One of the two cells in the middle at the top has a chunk of it missing on its lower edge and the cell beneath it has a hole inside it. I can fill in the hole of the bottom cell by using FillingTransform[localBinImage,1] and get this:

I would be interested if anyone has any suggestions on how to improve the cell at the top with the chunk missing from its lower border.

At any rate, with the exception of the top middle cell the rest of the cells now look close to passable but the background is still a mess from using LocalAdaptiveBinarize. I would like to have a way to clean up the background so I just have the cells by themselves on a plain black background that makes it easy to use MorphologicalComponents or something similar to segment the cells.

Any suggestions on how to clean up this background?

-
You may try something like ImageMultiply[#, Binarize@DeleteSmallComponents@Erosion[EntropyFilter[Blur[#, 5], 1], 2]] &@ Import@"http://i.stack.imgur.com/5ni1u.jpg" –  belisarius Oct 13 at 5:13
You could try Import["http://i.stack.imgur.com/5ni1u.jpg"] // EdgeDetect // DeleteSmallComponents // FillingTransform. The cell at the top has an "invisible" left boundary, so it doesn't get filled in. –  Stephen Luttrell Oct 13 at 10:04
I don't have Mathematica 9 on my work computer but you could try a HighpassFilter to remove the gradual (low frequency) changes in the background illumination while preserving the high frequency changes in the cells. –  s0rce Oct 13 at 18:03

A clunky way of doing this, and I can't resolve the smaller cells, but here it goes. Taking from my answer here

img  = Import["http://i.stack.imgur.com/5ni1u.jpg"];
imgp = Flatten[
Table[{x, y, imgd[[x, y]]}, {x, 1, 346}, {y, 1, 462}], {2, 1}];
imgbg = Table[imgd[[x, y]] - nlm[x, y], {x, 346}, {y, 462}]; (* takes a while *)


Here, I am fitting the image data to a plane, assuming that the lighting effect is linear. One may improve the fit with a different function in the NonlinearModelFit if desired. The results can be seen by plotting the ImageData:

Before:

After:

We got rid of the slant, which is what this question is asking for. As for whether or not this improves the cell isolation, I'm not sure:

MorphologicalComponents[ImageConvolve[Image[imgbg], DiskMatrix[1]],
0.3] // Colorize // DeleteSmallComponents


It does separate the two cells of interest to the OP, but I couldn't find a decent set of parameters or filters to isolate the two cells to the left or at the bottom of the image. The original microscope image, if it is of a higher resolution, may be needed at this point.

-
This looks quite nice and I like the idea of looking at and detrending the surface. Thanks. –  user13999 Oct 14 at 12:28

I believe that you should use a high-pass filter. The built-in HighpassFilter seems very slow and produces artifacts. Here is an approximate method that is faster and appears to yield a better result:

hp[img_Image, w_Integer] := Image[0.5 + Subtract @@ ImageData /@ {img, Blur[img, w]}]


Application:

img = Import["http://i.stack.imgur.com/5ni1u.jpg"];

img2 = hp[img, 30]


Threshold[img2, 0.52]


p.s. It is shorter to use ImageApply but also slower:

hp2[img_Image, w_Integer] := ImageApply[# - #2 + 0.5 &, {img, Blur[img, w]}]

-
This is what I thought would work but my Mathematica 8 didn't have the HighpassFilter and I didn't feel like figuring out how to implement it. +1. Free ImageJ also has a good Bandpass filter built in. –  s0rce Oct 13 at 20:04
@s0rce I figured out how to implement a Photoshop-like HPF and it is backward-compatible with v8. Take a look. –  Mr.Wizard Oct 13 at 20:50
Mr. Wizard, the result looks good and should be simple to fill and clean up. Just to understand the code, are you just generating a new image that is the difference of the original image with a blurred version of the image? So is this essentially unsharp masking without the step where you add the unsharp mask back to the original image? –  user13999 Oct 14 at 12:37
@user13999 Yes, that is correct. –  Mr.Wizard Oct 20 at 21:06

I guess it depends on exactly what you are looking for, but here is one way to approach this: smooth with a RangeFilter and then Binarize.

img = Import["http://i.stack.imgur.com/5ni1u.jpg"];
Binarize[RangeFilter[img, 1], 0.1]


-
Thanks for the suggestion, however ideally I would like to arrive at a closed and/or filled contour for each cell so I can get their area and also use the resulting segmentation as a mask overlay for other color channels (e.g. for fluorescence channel images taken from these cells). Any ideas? –  user13999 Oct 13 at 4:04
Your question was about cleaning up the background. Try different binarization values, or try using the above binarization as a mask (to multiply by the original). –  bill s Oct 13 at 4:25

Detect cells:

cellEdges =

MorphologicalComponents[cells] // Colorize

BTW, I discovered a pretty neat way to generate psychedelic images: mc = MorphologicalComponents[LocalAdaptiveBinarize[MeanShiftFilter[ImageAdjust@img, 4, .05, MaxIterations -> 100], 5]]; Colorize[mc /. MapThread[Rule, {#, RandomSample[#]}] &@ Range[1, Max[mc]]] produces this image: i.stack.imgur.com/ECYev.png –  shrx Oct 13 at 19:55