Python 複数の画像ファイルを連結して1枚の画像ファイルを作成する「OpenCV」

 本記事では、Pythonで複数の画像ファイル(jpg, png)を連結して1つの画像ファイルに保存する雛形コードを載せました。下図は、4つの行列散布図の画像ファイルを3列2行のひとつの画像ファイルにした例です。列数は指定できて、出力する画像フォーマットはjpgもしくはpngを指定できる仕様にしています。

f:id:HK29:20210117174422j:plain

 ライブラリは、matplotlibに加えて、OpenCV(cv2)とPillow(PIL)とNumpy(numpy)を使用します。
 特に、Pillowを使用する理由は、OpenCVでは日本語ファイルパスを読み込めずにエラーになるためです(Noneを返す)。そして、Numpyを使用するのはひとつの画像に複数の画像を行列に整列する際に、上図の2行目の2列の2箇所のように埋めきらない場合に無地で代替するためです。

■本プログラム

import os, glob, re
import math
import cv2
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

def main():
    # ファイル名(番号)でソート
    filepath_list = sorted(myimg_list, key=lambda x:int((re.search(r"[0-9]+", x)).group(0)))

    # 行数を算出(math.ceilで小数点を切り上げ)
    n_row = math.ceil(len(filepath_list) / n_col)
    
    # 行列の枠を設ける
    _, axs = plt.subplots(n_row, n_col, figsize=(10, 6)) # (x, y)
    axs = axs.flatten()
    
    # 画像ファイルを貼り付けてゆく
    sum = n_row * n_col
    for i in range(sum):
        print(i+1, '/', sum)
        if i < len(filepath_list):
            print(filepath_list[i])
            img = Image.open(filepath_list[i])
        else:
            img = np.zeros((1, 1, 3)) # 無地黒
            img += 255 # 無地白
        img = np.asarray(img)
        axs[i].imshow(img)
        axs[i].axis('off') # 目盛り表記をオフる
        if (i+1) <= n_col:
            # 1行目の上に列名をサブタイトルで記載する
            axs[i].set_title(str(i+1))

    # レイアウトを整える
    plt.tight_layout()
    #plt.show()
    plt.savefig(output_file_path, # 出力ファイル名
                format = os.path.splitext(output_file_path)[1][1:], # 拡張子の指定
                dpi=360)

if __name__ == "__main__":
    # 画像ファイルがあるフォルダパス
    myimg_list = glob.glob(r'D:/programming/python/05_グラフ化/グラフ日本語化/*.png')
    
    # 列数の指定
    n_col = 3
    
    # 保存するファイル名
    output_file_path = 'test.jpg' # jpg、pngのどちらでもOK
    
    main()
    print('finished')

以上

<広告>