framemixer.py - 連番 BMP を合成。
120fps 動画のフレームを合成して 15fps にしてみるテスト。
……に使ったプログラムをとりあえず公開。
あまり使い物になるものでもない感じですが、参考までに。
# -*- coding: utf-8 -*- u"""framemixer - 連番 BMP を合成。 連番 BMP 動画を合成して残像付きの減フレーム連番 BMP 動画を造る。 Python 2.6.5 + Pygame 1.9.1 'source' フォルダに入れた連番 BMP を処理し 'dest' フォルダに出力する。 ESC で中断、SPACE で一時停止。 """ from __future__ import division import os import os.path import pygame from pygame.locals import * #### #### 設定 #### #### SIMPLECOPY = False # ミックスせず間引くだけの時は True に FRAME_MIX_NO = 8 # ミックスするフレームの数。 # 例えば 120fps のものに 8 を指定すると 120/8 = 15fps になる ATTENUATION = 3 # 減衰率。1 で全てのフレームを等分に合成。 # 大きな値にするほど過去フレームが減衰する。(整数でなくても可) SOURCE = u'source' # ソースになる連番 BMP ファイルを置くフォルダ。 # ファイル名を文字列としてソートするので # ファイル名の長さを揃える必要がある。 DEST = u'dest' # 出来上がる連番 BMP ファイルを入れるフォルダ。 # 自動では作らないのであらかじめ作っておく必要がある。 # また出力前に自動で空にしたりはしないのであらかじめ空にしておくこと。 STARTFRAME = 0 # 開始フレーム。ファイル名でソートした時の順番。0 が先頭。 ENDFRAME = -1 # 終了フレーム。-1 ならば最後まで。 #### #### def simplecopy(frames): index = 0 file_no = 0 image = pygame.image.load(os.path.join(SOURCE, frames[index])) pygame.image.save(image, os.path.join(DEST, ('%08d.bmp' % file_no))) screen = pygame.display.set_mode(image.get_size()) pause = False while True: screen.blit(image, (0, 0)) pygame.display.flip() if not pause: index += FRAME_MIX_NO if index >= len(frames): return image = pygame.image.load(os.path.join(SOURCE, frames[index])) file_no += 1 pygame.image.save(image, os.path.join(DEST, ('%08d.bmp' % file_no))) pygame.display.set_caption('%s' % frames[index]) for e in pygame.event.get(): if e.type == QUIT: return elif e.type == KEYDOWN and e.key == K_ESCAPE: return elif e.type == KEYDOWN and e.key == K_SPACE: pause = not pause def framemix(frames): images = [pygame.image.load(os.path.join(SOURCE, filename)) for filename in frames] images.reverse() image = images[0] for i, s in enumerate(images[1:]): s.set_alpha(255 // ((i + 1) * ATTENUATION + 1)) image.blit(s, (0, 0)) return image def main(frames): index = 0 file_no = 0 image = pygame.image.load(os.path.join(SOURCE, frames[index])) pygame.image.save(image, os.path.join(DEST, ('%08d.bmp' % file_no))) screen = pygame.display.set_mode(image.get_size()) pause = False while True: screen.blit(image, (0, 0)) pygame.display.flip() if not pause: framelist = [] for i in range(FRAME_MIX_NO): index += 1 if index >= len(frames): return framelist.append(frames[index]) image = framemix(framelist) file_no += 1 pygame.image.save(image, os.path.join(DEST, ('%08d.bmp' % file_no))) pygame.display.set_caption('%s' % frames[index]) for e in pygame.event.get(): if e.type == QUIT: return elif e.type == KEYDOWN and e.key == K_ESCAPE: return elif e.type == KEYDOWN and e.key == K_SPACE: pause = not pause if __name__ == '__main__': try: pygame.init() frames = [x for x in os.listdir(SOURCE) if os.path.splitext(x)[-1].upper() == '.BMP'] frames.sort() frames = frames[STARTFRAME:ENDFRAME] if SIMPLECOPY: simplecopy(frames) else: main(frames) finally: pygame.quit() # Public Domain. 好きに流用してください。