フォルダ内の画像からスライドショーを作る(ブラックアウト、ホワイトアウト切り替え)
指定したフォルダ内の画像を読み出しスライドショーを作ります。画像はサイズがまちまちなのでスライドショーのサイズに対して横幅が大きい場合は左右を、高さが大きい場合は上下をカットして、スライドショーのサイズに自動で変換します。画像と画像の切り替えは前の画像が少しずつ薄れ黒画像(白画像)になってから次の画像が少しずつ濃くなるように(いわゆるブラックアウト、ホワイトアウト)画像を黒画像(白画像)とアルファブレンドしアルファ値を変化させています。
画像処理ライブラリ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ファイルに追加、続く10コマでアルファ値を変えながら画像を黒画像とアルファブレンド、続く10コマでアルファ値を変えながら黒画像と次の画像をアルファブレンドし一度ブラックアウトしてから次の画像に移るように見せます。最後の画像から最初の画像へのブラックアウトが必要なのでファイルのリストの最後に一番最初の画像をもう一度追加しています。
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 # ブラックアウト用黒画像作成 black = Image.new('RGB', (s_width, s_height), (0, 0, 0)) # 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(10): blend = Image.blend(im, black, j/9) images.append(blend) # 黒画像と次の画像をブレンドして画像をゆっくり出現させる for j in range(10): blend = Image.blend(black, im2, j/9) images.append(blend) # gif動画保存 images[0].save('slideshow_black.gif', save_all=True, append_images=images[1:], optimize=False, duration=50, loop=0)
実行結果
スライドショーがgifアニメーションになって保存されます。画像は黒画像を挟んで徐々に切り替わります(ブラックアウト)。
コード
画像切り替え時の画像を黒から白に変えてホワイトアウト切り替えにします。
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 # ホワイトアウト用白画像作成 white = Image.new('RGB', (s_width, s_height), (255, 255, 255)) # 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(10): blend = Image.blend(im, white, j/9) images.append(blend) # 白画像と次の画像をブレンドして画像をゆっくり出現させる for j in range(10): blend = Image.blend(white, im2, j/9) images.append(blend) # gif動画保存 images[0].save('slideshow_white.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)
Pythonの文法メモ > 【Pillow】画像の新規作成(Image.new)