概要
AIのセグメンテーション結果の流し見など、色々な画像を動画に合わせて同時にみたいという時があります。
その時、いちいちコード上でレイアウトを変更して...とかやっているとミスが多いため、すべてをjson上でまとめてそこで管理すればいいのでは?と考えてコードを作成してみたので公開します。
コード内容
動作環境
- opencv
- PIL
- python 3.10
ファイル構成
.
├── README.md
├── main.py # まとめて動かすためのコード
├── outline.json # レイアウトを記載
├── pictures # 複数の元画像を結合した画像を格納
├── src
│ ├── movie_maker.py # 動画作成
│ └── picture_maker.py # 画像生成
├── venv
├── video.mp4
└── video_output
JSONによる画像の配置の設定
1フレームごとの画像を生成する際、複数の画像の配置やサイズ、背景画像の大きさを設定すれば良い。
outline.json
{
"movie_property": {
"framerate": 60
},
"picture_property":{
"picture_number":2{
"movie_property": {
"framerate": 60
},
"picture_property":{
"picture_number":2,
"background": {
"width": 300,
"height": 300
},
"pictures": [{
"source": "sample/img/sample1",
"positionX": 0,
"positionY": 0
},
{
"source": "sample/img/sample2",
"positionX": 150,
"positionY": 0
}]
}
},
"background": {
"width": 300,
"height": 300
},
"pictures": [{
"source": "sample/img/sample1",
"positionX": 0,
"positionY": 0
},
{
"source": "sample/img/sample2",
"positionX": 150,
"positionY": 0
}]
}
}
movie_propertyにはfpsなどの動画作成に必要なものを記載
picture_propertyには画像のソースや配置などを記載
picture_makerによるフレームごとの画像の生成
あとはPILを使ってファイルの検索を行い、JSONでの指示にしたがって並べる。
※画像ファイルには00000.pngなど、ゼロ詰めにしておかないと順番がおかしくなる。
picture_maker.py
from PIL import Image
from pathlib import Path
import os
def make_picture(outline: dict):
#backgroundの作成
background_width = outline["background"]["width"]
background_height = outline["background"]["height"]
# 背景画像の作成
dst = Image.new(mode='RGB', size=(background_width, background_height))
# 各フォルダに対してfileリストを作成
image_pathlist = []
for i in range(len(outline['pictures'])):
path = Path(outline['pictures'][i]['source'])
plist = path.glob('*.png')
image_pathlist.append(sorted(list(plist)))
print(image_pathlist)
# 1個目のファイルリストの長さ分の画像を作る。
for i in range(len(image_pathlist[0])):
# 背景画像の生成list(plist)list(plist)
dst = Image.new(mode='RGB', size=(background_width, background_height))
# 画像の貼り付け
for j in range(len(image_pathlist)):
im = Image.open(image_pathlist[j][i])
dst.paste(im,
(outline['pictures'][j]['positionX'], outline['pictures'][j]['positionY']))
# 画像の保存
if not(os.path.isdir('pictures')):
os.mkdir('pictures')
dst.save(f'pictures/{str(i).zfill(5)}.png')
from PIL import Image
from pathlib import Path
import os
def make_picture(outline: dict):
#backgroundの作成
background_width = outline["background"]["width"]
background_height = outline["background"]["height"]
# 背景画像の作成
dst = Image.new(mode='RGB', size=(background_width, background_height))
# 各フォルダに対してfileリストを作成
image_pathlist = []
for i in range(len(outline['pictures'])):
path = Path(outline['pictures'][i]['source'])
plist = path.glob('*.png')
image_pathlist.append(sorted(list(plist)))
print(image_pathlist)
# 1個目のファイルリストの長さ分の画像を作る。
for i in range(len(image_pathlist[0])):
# 背景画像の生成list(plist)list(plist)
dst = Image.new(mode='RGB', size=(background_width, background_height))
# 画像の貼り付け
for j in range(len(image_pathlist)):
im = Image.open(image_pathlist[j][i])
dst.paste(im,
(outline['pictures'][j]['positionX'], outline['pictures'][j]['positionY']))
# 画像の保存
if not(os.path.isdir('pictures')):
os.mkdir('pictures')
dst.save(f'pictures/{str(i).zfill(5)}.png')
movie_makerによる動画の生成
下記サイトを参考にしつつ作成
https://note.nkmk.me/python-opencv-video-to-still-image/
movie_maker.py
import cv2
import os
def make_movie(config):
cap = cv2.VideoCapture(0)
codec = cv2.VideoWriter_fourcc(*'mp4v')
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
out_file_name = 'output/video.mp4'
video = cv2.VideoWriter(out_file_name,fourcc,
config['movie_property']['framerate'],
(config['picture_property']['background']['width'],
config['picture_property']['background']['height'])
)
image_list = sorted(os.listdir('pictures'))
for frame in image_list:
img = cv2.imread(os.path.join('pictures',frame))
video.write(img)
video.release()
今後の展開
- エラー対応(画像のファイル数が違うなど)
- 透過率への対応
- その他必要に応じて作成を行うよて