# Points in a given image file

I have scattered points of red, blue, and green in an image as follows:

Is there anyway to convert this image to Mathematica, and assign, for example, coordinates to points?

• Have you already seen ImageKeypoints[]? Feb 6, 2021 at 9:02
• No, thanks. I will look at it.
– user77186
Feb 6, 2021 at 9:03
• @J.M. I tried it but it didn't work very well. Feb 6, 2021 at 10:15

## 1 Answer

Start by running DominantColors on the image to find the colors of the disks. We find that there are five colors in the image, black, white, red, green, and blue. We are interested in the red, green and blue, so we assign those to variables:

red = RGBColor[0.7946611400853826, 0.041682311725958814, 0.19884515506202294, 1.];
green = RGBColor[0.06934047216488792, 0.36728457165771705, 0.21438939660431816, 1.];
blue = RGBColor[0.10353575350527286, 0.30406589393708666, 0.5195819244446633, 1.];


# Simple approach

We may start with a simple approach to understand the difficulties in the problem.

centroids[img_, color_] := ComponentMeasurements[
Binarize@ColorDetect[img, color],
"Centroid"
][[All, 2]]


This function selects all pixels of a certain color and makes them white, and all other pixels black. It then looks for contiguous areas of white and considers each such area a component. Finally, it extracts the centroid of each component. Here is an example of the result:

coords = centroids[img, red];
HighlightImage[img, ImageMarker[coords, "Cross"]]


As we can see, it works as well as can be expected. Unfortunately, it cannot separate disks that have been joined together.

# Separating overlapping disks

To solve the problem of overlapping disks, we have to use a process which is more complicated, at least counting the number of things we have to do.

processingPipeline = Composition[
HighlightImage[img, ImageMarker[#, "Cross"]] &,
#[[All, 2]] &,
ComponentMeasurements[#, "Centroid"] &,
Binarize[#, 0.7] &,
ImageAdjust,
DistanceTransform,
Binarize,
ColorDetect[#, red] &
];

processingPipeline[img]


The way it works is the following:

1. Detect the given color and make areas of that color white and all other pixels black.
2. Run DistanceTransform to take each pixels and change its level of white so that it corresponds to the distance from that pixel to a black pixel. This means that the middle of a disk will be whitest and the level of white will gradually drop off towards the edges of the disk.
3. Run ImageAdjust so that the brightest pixels are 1 and the darkest pixels are 0. This makes the result of the DistanceTransform easier to interpret.
4. Set all pixels brighter than 0.7 to 1 and all pixels below that to 0. This preserves only the centers of the disks since these are the areas that are brightest, following the DistanceTransform.
5. Run ComponentMeasurements to find the centroids of the white areas.

As we can see, the is a tunable parameter 0.7 in this code. One can try out different values if at first it doesn't work for a given image.

Here is the image for the green color:

And here is the image for the blue color:

• @Broccoli That is what I’ve done. Feb 6, 2021 at 10:33
• @Broccoli I have provided you with code that gives you coordinates for the dots. You can put these into ListPlot for example. The y-axis runs in the opposite direction in ListPlot compared to the image coordinate system, so you may want to negate the the y-values or the dots will be flipped vertically. Feb 6, 2021 at 20:14
• @Broccoli By taking away the top line in the composition, the HighlightImage line. Feb 6, 2021 at 20:38