目的
Povrayは強力な3次元描画ソフト.
ImageMagickのgif動画作成コマンドと組み合わせて3次元動画の作成が可能.
Linuxコマンドはpythonのsubprocessモジュールで実行が可能.
pythonを用いてこれら処理の自動化を目指す.
細かな注意事項など,備忘録的なまとめ.
環境
OS: Linux系
- python 2.7系
- povray
- ImageMagick
作業の流れ
- Povrayのソースコードの自動作成(基本はテキスト処理であるため省略)
- ソースコードをPovrayに用いてpng画像生成
- png画像群からgif動画の作成
使用モジュール
import subprocess
import glob
import shutil
import os
ソースコードをPovrayに用いてpng画像生成
あらかじめ,何らかの関数でソースコードを生成したと仮定.
最終的に動画を作成するため,時間tなどでfor loopを作るのを想定.
for t in t_list:
for ....:
srcname = srcdir+'/'+srcfile
CreatePovRaySrc(srcname, t, x, y,...)
png画像の名前の指定.
今回は例として,保存先と拡張子のみを置換する.
(補足)Povrayのデフォルトはソースと同じ場所に.pngに置換したファイルを出力する.
figname = srcname.replace('.pov','.png').replace(srcdir, pngdir)
png画像の作成.
subprocess.call()でLinuxコマンドを実行する.
Linuxコマンドが povray $srcname なら, subprocess.call(['povray',srcname]) とすればよい.
さらに,povrayコマンドのオプションを下記のように追加する.
subprocess.call(['povray',srcname,'-d','-O'+figname])
オプションの解説
- -d: 描画中に一時的にwindowを開いて画像を表示するモードをoffにする.
- -O{ファイル名}: 出力パスを指定する(デフォルトは先述の通り).
- その他,画像の高さと幅を指定する+H{px数},+W{px数}などがよく用いられる.
コマンドラインのフラグの詳細は*リンク*を参照する.
png画像群からgif動画の作成
gif動画作成:旧やり方
各作業を関数で区分けする.
gif動画作成のためには,必要となるpng画像群が連番である必要がある.
今回は,上記で作成したファイル名群が連番ではないが辞書式に並べられると仮定する.
まず,辞書式のpngファイル名リストを作成する.
sorted()を使用しないと,辞書式に並んでくれないので注意する.
png_list = sorted(glob.glob(pngdir+'pov_*.png'))
gif動画用の一時ファイルを作成する.
'{:03d}'.format(i) で,'000','001','002',...といった0埋め連番を作成する.
tailは,一番最後の画像を連番で複製するフラグである.
これを含めた理由は後述する.
def tmp_copy(pngdir, png_list, tail=0):
print 'COPY(temporal) png files.'
for (i,f) in enumerate(png_list):
shutil.copy(f,pngdir+'tmp{:03d}.png'.format(i))
if tail > 0:
for n in xrange(tail):
shutil.copy(pngdir+ 'tmp{:03d}.png'.format(i),pngdir+'tmp{:03d}.png'.format(i+1))
i+=1
一時ファイルを用いて,gif動画の作成を行う.
ImageMagickのconvertコマンドを用いる.
def tmp_png2gif(pngdir, gifname, span=100):
print 'PNG2GIF: create', gifname
subprocess.call(['convert', '-delay', str(span), '-loop', '0',
pngdir+'tmp*.png', gifname])
オプションの解説
- -delay {1/100秒数}: 動画の画像遷移スピード
- -loop {回数}: ループ回数の指定(0で無限ループ)
先ほど,一時png生成時にtailで最後の画像を複製したのは,無限ループをしつつループの終点を少し長時間表示させる動画にしたかったためである.
その他,convertのフラグの詳細は*リンク*を参照する.
個人的によく使うオプション以外あまり詳しくはないので,どれくらいフレキシブルに動画生成できるかは把握できていない.
最後に,一時png画像群を削除する.
def tmp_remove(pngdir):
print 'REMOVE(temporal) png files.'
for f in glob.glob(pngdir+'tmp*.png'):
os.remove(f)
以上をまとめて,次のようなメイン関数を実行する.
def main():
png_list = sorted(glob.glob(pngdir+'pov_*.png'))
# gif動画用の一時pngファイルを複製
tmp_copy(pngdir, png_list, tail=3)
# gif動画作成
gifname = gifdir + giffile
tmp_png2gif(pngdir, gifname, span=50)
# 一時png画像の削除
tmp_remove(paths.pngdir)
gif動画作成:新やり方
わざわざ連番を生成しなくても,ソートしたpng画像群をコマンドに順に指定すれば問題なし.
def png2gif(gifname, png_list, span=100, tail=0):
# ImageMagick用ベースのコマンド
cmd = ['convert', '-delay', str(span), '-loop', '0']
# png画像群の追加
for f in png_list:
cmd.append(f)
# 最後のpng画像を複製
if tail > 0:
for n in xrange(tail):
cmd.append(f)
# gif動画ファイル名の追加
cmd.append(gifname)
# コマンド実行
subprocess.call(cmd)
def main():
png_list = sorted(glob.glob(pngdir+'pov_*.png'))
gifname = gifdir + giffile
# gif動画作成
png2gif(gifname, png_list, span=50, tail=3)