質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

2617閲覧

Python3のモジュール'PIL'でエラーが発生する

YabQ

総合スコア35

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2019/04/29 06:45

編集2019/04/29 07:19

PILでエラーは発生する(Python3,PIL)

ツイッター画像を使ってモザイクアートを作る

(https://kenyu-life.com/2018/10/31/mosaic_art_python/)
を使って,モザイクアートを作るプログラムを書いていました.
試しに使う程度なので,素材画像の入っているフォルダのパスと目標となる画像のパスを変更したのみで,他は変えていません.
エラーを解決する方法はありますか.

発生している問題・エラーメッセージ

Traceback (most recent call last): File "mosaicA.py", line 123, in <module> src=[Image.open(SourceDir+i).resize(SourceImageSize) for i in Res] File "mosaicA.py", line 123, in <listcomp> src=[Image.open(SourceDir+i).resize(SourceImageSize) for i in Res] File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/Image.py", line 2690, in open im = _open_core(fp, filename, prefix) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/Image.py", line 2676, in _open_core im = factory(fp, filename) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/JpegImagePlugin.py", line 783, in jpeg_factory im = JpegImageFile(fp, filename) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/ImageFile.py", line 103, in __init__ self._open() File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/JpegImagePlugin.py", line 373, in _open handler(self, i) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/JpegImagePlugin.py", line 139, in APP self.info["photoshop"] = photoshop UnboundLocalError: local variable 'photoshop' referenced before assignment

該当のソースコード

参考にしたサイトから,ファイルのパス等を変えたのみなので割愛

[追記]コード提示の追記依頼を受けたため,掲載します.
参考にしたサイト「ツイッター画像を使ってモザイクアートを作る」

(https://kenyu-life.com/2018/10/31/mosaic_art_python/)
のソースコードからファイルパスを変えたのみです.
(ユーザ名の部分のみ[ユーザ名]で置き換えてあります.)

Python3

1from PIL import Image,ImageFilter 2import subprocess 3import os 4import random 5import math 6import time 7import cv2 as cv 8import numpy as np 9 10#==============設定=================== 11#素材画像の入っているフォルダ 12SourceDir="/Users/[ユーザ名]/Desktop/mosaicA/sozai/" 13 14#目標となる画像 15GoalImage="/Users/[ユーザ名]/Desktop/mosaicA/moto/moto1.jpg" 16 17#出力の名前 18OutputImage="output.jpg" 19 20#動画 21OutputMovie="movie.mp4" 22 23#動画のフレームレート 24Framerate=25 25 26#動画フォーマット 27fourcc="mp4v" 28 29#フレームスキップ 30FrameSkip=30 31 32#素材画像の色の平均値を出す時に色を取得する間隔 33PickInterval=(1,1) 34 35#素材の画像のサイズ(読み込み時にここで指定したサイズに変換される) 36SourceImageSize=(100,100) 37 38#x,yそれぞれ何個の画像を並べるか 39TileCount=(100,100) 40 41#ターゲット画像の倍率 42TargetZoom=5 43#===================================== 44 45 46def ColorAvg(img,interval=(1,1)): #pythonのループ使用 47 #画像の色の平均値を求める 48 s=(0,0,0) 49 n=0 50 for y in range(0,img.size[1],interval[1]): 51 for x in range(0,img.size[0],interval[0]): 52 c=img.getpixel((x,y)) 53 s=tuple(i+k for i,k in zip(s,c)) 54 n=n+1 55 s=tuple(math.floor(i/n) for i in s) 56 return s 57 58def ColorChange(img,col,Avg): 59 #imgの色の平均値がcolになるようにフィルターに掛ける 60 #元画像の平均値を必要とする 61 ds=tuple(i-k for i,k in zip(col,Avg)) 62 r,g,b=img.split()[0:3] 63 r=r.point(lambda x: x+ds[0] if 0 <= x+ds[0] and x+ds[0] < 256 else 0 if x+ds[0] < 0 else 255) 64 g=g.point(lambda x: x+ds[1] if 0 <= x+ds[1] and x+ds[1] < 256 else 0 if x+ds[1] < 0 else 255) 65 b=b.point(lambda x: x+ds[2] if 0 <= x+ds[2] and x+ds[2] < 256 else 0 if x+ds[2] < 0 else 255) 66 return Image.merge("RGB",(r,g,b)) 67 68def Mosaic(img,src,video=None,count=(100,100),interval=(10,10),FrameSkip=0): 69 #モザイクアートを生成する 70 #img:元画像 71 #dst:動画の保存先 72 #src:モザイクアートに使う画像群 73 #count:x方向,y方向にそれぞれ何個の画像を使うか 74 #split:画像の色平均を取る時に色を取得する間隔 75 76 Target=Image.new("RGB",img.size) 77 print("%s:各素材グラフィックの色平均値を導出開始"%(str(time.time()-startTime))) 78 SourceImg=[(i,ColorAvg(i,interval)) for i in src] 79 SourceImgTemp=[] 80 print("%s:各素材グラフィックの色平均値を導出完了"%(str(time.time()-startTime))) 81 print("%s:タイルリストを生成開始"%(str(time.time()-startTime))) 82 RectList=[] 83 for y in range(0,count[1]): 84 for x in range(0,count[0]): 85 tileRect=(x*img.size[0]/count[0],y*img.size[1]/count[1],(x+1)*img.size[0]/count[0],(y+1)*img.size[1]/count[1]) 86 tileRect=tuple(math.floor(i) for i in tileRect) 87 RectList.append(tileRect) 88 print("%s:タイルリストを生成完了"%(str(time.time()-startTime))) 89 print("%s:モザイクアートを生成開始"%(time.time()-startTime)) 90 TileCount=0 91 Frame=np.array(Target)[:,:,::-1] 92 video.write(Frame) 93 while(len(RectList)>0): 94 r=random.randrange(len(RectList)) 95 tileRect=RectList[r] 96 del RectList[r] 97 Pivot=img.getpixel((math.floor((tileRect[0]+tileRect[2])/2),math.floor((tileRect[1]+tileRect[3])/2))) 98 if(len(SourceImgTemp)==0): 99 SourceImgTemp=SourceImg.copy() 100 r=random.randrange(len(SourceImgTemp)) 101 tempSrc=ColorChange(SourceImgTemp[r][0],Pivot,SourceImgTemp[r][1]) 102 del SourceImgTemp[r] 103 tempSrc=tempSrc.resize((tileRect[2]-tileRect[0],tileRect[3]-tileRect[1])) 104 Target.paste(tempSrc,(tileRect[0],tileRect[1])) 105 if(TileCount%(FrameSkip+1)==0 and type(video)==cv.VideoWriter): 106 Frame=np.array(Target)[:,:,::-1] 107 video.write(Frame) 108 #cv.imshow("",Frame) 109 #cv.waitKey(1) 110 TileCount+=1 111 Frame=np.array(Target)[:,:,::-1] 112 video.write(Frame) 113 print("%s:モザイクアートを生成完了"%(str(time.time()-startTime))) 114 return Target 115 116if __name__=="__main__": 117 startTime=time.time() 118 Res=subprocess.run(["ls",SourceDir],stdout=subprocess.PIPE) 119 Res=Res.stdout.decode().split("\n") 120 Res=Res[:len(Res)-1] 121 src=[Image.open(SourceDir+i).resize(SourceImageSize) for i in Res] 122 target=Image.open(GoalImage) 123 target=target.resize(tuple(math.floor(i*TargetZoom) for i in target.size)) 124 fourcc2=cv.VideoWriter.fourcc(*fourcc) 125 v=cv.VideoWriter(OutputMovie,int(fourcc2),Framerate,target.size) 126 Mosaic(target,src,video=v,interval=PickInterval,count=TileCount,FrameSkip=FrameSkip).save(OutputImage) 127 v.release()

試したこと

  • pip3 install pillow -U でpillowをアップデートしてみましたが,エラーは発生
  • エラーの発生場所が,PILの内部と考えられるので,手詰まり

補足情報(FW/ツールのバージョンなど)

  • Python 3.7.3
  • opencv-python 4.1.0.25
  • Pillow 6.0.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2019/04/29 07:07

コードを提示しましょう
YabQ

2019/04/29 07:19

参考サイトそのままのため割愛してありましたが,掲載しました.
guest

回答2

0

ツイッター画像を使ってモザイクアートを作る」に掲載されているコード(以下mosaic.py)を動かそうとされている方で,こちらのページに来られた方がいらっしゃった時のために,私なりの解決方法を備忘録を兼ねてここに書いておこうと思います.
(2019/04/30 現在)

発生したエラー

  • PIL(Pillow)のJpegImagePlugin.py内で発生する

UnboundLocalError: local variable 'photoshop' referenced before assignment
コード

  • mosaic.py内で発生する

TypeError: zip argument #2 must support iteration

各エラーの対処法

  • UnboundLocalError: local variable 'photoshop' referenced before assignment

このエラーは,can110さんが回答してくださったように,Pillow6.0.0(質問時現在の最新)の不具合になります.次のアップデート以降で修正されると思いますが,6.0.0より新しいバージョンでも不具合が発生している場合は,JpegImagePlugin.pyを自力で修正するか,5.4.1を使うことでエラーを回避できます.mosaic.py6.0.0になる前に書かれていたので5.x.xで動かしても特に問題はないと思います.


  • TypeError: zip argument #2 must support iteration

エラーの全文は以下である.

Traceback (most recent call last): File "mosaic.py", line 130, in <module> Mosaic(target,src,video=v,interval=PickInterval,count=TileCount,FrameSkip=FrameSkip).save(OutputImage) File "mosaic.py", line 80, in Mosaic SourceImg=[(i,ColorAvg(i,interval)) for i in src] File "mosaic.py", line 80, in <listcomp> SourceImg=[(i,ColorAvg(i,interval)) for i in src] File "mosaic.py", line 55, in ColorAvg s=tuple(i+k for i,k in zip(s,c)) TypeError: zip argument #2 must support iteration

これは,関数ColorAvgに書かれているc=img.getpixel((x,y))という部分で,getpixcel()の戻り値がint型であることに由来するエラーである.rgbの値が入ったタプルが戻ってくる前提でプログラムが書かれているためエラーが発生している.
これは,if __name__=="__main__":以下にある
src=[Image.open(SourceDir+i).resize(SourceImageSize) for i in Res]

src=[Image.open(SourceDir+i).resize(SourceImageSize).convert('RGB') for i in Res]
とすることでエラーが発生しなくなる.RGBと指定していないと8bitグレースケールとなるらしい.

結果

ちゃんと動いた.素材の色を生かすモザイクアートかと思っていたが,そうではないらしい.ソースコードをすべて読もうとは思えなかったので知らなかった.参考までに,このプログラムで富嶽三十六景(46枚)で富嶽三十六景「神奈川沖浪裏」をモザイクアートにしてみた.
イメージ説明
見えますかね...

投稿2019/04/30 13:01

YabQ

総合スコア35

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

Pillowの既知の不具合のようです。
UnboundLocalError in PIL/JpegImagePlugin.py #3769
修正が最新バージョンに反映されるまではJpegImagePlugin.pyを自力で修正するしかないかと思います。

投稿2019/04/29 07:06

can110

総合スコア38234

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YabQ

2019/04/30 11:04

既知の不具合だったのですね,調べればすぐに分かりそうなところを...お手数おかけしました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問