2012-02-12 20 views
17

pensé que esto iba a ser más fácil, pero después de un tiempo Soy finalmente renunciar a esto, al menos durante un par de horas ...de apilamiento imágenes astronómicas con Python

que querían reproducir este un arrastre imagen de estrellas de un conjunto de imágenes de timelapse. Inspirado por esto: Inspiration

The original author utilizan marcos de video de baja resolución tomados con VirtualDub y combinados con imageJ. Imaginé que podía reproducir fácilmente este proceso pero con un enfoque más consciente de la memoria con Python, así que podría usar the original high-resolution images para obtener una mejor salida.

La idea de mi algoritmo es simple, combinando dos imágenes a la vez, y luego iterando combinando la imagen resultante con la siguiente imagen. Esto se hace cientos de veces y ponderándolo adecuadamente para que cada imagen tenga la misma contribución al resultado final.

Soy bastante nuevo en python (y no soy un programador profesional, eso será evidente), pero al mirar a mi alrededor me parece que la biblioteca de imágenes de Python es muy estándar, así que decidí usarla (corregir yo si piensas que otra cosa sería mejor).

Esto es lo que tengo hasta ahora:

#program to blend many images into one 
import os,Image 
files = os.listdir("./") 
finalimage=Image.open("./"+files[0]) #add the first image 
for i in range(1,len(files)): #note that this will skip files[0] but go all the way to the last file 
    currentimage=Image.open("./"+files[i]) 
    finalimage=Image.blend(finalimage,currentimage,1/float(i+1))#alpha is 1/i+1 so when the image is a combination of i images any adition only contributes 1/i+1. 
    print "\r" + str(i+1) + "/" + str(len(files)) #lousy progress indicator 
finalimage.save("allblended.jpg","JPEG") 

Esto hace lo que se supone que es, pero la imagen resultante es oscuro, y si yo simplemente trato de mejorarlo, es evidente que la información se perdió debido la falta de profundidad en los valores de píxel. (No estoy seguro de cuál es el término correcto aquí, profundidad de color, precisión de color, tamaño de píxel). Aquí está el resultado final usando imágenes de baja resolución:

Low resolution result

o uno que estaba tratando con la 4k su totalidad por resolución 2K (de otra serie de fotos):

High resolution result with another set of images

Por lo tanto, Traté de solucionarlo estableciendo el modo de imagen:

firstimage=Image.open("./"+files[0]) 
size = firstimage.size 
finalimage=Image.new("I",size) 

pero aparentemente Image.blend d oes no acepta ese modo de imagen.

ValueError: image has wrong mode

¿Alguna idea?

(también intenté hacer las imágenes "menos oscura" multiplicándolo antes de combinarlos con im.point (lambda i: i * 2), pero los resultados fueron igual de malo)

+1

Sus imágenes no tienen la misma ponderación. Por ejemplo, su primera imagen tiene opacidad '1/(1 + 1) = 0.5', mientras que su novena imagen tiene opacidad' 0.1'. – Blender

+1

Blender, creo que es igual de ponderado. cuando i = 0, 1/(i + 1) = 1, entonces para la primera iteración esa imagen tiene un peso de 0.5 porque la otra 0.5 es tomada por la segunda imagen (archivo [1]), y luego cuando i = 2 , el archivo [2] tiene un peso de 0.33, dejando los primeros dos combinados con un total de 0.66 ... es decir, 0.33 cada uno. Entonces, la novena imagen sí tiene 0.1 alfa, pero eso significa que las primeras 8 tienen una opacidad combinada de 0.9, es decir, 0.1 por imagen (considerando el archivo [0]). – JunCTionS

+3

No, @Blender tiene razón, necesita un * peso constante para cada imagen *, lo que significa '1/len (archivos)'. Si tiene 2 imágenes en total, cada imagen tiene un peso de 0.5. Si tiene 10 imágenes en total, cada imagen tiene un peso de 0.1. –

Respuesta

20

El problema aquí es que se están promediando el brillo en cada píxel. Esto puede parecer sensato, pero en realidad no es lo que quieres en absoluto: las estrellas brillantes serán "promediadas" porque se mueven a través de la imagen. Tome las siguientes cuatro cuadros:

1000 0000 0000 0000 
0000 0100 0000 0000 
0000 0000 0010 0000 
0000 0000 0000 0001 

Si usted hace un promedio aquellos, se obtiene:

0.25 0 0 0 
0 0.25 0 0 
0 0 0.25 0 
0 0 0 0.25 

Cuando desee:

1000 
0100 
0010 
0001 

En lugar de mezclar las imágenes que puede tratar de tomar la máximo visto en cualquier imagen para cada píxel.Si tiene PIL, puede probar la función de encendedor en ImageChops.

from PIL import ImageChops 
import os, Image 
files = os.listdir("./") 
finalimage=Image.open("./"+files[0]) 
for i in range(1,len(files)): 
    currentimage=Image.open("./"+files[i]) 
    finalimage=ImageChops.lighter(finalimage, currentimage) 
finalimage.save("allblended.jpg","JPEG") 

Esto es lo que tengo: Low res image set stacked

EDIT: leí la publicación de Reddit y veo que en realidad combina dos enfoques - uno para los senderos de estrellas y otro diferente para la Tierra . Aquí hay una mejor implementación del promedio que probaste, con la ponderación adecuada. Usé una matriz numpy para el almacenamiento intermedio en lugar de la matriz de imágenes uint8.

import os, Image 
import numpy as np 
files = os.listdir("./") 
image=Image.open("./"+files[0]) 
im=np.array(image,dtype=np.float32) 
for i in range(1,len(files)): 
    currentimage=Image.open("./"+files[i]) 
    im += np.array(currentimage, dtype=np.float32) 
im /= len(files) * 0.25 # lowered brightness, with magic factor 
# clip, convert back to uint8: 
final_image = Image.fromarray(np.uint8(im.clip(0,255))) 
final_image.save('all_averaged.jpg', 'JPEG') 

Aquí está la imagen, que luego podría combinar con los rastros de estrellas del anterior. Low res images added together

+1

¡¡Genial !! muchas gracias. [Aquí está el resultado final con las imágenes originales de tamaño completo] (http://i.imgur.com/P9mzc.jpg) (aunque un poco degradado por las limitaciones de tamaño de imgur) [1]: http: // i .imgur.com/P9mzc.jpg – JunCTionS

+0

@JunCTionS No se preocupe, se ve muy bien. De hecho, leí el comentario de Reddit y él hizo lo mismo que sugerí para los rastros de estrellas, pero algo así como su enfoque promedio original para la Tierra. Voy a tener una grieta rápida en eso y agregarlo como una edición. – simonb

Cuestiones relacionadas