Подтвердить что ты не робот

Укладка изображений астрономии с помощью Python

Я думал, что это будет легче, но через некоторое время я, наконец, откажусь от этого, по крайней мере, на пару часов...

Я хотел воспроизвести это изображение с закрытыми звездами из набора изображений по времени. Вдохновленный этим: Inspiration

Оригинальный автор использовал видеофрагменты низкого разрешения, снятые с VirtualDub, и в сочетании с imageJ. Я представил себе, что могу легко воспроизвести этот процесс, но с более сознательным подходом к Python, поэтому я мог бы использовать исходные изображения с высоким разрешением для лучший выход.

Моя идея алгоритма проста, слияние двух изображений за раз, а затем итерация путем слияния полученного изображения со следующим изображением. Это делалось несколько сотен раз и правильно взвешивало его так, чтобы каждое изображение имело тот же вклад в конечный результат.

Я новичок в python (и я не профессиональный программист, это будет очевидно), но, оглядываясь, мне кажется, что библиотека изображений Python очень стандартная, поэтому я решил использовать ее (исправьте меня если вы думаете, что что-то еще будет лучше).

Вот что я до сих пор:

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

Это делает то, что он должен, но результирующее изображение темное, и если я просто попытаюсь его улучшить, очевидно, что информация была потеряна из-за отсутствия глубины в значениях пикселей. (Я не уверен, что такое правильный термин, глубина цвета, точность цвета, размер пикселя). Здесь конечный результат с использованием изображений с низким разрешением:

Low resolution result

или один я пытался с полным разрешением 4k на 2k (из другого набора фотографий):

High resolution result with another set of images

Итак, я попытался исправить это, установив режим изображения:

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

но, очевидно, Image.blend не принимает этот режим изображения.

ValueError: изображение имеет неправильный режим

Любые идеи?

(Я также попытался сделать изображения "менее темными", умножив их, прежде чем комбинировать их с im.point(lambda i: я * 2), но результаты были такими же плохими)

4b9b3361

Ответ 1

Проблема заключается в том, что вы усредняете яркость на каждом пикселе. Это может показаться разумным, но на самом деле это совсем не то, что вы хотите - яркие звезды получат "усредненные", потому что они перемещаются по изображению. Возьмите следующие четыре кадра:

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

Если вы усредняете их, вы получите:

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

Если вы хотите:

1000
0100
0010
0001

Вместо того, чтобы смешивать изображения, вы можете попробовать взять максимальное изображение в любом изображении для каждого пикселя. Если у вас есть PIL, вы можете попробовать более легкую функцию в 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")

Вот что я получил: Low res image set stacked

EDIT: Я читаю сообщение Reddit и вижу, что он на самом деле объединил два подхода - один для звездных троп и другой для Земли. Вот лучшая реализация усреднения, которое вы пытались, с правильным взвешиванием. Я использовал массив numpy для промежуточного хранилища вместо массива изображений 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')

Вот изображение, которое вы могли бы затем объединить со звездообразными дорожками от предыдущего. Low res images added together