質問編集履歴
1
追記依頼の反映
test
CHANGED
File without changes
|
test
CHANGED
@@ -72,6 +72,282 @@
|
|
72
72
|
|
73
73
|
|
74
74
|
|
75
|
+
**[追記]コード提示の追記依頼を受けたため,掲載します.**
|
76
|
+
|
77
|
+
参考にしたサイト[「ツイッター画像を使ってモザイクアートを作る」
|
78
|
+
|
79
|
+
](https://kenyu-life.com/2018/10/31/mosaic_art_python/)
|
80
|
+
|
81
|
+
(https://kenyu-life.com/2018/10/31/mosaic_art_python/)
|
82
|
+
|
83
|
+
のソースコードからファイルパスを変えたのみです.
|
84
|
+
|
85
|
+
(ユーザ名の部分のみ[ユーザ名]で置き換えてあります.)
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
```Python3
|
90
|
+
|
91
|
+
from PIL import Image,ImageFilter
|
92
|
+
|
93
|
+
import subprocess
|
94
|
+
|
95
|
+
import os
|
96
|
+
|
97
|
+
import random
|
98
|
+
|
99
|
+
import math
|
100
|
+
|
101
|
+
import time
|
102
|
+
|
103
|
+
import cv2 as cv
|
104
|
+
|
105
|
+
import numpy as np
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
#==============設定===================
|
110
|
+
|
111
|
+
#素材画像の入っているフォルダ
|
112
|
+
|
113
|
+
SourceDir="/Users/[ユーザ名]/Desktop/mosaicA/sozai/"
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
#目標となる画像
|
118
|
+
|
119
|
+
GoalImage="/Users/[ユーザ名]/Desktop/mosaicA/moto/moto1.jpg"
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
#出力の名前
|
124
|
+
|
125
|
+
OutputImage="output.jpg"
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
#動画
|
130
|
+
|
131
|
+
OutputMovie="movie.mp4"
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
#動画のフレームレート
|
136
|
+
|
137
|
+
Framerate=25
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
#動画フォーマット
|
142
|
+
|
143
|
+
fourcc="mp4v"
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
#フレームスキップ
|
148
|
+
|
149
|
+
FrameSkip=30
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
#素材画像の色の平均値を出す時に色を取得する間隔
|
154
|
+
|
155
|
+
PickInterval=(1,1)
|
156
|
+
|
157
|
+
|
158
|
+
|
159
|
+
#素材の画像のサイズ(読み込み時にここで指定したサイズに変換される)
|
160
|
+
|
161
|
+
SourceImageSize=(100,100)
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
#x,yそれぞれ何個の画像を並べるか
|
166
|
+
|
167
|
+
TileCount=(100,100)
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
#ターゲット画像の倍率
|
172
|
+
|
173
|
+
TargetZoom=5
|
174
|
+
|
175
|
+
#=====================================
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
|
180
|
+
|
181
|
+
def ColorAvg(img,interval=(1,1)): #pythonのループ使用
|
182
|
+
|
183
|
+
#画像の色の平均値を求める
|
184
|
+
|
185
|
+
s=(0,0,0)
|
186
|
+
|
187
|
+
n=0
|
188
|
+
|
189
|
+
for y in range(0,img.size[1],interval[1]):
|
190
|
+
|
191
|
+
for x in range(0,img.size[0],interval[0]):
|
192
|
+
|
193
|
+
c=img.getpixel((x,y))
|
194
|
+
|
195
|
+
s=tuple(i+k for i,k in zip(s,c))
|
196
|
+
|
197
|
+
n=n+1
|
198
|
+
|
199
|
+
s=tuple(math.floor(i/n) for i in s)
|
200
|
+
|
201
|
+
return s
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
def ColorChange(img,col,Avg):
|
206
|
+
|
207
|
+
#imgの色の平均値がcolになるようにフィルターに掛ける
|
208
|
+
|
209
|
+
#元画像の平均値を必要とする
|
210
|
+
|
211
|
+
ds=tuple(i-k for i,k in zip(col,Avg))
|
212
|
+
|
213
|
+
r,g,b=img.split()[0:3]
|
214
|
+
|
215
|
+
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)
|
216
|
+
|
217
|
+
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)
|
218
|
+
|
219
|
+
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)
|
220
|
+
|
221
|
+
return Image.merge("RGB",(r,g,b))
|
222
|
+
|
223
|
+
|
224
|
+
|
225
|
+
def Mosaic(img,src,video=None,count=(100,100),interval=(10,10),FrameSkip=0):
|
226
|
+
|
227
|
+
#モザイクアートを生成する
|
228
|
+
|
229
|
+
#img:元画像
|
230
|
+
|
231
|
+
#dst:動画の保存先
|
232
|
+
|
233
|
+
#src:モザイクアートに使う画像群
|
234
|
+
|
235
|
+
#count:x方向,y方向にそれぞれ何個の画像を使うか
|
236
|
+
|
237
|
+
#split:画像の色平均を取る時に色を取得する間隔
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
Target=Image.new("RGB",img.size)
|
242
|
+
|
243
|
+
print("%s:各素材グラフィックの色平均値を導出開始"%(str(time.time()-startTime)))
|
244
|
+
|
245
|
+
SourceImg=[(i,ColorAvg(i,interval)) for i in src]
|
246
|
+
|
247
|
+
SourceImgTemp=[]
|
248
|
+
|
249
|
+
print("%s:各素材グラフィックの色平均値を導出完了"%(str(time.time()-startTime)))
|
250
|
+
|
251
|
+
print("%s:タイルリストを生成開始"%(str(time.time()-startTime)))
|
252
|
+
|
253
|
+
RectList=[]
|
254
|
+
|
255
|
+
for y in range(0,count[1]):
|
256
|
+
|
257
|
+
for x in range(0,count[0]):
|
258
|
+
|
259
|
+
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])
|
260
|
+
|
261
|
+
tileRect=tuple(math.floor(i) for i in tileRect)
|
262
|
+
|
263
|
+
RectList.append(tileRect)
|
264
|
+
|
265
|
+
print("%s:タイルリストを生成完了"%(str(time.time()-startTime)))
|
266
|
+
|
267
|
+
print("%s:モザイクアートを生成開始"%(time.time()-startTime))
|
268
|
+
|
269
|
+
TileCount=0
|
270
|
+
|
271
|
+
Frame=np.array(Target)[:,:,::-1]
|
272
|
+
|
273
|
+
video.write(Frame)
|
274
|
+
|
275
|
+
while(len(RectList)>0):
|
276
|
+
|
277
|
+
r=random.randrange(len(RectList))
|
278
|
+
|
279
|
+
tileRect=RectList[r]
|
280
|
+
|
281
|
+
del RectList[r]
|
282
|
+
|
283
|
+
Pivot=img.getpixel((math.floor((tileRect[0]+tileRect[2])/2),math.floor((tileRect[1]+tileRect[3])/2)))
|
284
|
+
|
285
|
+
if(len(SourceImgTemp)==0):
|
286
|
+
|
287
|
+
SourceImgTemp=SourceImg.copy()
|
288
|
+
|
289
|
+
r=random.randrange(len(SourceImgTemp))
|
290
|
+
|
291
|
+
tempSrc=ColorChange(SourceImgTemp[r][0],Pivot,SourceImgTemp[r][1])
|
292
|
+
|
293
|
+
del SourceImgTemp[r]
|
294
|
+
|
295
|
+
tempSrc=tempSrc.resize((tileRect[2]-tileRect[0],tileRect[3]-tileRect[1]))
|
296
|
+
|
297
|
+
Target.paste(tempSrc,(tileRect[0],tileRect[1]))
|
298
|
+
|
299
|
+
if(TileCount%(FrameSkip+1)==0 and type(video)==cv.VideoWriter):
|
300
|
+
|
301
|
+
Frame=np.array(Target)[:,:,::-1]
|
302
|
+
|
303
|
+
video.write(Frame)
|
304
|
+
|
305
|
+
#cv.imshow("",Frame)
|
306
|
+
|
307
|
+
#cv.waitKey(1)
|
308
|
+
|
309
|
+
TileCount+=1
|
310
|
+
|
311
|
+
Frame=np.array(Target)[:,:,::-1]
|
312
|
+
|
313
|
+
video.write(Frame)
|
314
|
+
|
315
|
+
print("%s:モザイクアートを生成完了"%(str(time.time()-startTime)))
|
316
|
+
|
317
|
+
return Target
|
318
|
+
|
319
|
+
|
320
|
+
|
321
|
+
if __name__=="__main__":
|
322
|
+
|
323
|
+
startTime=time.time()
|
324
|
+
|
325
|
+
Res=subprocess.run(["ls",SourceDir],stdout=subprocess.PIPE)
|
326
|
+
|
327
|
+
Res=Res.stdout.decode().split("\n")
|
328
|
+
|
329
|
+
Res=Res[:len(Res)-1]
|
330
|
+
|
331
|
+
src=[Image.open(SourceDir+i).resize(SourceImageSize) for i in Res]
|
332
|
+
|
333
|
+
target=Image.open(GoalImage)
|
334
|
+
|
335
|
+
target=target.resize(tuple(math.floor(i*TargetZoom) for i in target.size))
|
336
|
+
|
337
|
+
fourcc2=cv.VideoWriter.fourcc(*fourcc)
|
338
|
+
|
339
|
+
v=cv.VideoWriter(OutputMovie,int(fourcc2),Framerate,target.size)
|
340
|
+
|
341
|
+
Mosaic(target,src,video=v,interval=PickInterval,count=TileCount,FrameSkip=FrameSkip).save(OutputImage)
|
342
|
+
|
343
|
+
v.release()
|
344
|
+
|
345
|
+
```
|
346
|
+
|
347
|
+
|
348
|
+
|
349
|
+
|
350
|
+
|
75
351
|
### 試したこと
|
76
352
|
|
77
353
|
* ```pip3 install pillow -U``` でpillowをアップデートしてみましたが,エラーは発生
|