pythonでスターウォーズのOP風映像を作ってみる

python,映像

なんとなく作りたくなったので。

こんなのが割と簡単に出来ます。

事前準備

必要なアプリとライブラリをインストールしてください。

ImageMagick

必要なアプリをインストール。

以下から環境に適したものをインストールしてください。

scikit-image

必要なライブラリインストール。

pip install scikit-image

MoviePy

必要なライブラリインストール。(*最新のverである「2.0.0dev2」を指定)

pip install moviepy==2.0.0dev2

そのままだとうまく動かなかったりするので、ImageMagickへのパスを見直してください。

修正ファイル

フォルダ C:\Users\ユーザー名\AppData\Local\Programs\Python\Python38\Lib\site-packages\moviepy

ファイル config_defaults.py

修正内容

IMAGEMAGICK_BINARY がある行をコメントして、インストールされた「magick.exe」を指定 。

# //IMAGEMAGICK_BINARY = os.getenv('IMAGEMAGICK_BINARY', 'auto-detect') 

IMAGEMAGICK_BINARY = "C:\\Program Files\\ImageMagick-7.0.10-Q16\\magick.exe"

背景画像

背景画像を用意しておきましょう。

今回は以下から借用しました。

実装

PIC_PATH は事前に用意したバックグラウンド用の画像パスを指定。

import numpy as np
from skimage import transform as tf

from moviepy.editor import *
from moviepy.video.tools.drawing import color_gradient

# PIC PATH

PIC_PATH = 'back.jpg'

# # RESOLUTION

w = 720
h = w*9//16
moviesize = w,h

#INSERT THE RAW TEXT (here: "A New Hope")

txt = "\n".join([
"",
"とにかく観てほしい映画ベストテン",
"1. シューテムアップ",
"2. ポーラー 狙われた暗殺者",
"3. コンティニュー",
"4. ザ・レイド",
"5. 6アンダーグラウンド",
"6. グレイマン",
"7. ヒットマンズ・ボディガード",
"8. Mr.ノーバディ",
"9. メッセージマン",
"10. ブラックアウト 記憶の彼方に",
"",
"",
"",
"",
"",
"",
"",
])

# txt = "\n".join([
# "",
# "It is a period of civil war. Rebel",
# "spaceships, striking from a",
# "hidden base, have won their",
# "first victory against the evil",
# "Galactic Empire. During the battle,",
# "Rebel spies managed to steal secret",
# "plans to the Empire’s ultimate weapon,",
# "the DEATH STAR, an armored space station",
# "with enough power to destroy an entire planet."
# "",
# "",
# "",
# "",
# "",
# "",
# "",
# "",
# "",
# ])

# Add blanks before and after text
txt = 10*"\n" +txt + 10*"\n"

clip_txt = TextClip(txt,color='yellow', align='West',fontsize=25,
                    font="MS-Gothic-&-MS-UI-Gothic-&-MS-PGothic", method='label')

# SCROLL THE TEXT IMAGE BY CROPPING A MOVING AREA

txt_speed = 10
fl = lambda gf,t : gf(t)[int(txt_speed*t):int(txt_speed*t)+h,:]
moving_txt= clip_txt.fl(fl, apply_to=['mask'])


# ADD A VANISHING EFFECT ON THE TEXT WITH A GRADIENT MASK

grad = color_gradient(moving_txt.size,p1=(0,2*h/3),p2=(0,h/4),col1=0.0,col2=1.0)
gradmask = ImageClip(grad,ismask=True)
fl = lambda pic : np.minimum(pic,gradmask.img)
moving_txt.mask = moving_txt.mask.fl_image(fl)


# WARP THE TEXT INTO A TRAPEZOID (PERSPECTIVE EFFECT)

def trapzWarp(pic,cx,cy,ismask=False):
    Y,X = pic.shape[:2]
    src = np.array([[0,0],[X,0],[X,Y],[0,Y]])
    dst = np.array([[cx*X,cy*Y],[(1-cx)*X,cy*Y],[X,Y],[0,Y]])
    tform = tf.ProjectiveTransform()
    tform.estimate(src,dst)
    im = tf.warp(pic, tform.inverse, output_shape=(Y,X))
    return im if ismask else (im*255).astype('uint8')

fl_im = lambda pic : trapzWarp(pic,0.2,0.3)
fl_mask = lambda pic : trapzWarp(pic,0.2,0.3, ismask=True)
warped_txt= moving_txt.fl_image(fl_im).set_position('center','bottom')
warped_txt.mask = warped_txt.mask.fl_image(fl_mask)


# BACKGROUND IMAGE, DARKENED HERE AT 60%

stars = ImageClip(PIC_PATH)
stars_darkened = stars.fl_image(lambda pic: (0.6*pic).astype('int16')).set_position('center','bottom')


# COMPOSE THE MOVIE

final = CompositeVideoClip([
         stars_darkened,warped_txt],
         size = moviesize)

# WRITE TO A FILE
# duration here set to 35 seconds, with 18 frames per second

final.set_duration(35).write_videofile("star_wars_crawl.webm", fps=18)

つまずいたこと

日本語を使いたいときは、フォント指定を以下のように見直す必要があった。

clip_txt = TextClip(txt,color='yellow', align='Center',fontsize=35,
                    font="MS-Gothic-&-MS-UI-Gothic-&-MS-PGothic", method='label')

参考サイト

pythonpython,映像