MotionProで画像からアニメーション作った: 3.コマンドでエラーなく動かす
前回は付属のGRADIOでもコードを動かすところまで解説しました。
ただし、基本的にモデルに入力する前の入力データの整形がうまくいってないことが原因のようです。
そこで今回は、整形データの作成方法とその入力を利用して動かす方法を解説します。
整形データの作成方法はいずれWEBページからFLASKで作成したAPIサーバーを呼べるように作ってます。
ただしそこは機能しませんが、入力データをダウンロードするとこまではできております。
MotionProへの入力データの作成
generate_motionpro_input.html を以下からダウンロードしてブラウザ(CHORME推奨)で開くと画面がたちあがります。
-
画面が開いたら画像をアップロードします。
-
動かしたい部分をブラシで塗ります。
マウス左クリックで左ボタンを抑えたままマウスをドラッグして塗ります。終わったらひらりクリックを開放します。
-
これでmotionpro用にリサイズされた画像とマスク画像がダウンロードできます。(アップロード元の画像をそのまま後述するモデル入力すると入力テンソルのSHAPEのずれでエラーになります。)
イメージはリサイズされたものがダウンロードされ、マスクはそれに合わせたマスク画像としてダウンrノードされます。
-
次に軌跡を描きます。
基本的にマウスをマスク内でクリックして動かす起点から終点まで動かします。終わるときはダブルクリックかFinish Pathで追えます。マスク内に収まる必要はないですが、収めたほうがおり精度の高い動きを再現できます。
-
軌跡ダウンロード
軌跡もダウンロードできます。またプレビューをみることもできます。
MotionProで実行
基本的な流れは3_Commandバージョン.ipynb でCOLABで実行できます。
コマンドは
python mp_client.py --img [リサイズ後の画像へのパス] --mask [マスク画像へのパス] --traj [軌跡JSONへのパス] --out [出力フォルダへのパス] --gifname [出力GIFファイル名]
で実行できます。たとえばリサイズ画像、マスク画像、軌跡JSONをそれぞれimage1.png, mask1.pmg, track1.jsonとしてinputい保存し、動きのあるGIFをoutputにout1.gifとして保存したければ以下のようなコマンドを実行します。
(motionpro)$ cd MotionPro
$ python mp_client.py --img input/image1.png --mask input/mask1.png --traj input/track1.json --out output --gifname out1.gif
実際に3_Commandバージョン.ipynb
ではそれぞれの元画像や中身が確認できるようなノートにしてます。
!pip install pillow
# Python コードセル
from PIL import Image, ImageDraw
import json, math
from IPython.display import Image as ImgIpy, display
入力データの可視化
# ───────────────────────── 入力パス ─────────────────────────
IMG_PATH = f"{code_path}/MotionPro/input/image2.png"
MASK_PATH = f"{code_path}/MotionPro/input/mask2a.png"
TRACK_PATH = f"{code_path}/MotionPro/input/track2a.json"
# ───────────────────────── 1. 画像とマスクを読み込み ─────────────────────────
base = Image.open(IMG_PATH).convert('RGBA') # 元画像
mask = Image.open(MASK_PATH).convert('L') # 1ch マスク
# ── マスクを赤半透明レイヤに変換
red_layer = Image.new('RGBA', base.size, (255, 0, 0, 128))
red_layer.putalpha(mask)
# ── 合成(オーバーレイ)
overlay = Image.alpha_composite(base, red_layer)
# ───────────────────────── 2. 軌跡を描画(線+矢印ヘッド) ─────────────────────────
with open(TRACK_PATH, 'r') as f:
tracks = json.load(f)
draw = ImageDraw.Draw(overlay)
ARROW_LEN = 14 # 矢印ヘッドの長さ(px)
ARROW_WIDTH = 10 # ヘッド三角形の幅(px)
LINE_COLOR = (0, 255, 0, 255)
LINE_W = 3
for track in tracks:
pts = [tuple(pt) for pt in track]
# ── 線を描く
if len(pts) >= 2:
draw.line(pts, fill=LINE_COLOR, width=LINE_W)
# ── 矢印ヘッド(三角形)を追加
p1, p2 = pts[-2], pts[-1] # 最後とその一つ前
dx, dy = p2[0]-p1[0], p2[1]-p1[1]
length = math.hypot(dx, dy) or 1.0
ux, uy = dx/length, dy/length # 単位ベクトル
tip = p2
left = (p2[0] - ux*ARROW_LEN + uy*ARROW_WIDTH/2,
p2[1] - uy*ARROW_LEN - ux*ARROW_WIDTH/2)
right = (p2[0] - ux*ARROW_LEN - uy*ARROW_WIDTH/2,
p2[1] - uy*ARROW_LEN + ux*ARROW_WIDTH/2)
draw.polygon([tip, left, right], fill=LINE_COLOR)
# ── 1 点だけの軌跡なら丸印
elif len(pts) == 1:
x, y = pts[0]
r = 5
draw.ellipse((x-r, y-r, x+r, y+r), outline=LINE_COLOR, width=LINE_W)
# ───────────────────────── 3. 左右に並べて表示 ─────────────────────────
w, h = base.size
combined = Image.new('RGBA', (w*2, h))
combined.paste(base, (0, 0))
combined.paste(overlay, (w, 0))
動きを生成
!python mp_client.py --img input/image2.png --mask input/mask2a.png --traj input/track2a.json --out output --gifname out2a.gif
結果を表示
# GIFファイルのパスを指定
gif_path = f'{code_path}/MotionPro/output/out2a.gif'
# Colab上で表示
display(ImgIpy(filename=gif_path))
結果のGIFが3Mを超えていたためここに添付できませんでしたがCOLABもしくはLOCALで動くと思います。
次回は、COLABではなくLOCAL(EC2上のサーバー)に先ほどの入力データの生成からそれを直接FLASKのAPIサーバーに送って結果をうけとるところを解説します。
Discussion