Calculate the size of the moon The size of the moon mystery

I am sure you have heard that the moon changes its size. When you're in love and you're lucky, the moon is almost twice in size compared to normal situations. Some people say the reason is the atmosphere which acts as a lens. Others think that it is only a matter of comparison to other objects such as trees nearby. Whatever explanation you read, it's quite subjective.

The size of the moon science

Ok, we're programmers, aren't we? We rely on facts, right? So here's the experiment:


Take a nice camera which supports setting time and aperture manually.
Set your camera to maximum zoom level.
Go out, take some photographs of the moon in order to detect the best settings so that the moon is sharp and lighting is just fine.
Remember the settings
Take photos of the moon with those settings every time you think the moon is large or small.
Calculate the size of the moon in pixels


The camera won't lie, would it? By counting the bright pixels we can effectively measure the size of the moon - at least in pixels.

If the size is the same across all photos, then it's a bug in our brain. If the size differs, then there's room for speculation


the moon really grows (but what does it eat?)
there's an atmospherical lens effect
the moon has an elliptical curve and is sometimes nearer, sometimes further away from earth
...


But I'll leave that open until your task is completed. Of course you want to know in advance if your software can calculate the moon size accurately.

The task

Given a few optimized pictures of the moon, please calculate the size of the moon. The optimization is: the pixels are either black or white. Nothing in between. No antialiasing. That makes it easy, doesn't it?

The caveat: the moon is not always full, you know ... it can be a sickle! But even in shape of a sickle, the size of the moon is larger. So you'll calculate the full size, please.


Your program takes a PNG as input, e.g. as file name command line argument, piped into stdin or as a Bitmap object (of a standard framework library) if you write a function instead of a program.
Your program works with any reasonable input bitmap size, not necessarily square. Minimum width and height of 150 pixels are guaranteed.
The full moon covers at least 25% of the picture.
Your program outputs the calculated size of the moon in pixels as if it were a full moon.
We assume that the moon is a perfect sphere.
The exact size is always an integer number, but you can output a decimal number if your calculation returns that.
The accuracy should be between 98% and 102%. (That's rather a guess than something I could guarantee to be achievable. If you think it's too hard to reach, please leave a comment.)


Update:


The center of the moon isn't necessarily in the middle of the picture.
The minimum visible area is 5% of the moon or 1.25% of the total number of pixels.
The picture is taken in a way that the whole moon would fit the image, i.e. the total number of pixels is an upper boundary for the moon size.
The moon will not be cropped / clipped.


The samples

You can generate your own samples using the blend file if you like. I have created the following pictures for you. You can count pixels in a PNG file using WhitePixelCounter.exe (needs .NET) to check whether the image contains black and white pixels only and how many of them.

The following 256x256 pixel images differ in the amount of white pixels, but should all result in a calculated moon size of 16416 pixels.








And these 177x177 pixel images should return 10241 pixels. The images are basically the same, but this time a camera with a different focal length was used.








Non-square and non-centered samples with a result of 9988:







Oh, I don't have a reference implementation for now and I even don't know whether I am able to implement something. But in my brain there is a strong belief that tells me it must be mathematically solvable.

The rules

This is Code Golf. The shortest code on 2015-03-30 gets accepted.
Mathematica 126 119 109 bytes
Mathematica can measure the elongation of a component in an image.  A full moon, being perfectly symmetric, has an elongation of 0, on a scale of 0 to 1.
A diminishing moon becomes increasingly elongated, to a maximum of roughly 0.8.
0.998 -0.788 x-0.578 x^2 was the empirically determined model (based on the large photos) for `predicting the fullness of the moon (by area), given its elongation.
I adjusted the model to 1- 0.788 x -0.578 x^2 so that with exactly zero elongation (full moon) the model will return 1 for the pixel scale factor.  It saves 4 bytes and still stays within the accuracy limits.
This model is used for any size images.  The moon image does not need to be centered. It also does not need to cover a fixed proportion of the photo.
Here are the data points (elongation, displayedMoonPixels/fullMoonPixels) for the large images and the parabolic model that was generated to fit the data. Linear models fit ok, but the quadratic model is dead on, within limits (see below).
Here the data are from the large pictures.  So is the model


Below, the data (the red points) are from the small pictures.  The model (the blue curve) is the one generated by the large pictures, the same one as displayed above.
The smallest crescent has 7.5% the area of a full moon.  (The smallest crescent among the large photos is 19% of a full moon.)  If the quadratic model had been based on the small photos the fit below would be better, only because it accommodated the small crescent.  A robust model, that would stand up under a wide range of conditions, including very small crescents, would be better made from a larger variety of pictures.
The closeness of fit shows that the model was not hard-coded for the given pictures. We can be fairly certain that the elongation of a moon is independent of the size of the photo, as one would expect.

f takes the image, i, as input and outputs the predicted size of the full moon, in pixels.  It works for off-center shots.
As the data below show, it all of the test cases except one.
The moons were arranged from full to most diminished.
i_~c~t_ := Max@ComponentMeasurements[i, t][[All, 2]];
f@i_ := i~c~&quot;Count&quot;/(1 - 0.788 x - 0.578 x^2 /. x -&gt; i~c~&quot;Elongation&quot;)

More than one image component may turn up in a photo.  Even a single pixel separated from the others will be considered a distinct component.  For this reason, it is necessary to search &quot;all&quot; components, to find the one that has the greater number of pixels.  (One of the small photos has more than one image component.)
Large pictures
Predictions of moon size made from the large photos were uniformly accurate.
{&quot;predicted size of full moon&quot;, f[#] &amp; /@ large}
{&quot;accuracy&quot;, %[[2]]/16416}


{&quot;predicted sizes of full moon&quot;, {16422., 16270.9, 16420.6, 16585.5, 16126.5, 16151.6}}
{&quot;accuracy&quot;, {1.00037, 0.991161, 1.00028, 1.01033, 0.982367, 0.983891}}


Small pictures
Predictions of moon size made from the small photos were uniformly, with one great exception, the final picture.  I suspect the issue stems from the fact that the crescent is very narrow.
{&quot;predicted sizes of full moon&quot;, f[#] &amp; /@ small}
{&quot;accuracy&quot;, %[[2]]/10241}


{&quot;predicted sizes of full moon&quot;,{10247.3, 10161., 10265.6, 10391., 10058.9, 7045.91}}
{&quot;accuracy&quot;, {1.00061, 0.992192, 1.0024, 1.01465, 0.982221, 0.68801}}