'20/07/26更新:本文を一部編集しました。 下記動画は写真を連結をして作成しました。音楽の挿入はWindows10標準搭載のフォトを使用していますが、それ以外の加工は全てPython です。
VIDEO www.youtube.com
▼本プログラム実行のためのフォルダ環境
① jpg2avi.py…本体ファイル(コードは本記事の最後に記載してます)
②openh264-1.8.0-win64 .dll…mp4も作成できるコーデック(DL先は下記)
https://github.com/cisco/openh264/releases
③img…動画作成のための連結する画像ファイルを入れておくフォルダ
▼imgフォルダ内 画像ファイルのアスペクト比 (縦横比)は統一されてなくて構いません。本コードには、指定した解像度へ画像を調整後に動画にします。
▼実行後のフォルダ内 編集された画像と、それらを連結して出来た動画が出来る。
次の2つの画像を見ると、実際に撮影した時の写真のアスペクト比 (縦横比)が異なっていても(2つ目画像の黒塗り潰り以外が元の画像サイズ)、指定した解像度に合わせて画像を出力している様子がわかります。その方法は、指定したサイズの黒無地の画像を下地にして、それに合成することで、全ての画像サイズを同一にします。これにより画像を連結して動画を作成できます。
▼本プログラム 解像度と動画時間の設定は if __name__ == '__main__': 以下にある変数で指定できます。
import os, glob, shutil
import cv2
from PIL import Image, ImageFont, ImageDraw
import numpy as np
def image_resize (image, height):
scale = height / image.shape[0 ]
return cv2.resize(image, dsize=None , fx=scale, fy=scale)
def image_add_message (img, message):
font_path = 'C:\Windows\Fonts\meiryo.ttc'
font_size = 54
font = ImageFont.truetype(font_path, font_size)
img = Image.fromarray(img)
draw = ImageDraw.Draw(img)
draw.text((50 , 50 ), message, font=font, fill=(255 , 255 , 255 , 0 ))
img = np.array(img)
return img
def jpg2mp4 (folder, outfile, width, height, time):
img_list = glob.glob(folder + '*.jpg' )
print (img_list)
fps = len (img_list) / (time*60 )
for i, e in enumerate (img_list):
e2 = str (i).zfill(4 ) + '.jpg'
shutil.copy2(e, e2)
img = cv2.imread(e2)
dst = image_resize(img, height)
print (f"{img.shape} -> {dst.shape}" )
dst_height, dst_width = dst.shape[:2 ]
print ("i -> " + str (i) + "/" + str (len (img_list)-1 ))
print (str (dst_width) + " " + str (dst_height))
new_img = np.zeros((height, width, 3 ), np.uint8)
if dst_width == width:
print ("set A" )
new_img[0 :dst_height, 0 :dst_width] = dst
else :
print ("set B" )
offset = int ((width - dst_width)/2 )
print ("offset -> " + str (offset))
new_img[0 :height, offset:dst_width+offset] = dst
new_img = image_add_message(new_img, global_list[i])
cv2.imwrite(e2 , new_img)
cap = cv2.VideoCapture('%04d.jpg' )
#fourcc = cv2.VideoWriter_fourcc(*'X264' ) fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
writer = cv2.VideoWriter(outfile, fourcc, fps, (width, height))
while True :
ret, frame = cap.read()
if not ret:
break
writer.write(frame)
writer.release()
cap.release()
print ("fps -> " + str (fps))
global_list = ['ハロー コサチューブ' , 'Hello KosaTube' ,
" \' 19/5月 黒幹之(みゆき)メダカを \n 3匹買った" ,
'水草ウィローモスを入れたり \n ↓(これ)' ,
'ホテイアオイが枯れたりした \n ' ,
'一方、赤ちゃん用水槽は \n ダイソーの300円タッパー' ,
'水草と溶岩石くらいは入れましょう' ,
'卵を生んだら \n 優しく腹下を指で摘まんで取る' ,
'生きてる卵は硬くて、簡単に潰れはしない' ,
'図のように広告の上に置く' ,
'指で転がして粘着糸をとる' ,
'一粒ずつばらばらになった。 \n カビ生え時の共連れ死防止のため' ,
'孵化方法 その1 \n 卵を水草の上に置いたり、' ,
'ホテイアオイに付けたりして、' ,
'それを300円タッパーに入れる' ,
'10日前後で孵化する' ,
'孵化方法 その2 \n 500mlペットボトルを半分切って、水入れて卵を入れる' ,
'水道水でOK。 \n この場合、毎日半分水換え' ,
'メチレンブルーを入れても良い' ,
'この場合、水換えは3日に1度でOK' ,
' 水量はこれくらいに、一滴落とす' ,
'生まれそうになると目が出来る' ,
'ちょっと引いて撮影' , 'もっと引くとこんなん' ,
'生まれました!! \n どこ?' ,
'めだか「ここじゃー」 \n 中央と左上' ,
'生まれたら、引っ越し♪ \n コンビニのスプーンですくう' ,
'表面張力で~' ,
'落ちない\(^o^)/' ,
'300円タッパーへ浸けて離す。泳ぎ回る稚魚達' ,
'エサは、稚魚用を与える' ,
'普通サイズでは、大きすぎて食べられないため' ,
'タッパーはフタしてホコリ入らないようにする \n 完全密閉はしない' ,
'絶対にダメ \n →全水換えして、全滅した経験あり。。' ,
r"'19/10月現在 弟妹達はすくすく育つ" ,
'Hello KosaTube \n 次回へつづく' ]
if __name__ == '__main__' :
input_folder = r"./img/"
out_file = 'output.mp4'
out_width = 1920
out_height = 1080
time = 1.5
jpg2mp4(input_folder, out_file, out_width, out_height, time)
上記プログラムは、下記のような流れで処理をします。 1. imgフォルダ内にあったファイルをカレントフォルダへコピー 2. ファイル名を連番に変更 3. 指定した解像度へ全てのファイルを一旦、縦のドットに合わして変換 この時点で横サイズが異なる画像が存在する。 4. 指定した解像度の無地(黒色)の画像をnumpyで作成 5. 4の画像を下地にして3の画像を合成する 6. 日本語文字列を画像に挿入してゆくが、ライブラリはPILを利用しています 7. 画像を連結して動画にする (指定した再生時間と、imgフォルダ内にあるファイル数からfpsを計算しています)
本コード作成に至るまでに遭遇したエラーのQ&A
◆エラー例1:Could not open codec 'libopenh264': Unspecified error コーデックがないためのエラー。コーデックをDLする。ver違いを示すエラーが出る場合もある。本記事の冒頭にも記載してますが、DL先は下記リンクです。
https://github.com/cisco/openh264/releases
◆エラー例2:OpenCV: FFMPEG: tag 0x34363258/'X264' is not supported with codec id 27 and format 'mp4 / MP4 (MPEG-4 Part 14)' mp4ファイル作成する時のコーデックエラー。解像度を大きくすると解決する場合があった。
◆エラー例3:ValueError: could not broadcast input array from shape (960,1707,3) into shape (0,0,3) 画像サイズがはみ出てるエラー。画像を合成する際に、小さいサイズの画像に大きい画像を挿入しようとしてるため。
以上
<広告>
リンク