Calcola la dimensione della luna


19

La dimensione del mistero della luna

Sono sicuro che hai sentito che la luna cambia dimensione. Quando sei innamorato e sei fortunato, la luna è quasi due volte più grande rispetto alle situazioni normali. Alcune persone dicono che il motivo sia l'atmosfera che funge da obiettivo. Altri pensano che sia solo una questione di confronto con altri oggetti come alberi nelle vicinanze. Qualunque sia la spiegazione che leggi, è abbastanza soggettiva.

La dimensione della scienza della luna

Ok, siamo programmatori, vero? Facciamo affidamento sui fatti, giusto? Quindi ecco l'esperimento:

  1. Prendi una bella fotocamera che supporti l'impostazione manuale del tempo e dell'apertura.
  2. Imposta la fotocamera al massimo livello di zoom.
  3. Esci, scatta alcune fotografie della luna per rilevare le migliori impostazioni in modo che la luna sia nitida e l'illuminazione sia perfetta.
  4. Ricorda le impostazioni
  5. Scatta foto della luna con queste impostazioni ogni volta che pensi che la luna sia grande o piccola.
  6. Calcola la dimensione della luna in pixel

La macchina fotografica non mentirà, vero? Contando i pixel luminosi possiamo misurare efficacemente la dimensione della luna - almeno in pixel.

Se la dimensione è la stessa in tutte le foto, allora è un bug nel nostro cervello. Se la dimensione differisce, allora c'è spazio per le speculazioni

  • la luna cresce davvero (ma cosa mangia?)
  • c'è un effetto lente atmosferico
  • la luna ha una curva ellittica ed è talvolta più vicina, a volte più lontana dalla terra
  • ...

Ma lo lascerò aperto fino a quando il tuo compito non sarà completato. Ovviamente vuoi sapere in anticipo se il tuo software è in grado di calcolare accuratamente le dimensioni della luna.

L'obiettivo

Date alcune immagini ottimizzate della luna, si prega di calcolare la dimensione della luna. L'ottimizzazione è: i pixel sono bianchi o neri. Niente in mezzo. Nessun antialiasing. Questo lo rende facile, vero?

L'avvertimento: la luna non è sempre piena, sai ... può essere una falce! Ma anche a forma di falce, la dimensione della luna è più grande. Quindi calcolerai la dimensione intera, per favore.

  • Il tuo programma accetta un PNG come input, ad es. Come argomento della riga di comando del nome file, reindirizzato stdino come oggetto Bitmap (di una libreria di framework standard) se scrivi una funzione anziché un programma.
  • Il tuo programma funziona con qualsiasi dimensione bitmap di input ragionevole, non necessariamente quadrata. La larghezza e l'altezza minima di 150 pixel sono garantite.
  • La luna piena copre almeno il 25% dell'immagine.
  • Il tuo programma genera la dimensione calcolata della luna in pixel come se fosse una luna piena.
  • Partiamo dal presupposto che la luna è una sfera perfetta.
  • La dimensione esatta è sempre un numero intero, ma è possibile generare un numero decimale se il calcolo lo restituisce.
  • La precisione dovrebbe essere compresa tra il 98% e il 102%. (È piuttosto un'ipotesi che qualcosa che potrei garantire per essere realizzabile. Se pensi che sia troppo difficile da raggiungere, lascia un commento.)

Aggiornamento :

  • Il centro della luna non è necessariamente al centro dell'immagine.
  • L'area minima visibile è il 5% della luna o l'1,25% del numero totale di pixel.
  • L'immagine è scattata in modo tale che l'intera luna si adatterebbe all'immagine, cioè il numero totale di pixel è un limite superiore per la dimensione della luna.
  • La luna non sarà ritagliata / tagliata.

I campioni

Se lo desideri, puoi generare i tuoi campioni usando il file di fusione . Ho creato le seguenti immagini per te. Puoi contare i pixel in un file PNG usando WhitePixelCounter.exe (necessita di .NET) per verificare se l'immagine contiene solo pixel in bianco e nero e quanti di essi.

Le seguenti immagini di 256x256 pixel differiscono nella quantità di pixel bianchi, ma dovrebbero tutti tradursi in una dimensione lunare calcolata di 16416 pixel.

Luna piena Luna Luna Luna Luna Luna

E queste immagini di 177x177 pixel dovrebbero restituire 10241 pixel. Le immagini sono sostanzialmente le stesse, ma questa volta è stata utilizzata una fotocamera con una lunghezza focale diversa.

Luna Luna Luna Luna Luna Luna

Campioni non quadrati e non centrati con un risultato di 9988:

Luna in una cornice non quadrata Luna in una cornice non quadrata Luna in una cornice non quadrata Luna in una cornice non quadrata Luna in una cornice non quadrata

Oh, non ho un'implementazione di riferimento per ora e non so nemmeno se sono in grado di implementare qualcosa. Ma nel mio cervello c'è una forte convinzione che mi dice che deve essere matematicamente risolvibile.

Le regole

Questo è Code Golf. Viene accettato il codice più breve del 30-03-2015.


9
In tutti gli esempi, il centro della luna sembra essere centrato all'interno dell'immagine. Possiamo supporre che la luna sarà sempre centrata?
Trauma digitale

1
la precisione del +/- 2% sull'area corrisponde al +/- 1% sul diametro: esempio r = 100 pixel, area = 10000 * pi; r = 101 pixel, area = 10201 * pi. L'immagine più piccola ha r = 72 quindi d = 144 quindi dovrebbe semplicemente essere possibile. Per immagini inferiori a d = 100, tuttavia, non è possibile raggiungere la precisione.
Level River St

@DigitalTrauma: il centro non deve essere nel mezzo.
Thomas Weller,

@ MartinBüttner: la percentuale minima visibile è il 5% della luna o l'1,25% dell'immagine.
Thomas Weller,

@ MartinBüttner: ok, ho aggiornato la domanda, aggiornato il file di fusione per produrre immagini non quadrate e non centrate per impostazione predefinita. Puoi scaricare tutte le immagini qui (* .png.zip) . Anche il contatore dei pixel aggiornato: genera ulteriori informazioni e controlla la regola dell'1,25%.
Thomas Weller,

Risposte:


10

Mathematica 126 119 109 byte

Mathematica può misurare l'allungamento di un componente in un'immagine. Una luna piena, essendo perfettamente simmetrica, ha un allungamento di 0, su una scala da 0 a 1.

Una luna calante diventa sempre più allungata, fino a un massimo di circa 0,8.

0.998 -0.788 x-0.578 x^2 era il modello empiricamente determinato (basato sulle grandi foto) per `prevedere la pienezza della luna (per area), dato il suo allungamento.

Ho regolato il modello in 1- 0.788 x -0.578 x^2modo che con un allungamento esattamente zero (luna piena) il modello restituisca 1 per il fattore di scala dei pixel. Salva 4 byte e rimane comunque entro i limiti di precisione.

Questo modello viene utilizzato per immagini di qualsiasi dimensione. L'immagine della luna non ha bisogno di essere centrata. Inoltre, non è necessario coprire una parte fissa della foto.

Ecco i punti dati (allungamento, displayMoonPixels / fullMoonPixels) per le immagini di grandi dimensioni e il modello parabolico che è stato generato per adattarsi ai dati. I modelli lineari si adattano bene, ma il modello quadratico è morto, entro i limiti (vedi sotto).

Qui i dati provengono dalle immagini di grandi dimensioni. Così è il modello

mezzaluna di grandi dimensioni


Sotto, i dati (i punti rossi) provengono dalle piccole immagini. Il modello (la curva blu) è quello generato dalle immagini di grandi dimensioni, lo stesso mostrato sopra.

La mezzaluna più piccola ha il 7,5% dell'area di una luna piena. (La mezzaluna più piccola tra le grandi foto è il 19% di una luna piena.) Se il modello quadratico fosse basato sulle piccole foto, l'adattamento sotto sarebbe migliore, solo perché ospitava la piccola mezzaluna. Un modello robusto, in grado di resistere in una vasta gamma di condizioni, tra cui mezzalune molto piccole, sarebbe meglio realizzato da una più ampia varietà di immagini.

La vicinanza di adattamento mostra che il modello non è stato codificato per le immagini fornite. Possiamo essere abbastanza certi che l'allungamento di una luna è indipendente dalle dimensioni della foto, come ci si aspetterebbe.

piccole mezzaluna

fprende l'immagine, icome input e genera la dimensione prevista della luna piena, in pixel. Funziona per scatti fuori centro.

Come mostrano i dati seguenti, tutti i casi di test tranne uno. Le lune erano disposte dal più pieno al più ridotto.

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")

Più di un componente dell'immagine può apparire in una foto. Anche un singolo pixel separato dagli altri sarà considerato un componente distinto. Per questo motivo, è necessario cercare "tutti" i componenti, per trovare quello con il maggior numero di pixel. (Una delle piccole foto ha più di un componente immagine.)

Immagini grandi

Le previsioni sulla dimensione della luna fatte dalle grandi foto erano uniformemente accurate.

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

{"dimensioni previste della luna piena", {16422., 16270.9, 16420.6, 16585.5, 16126.5, 16151.6}}

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


Piccole immagini

Le previsioni sulla dimensione della luna fatte dalle piccole foto erano uniformemente, con una grande eccezione, il quadro finale. Sospetto che il problema derivi dal fatto che la mezzaluna è molto stretta.

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

{"dimensioni previste della luna piena", {10247.3, 10161., 10265.6, 10391., 10058.9, 7045.91}}
{"accuratezza", {1.00061, 0.992192, 1.0024, 1.01465, 0.982221, 0.68801}}


Sembra che dovrei imparare Mathematica un giorno. Quanto tempo hai impiegato per risolverlo senza giocare a golf?
Thomas Weller,

1
@Thomas W Ci sono volute 2-3 ore di sperimentazione con vari tipi di funzionalità di elaborazione delle immagini e altri modelli (lineari) fino a quando non ho ottenuto il grafico che vedi pubblicato. La codifica non è stata molto difficile. E non c'è quasi nessun golf oltre all'unione di funzioni separate in un'unica funzione.
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,

Per motivi sconosciuti, il #2&@@@suggerimento non funziona
DavidC

Huh, ci penserò più tardi. Un altro modo per abbreviare cèc=Max@ComponentMeasurements[##][[All,2]]&
Martin Ender,

5

J, 227 207 byte (errore massimo 1,9%)

La mia idea principale è che se possiamo trovare 3 punti sul contorno della luna che si trovano anche sul contorno della luna piena, possiamo calcolare il cerchio di questi punti. Quel cerchio sarà alla luna piena.

Se troviamo due punti bianchi con la massima distanza, questi saranno sempre tali in quanto saranno o una vera diagonale nella luna piena o i punti finali della mezzaluna. Possiamo trovare la coppia di punti con la massima distanza in qualsiasi grafico selezionando il punto più lontano da qualsiasi dato punto iniziale e quindi selezionando il punto più lontano da quello selezionato.

Troviamo un terzo punto con un valore massimo dei prodotti delle distanze dai punti precedenti. Questo sarà sempre sul contorno e sul lato esterno di una mezzaluna o sul lato più grande di un gibboso.

Il diametro del cerchio è calcolato come la lunghezza di un lato diviso per il seno dell'angolo opposto.

La complessità temporale di questo metodo è lineare nella dimensione dell'immagine di input.

Codice

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
)

La funzione prevede che il nome file di input sia una stringa.

(Per una (poco) versione più leggibile controlla la cronologia delle revisioni.)

Spiegazione del codice

  • p è un elenco di coordinate di pixel bianchi (chiamati punti in futuro)
  • la funzione d calcola le distanze tra gli elementi di p e un dato punto
  • la seconda parte della definizione di s crea un elenco di 3 punti:

    • A è il punto più lontano dal primo punto nell'elenco
    • B è il punto più lontano da A
    • C è un punto con un valore massimo di distanza forma A volte distanza da B
  • s è la lunghezza laterale del triangolo ABC

  • l'ultima riga calcola l'area del cerchio di ABC che è la luna piena

risultati

L'errore più grande è dell'1,9%.

Le immagini sono nello stesso ordine della domanda.

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

+1 per partecipare e menzionare l'approccio. Mi dispiace non aver specificato che il centro non debba essere nel mezzo. Per inciso, le immagini di esempio sono tutte centrate. È colpa mia.
Thomas Weller,

@ThomasW. Eliminata temporaneamente la mia risposta fino a quando non la correggo.
randomra,

2

Matlab 162 156 (non abbastanza nell'attuale margine di errore)

Prima di tutto: la precisione è inferiore al 2% per tutte tranne un'immagine in ciascuna delle due serie, dove è maggiore (circa il 5% e il 14%). Il mio approccio consisteva nel trovare i due pixel della luna più lontani l'uno dall'altro, e quindi usarli come stima del diametro.

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

Questi sono i risultati dell'accuratezza (deviazione relativa 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

1

C # - 617

Questa soluzione non funziona per tutte le immagini, perché su una delle immagini la pendenza (m) diventa infinita.

Il principio è stato menzionato prima:

  1. Trova due punti con la distanza massima (rosso)
  2. Immagina una linea tra loro (rosso)
  3. Immagina una linea con angolo rettangolare al centro (verde)
  4. Trova i punti bianchi sulla linea verde
  5. Usa quello con la massima distanza dagli altri punti (verde)
  6. Calcola l'area di un cerchio da tre punti

Spiegazione

Il caso problematico è questo, in cui la pendenza è infinita. È possibile risolvere il problema ruotando l'immagine di 90 ° o in codice, passare sopra l' yasse anziché x.

Luna problematica

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;}

La precisione minima è

  • + 1,89% per le immagini a 256 pixel
  • -0,55% per le immagini da 177 pixel
  • -1,66% per le immagini non quadrate
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.