web-dev-qa-db-ja.com

NumPy、PILが画像を追加

NumPyとPILを使用して2つの画像を一緒に追加しようとしています。 [〜#〜] matlab [〜#〜] でこれを行う方法は、次のようになります。

_>> M1 = imread('_1.jpg');
>> M2 = imread('_2.jpg');
>> resM = M1 + M2;
>> imwrite(resM, 'res.jpg');
_

私はこのようなものを手に入れます:

代替テキストhttp://www.deadlink.cc/matlab.jpg

合成プログラムを使用して画像を追加すると、MATLABの結果は正しいようです。

Python私は次のように同じことをしようとしています:

_from PIL import Image
from numpy import *

im1 = Image.open('/Users/rem7/Desktop/_1.jpg')
im2 = Image.open('/Users/rem7/Desktop/_2.jpg')

im1arr = asarray(im1)
im2arr = asarray(im2)

addition = im1arr + im2arr

resultImage = Image.fromarray(addition)
resultImage.save('/Users/rem7/Desktop/a.jpg')
_

そして私はこのようなものを手に入れます:

代替テキストhttp://www.deadlink.cc/python.jpg

なぜ私はそれらすべてのファンキーな色を手に入れているのですか? ImageMath.eval("a+b", a=im1, b=im2)も使用してみましたが、RGBがサポートされていないというエラーが表示されます。

また、Image.blend()があることもわかりましたが、これにはアルファが必要です。

私が探しているものを達成するための最良の方法は何ですか?

ソース画像(画像は削除されました):

代替テキストhttp://www.deadlink.cc/_1.jpg代替テキストhttp://www.deadlink.cc/_2.jpg

うーん、わかりました。画像の追加アイコンを使用してソース画像を追加しました。投稿を編集しているときに画像が表示されますが、何らかの理由で画像が投稿に表示されません。

(画像は削除されました)2013 05 09

23
rem7

誰もがすでに示唆しているように、あなたが観察している奇妙な色は溢れています。そして、あなたが schnaaderの答えのコメント あなたまだオーバーフローするで指摘するように、あなたがこのようにあなたの画像を追加するならば:

addition=(im1arr+im2arr)/2

このオーバーフローの理由は、NumPy配列(im1arrim2arr)がint8タイプであるためです。 (つまり、8ビット)。つまり、配列の各要素は最大255の値しか保持できないため、合計が255を超えると、0を中心にループバックします。

>>>array([255,10,100],dtype='uint8') +  array([1,10,160],dtype='uint8')
array([ 0, 20,  4], dtype=uint8)

オーバーフローを回避するには、配列に255を超える値を含めることができる必要があります。たとえば、フロートに変換、ブレンド操作を実行し、結果をuint8に変換する必要があります。 :

im1arrF = im1arr.astype('float')
im2arrF = im2arr.astype('float')
additionF = (im1arrF+im2arrF)/2
addition = additionF.astype('uint8')

あなたすべきではないこれを行う:

addition = im1arr/2 + im2arr/2

情報が失われると、ブレンディング情報を実行する前に、画像のダイナミクスを押しつぶして(効果的に画像を7ビットにします)。

MATLAB注:MATLABでこの問題が発生しない理由は、MATLABが関数の1つで暗黙的にオーバーフローを処理しているためと考えられます。

32
Ivan

アルファ値が0.5のPILのblend()を使用すると、(im1arr + im2arr)/ 2と同等になります。 Blendでは、画像にアルファレイヤーが含まれている必要はありません。

これを試して:

from PIL import Image
im1 = Image.open('/Users/rem7/Desktop/_1.jpg')
im2 = Image.open('/Users/rem7/Desktop/_2.jpg')
Image.blend(im1,im2,0.5).save('/Users/rem7/Desktop/a.jpg')
18
Paul

あなたが投稿したコードは値を合計しただけで、256より大きい値がオーバーフローしているようです。 「(a + b)/ 2」または「min(a + b、256)」のようなものが必要です。後者は、Matlabの例がそれを行う方法のようです。

2
schnaader

Numpy配列値をクランプするには:

>>> c = a + b
>>> c[c > 256] = 256
2
jfs

サンプル画像が表示されないので、少し推測します。

Numpyからpilへの変換がどのように機能するかを正確に思い出せませんが、2つの可能性のあるケースがあります。私はそれが1であると95%確信していますが、私が間違っている場合に備えて2を与えています。 1)1 im1Arrは整数のMxN配列(ARGB)であり、im1arrとim2arrを一緒に追加すると、コンポーネントb1 + b2> 255の場合、あるチャネルから次のチャネルにオーバーフローします。 matlabは画像をMxNx3配列として表すため、各カラーチャネルは分離されていると思います。これを解決するには、PILイメージチャネルを分割してから、numpy配列を作成します。

2)1 im1ArrはバイトのMxNx3配列であり、im1arrとim2arrを一緒に追加すると、コンポーネントがラップされます。

また、表示する前に、範囲を0〜255の範囲に再スケーリングする必要があります。 2で割るか、255/array.max()でスケーリングするか、クリップを実行します。 matlabが何をするのかわかりません

0
hacken