# Finding objects in images with inhomogeneous background

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. 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];
subImage = Image[ImageData[image] - ImageData[background]];

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

resultImage =
Show[image,
Graphics[{Red, Thick,
Circle[#[], #[]] & /@
ComponentMeasurements[
ImageMultiply[image, binImg], {"Centroid",

Export[fileNameSave, resultImage];


That gives as output: 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.

so

BilateralFilter[i, 4, 1] 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]],
"Centroid"];

Show[i, Graphics[{Red, Point[pts[[All, 2]]]}]] • I like that very much ... you found even all objects at the edges ... solved ... thanks a lot.
– mrz
Mar 10 '16 at 17:51
• What is the j where you calculate the 4?
– mrz
Mar 11 '16 at 9:45
• @mrz Sorry, I forgot to paste it. Done. Mar 11 '16 at 9:54
• @mrz if other images don't perform well please upload a few to analyze them Mar 11 '16 at 9:55
• 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
– 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]]}]
] • 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.
– mrz
Mar 10 '16 at 17:47