フォルダ内の画像からスライドショーを作る(フェード切り替え)
指定したフォルダ内の画像を読み出しスライドショーを作ります。画像はサイズがまちまちなのでスライドショーのサイズに対して横幅が大きい場合は左右を、高さが大きい場合は上下をカットして、スライドショーのサイズに自動で変換します。画像と画像の切り替えは前の画像が少しずつ薄れ次の画像が少しずつ濃くなるように(いわゆるフェードもしくはディゾルブ)前後の画像をアルファブレンドしアルファ値を変化させています。
画像処理ライブラリPillowのcropで画像のサイズ合わせを、blendで前後の画像のアルファブレンドを行っています。
環境
- windows10 home
- Anaconda 3/ jupyter notebook 5.6.0
- Python 3.8.8
- Pillow 8.2.0
準備
以下の画像ファイルをフリー写真素材ぱくたそからダウンロードさせていただき、jupyter notebookファイル(***.ipynb)と同じディレクトリにフォルダ'photos'を作成しその中に保存しました。
asama.jpg
autumn.jpg
cat.jpg
girl.jpg
hongkong.jpg
xmas.jpg
コード
photosフォルダに含まれるファイルのリストを作り、画像を読み出してサイズを調整しtempフォルダに格納します。tempフォルダから画像を読み出し20コマgifファイルに追加、続く20コマで前後の画像をアルファブレンドし徐々に次の画像に移るように見せます。最後の画像から最初の画像へのディゾルブが必要なのでファイルのリストの最後に一番最初の画像をもう一度追加しています。
import os from PIL import Image # 画像フォルダのパス dir_path = 'photos/' # フォルダ内のファイルをリストに files = os.listdir(dir_path) # 1番目のファイルをリストの最後に追加 files.append(files[0]) # スライドショーの幅、高設定 s_width, s_height = 500, 250 # スライドショーのアスペクト比(高さ/幅) s_aspect = s_height/s_width # gifファイル作成用イメージリスト images =[] # サイズ調整した画像の一時保存用リスト temp = [] # 画像をサイズ調整しリストに追加 for i in range(len(files)): # 画像の読み出し im = Image.open(dir_path + files[i]) # 画像幅、高さの取得、アスペクト比(高さ/幅)の算出 width = im.width height = im.height aspect = height/width # 画像のアスペクト比がスライドショーと同じ場合そのままスライドショーサイズにリサイズ if aspect == s_aspect: resize = im.resize((s_width, s_height)) # 画像のアスペクト比がスライドショーより大きい場合上下をカットしスライドショーサイズにリサイズ if aspect > s_aspect: crop_size = int((height-s_aspect*width)/2) crop = im.crop((0, crop_size, width, height-crop_size)) resize = crop.resize((s_width, s_height)) # 画像のアスペクト比がスライドショーより小さい場合左右をカットしスライドショーサイズにリサイズ if aspect < s_aspect: crop_size = int((width-height/s_aspect)/2) crop = im.crop((crop_size, 0, width-crop_size, height)) resize = crop.resize((s_width, s_height)) # リサイズした画像をリストに追加 temp.append(resize) # リストから画像を読みだしスライドショーに for i in range(len(files)-1): # 画像の読み出し im = temp[i] # 次の画像の読み出し im2 = temp[i+1] # gifファイルに画像を20コマ追加 for j in range(20): images.append(im) # 次の画像とブレンドして画像をゆっくり切り替える for j in range(20): blend = Image.blend(im, im2, j/19) images.append(blend) # gif動画保存 images[0].save('slideshow.gif', save_all=True, append_images=images[1:], optimize=False, duration=50, loop=0)
実行結果
スライドショーがgifアニメーションになって保存されます。画像は徐々に切り替わります(フェードもしくはディゾルブ)。
以下のサイトを参考にさせていただきました
note.nkmk.me>>Python, OpenCV, Pillow(PIL)で画像サイズ(幅、高さ)を取得
Pythonの文法メモ > 【Pillow】画像のアルファブレンド(blend、alpha_composit)
Pythonの文法メモ > 【Pillow】画像の縮小拡大(resize)、切り抜き(crop)