El tamaño del misterio de la luna
Estoy seguro de que has oído que la luna cambia de tamaño. Cuando estás enamorado y tienes suerte, la luna tiene casi el doble de tamaño en comparación con las situaciones normales. Algunas personas dicen que la razón es la atmósfera que actúa como lente. Otros piensan que es solo una cuestión de comparación con otros objetos como árboles cercanos. Cualquier explicación que leas, es bastante subjetiva.
El tamaño de la ciencia lunar
Ok, somos programadores, ¿no? Confiamos en los hechos, ¿verdad? Así que aquí está el experimento:
- Tome una buena cámara que admita el tiempo de ajuste y la apertura manualmente.
- Configure su cámara al máximo nivel de zoom.
- Salga, tome algunas fotografías de la luna para detectar la mejor configuración para que la luna sea nítida y la iluminación esté bien.
- Recuerda la configuración
- Tome fotos de la luna con esos ajustes cada vez que piense que la luna es grande o pequeña.
- Calcular el tamaño de la luna en píxeles
La cámara no mentirá, ¿verdad? Al contar los píxeles brillantes, podemos medir efectivamente el tamaño de la luna, al menos en píxeles.
Si el tamaño es el mismo en todas las fotos, entonces es un error en nuestro cerebro. Si el tamaño difiere, entonces hay espacio para la especulación.
- la luna realmente crece (pero ¿qué come?)
- hay un efecto de lente atmosférico
- la luna tiene una curva elíptica y a veces está más cerca, a veces más lejos de la tierra
- ...
Pero lo dejaré abierto hasta que se complete su tarea. Por supuesto, desea saber de antemano si su software puede calcular el tamaño de la luna con precisión.
La tarea
Dadas algunas imágenes optimizadas de la luna, calcule el tamaño de la luna. La optimización es: los píxeles son blancos o negros. Nada en el medio. Sin antialiasing. Eso lo hace fácil, ¿no?
La advertencia: la luna no siempre está llena, ya sabes ... ¡puede ser una hoz! Pero incluso en forma de hoz, el tamaño de la luna es más grande. Así que calcularás el tamaño completo, por favor.
- Su programa toma un PNG como entrada, por ejemplo, como argumento de línea de comando de nombre de archivo, canalizado en
stdin
o como un objeto de mapa de bits (de una biblioteca de marco estándar) si escribe una función en lugar de un programa. - Su programa funciona con cualquier tamaño de mapa de bits de entrada razonable, no necesariamente cuadrado. Se garantiza un ancho mínimo y una altura de 150 píxeles.
- La luna llena cubre al menos el 25% de la imagen.
- Su programa genera el tamaño calculado de la luna en píxeles como si fuera una luna llena.
- Asumimos que la luna es una esfera perfecta.
- El tamaño exacto siempre es un número entero, pero puede generar un número decimal si su cálculo lo devuelve.
- La precisión debe estar entre 98% y 102%. (Eso es más una conjetura que algo que podría garantizar que se pueda lograr. Si cree que es demasiado difícil de alcanzar, deje un comentario).
Actualización :
- El centro de la luna no está necesariamente en el medio de la imagen.
- El área visible mínima es el 5% de la luna o el 1,25% del número total de píxeles.
- La imagen se toma de manera que la luna entera se ajuste a la imagen, es decir, el número total de píxeles es un límite superior para el tamaño de la luna.
- La luna no se recortará / recortará.
Las muestras
Puede generar sus propias muestras utilizando el archivo de mezcla si lo desea. He creado las siguientes imágenes para ti. Puede contar píxeles en un archivo PNG con WhitePixelCounter.exe (necesita .NET) para verificar si la imagen contiene solo píxeles en blanco y negro y cuántos de ellos.
Las siguientes imágenes de 256x256 píxeles difieren en la cantidad de píxeles blancos, pero todas deben dar como resultado un tamaño de luna calculado de 16416 píxeles.
Y estas imágenes de 177x177 píxeles deberían devolver 10241 píxeles. Las imágenes son básicamente las mismas, pero esta vez se utilizó una cámara con una distancia focal diferente.
Muestras no cuadradas y no centradas con un resultado de 9988:
Oh, no tengo una implementación de referencia por ahora e incluso no sé si puedo implementar algo. Pero en mi cerebro hay una fuerte creencia que me dice que debe ser matemáticamente solucionable.
Las normas
Este es el código de golf. Se acepta el código más corto el 30/03/2015.
fuente
Respuestas:
Mathematica
126119109bytesMathematica puede medir el alargamiento de un componente en una imagen. Una luna llena, siendo perfectamente simétrica, tiene un alargamiento de 0, en una escala de 0 a 1.
Una luna decreciente se alarga cada vez más, hasta un máximo de aproximadamente 0,8.
0.998 -0.788 x-0.578 x^2
fue el modelo empíricamente determinado (basado en las fotos grandes) para `predecir la plenitud de la luna (por área), dado su alargamiento.Ajusté el modelo para
1- 0.788 x -0.578 x^2
que con exactamente elongación cero (luna llena) el modelo devuelva 1 para el factor de escala de píxeles. Ahorra 4 bytes y aún se mantiene dentro de los límites de precisión.Este modelo se utiliza para imágenes de cualquier tamaño. La imagen de la luna no necesita estar centrada. Tampoco necesita cubrir una proporción fija de la foto.
Aquí están los puntos de datos (alargamiento, displaysMoonPixels / fullMoonPixels) para las imágenes grandes y el modelo parabólico que se generó para ajustarse a los datos. Los modelos lineales se ajustan bien, pero el modelo cuadrático está totalmente activado, dentro de los límites (ver más abajo).
Aquí los datos son de las imágenes grandes. Así es el modelo
A continuación, los datos (los puntos rojos) son de las imágenes pequeñas. El modelo (la curva azul) es el generado por las imágenes grandes, el mismo que se muestra arriba.
La media luna más pequeña tiene un 7,5% del área de luna llena. (La media luna más pequeña entre las fotos grandes es el 19% de la luna llena.) Si el modelo cuadrático se hubiera basado en las fotos pequeñas, el ajuste a continuación sería mejor, solo porque acomoda la media luna pequeña. Un modelo robusto, que se mantendría en pie en una amplia gama de condiciones, incluidas las medias lunas muy pequeñas, estaría mejor hecho de una mayor variedad de imágenes.
La cercanía de ajuste muestra que el modelo no estaba codificado para las imágenes dadas. Podemos estar bastante seguros de que el alargamiento de una luna es independiente del tamaño de la foto, como cabría esperar.
f
toma la imagen,i
como entrada y salida del tamaño predicho de la luna llena, en píxeles. Funciona para disparos descentrados.Como muestran los datos a continuación, todos los casos de prueba excepto uno. Las lunas se arreglaron de lleno a más disminuido.
Más de un componente de imagen puede aparecer en una foto. Incluso un solo píxel separado de los demás se considerará un componente distinto. Por esta razón, es necesario buscar "todos" los componentes, para encontrar el que tenga la mayor cantidad de píxeles. (Una de las fotos pequeñas tiene más de un componente de imagen).
Cuadros grandes
Las predicciones del tamaño de la luna hechas a partir de las fotos grandes fueron uniformemente precisas.
Fotos pequeñas
Las predicciones del tamaño de la luna hechas a partir de las fotos pequeñas fueron uniformes, con una gran excepción, la imagen final. Sospecho que el problema se debe al hecho de que la media luna es muy estrecha.
fuente
i_~c~t_:=Max[#2&@@@i~ComponentMeasurements~t];f@i_:=i~c~"Count"/(1-0.788x-0.578x^2/.x->i~c~"Elongation")
#2&@@@
sugerencia no funcionac
esc=Max@ComponentMeasurements[##][[All,2]]&
J,
227207bytes (error máximo 1.9%)Mi idea principal es que si podemos encontrar 3 puntos en el contorno de la luna que también están en el contorno de la luna llena, podemos calcular el círculo de estos puntos. Esa circunferencia será a luna llena.
Si encontramos dos puntos blancos con una distancia máxima, siempre serán esos puntos, ya que serán una diagonal real en la luna llena o los puntos finales de la media luna.
Podemos encontrar el par de puntos con la mayor distancia en cualquier gráfico seleccionando el punto más alejado de cualquier punto de partida dado y luego seleccionando el punto más alejado del seleccionado.Encontramos un tercer punto con un valor máximo de los productos de las distancias desde los puntos anteriores. Esto siempre estará en el contorno y en el lado exterior de una media luna o el lado más grande de un giboso.
El diámetro del círculo circunferencial se calcula como la longitud de un lado dividido por el seno del ángulo opuesto.
La complejidad temporal de este método es lineal en el tamaño de la imagen de entrada.
Código
La función espera el nombre de archivo de entrada como una cadena.
(Para una versión (poco) más legible, verifique el historial de revisiones).
Explicación del código
La segunda parte de la definición de s crea una lista de 3 puntos:
s es la longitud lateral del triángulo ABC
Resultados
El mayor error es 1.9%.
Las imágenes están en el mismo orden que en la pregunta.
fuente
Matlab
162156(no exactamente en el margen de error actual)En primer lugar: la precisión es inferior al 2% para todas las imágenes menos una en cada una de las dos series, donde es mayor (aproximadamente 5% y 14%). Mi enfoque fue encontrar los dos píxeles de la luna que están más alejados el uno del otro, y luego usar esto como una estimación del diámetro.
Estos son los resultados de precisión (desviación relativa
1 - (predicted size / real size)
)fuente
C # - 617
Esta solución no funciona para todas las imágenes, porque en una de las imágenes, la pendiente (m) se convierte en infinito.
El principio fue mencionado antes:
El caso problemático es este, donde la pendiente es infinita. Es posible solucionarlo girando la imagen 90 ° o en código, bucle sobre el
y
eje en lugar dex
.La precisión mínima es
fuente