web-dev-qa-db-ja.com

Python画像ライブラリ:4つの画像を2 x 2グリッドに組み合わせる方法は?

アニメーション用の画像を含む4つのディレクトリがあります。画像のセットを取り、アニメーションの各フレームに対して2x2グリッドに配置された4つの画像で単一の画像を生成したいと思います。

これまでの私のコードは:

import Image

fluid64 = "Fluid64_half_size/00"
fluid128 = "Fluid128_half_size/00"
fluid512 = "Fluid512_half_size/00" 
fluid1024 = "Fluid1024_half_size/00" 

out_image = "Fluid_all/00"

for pic in range(1, 26):
    blank_image = Image.open("blank.jpg")

    if pic < 10:
        image_num = "0"+str(pic)
    else:
        image_num = str(pic)

    image64 = Image.open(fluid64+image_num+".jpg")
    image128 = Image.open(fluid128+image_num+".jpg")
    image512 = Image.open(fluid512+image_num+".jpg")
    image1024 = Image.open(fluid1024+image_num+".jpg")
    out = out_image + image_num + ".jpg"

    blank_image.paste(image64, (0,0)).paste(fluid128, (400,0)).paste(fluid512, (0,300)).paste(fluid1024, (400,300)).save(out)

なぜ機能しないのかわかりません。エラーが発生します:

Traceback (most recent call last):
  File "C:\Users\Casey\Desktop\Image_composite.py", line 24, in <module>
    blank_image.paste(image64, (0,0)).paste(fluid128, (400,0)).paste(fluid512, (
ste(fluid1024, (400,300)).save(out)
AttributeError: 'NoneType' object has no attribute 'paste'
Shell returned 1

どんな助けでも素晴らしいでしょう。ありがとう!

27
Nope

唯一の問題は、「貼り付け」が画像オブジェクトを返さないことです。むしろ、「空白」の画像をその場で変更します。

したがって、2番目のペースト(fuild128画像を使用するもの)が呼び出されると、最初の画像の戻り値である「なし」に適用されます。

それが唯一の問題である場合は、次のように1行に1回だけ貼り付けを呼び出します。

blank_image.paste(image64, (0,0))
blank_image.paste(fluid128, (400,0))
blank_image.paste(fluid512, (0,300))
blank_image.paste(fluid1024, (400,300))
blank_image.save(out)

ただし、フォーマットが一致するように各画像を拡大縮小する必要があるようです。また、「image_num」変数のコードは不要です。 Pythonは文字列に非常に適しています-次のようなことをしてください:

image64 = Image.open(fluid64 + "%02d.jpg" % pic)
39
jsbueno

あなたは次のように何かを使いたいかもしれません:

blank_image = Image.new("RGB", (800, 600))

これにより、画像を生成できるメモリ内に新しい領域が作成されます。その後、そこに画像を貼り付けることができるはずです。

次に、後でもう一度保存する必要があります。

blank_image.save("blank.jpg")
10
David Hewitt

エラーメッセージを確認します。

AttributeError: 'NoneType' object has no attribute 'paste'

つまり、NoneTypeタイプの何か、つまりNoneオブジェクトで.pasteを呼び出そうとしました。

Image.pasteはNoneを返します。関数がサポートするように特別に設計されており、Image.pasteがそうではない場合を除いて、そのような呼び出しを「チェーン」することはできません。 (この種のサポートは、return self関数を使用することで実現されます。NoneTypeに関するエラーが発生します。関数は何も返さないように記述されているため、Python他に何も明示的に返されない場合、デフォルトでNoneを返します。これはPythonicと見なされます。メソッドは新しい値を返すか、selfを変更してNoneを返します。このため、関数に副作用がある場合、いわゆる「流れるようなインターフェイス」は使用されません- Pythonistaはそれを有害だと考えています。Noneを返すと、関数に副作用があるという警告が表示されます。

4つの個別の.paste呼び出しを実行するだけです。

4
Karl Knechtel

copyオブジェクトを返すcropresizerotateImageとは異なり、pasteNoneを返し、メソッドの連鎖呼び出しを防ぎます。それほど便利ではない [〜#〜] api [〜#〜] デザイン。

1
michaelliu

2行2列のグリッドに数字を並べるのは、この返信で定義されているappend_images関数で簡単に実現できます https:// stackoverflow .com/a/46623632/873811

例えば:

img1 = append_images([image64, image128], direction='horizontal')
img2 = append_images([image512, image1024], direction='horizontal')
final = append_images([img1, img2], direction='vertical')
final.save("Fluid_all/00.jpg")
1
teekarna