見出し画像

manga109のキャラ画像加工③

背景

所属研究室で行っている研究の一環として、漫画用のキャラクタ画像データセットを構築する試みを検討している。manga109 という学術用の許可済み漫画画像データセットが存在するが、そのままではキャラクタの画像が切り抜かれていないため加工して使用することにした。これら処理を行うためにpythonの調査を行い実践しまとめていく。

前回まで

前回までで、各ページから人物の顔の座標を抽出することができた。今回は、前回のプログラムで作成したページ顔座標辞書をもとにして画像を加工するプログラムを作成していく

仕様


擬似コード(雑)

特に今回は辞書の値がリストのリストになっているのでわけがわからなくなってくる。そこで整理のためにも擬似コードを作成した。これまで擬似コードなんて院試でしか書いて来なかったが、ここにきて役に立つとは思わなかった。

画像をクロップを行うのは前回作成したプログラムとは別のプログラムとした。そのためpagedict辞書をインポートする必要がある。

実装

先に完成したプログラムを載せておく。

from PIL import Image
import manga109_xmlread
import os

pagedict = manga109_xmlread.pagedict #変数の引き継ぎ、これで辞書が使える。
pagesum = len(pagedict) #pagesumにpagedictの要素数を格納
os.mkdir('cut_face_pages') # cut_face_pagesディレクトリを作成する

#ページ数分だけ以下の処理を繰り返す
for num in range(pagesum):
    Coordinatelist = pagedict[num] #pagedict辞書のnumキーに対応する要素(座標リスト)を格納
    Coordinatelen = len(Coordinatelist) #キーのページにおけるface座標の個数を取得

    foldaname = 'cut_face_pages/page{0}'.format(f"{num:03}") # numについてゼロ埋め処理を施したのちにその名のファイル名を作成
    os.mkdir(foldaname) # 各ページごとのフォルダを作成
    imagename = '/Users/~(省略)/images/LoveHina_vol14/{0}.jpg'.format(f"{num:03}")
    im = Image.open(imagename) #キーに対応する名称の画像を開く

    # 座標の個数だけ以下を繰り返す
    for facenum in range(Coordinatelen):

        face = Coordinatelist[facenum] #座標リストのfacenum番目の座標をfaceに格納
        #faceの座標の値を取得 
        xmin = face[0]
        ymin = face[1]
        xmax = face[2]
        ymax = face[3]

        facefilename = 'face_{0}_{1}_{2}_{3}_{4}.jpg'.format(num, xmin, ymin, xmax, ymax) # 切り抜いた後の顔の画像はface_ページ番号_座標.jpgの名称で保存する
        savepass = 'cut_face_pages/page{0}/'.format(f"{num:03}") + facefilename           # ディレクトリ名と先ほど作成したファイル名をつなげ、保存用のパスとする。
        im_crop = im.crop((xmin, ymin, xmax, ymax)) #画像のクロップ
        im_crop.save(savepass, quality=95) #画像の保存

    
    

辞書にしてもその値にしても「要素数」を知る必要があるためlen()で取得している。画像の切り抜きにはPILを用いた。

詳細

from PIL import Image
import manga109_xmlread
import os

画像の一部の領域を切り抜くメソッドcrop()を使いたいため、Pythonの画像処理ライブラリPillow(PIL)のImageモジュールをインポートする。また、前回作成したプログラムを実行し、ページ番号とページ内の顔や身体の座標の辞書形式のデータを用いためこちらもインポートする。最後にフォルダを作成したいためosもインポートする。

pagedict = manga109_xmlread.pagedict #変数の引き継ぎ、これで辞書が使える。
pagesum = len(pagedict) #pagesumにpagedictの要素数を格納
os.mkdir('cut_face_pages') # cut_face_pagesディレクトリを作成する

pagedictという名前で再度前回作成した辞書を格納し直す。またその辞書のキーの数をlenで取得する。さらに作成した顔画像をフォルダにまとめたものを格納する親フォルダcut_face_pagesを作成する

for num in range(pagesum):
    Coordinatelist = pagedict[num] #pagedict辞書のnumキーに対応する要素(座標リスト)を格納
    Coordinatelen = len(Coordinatelist) #キーのページにおけるface座標の個数を取得

    foldaname = 'cut_face_pages/page{0}'.format(f"{num:03}") # numについてゼロ埋め処理を施したのちにその名のファイル名を作成
    os.mkdir(foldaname) # 各ページごとのフォルダを作成
    imagename = '/Users/~(省略)/images/LoveHina_vol14/{0}.jpg'.format(f"{num:03}")
    im = Image.open(imagename) #キーに対応する名称の画像を開く

これ以降のコードはページ数分だけ繰り返す。まずCoordinatelistという変数に、辞書データにてページ番号キーに対応する値(座標のリスト)を格納する。さらにその座標のリスト内に幾つの座標セットがあるのかをCoordinatelenに格納する。

foldanameにcut_face_pages_page(ページ数)を格納する。そしてimagenameには今見ているページ数に対応するmanga109の原稿データのページ画像アドレスを参照する。そしてそれを開いておく。

# 座標の個数だけ以下を繰り返す
    for facenum in range(Coordinatelen):

        face = Coordinatelist[facenum] #座標リストのfacenum番目の座標をfaceに格納
        #faceの座標の値を取得 
        xmin = face[0]
        ymin = face[1]
        xmax = face[2]
        ymax = face[3]

        facefilename = 'face_{0}_{1}_{2}_{3}_{4}.jpg'.format(num, xmin, ymin, xmax, ymax) # 切り抜いた後の顔の画像はface_ページ番号_座標.jpgの名称で保存する
        savepass = 'cut_face_pages/page{0}/'.format(f"{num:03}") + facefilename           # ディレクトリ名と先ほど作成したファイル名をつなげ、保存用のパスとする。
        im_crop = im.crop((xmin, ymin, xmax, ymax)) #画像のクロップ
        im_crop.save(savepass, quality=95) #画像の保存

さらに、今見ているページに存在する顔座標の数(Coordinatelenで取得した)だけ操作をくりかえす。Coordintatelistに格納されている座標データについて、0番目から順に見ていく。faceという変数に一つの座標(xmiin, ymin, xmax, ymax)を格納し、座標の各値を取得する。

切り抜いた画像の名称(facefilename)としてface_ページ番号_xmin_ymin_xmax_ymaxとなるようにする。また保存先のパス(savepass)として'cut_face_pages/page(ページ番号)と先のfacefilenameを組み合わせる。
最終的に取得した座標で画像をクロップし、作成したsavepassの場所に保存する。(pathなのかpassなのか未だによくわからない。)

実行結果。

まとめ

以上、ひとまず顔画像の切り抜きを行い、名称をつけたフォルダに保存することができた。今回の一連のデータ加工は特定の巻のみについて行ったが、今後は他の作品も自動で一気に同じような加工ができるようにしていきたい。おそらく関数的なものを作成することになるが、フォルダ名をリストに格納する方法やプログラムの関数化についてしらべてゆく。また身体についても同様の加工をおこなっていきたい。ひとまず大きな区切りがついた。

いいなと思ったら応援しよう!