thumbnailというディレクトリに画像を放り込んで以下のスクリプトを実行するとこんな感じの画像になります。昨日書いたエントリはこれに繋がっていて、透過しながら全体を回転させてランダムに配置することでこうなりました。ウェブでサービス作るのも面白いかもしれませんが、イメージのアーカイブをアップロードしてもらう必要があるとか(ちまちま1枚ずつはきつそうだから)、勉強しなきゃいけない事が意外とありました。なので、サービス化は後回しで、とりあえずやってみたかった、このバラ撒かれるまでの様子を動画にしたスクリプトを後述しています。
コード
import Image, ImageFilter, os, glob, random, math
imgWidth = 1280
imgHeight = 960
thumbRate = 4
files = glob.glob( "thumbnail/*.*" )
ground = Image.new( "RGB", ( imgWidth, imgHeight ), ( 0, 0, 0 ) )
ground.putalpha( Image.new( "L", ( imgWidth, imgHeight ), 0 ) )
for item in files:
try:
im = Image.open( item )
if imgWidth / thumbRate < im.size[ 0 ] and imgHeight / thumbRate < im.size[ 1 ] :
im = im.resize( ( imgWidth / thumbRate, imgWidth / thumbRate * im.size[ 1 ] / im.size[ 0 ] ) )
r = math.sqrt( pow( ( im.size[ 0 ] / 2 ), 2 ) + pow( ( im.size[ 1 ] / 2 ), 2 ) )
base = Image.new( "RGB",( r * 2, r * 2 ), ( 0, 0, 0 ) )
base.putalpha( Image.new( "L", ( r * 2, r * 2 ), 0 ) )
base.paste( im, ( ( base.size[ 0 ] - im.size[ 0 ] ) / 2, ( base.size[ 1 ] - im.size[ 1 ] ) / 2 ) )
base = base.rotate( random.random() * 360 ).filter( ImageFilter.SMOOTH_MORE )
ground.paste( base, ( random.random() * ( imgWidth - base.size[ 0 ] ), random.random() * ( imgHeight - base.size[ 1 ] ) ), base )
except Exception, ex:
print "illegal Image Format : " + item + " exception : " + str( ex )
ground.save( "photoMess.png" )
で、このひとつひとつの写真が回転しながらスライドインして行く様子を1フレームずつ出力するのが以下のコード。実際に動画にするのはffmpegでやります。
動画フレーム毎に出力するコード
import Image, ImageFilter, os, glob, random, math
FRAME = 60
SLIDEPOS = [ round( idx * idx * 0.3, 0 ) for idx in range( FRAME + 1, 1, -1 ) ]
IMGWIDTH = 1280
IMGHEIGHT = 960
THUMBRATE = 4
files = glob.glob( "thumbnail/*.*" )
ground = Image.new( "RGB", ( IMGWIDTH, IMGHEIGHT ), ( 0, 0, 0 ) )
ground.putalpha( Image.new( "L", ( IMGWIDTH, IMGHEIGHT ), 0 ) )
for idx in range( len ( files ) ):
try:
im = Image.open( files[ idx ] )
if IMGWIDTH / THUMBRATE < im.size[ 0 ] and IMGHEIGHT / THUMBRATE < im.size[ 1 ] :
im = im.resize( ( IMGWIDTH / THUMBRATE, IMGWIDTH / THUMBRATE * im.size[ 1 ] / im.size[ 0 ] ) )
r = math.sqrt( pow( ( im.size[ 0 ] / 2 ), 2 ) + pow( ( im.size[ 1 ] / 2 ), 2 ) )
base = Image.new( "RGB",( r * 2, r * 2 ), ( 0, 0, 0 ) )
trgtRotate = round( random.random() * 360, 0 )
trgtPosX = random.random() * ( IMGWIDTH - base.size[ 0 ] )
trgtPosY = random.random() * ( IMGHEIGHT - base.size[ 1 ] )
startPosX = SLIDEPOS[ 0 ]
startPosY = random.random() * SLIDEPOS[ 0 ]
rate = startPosY / startPosX
for sdx in range( FRAME ) :
curGround = ground.copy().filter( ImageFilter.BLUR)
im = Image.open( files[ idx ] )
if IMGWIDTH / THUMBRATE < im.size[ 0 ] and IMGHEIGHT / THUMBRATE < im.size[ 1 ] :
im = im.resize( ( IMGWIDTH / THUMBRATE, IMGWIDTH / THUMBRATE * im.size[ 1 ] / im.size[ 0 ] ) )
r = math.sqrt( pow( ( im.size[ 0 ] / 2 ), 2 ) + pow( ( im.size[ 1 ] / 2 ), 2 ) )
base = Image.new( "RGB",( r * 2, r * 2 ), ( 0, 0, 0 ) )
base.putalpha( Image.new( "L", ( r * 2, r * 2 ), 0 ) )
base.paste( im, ( ( base.size[ 0 ] - im.size[ 0 ] ) / 2, ( base.size[ 1 ] - im.size[ 1 ] ) / 2 ) )
base = base.rotate( trgtRotate - sdx * 2 )
curGround.paste( base, ( trgtPosX + SLIDEPOS[ sdx ], trgtPosY + SLIDEPOS[ sdx ] * rate), base )
print "%06d.png" % ( sdx + idx * FRAME )
curGround.save( "%06d.png" % ( sdx + idx * FRAME ) )
if sdx == len( range( FRAME ) ) -1 :
ground = curGround.copy()
except Exception, ex:
print str(ex)
始めはファイル読み込みループ内で1度だけ画像ファイルを読み込んでrotate(回転)掛けながら出力していたのですが、回転するたびに画像が粗くなって行くので、回転の度に画像を読み込みなおしています。あとは、始めの方に読み込まれて背景となって行く写真はどんどんぼかしがかかって行きます。で、写真が1枚スライドインするまで、画像が60回書き出されるので、動画にすると1枚あたりのスライドインに2秒かかります。今回の動画は30枚の写真を利用しているので、60×30=1800枚になり、動画にすると1分程のムービーになります。(動画化はffmpegでやります)パソコンのスペックに依存するかと思いますが、pythonスクリプトの方は1800枚出力するのに数十分時間がかかりました。ffmpegの方はすぐに動画になります。(2分くらい)
スライドインの動画化
youtubeなのでちょっと画像は粗いですが雰囲気はつかめるかと思います。