# what scheme to use to segment this aggregate of cells in such a poor illumination

Due to issues with the microscope I have the following image which is inherently dark. At the center of the image is an aggregate (a cluster of cells). I can get a binarized mask using the mask draw capability in mathematica. But how can it be automated? What scheme should I use to segment it. I have not worked with such poorly illuminated image (Figure 1) before. GradientOrientationFilter?

If you play with brightness contrast of the image you can find the aggregate

As per @SquareOne's recommendation: LocalAdaptiveBinarize seems to work pretty well. still not a complete solution.

• To automize it I think more Information are needed E.g. how should a Software now that the bright spot in the top left are not the cells. The best way would be to fix the microscope. But if you come up with additional Information about expected size of the cell, app. Position... . Then I could think of an iterative scheme to find the Cluster. Mar 1, 2017 at 7:41
• See LocalAdaptiveBinarize Mar 1, 2017 at 15:18
• @SquareOne LocalAdaptiveBinarize seems to work pretty well. I have the picture posted in the question and credited you with it. Do you have a strategy to extract a Morphological Perimeter of the cluster inside in the image after the adaptive binarize Mar 1, 2017 at 18:31

If I assume that the cells always have similar size (~100-200 pixel diameter), I think I can do this.

img = ColorConvert[Import["https://i.stack.imgur.com/pFvT7.png"],
"Grayscale"]


I'm going to use the model

• that your image is the inhomogeneous brightness due to the microscope times the "actual" image content (including the cell borders)
• that the inhomogeneous brightness is varies very slowly and thus can be approximated using GaussianFilter[img,50]

so $img / GaussianFilter[img,50]$ is a good approximation of the "actual" image content:

eps = 10^-10; (* add a small value to the denominator to prevent division by zero *)
equalBrightness =
Image[Rescale[
ImageData[img]/(GaussianFilter[ImageData[img], 50] + eps)]]


Next, I'll want the gradient of this preprocessed image:

gradient =
GaussianFilter[ImageData[equalBrightness], 10, #] & /@
IdentityMatrix[2];


...as an array of complex numbers, for convenience:

gradientC = {1, I}.gradient;


I'm going to use template matching to find "something roughly circular" in this gradient image. The template will simply consist of complex numbers pointing "outwards" from the center, times some window function. That's the gradients we're looking for:

template = Array[
(#1 + I*#2)*HammingWindow[#1]*HammingWindow[#2] &, {256,
256}, {{-.5, .5}, {-.5, .5}}];

ListVectorPlot[ReIm[template]]


Export["F:\\imgs\\so2.png", %]


The correlation between this template and the gradients found above is highest in the cell's center. (I have no idea how reliable this is. You'll have to check with other images, and play with filter sizes, preprocessing functions above):

corr = Image[


Finding the point of highest correlation is easy:

maxPos = PixelValuePositions[corr, "Max"][[1]] + Dimensions[template]/2;
HighlightImage[equalBrightness, {maxPos}]


Now we can use this position to create a marker mask for WatershedComponents:

markers =
Binarize@Rasterize[
Graphics[{White, Point[maxPos], Circle[maxPos, 256]},
PlotRange -> {{0, 0}, ImageDimensions[img]}\[Transpose],
ImageSize -> ImageDimensions[img], Background -> Black]]


This mask basically says: I'm looking for two components. One component contains the center point, the other component contains all points on the circle radius. Other than that, choose the components so that they best "fit" to the gradient strengths:

components =