Berechnen Sie die Größe des Mondes

19

Die Größe des Mondgeheimnisses

Ich bin sicher, Sie haben gehört, dass der Mond seine Größe ändert. Wenn Sie verliebt sind und Glück haben, ist der Mond im Vergleich zu normalen Situationen fast doppelt so groß. Einige Leute sagen, der Grund dafür sei die Atmosphäre, die als Linse fungiert. Andere meinen, es handele sich nur um einen Vergleich mit anderen Objekten wie Bäumen in der Nähe. Welche Erklärung Sie auch lesen, sie ist ziemlich subjektiv.

Die Größe der Mondwissenschaft

Ok, wir sind Programmierer, nicht wahr? Wir verlassen uns auf Fakten, oder? Also hier ist das Experiment:

  1. Nehmen Sie eine schöne Kamera, die das manuelle Einstellen von Zeit und Blende unterstützt.
  2. Stellen Sie Ihre Kamera auf die maximale Zoomstufe ein.
  3. Machen Sie ein paar Fotos vom Mond, um die besten Einstellungen zu ermitteln, damit der Mond scharf ist und die Beleuchtung in Ordnung ist.
  4. Merken Sie sich die Einstellungen
  5. Machen Sie mit diesen Einstellungen jedes Mal Fotos vom Mond, wenn Sie glauben, der Mond sei groß oder klein.
  6. Berechnen Sie die Größe des Mondes in Pixel

Die Kamera lügt doch nicht, oder? Durch Zählen der hellen Pixel können wir die Größe des Mondes effektiv messen - zumindest in Pixel.

Wenn die Größe aller Fotos gleich ist, ist dies ein Fehler in unserem Gehirn. Wenn die Größe unterschiedlich ist, gibt es Raum für Spekulationen

  • der Mond wächst wirklich (aber was isst er?)
  • Es gibt einen atmosphärischen Linseneffekt
  • Der Mond hat eine elliptische Kurve und ist manchmal näher, manchmal weiter von der Erde entfernt
  • ...

Aber ich lasse das offen, bis deine Aufgabe erledigt ist. Natürlich möchten Sie im Voraus wissen, ob Ihre Software die Mondgröße genau berechnen kann.

Die Aufgabe

Berechnen Sie anhand einiger optimierter Bilder des Mondes die Größe des Mondes. Die Optimierung ist: Die Pixel sind entweder schwarz oder weiß. Nichts dazwischen. Kein Antialiasing. Das macht es einfach, nicht wahr?

Der Vorbehalt: Der Mond ist nicht immer voll, wissen Sie ... es kann eine Sichel sein! Aber auch in Sichelform ist der Mond größer. Also berechnen Sie bitte die volle Größe.

  • Ihr Programm verwendet eine PNG als Eingabe, z. B. als Befehlszeilenargument für Dateinamen, als Pipeline stdinoder als Bitmap-Objekt (einer Standard-Framework-Bibliothek), wenn Sie eine Funktion anstelle eines Programms schreiben.
  • Ihr Programm arbeitet mit einer angemessenen Bitmap-Eingabegröße, die nicht unbedingt quadratisch sein muss. Minimale Breite und Höhe von 150 Pixel sind garantiert.
  • Der Vollmond bedeckt mindestens 25% des Bildes.
  • Ihr Programm gibt die berechnete Größe des Mondes in Pixeln aus, als wäre es ein Vollmond.
  • Wir nehmen an, dass der Mond eine perfekte Kugel ist.
  • Die genaue Größe ist immer eine Ganzzahl, aber Sie können eine Dezimalzahl ausgeben, wenn Ihre Berechnung dies ergibt.
  • Die Genauigkeit sollte zwischen 98% und 102% liegen. (Das ist eher eine Vermutung als etwas, das ich garantieren könnte, um erreichbar zu sein. Wenn Sie denken, dass es zu schwer zu erreichen ist, hinterlassen Sie bitte einen Kommentar.)

Update :

  • Der Mittelpunkt des Mondes muss nicht unbedingt in der Mitte des Bildes liegen.
  • Die minimale sichtbare Fläche beträgt 5% des Mondes oder 1,25% der Gesamtzahl der Pixel.
  • Das Bild wird so aufgenommen, dass der gesamte Mond zum Bild passt, dh die Gesamtzahl der Pixel ist eine Obergrenze für die Mondgröße.
  • Der Mond wird nicht beschnitten.

Die Beispiele

Sie können Ihre eigenen Samples mit der Blend-Datei erzeugen, wenn Sie möchten. Ich habe die folgenden Bilder für Sie erstellt. Sie können Pixel in einer PNG-Datei mithilfe von WhitePixelCounter.exe (benötigt .NET) zählen, um zu überprüfen, ob das Bild nur schwarze und weiße Pixel enthält und wie viele davon.

Die folgenden 256 x 256 Pixel großen Bilder unterscheiden sich in der Anzahl der weißen Pixel, sollten jedoch alle zu einer berechneten Mondgröße von 16416 Pixel führen.

Vollmond Mond Mond Mond Mond Mond

Und diese 177x177 Pixel-Bilder sollten 10241 Pixel zurückgeben. Die Bilder sind grundsätzlich gleich, diesmal wurde jedoch eine Kamera mit einer anderen Brennweite verwendet.

Mond Mond Mond Mond Mond Mond

Nicht quadratische und nicht zentrierte Samples mit einem Ergebnis von 9988:

Mond in einem nicht quadratischen Rahmen Mond in einem nicht quadratischen Rahmen Mond in einem nicht quadratischen Rahmen Mond in einem nicht quadratischen Rahmen Mond in einem nicht quadratischen Rahmen

Oh, ich habe momentan keine Referenzimplementierung und ich weiß nicht einmal, ob ich etwas implementieren kann. Aber in meinem Gehirn gibt es einen starken Glauben, der mir sagt, dass es mathematisch lösbar sein muss.

Die Regeln

Das ist Code Golf. Der kürzeste Code am 30.03.2015 wird akzeptiert.

Thomas Weller
quelle
9
In allen Beispielen scheint der Mittelpunkt des Mondes im Bild zentriert zu sein. Können wir annehmen, dass der Mond immer zentriert sein wird?
Digital Trauma
1
Ihre Genauigkeit von +/- 2% auf der Fläche entspricht +/- 1% auf dem Durchmesser: Beispiel r = 100 Pixel, Fläche = 10000 * pi; r = 101 Pixel, Fläche = 10201 * pi. Ihr kleineres Bild hat r = 72, d = 144, also sollte es einfach möglich sein. Bei Bildern unter d = 100 konnte die Genauigkeit meines Erachtens jedoch nicht erreicht werden.
Level River St
@DigitalTrauma: Das Zentrum muss nicht in der Mitte sein.
Thomas Weller
@ MartinBüttner: Der minimale sichtbare Prozentsatz beträgt 5% des Mondes oder 1,25% des Bildes.
Thomas Weller
@ MartinBüttner: ok, ich habe die Frage aktualisiert und die Überblendungsdatei so aktualisiert, dass standardmäßig nicht quadratische, nicht zentrierte Bilder erzeugt werden. Sie können alle Bilder hier herunterladen (* .png.zip) . Pixelzähler ebenfalls aktualisiert: Gibt weitere Informationen aus und überprüft die 1,25% -Regel.
Thomas Weller

Antworten:

10

Mathematica 126 119 109 Bytes

Mathematica kann die Dehnung einer Komponente in einem Bild messen. Ein Vollmond, der perfekt symmetrisch ist, hat eine Dehnung von 0 auf einer Skala von 0 bis 1.

Ein abnehmender Mond wird zunehmend länglicher und erreicht ein Maximum von ungefähr 0,8.

0.998 -0.788 x-0.578 x^2 war das empirisch ermittelte Modell (basierend auf den großen Fotos) zur Vorhersage der Fülle des Mondes (nach Fläche) aufgrund seiner Ausdehnung.

Ich habe das Modell 1- 0.788 x -0.578 x^2so angepasst, dass das Modell bei genau null Dehnung (Vollmond) 1 für den Pixel-Skalierungsfaktor zurückgibt. Es spart 4 Bytes und bleibt dennoch innerhalb der Genauigkeitsgrenzen.

Dieses Modell wird für Bilder jeder Größe verwendet. Das Mondbild muss nicht zentriert sein. Es muss auch keinen festen Anteil des Fotos bedecken.

Hier sind die Datenpunkte (Dehnung, angezeigte Mondpixel / volle Mondpixel) für die großen Bilder und das Parabolmodell, die für die Daten generiert wurden. Lineare Modelle passen in Ordnung, aber das quadratische Modell ist in Grenzen tot (siehe unten).

Hier sind die Daten aus den großen Bildern. So ist das Modell

große Halbmonde


Unten sind die Daten (die roten Punkte) von den kleinen Bildern. Das Modell (die blaue Kurve) wird aus den großen Bildern wie oben dargestellt erzeugt.

Der kleinste Halbmond hat 7,5% der Fläche eines Vollmonds. (Der kleinste Halbmond unter den großen Fotos ist 19% eines Vollmonds.) Wenn das quadratische Modell auf den kleinen Fotos basiert hätte, wäre die Passform darunter besser, nur weil sie den kleinen Halbmond aufnimmt. Ein robustes Modell, das unter einer Vielzahl von Bedingungen standhält, einschließlich sehr kleiner Halbmonde, sollte besser aus einer größeren Vielfalt von Bildern hergestellt werden.

Die Passgenauigkeit zeigt, dass das Modell für die angegebenen Bilder nicht fest codiert war. Wir können ziemlich sicher sein, dass die Ausdehnung eines Mondes unabhängig von der Größe des Fotos ist, wie man es erwarten würde.

kleine Halbmonde

fNimmt das Bild ials Eingabe und gibt die vorhergesagte Größe des Vollmonds in Pixeln aus. Dies funktioniert bei Aufnahmen außerhalb der Bildmitte.

Wie die Daten unten zeigen, sind es alle Testfälle bis auf einen. Die Monde waren von voll bis sehr verkleinert angeordnet.

i_~c~t_ := Max@ComponentMeasurements[i, t][[All, 2]];
f@i_ := i~c~"Count"/(1 - 0.788 x - 0.578 x^2 /. x -> i~c~"Elongation")

Ein Foto kann mehr als eine Bildkomponente enthalten. Sogar ein einzelnes Pixel, das von den anderen getrennt ist, wird als eindeutige Komponente betrachtet. Aus diesem Grund ist es notwendig, "alle" Komponenten zu durchsuchen, um die zu finden, die die größere Anzahl von Pixeln aufweist. (Eines der kleinen Fotos hat mehr als eine Bildkomponente.)

Große Bilder

Die auf den großen Fotos gemachten Vorhersagen der Mondgröße waren gleichmäßig genau.

{"predicted size of full moon", f[#] & /@ large}
{"accuracy", %[[2]]/16416}

{"prognostizierte Größen des Vollmonds", {16422., 16270.9, 16420.6, 16585.5, 16126.5, 16151.6}}

{"Genauigkeit", {1.00037, 0.991161, 1.00028, 1.01033, 0.982367, 0.983891}}


Kleine bilder

Die auf den kleinen Fotos gemachten Vorhersagen der Mondgröße waren einheitlich, mit einer großen Ausnahme, dem endgültigen Bild. Ich vermute, das Problem rührt von der Tatsache her, dass der Halbmond sehr eng ist.

{"predicted sizes of full moon", f[#] & /@ small}
{"accuracy", %[[2]]/10241}

{"prognostizierte Größen des Vollmonds", {10247,3, 10161, 10265,6, 10391, 10058,9, 7045,91}}
{"Genauigkeit", {1.00061, 0.992192, 1.0024, 1.01465, 0.982221, 0.68801}}

DavidC
quelle
Scheint, als sollte ich eines Tages Mathematica lernen. Wie lange haben Sie gebraucht, um es zu lösen, ohne Golf zu spielen?
Thomas Weller
1
@Thomas W Es hat 2-3 Stunden gedauert, bis ich mit verschiedenen Bildverarbeitungsfunktionen und anderen (linearen) Modellen experimentiert habe. Die Codierung war nicht sehr schwierig. Und es gibt fast kein Golfspiel außer dem Zusammenführen einzelner Funktionen zu einer einzigen Funktion.
DavidC
104:i_~c~t_:=Max[#2&@@@i~ComponentMeasurements~t];f@i_:=i~c~"Count"/(1-0.788x-0.578x^2/.x->i~c~"Elongation")
Martin Ender
Aus unbekannten Gründen #2&@@@funktioniert der Vorschlag nicht
DavidC
Huh, das werde ich später untersuchen. Ein anderer Weg zu verkürzen cistc=Max@ComponentMeasurements[##][[All,2]]&
Martin Ender
5

J, 227 207 Bytes (maximaler Fehler 1,9%)

Meine Hauptidee ist, dass wir, wenn wir 3 Punkte auf der Kontur des Mondes finden, die auch auf der Kontur des Vollmonds sind, den Umkreis dieser Punkte berechnen können . Dieser Umkreis ist zum Vollmond.

Wenn wir zwei weiße Punkte mit maximalem Abstand finden, sind dies immer solche Punkte, die entweder eine echte Diagonale im Vollmond oder die Endpunkte des Halbmonds sind. Wir können das Paar von Punkten mit der größten Entfernung in jedem Diagramm finden, indem wir den Punkt auswählen, der von einem gegebenen Startpunkt am weitesten entfernt ist, und dann den Punkt auswählen, der am weitesten von dem ausgewählten entfernt ist.

Wir finden einen dritten Punkt mit einem Maximalwert der Produkte der Entfernungen von den vorhergehenden Punkten. Dies wird immer auf der Kontur und auf der Außenseite eines Halbmonds oder der größeren Seite eines Gibbous sein.

Der Durchmesser des Kreises wird berechnet als die Länge einer Seite geteilt durch den Sinus des entgegengesetzten Winkels.

Die zeitliche Komplexität dieser Methode ist in der Größe des Eingabebildes linear.

Code

f=.3 :0
load'graphics/png'
i=.readpng y
p=.(,i=_1)#|:,"%.0 1|:,"0/&>/<@i."*$i
s=.%:+/|:*:(-1|.]) (([,],:m@(*&d))(m@d))(m=.p{~(i.>./)@])(d=.+/@:*:@((|:p)-])) 0{p
o.*:-:({.s)%0 o.((+/-2*{.)*:s)%2**/}.s
)

Die Funktion erwartet den eingegebenen Dateinamen als Zeichenfolge.

(Eine (etwas) besser lesbare Version finden Sie im Versionsverlauf.)

Code Erklärung

  • p ist eine Liste von weißen Pixelkoordinaten (Punkte in der Zukunft genannt)
  • Funktion d berechnet Abstände zwischen Elementen von p und einem gegebenen Punkt
  • Der zweite Teil der Definition von s erzeugt eine 3-Punkte-Liste:

    • A ist der am weitesten vom ersten Punkt der Liste entfernte Punkt
    • B ist der am weitesten von A entfernte Punkt
    • C ist ein Punkt mit einem Maximalwert von Abstand von A mal Abstand von B
  • s ist die Seitenlänge des Dreiecks ABC

  • Die letzte Zeile berechnet die Fläche des Kreises von ABC, die der Vollmond ist

Ergebnisse

Der größte Fehler liegt bei 1,9%.

Die Bilder sind in der gleichen Reihenfolge wie in der Frage.

Output  Accuracy
----------------
  16407 0.999453 NB. Large images
16375.3 0.997523
16223.9 0.988301
16241.5 0.989369
16262.6 0.990654
16322.1 0.994279
10235.3 0.999445 NB. Small images
10235.3 0.999444
10221.2 0.998067
10220.3 0.997978
  10212 0.997169
10229.6  0.99889
9960.42 0.997239 NB. Offset images
9872.22 0.988408
10161.8   1.0174
9874.95 0.988681
 9805.9 0.981768
randomra
quelle
+1 für die Teilnahme und Erwähnung des Ansatzes. Es tut mir leid, dass ich nicht angegeben habe, dass das Zentrum nicht in der Mitte sein muss. Aus Versehen sind die Beispielbilder alle zentriert. Das ist meine Schuld.
Thomas Weller,
@ThomasW. Meine Antwort wurde vorübergehend gelöscht, bis ich sie korrigiert habe.
Randomra
2

Matlab 162 156 (nicht ganz im aktuellen Fehlerbereich)

Erstens: Die Genauigkeit beträgt weniger als 2% für alle außer einem Bild in jeder der beiden Serien, wo sie größer ist (ungefähr 5% und 14%). Mein Ansatz bestand darin, die zwei Pixel des Mondes zu finden, die am weitesten voneinander entfernt sind, und diese dann als Schätzung für den Durchmesser zu verwenden.

a=imread(input(''));                 %read input image
b=a(:,:,1)>0;                        %binarize red channel
s=size(b);                           %get size of the image
[x,y]=meshgrid(1:s(1),1:s(2));       
z=(x+i*y).*b;z=z(z~=0);              %find the coordinates of all white pixels (as a list)
o=ones(size(z(:)))*z(:)';            
disp(max(max(abs(o-o.').^2))*pi/4);  %calculate the maximum of the distance between each possible pair and evaluate area formula

Dies sind die Genauigkeitsergebnisse (reltative Abweichung 1 - (predicted size / real size))

0.0006 0.0025 0.0169 0.0500 0.0521 0.0113 0.0006 0.0006 0.0026 0.0472 0.1383 0.0131
fehlerhaft
quelle
1

C # - 617

Diese Lösung funktioniert nicht für alle Bilder, da auf einem der Bilder die Steigung (m) unendlich wird.

Das Prinzip wurde bereits erwähnt:

  1. Finde zwei Punkte mit maximaler Entfernung (rot)
  2. Stellen Sie sich eine Linie zwischen ihnen vor (rot)
  3. Stellen Sie sich eine Linie mit rechteckigem Winkel in der Mitte vor (grün)
  4. Finde weiße Punkte auf der grünen Linie
  5. Verwenden Sie den Punkt mit dem maximalen Abstand zu anderen Punkten (grün)
  6. Berechnen Sie die Fläche eines Kreises aus drei Punkten

Erläuterung

Der problematische Fall ist dieser, bei dem die Steigung unendlich ist. Sie können das Problem umgehen, indem Sie das Bild um 90 ° drehen oder in einer Codeschleife über die yAchse ziehen x.

Problematischer Mond

double A(Bitmap b){var a=new List<P>();for(var y=0;y<b.Height;y++)for(var x=0;x<b.Width;x++)if(b.GetPixel(x,y).R>0)a.Add(new P{x=x,y=y});double c=0.0,d=0.0,e=0.0,f=0.0,g=0.0,n=double.MaxValue;foreach(var h in a)foreach(var i in a){var t=Math.Sqrt(Math.Pow(h.x-i.x,2)+Math.Pow(h.y-i.y,2));if(t>c){d=h.x;f=i.x;e=h.y;g=i.y;c=t;}}c=(f-d)/(e-g);for(int x=0;x<b.Width;x++){int y=(int)(c*x+((e+g)/2-c*(d+f)/2));if(y>=0&&y<b.Height&&b.GetPixel(x,y).R>0){var s=(g-e)/(f-d);var q=(y-g)/(x-f);var j=(s*q*(e-y)+q*(d+f)-s*(f+x))/(2*(q-s));var k=-(j-(d+f)/2)/s+(e+g)/2;var l=(j-d)*(j-d)+(k-e)*(k-e);if(l<n)n=l;}}return Math.PI*n;}

Die Mindestgenauigkeit beträgt

  • + 1,89% für die 256-Pixel-Bilder
  • -0,55% für die 177-Pixel-Bilder
  • -1,66% für die nicht quadratischen Bilder
Thomas Weller
quelle