データセットを作成する関数を自作した

自分で撮影した画像からデータセットを簡単に作成できる関数を作成しましたので、使い方を説明したいと思います。

コード全体

プログラムコードを示します。コメントとして使用方法と説明を大まかに記載しました。

# -*- coding: utf-8 -*-

"""
・関数の大まかな説明
画像データを読み込みNumPy配列として格納し、教師信号として数字を割り当てます。
・引数
 画像データが格納されているファイルのpath
 クラスに対応する数値
(例) じゃんけんの画像データセットを作成
1.「じゃんけん」フォルダを作成する。
2.「じゃんけん」フォルダの直下に、「グー」、「チョキ」、「パー」の3つのフォルダを作成する。
3.グー・チョキ・パーの画像を撮影し、対応するフォルダ内部に格納する。
4.3つのクラスの番号を0, 1, 2にしたいので、target = [0, 1, 2]とする。
5.data = make_dataset("「じゃんけん」フォルダのpath", target)
"""

import numpy as np
import glob              #フォルダの中身のリストを得ることができる
from PIL import Image    #画像データを読み込むときに使用する

#globでファイルイストを得るためにpathへ'*'を追加する。
def add_ast(pa):
    if pa[-1] == '/':
        pa += '*'
    elif pa[-1] == '\ ':
        pa += '*'
    elif pa[-1] != '*':
        pa += '/*'
    return(pa)

#データセットの作成をする関数の定義
def make_dataset(pa, ta): #paはpath、taはtarget
    data = []
    target = []
    pa = add_ast(pa)
    folder_list = glob.glob(pa)    #各クラスごとの画像が格納されているフォルダのpathをリストとして取得
    for i in range(len(ta)):
        img_path = glob.glob(add_ast(folder_list[i]))
        for j in range(len(img_path)):
            data.append(np.asarray(Image.open(img_path[0])))    #画像データをndarrayオブジェクトにしてリストに追加
            target.append(ta[i])                                #クラス番号を追加

    #画像データをすべて格納できたらリストをndarrayオブジェクトにする
    data = np.array(data)
    target = np.array(target)
    return(data, target)

これを、make_dataset.pyとして保存することで、

from make_dataset import make_dataset

のように読み込むことができます。

使用方法

使用方法をじゃんけんデータの学習セットを作成する例とともに示していきます。まずは画像を用意しましょう。私は以下のような位置関係のフォルダを作成し、適切なフォルダに画像ファイルを大量に撮影して保存しました。

図1 作成したフォルダーの位置関係

作成したいデータセットの名前のフォルダを作成し、その下に、各クラスの名前のフォルダを作成すると分かりやすいでしょう。各クラスの名前のフォルダには対応する画像データを保存します。画像ファイルの名前は以降の作業に全く影響はないので、変更する必要はありません。

ここまで準備が整ったら、「じゃんけんデータ」フォルダのpathをコピーします。pathは、\\か/で区切られたものにしてください。図1の例であれば、

C:/Users/User/じゃんけんデータ
C:\\Users\\User\\じゃんけんデータ

です。つぎに、各クラスに与える番号を決めます。今回はグーチョキパーの3種類なので、0, 1, 2と番号を割り当てることにしました。これにより、

data, target = make_dataset('C:/Users/User/じゃんけんデータ', [0,1,2]) 

を実行することで、MNISTやCIFAR 10のようなデータセットと同様に扱うことができる形になりました。

ここで、私の場合、dataは

array([[[[171, 167, 166],
         [169, 165, 164],
         [178, 174, 175],
         ...,
         [198, 193, 189],
         [199, 194, 190],
         [199, 194, 190]],

        [[ 48,  49,  54],
         [ 46,  47,  52],
         [ 53,  54,  59],
         ...,
         [ 22,  38,  64],
         [ 92, 108, 133],
         [ 21,  39,  61]]],

       [[[ 72,  49,  41],
         [ 83,  63,  56],
         [ 94,  75,  69],
         ...,
         [ 96,  61,  55],
         [ 96,  59,  53],
         [ 95,  56,  51]],

        [[ 48,  49,  54],
         [ 46,  47,  52],
         [ 53,  54,  59],
         ...,
         [ 22,  38,  64],
         [ 92, 108, 133],
         [ 21,  39,  61]]]], dtype=uint8)

targetは

array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2])

になりました。この関数があれば、適切なフォルダを作成し、そこに画像を保存するだけで、上記の例のように学習データセットを得ることができます。

追加

今回のプログラムは教師信号として1次元の数値を使用しましたが、直接OneHot表現を出力するよう改造するとより便利になると思いますので、ぜひ自分の使用ようとにカスタマイズして使用していただければと思います。

Follow me!