I have the following image where bright circular shaped objects are seen. The image has usually an inhomogeneous background and the objects have different sizes and brightness's.

enter image description here

The aim is to remove the background noise and to detect all object's positions.

How can that be done best?

My solution for the example image is:

fileNameOpen = SystemDialogInput["FileOpen"];
image = Import[fileNameOpen]

background = ImageConvolve[image, GaussianMatrix[7]];
subImage = Image[ImageData[image] - ImageData[background]];

t = FindThreshold[subImage, Method -> "Entropy"];
binImg = Binarize[subImage, t];
binImg = DeleteSmallComponents[binImg, 1];

resultImage = 
  Graphics[{Red, Thick, 
    Circle[#[[1]], #[[2]]] & /@ 
       ImageMultiply[image, binImg], {"Centroid", 
        "EquivalentDiskRadius"}][[All, 2]]}]]

fileNameSave = SystemDialogInput["FileSave"];
Export[fileNameSave, resultImage];

That gives as output:

enter image description here

The problem is that I have to adjust manually the radius of GaussianMatrix and the number in DeleteSmallComponents. Their optimum values depend also on the Method used in FindThreshold (e.g. "MinimumError" can also be used") .


BilateralFilter replaces each pixel by a weighted average of its neighbors, using normalized Gaussian matrices as weights.


BilateralFilter[i, 4, 1]

Mathematica graphics

is "almost" your background.

If you have troubles with fine-tuning for other images, you may "calculate" the 4 as

Round[Sqrt[Total@Flatten@ImageData@SelectComponents[MaxDetect[i], "Area", -1]/Pi] // N]
(* 4 *)

Use it like this:

pts = ComponentMeasurements[Binarize@ImageSubtract[i, BilateralFilter[i, 4, 1]], 

Show[i, Graphics[{Red, Point[pts[[All, 2]]]}]]

enter image description here

  • $\begingroup$ I like that very much ... you found even all objects at the edges ... solved ... thanks a lot. $\endgroup$
    – mrz
    Mar 10 '16 at 17:51
  • $\begingroup$ What is the j where you calculate the 4? $\endgroup$
    – mrz
    Mar 11 '16 at 9:45
  • $\begingroup$ @mrz Sorry, I forgot to paste it. Done. $\endgroup$ Mar 11 '16 at 9:54
  • $\begingroup$ @mrz if other images don't perform well please upload a few to analyze them $\endgroup$ Mar 11 '16 at 9:55
  • $\begingroup$ Thank you for you help. Here I have a difficult image (with 2 blurred objects due to movement during the image duration) which I cannot solve this way ... may be I am doing something wrong: goo.gl/5sg89w $\endgroup$
    – mrz
    Mar 13 '16 at 9:36

A better way of removing the background might be to use a TotalVariationFilter, which seems to be less sensitive to the parameter it is given compared to convolution. In fact, I've not even used any parameters.

Your code can also be simplified since Binarize takes a Method option. In fact, you don't actually need it, the automatic method works just as well.

The size option of DeleteSmallComponents[] depends on the minimum feature size in your image, so using a value of 1 is a good assumption in this example, but may vary for other images.

image = Import["http://i.stack.imgur.com/czhuI.png"];
background = TotalVariationFilter[image];
subImage = ImageSubtract[image, background];

(* Or use Binarize[subImage, Method -> "Entropy"]; *)
binImg = DeleteSmallComponents[Binarize@subImage, 1];

resultImage = Show[image, 
                   Graphics[{Red, Disk[#, 2] & /@ 
                   ComponentMeasurements[binImg, "Centroid"][[All, 2]]}]

enter image description here

  • $\begingroup$ Great ... only at the lower left and right corners you detect objects which are not seen in the image. But when I use TotalVariationFilter[image, MaxIterations -> 100]; your code produces perfect results. $\endgroup$
    – mrz
    Mar 10 '16 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.