# Noisy and vague shape recognition

Consider the following image:

Imagine I have several images (let's say 40), that look like this one but with slightly different cloud shapes, pixel count intensities and distances between the clouds.

Do you have a sure fire algorithm that would be able to localize all seven clouds with preferably no human input except for the 40 images. In the end the goal is to get the total pixel count in each cloud for the 40 images. I am aware that it is difficult to define what a cloud is exactly given the smooth nature of the shapes and the noisy nature of the image. Any definition you'll choose is fine by me.

I am looking for ideas, methods or algorithm names, code is not necessary, but if you want i could provide images like this one. Happy to answer any practical questions.

EDIT: as requested here are other images, the first three come from the same set as the image above, the last ones come from another set, sometimes you have images with no clouds (but that's a complication I can do away with myself) :

• Can you include two or three more images to help us figure out just how general the solution needs to be? Sep 9, 2021 at 10:08
• @CarlLange done
– yfs
Sep 9, 2021 at 10:17
• You should probably deal with the noise by doing: ImageAdjust@TotalVariationFilter[img, 1] Sep 9, 2021 at 13:07

Closest I can get with minimal input from the user. The key here is to pull an example object from one dataset to use for image correlation. (A strategy borrowed from this answer).

imgs = {
"https://i.stack.imgur.com/uPOHl.jpg",
"https://i.stack.imgur.com/oJCJO.jpg",
"https://i.stack.imgur.com/XNRwG.jpg",
"https://i.stack.imgur.com/1tvCA.jpg",
"https://i.stack.imgur.com/6zhu3.jpg",
"https://i.stack.imgur.com/9w3PR.jpg"};
i = Import /@ imgs;
object = ImageTake[i[[1]], {150, 200}, {225, 275}]


Here's how I isolate the objects:

ib = ColorNegate@
Binarize[
ImageCorrelate[#, object, NormalizedSquaredEuclideanDistance],
0.465] & /@ i
if = ImageAdjust@LaplacianGaussianFilter[#, 20] & /@ ib
Length@ComponentMeasurements[ColorNegate@Binarize@#, "Count"] & /@ if
ComponentMeasurements[ColorNegate@Binarize@#, "Centroid"] & /@ if


ib uses ImageCorrelate to find similar disks. I selected a level for Binarize that suited the entire dataset. Next, if is used to clean up the objects. A nice feature here is that the filter creates a halo around the objects that allows for relatively straightforward component isolation. (Which I learned from this answer) The next line just makes sure there are 7 objects detected in the image and then the centroids of the objects can found with ComponentMeasurements.

The center points found here can be used to determine distances. What's missing from this answer is an estimate of the intensity in each object. For that, the end user must make a decision on whether or not the objects are the same size. if they are, one could create a mask of fixed size at the centroid positions and count the intensity of the resulting images.