2012-02-12 13 views
17

myślałem, że to będzie łatwiejsze, ale po pewnym czasie ja ostatecznie rezygnując z tego, przynajmniej na kilka godzin ...Stacking zdjęć astronomia Pythona

Chciałem odtworzyć ten jest przecinkiem obraz gwiazdy z zestawu zdjęć timelapse. Inspirowany przez sposób: Inspiration

The original author stosowane klatki wideo o niskiej rozdzielczości przyjmować VD i połączone z ImageJ. Wyobraziłem sobie, że mogę łatwo odtworzyć ten proces, ale z bardziej świadomym pamięcią podejściem z Pythonem, więc mógłbym użyć the original high-resolution images dla lepszego wyjścia.

Pomysł mojego algorytmu jest prosty, łącząc dwa obrazy naraz, a następnie iterując, łącząc wynikowy obraz z następnym obrazem. Dokonano tego setki razy i właściwie ważono, aby każdy obraz miał taki sam wkład do końcowego wyniku.

Jestem całkiem nowy dla Pythona (i nie jestem profesjonalnym programistą, to będzie oczywiste), ale rozglądając się wokół wydaje mi się, że Python Imaging Library jest bardzo standardowa, więc zdecydowałem się go użyć (poprawne mnie, jeśli myślisz, że coś innego byłoby lepsze).

Oto co mam do tej pory:

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

To co robi to miało jednak uzyskany obraz jest ciemny, a jeśli ja po prostu staram się poprawić to, to jest oczywiste, że informacje zostały utracone z powodu braku głębokości w wartościach pikseli. (Nie jestem pewien, jaki jest tu właściwy termin, głębia koloru, precyzja koloru, rozmiar w pikselach). Oto ostateczny wynik stosując obrazy o niskiej rozdzielczości:

Low resolution result

lub jeden starałem pełną 4k uchwałą 2k (z innego zestawu zdjęć):

High resolution result with another set of images

Więc, próbowałem to naprawić poprzez ustawienie trybu obrazu:

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

ale widocznie Image.blend d Oe nie akceptują tego trybu obrazu.

ValueError: image has wrong mode

Wszelkie pomysły?

(próbowałem też podejmowania obrazy „mniej ciemno” przez pomnożenie go przed połączeniem ich z im.point (lambda I: I * 2), ale wyniki były tak złe)

+1

Twoje zdjęcia nie są jednakowo ważone. Na przykład, twoje pierwsze zdjęcie ma krycie "1/(1 + 1) = 0,5", a twoje 9 zdjęcie ma krycie "0,1". – Blender

+1

Blender, myślę, że jest równie ważony. gdy i = 0, 1/(i + 1) = 1, to dla pierwszej iteracji obraz ma wagę 0,5, ponieważ drugi 0.5 jest brany przez drugi obraz (plik [1]), a następnie, gdy i = 2 , plik [2] ma wagę 0,33, pozostawiając pierwsze dwa w sumie 0,66 .. czyli 0,33 każdy. Tak więc dziewiąty obraz rzeczywiście ma 0,1 alfa, ale oznacza to, że pierwsze 8 ma połączone krycie 0,9, to jest 0,1 na obraz (biorąc pod uwagę plik [0]). – JunCTionS

+3

Nie, @Blender ma rację, potrzebujesz * stałej wagi dla każdego obrazu *, co oznacza '1/len (pliki)'. Jeśli masz 2 obrazy, każdy obraz dostaje 0,5. Jeśli masz 10 zdjęć, każdy obraz ma wagę 0,1. –

Odpowiedz

20

Problem polega na tym, że ciebie uśredniają jasność każdego piksela. To może wydawać się rozsądne, ale w rzeczywistości wcale nie jest tym, czego chcesz - jasne gwiazdy zostaną "uśrednione", ponieważ poruszają się po obrazie. Podjąć następujące cztery ramki:

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

Jeśli średnia tych, dostaniesz:

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

Gdy chcesz:

1000 
0100 
0010 
0001 

Zamiast mieszania obrazów można spróbować biorąc maksimum widoczne w każdym obrazie dla każdego piksela.Jeśli masz PIL możesz wypróbować lżejszą funkcję w 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") 

Oto co mam: Low res image set stacked

EDIT: czytałem post Reddit i zobaczyć, że rzeczywiście łączy dwa podejścia - jedno dla szlaków gwiazda i inny dla Ziemi . Oto lepsza implementacja uśredniania, które wypróbowałeś, z odpowiednią wagą. Użyłem tablicy numpy do przechowywania pośredniego zamiast tablicy obrazów 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') 

Oto obraz, który można następnie połączyć ze śladami gwiazdy z poprzedniego. Low res images added together

+1

Świetne !! Dziękuję Ci bardzo. [Oto ostateczny wynik z oryginalnymi pełnowymiarowymi obrazami] (http://i.imgur.com/P9mzc.jpg) (chociaż nieco obniżony przez ograniczenia rozmiaru imgura) [1]: http: // i .imgur.com/P9mzc.jpg – JunCTionS

+0

@JunCTIONS Bez obaw, wygląda naprawdę dobrze. Właściwie przeczytałem komentarz Reddita i zrobił to samo, co sugerowałem dla szlaków gwiazd, ale coś w rodzaju twojego pierwotnego podejścia uśredniającego dla Ziemi. Będę miał do tego szybkie pęknięcie i dodaję go jako edycję. – simonb