たとえば、同じ解像度の写真が 100 枚あり、それらを 1 つの写真に結合したいとします。最終的な画像の場合、各ピクセルの RGB 値は、その位置での 100 個の画像の平均です。getdata
この状況で関数が機能することは知っていますが、PIL(Python Image Library)でこれを行うためのより簡単で高速な方法はありますか?
6 に答える
画像がすべて .png ファイルであり、それらがすべて現在の作業ディレクトリに保存されていると仮定しましょう。以下の python コードは、あなたが望むことを行います。Ignacio が示唆するように、ここでは PIL と共に numpy を使用することが重要です。平均的なピクセル強度を構築する際に、整数配列と浮動小数点配列の切り替えについて少し注意する必要があります。
import os, numpy, PIL
from PIL import Image
# Access all PNG files in directory
allfiles=os.listdir(os.getcwd())
imlist=[filename for filename in allfiles if filename[-4:] in [".png",".PNG"]]
# Assuming all images are the same size, get dimensions of first image
w,h=Image.open(imlist[0]).size
N=len(imlist)
# Create a numpy array of floats to store the average (assume RGB images)
arr=numpy.zeros((h,w,3),numpy.float)
# Build up average pixel intensities, casting each image as an array of floats
for im in imlist:
imarr=numpy.array(Image.open(im),dtype=numpy.float)
arr=arr+imarr/N
# Round values in array and cast as 8-bit integer
arr=numpy.array(numpy.round(arr),dtype=numpy.uint8)
# Generate, save and preview final image
out=Image.fromarray(arr,mode="RGB")
out.save("Average.png")
out.show()
以下の画像は、上記のコードを使用して一連の HD ビデオ フレームから生成されたものです。
ここでメモリが問題になる状況を想像するのは難しいと思いますが、元の答えに必要な浮動小数点数の配列を作成する余裕が絶対にない (ありそうもない) イベントでは、@が示唆するように、PIL のブレンド関数を使用できます。次のように mHurley:
# Alternative method using PIL blend function
avg=Image.open(imlist[0])
for i in xrange(1,N):
img=Image.open(imlist[i])
avg=Image.blend(avg,img,1.0/float(i+1))
avg.save("Blend.png")
avg.show()
PIL のブレンド関数の定義から始めて、アルファ値の正しいシーケンスを導き出すことができます。
out = image1 * (1.0 - alpha) + image2 * alpha
その関数を (画像ではなく) 数値のベクトルに再帰的に適用して、ベクトルの平均を取得することを考えてみてください。長さ N のベクトルの場合、N-1 の異なるアルファ値を使用して、N-1 のブレンド操作が必要になります。
ただし、操作については直感的に考えた方がおそらく簡単です。各ステップで、平均画像に前のステップのソース画像が同じ割合で含まれるようにします。1 番目と 2 番目のソース イメージをブレンドするときは、比率を等しくするためにアルファを 1/2 にする必要があります。3 番目の画像を最初の 2 つの画像の平均とブレンドする場合、新しい画像は 3 番目の画像の 1/3 で構成され、残りは前の画像の平均で構成されます (avg の現在の値)。 、 等々。
原則として、ブレンディングに基づくこの新しい答えは問題ないはずです。ただし、ブレンド機能がどのように機能するかは正確にはわかりません。これにより、各反復後にピクセル値がどのように丸められるかが心配になります。
以下の画像は、元の回答のコードを使用して 288 のソース画像から生成されたものです。
一方、この画像は、同じ 288 枚の画像に PIL のブレンド関数を繰り返し適用して生成されたものです。
2 つのアルゴリズムからの出力が著しく異なることがおわかりいただけたと思います。これは、Image.blend を繰り返し適用している間に小さな丸め誤差が蓄積されたためだと思います。
この代替案よりも元の回答を強くお勧めします。
すべて (0, 0, 0) で始まる x x y 整数の配列を作成し、各ファイルの各ピクセルに RGB 値を追加し、すべての値を画像の数で除算してから画像を作成することを検討します。それ - おそらく numpy が役立つことがわかるでしょう。
誰かが青写真のnumpyソリューションに興味がある場合(私は実際にそれを探していました)、コードは次のとおりです。
mean_frame = np.mean(([frame for frame in frames]), axis=0)