# How to calculate the areas of cells in an image with Mathematica?

Below is an image of cells (adapted from here, Figure 1):

where the scale bar is $$20 \mu m$$. Is there any way to calculate the areas of cells with Mathematica?

• What have you tried? Have you looked at posts like this Area of a image region? Commented Aug 20, 2021 at 22:27
• As @creidhne already mentioned, please provide some of your code. Otherwise, the key functions would be ComponentMeasurements and MorphologicalComponents. However, some image preprocessing will be needed, together with the appropriate calibration with the scale bar. Simple, but quite inaccurate example: ComponentMeasurements[ColorNegate@Erosion[Dilation[EdgeDetect[img, 1.5, .05], 1.6], 1.4], "Area"]. Commented Aug 20, 2021 at 22:34
• A student, I see you edited this post recently; if you find that an answer has answered your question, it is helpful to mark it as “accepted” by turning the checkmark green by clicking on it—it is located under the +/-1 vote buttons. It looks like this is solved, from my perspective, as the answer from @Domen would work well if the image was preprocessed to remove the (b) marking from the image. Commented Aug 29, 2021 at 23:36
• I have implemented the idea of @GeorgeVarnavides and also provided the results for figure (a). Commented Aug 30, 2021 at 15:50

## Import all images

figA = Import["https://i.sstatic.net/XM8fK.jpg"];
figB = Import["https://i.sstatic.net/4WFEF.jpg"];
figBSmall = Import["https://i.sstatic.net/LjnRy.png"];


## Select and crop the image

imgOrig = figBSmall;
img = ImageCrop[imgOrig];


## Find the white scale bar

We look for the scale bar in the bottom-right part of the image. Only one morphological component should be found.

imgLowerThird =
ImageTake[
img, -ImageDimensions[img][[2]]/3, -ImageDimensions[img][[1]]/3];
imgBW = Dilation[Erosion[Binarize[imgLowerThird, .9], 1], 1];
scaleBar = MorphologicalComponents[DeleteBorderComponents@imgBW];
Max[scaleBar]
(* 1 *)

scaleBar // Colorize


## Determine scale bar height and calculate area factor

scaleBarRealHeight = Quantity[20, "Micrometers"];

scaleBarHeight = #[[2, 2]] - #[[1, 2]] &@(1 /.
ComponentMeasurements[scaleBar, "BoundingBox"])
(* 25. *)

areaFactor = scaleBarRealHeight^2/scaleBarHeight^2
(* Quantity[0.64, ("Micrometers")^2] *)


## Preprocess image

First, we remove the image label (b) and the scalebar, as proposed by @GeorgeVarnavides in the comment.

maxComponentSize = 15;
inpaintDilation = 1;

imgInpaint =
Inpaint[img,
Dilation[DeleteBorderComponents[
DeleteSmallComponents[Binarize[img, 0.9], maxComponentSize]],
inpaintDilation]]


Since cell borders are much darker than the interior, we convert the image to HSL color space and take the lightness channel. Furthermore, we crop the image and make a thin border so that the boundary cells are well separated. Small specks are removed by DeleteSmallComponents (once for the black and once for the white specks).

In this step, manual adjustment of four parameters can be made so that the output image edgesWithBorder has well-defined and connected cell boundaries without any black or white specks.

contrastAdj = 1;
threshold = .95;
cropWidth = 2;
specksSize = 50;

imgBinarized = Binarize[imgB, threshold];
edges = ColorNegate@
DeleteSmallComponents[ColorNegate@imgBinarized, specksSize,
CornerNeighbors -> False];
edges = DeleteSmallComponents[edges, specksSize,
CornerNeighbors -> False];
edgesCropped =
ImageTake[edges, {cropWidth, -cropWidth}, {cropWidth, -cropWidth}];
{imgB, edgesWithBorder} // GraphicsRow


## Find cells

cells = MorphologicalComponents[edgesWithBorder,
CornerNeighbors -> False];
cells // Colorize


## Calculate cell centroid and area

centroid = ComponentMeasurements[cells, {"Centroid"}];
centroidLoc = centroid[[All, 2, 1]];
area = ComponentMeasurements[cells, {"Area"}];


## Output the results

HighlightImage[#, Table[ImageMarker[centroidLoc[[i]],
Graphics[Style[Text@ToString@i, White, Bold]]], {i, 1,
Length@centroidLoc}]
] & /@ {img,
Colorize[cells, ColorFunction -> "DarkRainbow"]} // GraphicsRow
Partition[
Table[Row[{ToString@i, ": ",
Round[areaFactor*First[i /. area]]}], {i, 1,
Length@centroid}], UpTo[10]]), Alignment -> Left]


## Figure (a)

inpaintDilation = 6;
threshold = .94;
cropWidth = 8;
specksSize = 300;


## Evaluation

Most of the cells seem to be correctly recognized and measured. However, expect the results to have an error of about $$5 \%$$ for the middle cells (and significantly more for the cells on the edge of the figure). This can be seen by varying the preprocessing parameters or using high-resolution image (figB vs. figBSmall). Also note that the removal of image label and scalebar with InPaint produces artificial cell boundaries, which means the areas of surrounding cells have greater error.

• @Astudent, I have made some updates to make the code more robust. The problem was with figure 1 (a) was finding the scale bar, so now it takes only the bottom right part. Furthermore, I have explicitly specified two parameters that can be manually varied. Of course, in the preprocessing stage, you can apply some additional adjustments that will enhance cell boundaries. Commented Aug 22, 2021 at 11:39
• Re: removing the scale-bar/label while preserving cell boundaries, perhaps Inpaint can help. E.g. pre-processing with something like this seems to work well Inpaint[imageA, Dilation[DeleteBorderComponents[ DeleteSmallComponents[Binarize[imageA, 0.9], 250]], 5]] (where imageA is a 1048x962 image of Figure 1a from the attached paper) Commented Aug 23, 2021 at 21:16