Pythonでいろいろやってみる

Pythonを使った画像処理や機械学習などの簡単なプログラムを載せています。

フォルダ内の画像からスライドショーを作る(スワイプ切り替え)

 指定したフォルダ内の画像を読み出しスライドショーを作ります。画像はサイズがまちまちなのでスライドショーのサイズに対して横幅が大きい場合は左右を、高さが大きい場合は上下をカットして、スライドショーのサイズに自動で変換します。画像と画像の切り替えは左から次の画像が少しずつ現れるいわゆるスワイプ切り替えします。
 画像処理ライブラリPillowのcropで画像のサイズ合わせを、compositeでマスク画像を使って次の画像を左から少しずつ表示させます。   

関連記事

フォルダ内の画像からスライドショーを作る(フェード切り替え)
フォルダ内の画像からスライドショーを作る(ブラックアウト、ホワイトアウト切り替え)

環境
  • windows10 home
  • Anaconda 3/ jupyter notebook 5.6.0
  • Python 3.8.8
  • Pillow 8.2.0
準備

 以下の画像ファイルをフリー写真素材ぱくたそからダウンロードさせていただき、jupyter notebookファイル(***.ipynb)と同じディレクトリにフォルダ'photos'を作成しその中に保存しました。
f:id:T_A_T:20220124191718j:plain
asama.jpg

f:id:T_A_T:20220124191740j:plain
autumn.jpg

f:id:T_A_T:20220124191819j:plain
cat.jpg

f:id:T_A_T:20220124191906j:plain
girl.jpg

f:id:T_A_T:20220124191925j:plain
hongkong.jpg

f:id:T_A_T:20220124191937j:plain
xmas.jpg

コード

 photosフォルダに含まれるファイルのリストを作り、画像を読み出してサイズを調整しtempフォルダに格納します。tempフォルダから画像を読み出し20コマgifファイルに追加、続く20コマで黒地に白い四角を描いたマスク画像を用意し、その白い領域を変えながら画像と次の画像を合成し次の画像が左から現れるように見せます(スワイプ)。最後の画像から最初の画像へのスワイプが必要なのでファイルのリストの最後に一番最初の画像をもう一度追加しています。

import os
from PIL import Image, ImageDraw

# 画像フォルダのパス
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(30):
        mask = Image.new('1', (s_width, s_height))
        draw = ImageDraw.Draw(mask)
        draw.rectangle([(int(j/29*s_width), 0), (s_width, s_height)], 
                fill='white', outline='white', width=1)
        blend = Image.composite(im, im2, mask)
        images.append(blend)
        
# gif動画保存
images[0].save('slideshow_swipe.gif', save_all=True, append_images=images[1:], 
               optimize=False, duration=50, loop=0)      

実行結果

スライドショーがgifアニメーションになって保存されます。次の画像が左から徐々に現れて切り替わります(スワイプ)。
f:id:T_A_T:20220124203928g:plain

以下のサイトを参考にさせていただきました

note.nkmk.me>>Python, OpenCV, Pillow(PIL)で画像サイズ(幅、高さ)を取得
Pythonの文法メモ > 【Pillow】画像の縮小拡大(resize)、切り抜き(crop)
Pythonの文法メモ > 【Pillow】画像の新規作成(Image.new)
Pythonの文法メモ > 【Pillow】マスクを使った画像の合成
Pythonの文法メモ > 【Pillow】ImageDrawモジュールによる直線、四角、円、多角形描画

ブログランキングに参加しています

にほんブログ村 IT技術ブログへ
にほんブログ村