# Finding the centroid of a disk in an image

I got about 100 images of the sun and have to find the centre of the star in the images. I have binarized the images and used ComponentMeasurementsto find the Centroid and the EquivalentDiskRadius. So far so good, but I have noticed that in Mma's calculation the centroid appears to have the tendency to gravitate slightly towards the right bottom edge. I first thought that is due to the fact the the disk of the sun is a slight ellipse due to objective imperfection etc but I can replicate the effect with an image I create in Mma using the Disk command.

disk = Rasterize[Graphics[{Disk[]}], ImageResolution -> 100];
ndisk = 1 /.
ComponentMeasurements[
pdisk = 1 /.
Show[{disk,
Graphics[{{Red, Circle[ndisk[[1]], ndisk[[2]]]}, {Green,
Circle[pdisk[[1]], pdisk[[2]]]}}]}]


The result of the centroid calculation depends also on whether the disk is positive or negative. What am I missing here or how could I fit a circle to a binary image which contains a slightly distorted disk?

Edit: Based on some of the answers I simpified the input image by using an even and an odd sized array.

m = {{0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 1, 0, 0, 0},{0, 0, 1, 1, 1, 0, 0},
{0, 1, 1, 1, 1, 1, 0},{0, 0, 1, 1, 1, 0, 0},{0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0}};

k = {{0, 0, 1, 1, 0, 0},{0, 1, 1, 1, 1, 0},{1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1},{0, 1, 1, 1, 1, 0},{0, 0, 1, 1, 0, 0}};

circ = 1 /.
(* {{3.5, 3.5}, 2.03421} *)

circ2 = 1 /.
(* {{3., 3.}, 2.76395} *)

Show[{ArrayPlot[m],
Graphics[{Red, Thick, Circle[circ[[1]], circ[[2]]]}]}]
Show[{ArrayPlot[k],
Graphics[{Red, Thick, Circle[circ2[[1]], circ2[[2]]]}]}]


Gives the results below. ComponentMeasurements finds the right centre in both cases what is off is the Circle that I draw over it. Look at the sizes of the small triangle the circle cuts off the black squares.

• Would a simple correction of the effect help? If yes, then you could try something like Show[{disk,Graphics[{{Red,Circle[ndisk[[1]],ndisk[[2]]]},{Green,Circle[pdisk[[1]]+ndisk[[1,1]]-pdisk[[1,1]],pdisk[[2]]+ndisk[[1,2]]-pdisk[[1,2]]]}}]}] – partial81 Jun 25 '12 at 12:51
• Thanks everyone for your valuable input. I am convinced that 'ComponentMeasurement' delivers the right result but the circle I draw to visually inspect the result is slightly off. This offset disapears when I enlarge the plot. – Matariki Jun 26 '12 at 0:40

I think the shift of the circle with respect to the disk is at least partially due to antialiasing effects. Compare for example:

disk = Binarize@Rasterize[Graphics[Disk[]]];
ndisk = 1 /. ComponentMeasurements[ColorNegate@disk, {"Centroid", "EquivalentDiskRadius"}];

Show[{disk, Graphics[{{Red, Antialiasing -> True, Circle @@ ndisk}}]}]


with

Show[{disk, Graphics[{{Red, Antialiasing -> False, Circle @@ ndisk}}]}]


• How come an option can be inserted in a list of directives and primitives? Is this some undocumented usage, or did I just miss something from the documentation? – István Zachar Jun 25 '12 at 13:53
• @IstvánZachar I don't think it's documented. I came across this usage here – Heike Jun 25 '12 at 13:58
• @Heike Interesting effect. For some reason I didn't see the effect when I tried it. The binarized image of the sun has however no antialiasing. – Matariki Jun 25 '12 at 20:54
• @Matariki I was referring to the influence of antialiasing on the circle drawn on top of the binarized image, not of the image itself. – Heike Jun 25 '12 at 23:02

Compare:

l = Rasterize[Show[Graphics[{Disk[{1, 1}, 10], Disk[{20, 20}, 10]}]]];


ComponentMeasurements does not work for black objects ... they are not components ...

• Yes, that's what I suspected when I tried it for various objects, however the documentation isn't mentioning this. It only hinds at it in its examples.So the algorithm object search needs the objects to be 0 to find them. Thanks. – Matariki Jun 25 '12 at 18:34

I feel the doc page for ComponentMeasurements contains the solution:

Position, area, and length measurements are taken in the standard image coordinate system where position {0,0} corresponds to the bottom-left corner, x runs from 0 to width, and y runs from 0 to height.

You are counting whole pixels and ComponentMeasurements measures pixel positions. In this system, the center of the bottom left pixel is at {1/2,1/2}.

I have been looking somewhat closer to Heike's answer to bring out the differences caused by anti-aliasing better.

Without anti-aliasing:

disk = Rasterize[Graphics[{Antialiasing -> False, Disk[]}], ImageSize -> 61];
ndisk = 1 /. ComponentMeasurements[

• I understand that but shouldn't I still expect the circle to be in the middle of the component when I plot it where ComponentMeasurements deems the Centroid to be? – Matariki Jun 25 '12 at 20:20