19

これはもっと簡単になるだろうと思っていましたが、しばらくして、少なくとも数時間は、ついにこれをあきらめました...

タイムラプスの一連の写真から、これを追跡星の画像で再現したかったのです。これに触発されました: インスピレーション

原作者は、VirtualDubで撮影し、imageJと組み合わせた低解像度のビデオフレームを使用しました。このプロセスを簡単に再現できると思いましたが、Pythonを使用したよりメモリを意識したアプローチで、元の高解像度画像を使用してより良い出力を得ることができました。

私のアルゴリズムのアイデアは単純で、一度に2つの画像をマージし、結果の画像を次の画像とマージすることで反復します。これは数百回行われ、すべての画像が最終結果に同じ貢献をするように適切に計量しました。

私はPythonにかなり慣れていません(そして私はプロのプログラマーではありません、それは明らかです)が、それを見回すとPython Imaging Libraryは非常に標準的であるように見えるので、それを使用することにしました(他の何かが良いでしょう)。

これが私がこれまでに持っているものです:

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

これは想定どおりの動作をしますが、結果の画像は暗くなります。単に強調しようとすると、ピクセル値の深さが不足しているために情報が失われたことは明らかです。(ここでの適切な用語、色深度、色精度、ピクセルサイズはわかりません)。低解像度の画像を使用した最終結果は次のとおりです。

低解像度の結果

または、4k x 2kのフル解像度で試していたもの(別の写真セットから):

別の画像セットによる高解像度の結果

だから、私は画像モードを設定することによってそれを修正しようとしました:

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

しかし、どうやらImage.blendはその画像モードを受け入れません。

ValueError:画像のモードが間違っています

何か案は?

(また、im.point(lambda i:i * 2)と組み合わせる前に、画像を乗算して「暗くしない」ようにしましたが、結果も同様に悪かったです)

4

1 に答える 1

22

ここでの問題は、各ピクセルの明るさを平均していることです。これは理にかなっているように見えるかもしれませんが、実際にはまったく望んでいないことです。明るい星は画像を横切って移動するため、「平均化」されます。次の4つのフレームを取ります。

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

これが私が得たものです: 低解像度の画像セットがスタックされています

編集: Redditの投稿を読んだところ、彼が実際に2つのアプローチを組み合わせていることがわかりました。1つはスタートレイル用で、もう1つは地球用です。これは、適切な重み付けを使用して、試した平均化のより良い実装です。uint8 Image配列の代わりに、中間ストレージにnumpy配列を使用しました。

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

これが前の画像のスタートレイルと組み合わせることができる画像です。 低解像度の画像を一緒に追加

于 2012-02-13T00:54:56.717 に答える