Pythonでデータセットを作る方法とデータセットの中身を確認する方法(pickle編)

2020年4月29日

前回の記事では、拡張子が npz の場合のデータセットの作り方を説明しました。

今日は、拡張子が pickle の場合のデータセットの作り方を説明します。

前回の繰り返しになりますが、このページを始めて見に来た方のためにもう一度説明します。

今回ご紹介するデータセットは、画像とラベルがセットになったファイルです。

データセットは、Deep Learning で物体分類や物体検出の学習をさせる際や、主成分分析(PCA:Principal component analysis)、多様体学習の等尺性マッピング(Isomap:isometric mapping)を行う際に使用します。

Deep Learning では教師あり学習用のデータとして利用できます。

また、PCAやIsomap では教師なし学習用のデータとして利用できます。(この場合はラベルは無視)

何れにしても、大量の画像とラベルのデータをセットで保存しておくことができます。

ソースコード(pickle編)

以下のソースコードを見てください。

# read_image_pickle.py # プログラム名

import cv2
import glob
import pickle
import random
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

def read_image():

    # 設定パラメータ
    class_n = 2   # クラス数
    z = []        # データリスト: pickle用

    # pickleで保存
    outfile_pickle ="./photo/" + str("224px_") + str(class_n) +  ".pickle"

    # path 以下の画像を読み込む
    def glob_files(path, label):
        files = glob.glob(path + "/*.jpg")  # pathにある画像を読み込む
        random.shuffle(files)               # ランダムに画像を読み込む 

        # 各ファイルを処理
        num = 0
        for f in files:
            if num >= len(files): break
            num += 1
            # 画像ファイルを読む
            img = Image.open(f)    # Pillow(PIL)で画像読込み。色順番はRGB
            img = np.asarray(img)  # ndarray化
            img = cv2.resize(img, (224, 224), cv2.INTER_LANCZOS4)  # 画像サイズを224px × 224pxにする

            # pickleで保存
            z.append([label, img])

    i = 0
    for i in range(class_n):
        glob_files("./photo/" + str(i), i)  # 各画像のフォルダーを読む
        print("file: " + str(i))

    ### ファイルへ保存 ###
    # pickleで作成する場合
    pickle.dump(z, open(outfile_pickle, "wb"))
    print("pickleを保存しました :" + outfile_pickle, len(z))

if __name__ == '__main__':
    read_image()

ポイント

1.pickle ファイルを保存する際は、pickle.dump( ) を使用する

これは決まり事です。

npz でファイルを保存する際は np.savez( ) を使いました。

今回は pickle.dump( ) を使います。

下記のコードついて説明します。

pickle.dump(z, open(outfile_pickle, "wb"))

カッコの中の第一引数「z」の部分には、z.append( ) で保存したラベルと画像のデータ、つまり [ label, img ] のデータが入ります。

この [ label, img ] のデータは、ラベルと画像がこの順番でセットでリストに保存されることを意味しています。

次に、open( ) の部分について説明します。

第一引数は、pickle ファイルの保存先のパスを示しています。

第二引数の ” wb ” は書き込みモードであることを示しています。

2.画像をランダムに読み込む際は、random.shuffle( ) を使用する

前回記事でも書きましたが、データセット作成時にデータに偏りを持たせないために使用します。

データセットをDeep Learning の学習に使うのであれば必須です。

なおランダム化が必要なければ、ソースコードの先頭に # を付けてコメントアウトしてください。

コメントアウトすればこのソースコードは実行されません。

実行結果

上記プログラムを実行してみます。

まず、上記ソースコードをread_image_pickle.py という名前で好きなフォルダ内に保存してください。

次に、上記のプログラムファイルが置いてある同じフォルダ内に、photo というフォルダを作ってください。

さらにそのphotoフォルダ内に「0」と「1」という名前のフォルダを作ってください。

この「0」と「1」フォルダ内に画像をとりあえず各10枚くらい保存してください。

なお、今回のプログラムでは画像はリサイズされます。

理由は計算負荷を小さくするためと pickle ファイルのサイズを小さくしたいからです。

リサイズが不要であれば、img = cv2.resize( ) の先頭に # を付けてコメントアウトしてください。

リサイズする場合は、画像は正方形にトリミングしておくことをおすすめします。

理由は、画像に映っている像が変形してしまうためです。

画像サイズは 224px × 224px にするか、それよりも多少大きければよいです。

最近のデジタルカメラで写真を撮ると、3000px × 2000px サイズ等で撮影できますが、サイズが大きいと計算負荷が大きく処理に時間が掛かります。

また、pickle ファイルのサイズも数百MB、数GBになる可能性があります。

今回は参考プログラムなので写真サイズは小さくしています。

プログラムを実行すると以下のファイルが作成されます。

224px_2.pickle

このファイルは、各画像に「0」というラベルと「1」というラベルが付いたデータになります。

次に、この pickle ファイルの中身を確認してみます。

データセットの中身を確認する方法

以下のソースコードを見てください。

# image_plot_pickle.py #  プログラム名

import pickle
import numpy as np
import matplotlib.pyplot as plt

# 設定パラメータ
img_n = 9

### pickle用 ###
### データセットをpickleで作成した場合 ###
photos = pickle.load(open('./photo/224px_2.pickle', "rb"))

x0 = []
x1 = []
for d in photos:
    (num, img) = d
    x0.append(num)
    x1.append(img)

# 開始インデックス(idx = 0 一番最初の画像)
idx = 0

# 画像表示
plt.figure(figsize=(10, 10))
for i in range(img_n):
    plt.subplot(3, 3, i+1)   # 3行3列の1番目から9番目まで表示
    plt.axis('off')          # 画像にスケールを入れない
    plt.title(x0[i + idx])   # タイトルにインデックスを表示
    plt.imshow(x1[i + idx])  # 画像がカラー(RGB)の場合
    #plt.imshow(x1[i + idx], cmap='gray')  # 画像がグレーの場合
plt.show()

ポイント

1.pickle ファイルを読み込む際は、pickle.load( ) を使用する

pickle.load( ) のカッコの中に open( './photo/224px_2.pickle’, “rb" ) と記載されています。

第一引数は、pickle ファイルが置かれているパスを示しています。

第二引数の” rb ” は読み込みモードであることを示しています。

2.ラベルデータと画像データを扱いやすくするため分離する

pickle.load( ) で読み込んだ pickle ファイルを一旦 photos に代入します。

photos に代入されたデータは [ label, img ] の順番でラベルデータと画像データがセットで保存されています。

これらのデータを一旦分離して、ラベルデータを x0 のリストに、画像データを x1 のリストに保存します。

理由は、分離することでラベルデータと画像データが扱いやすくなるからです。

3.画像表示は matplotlib の plt を使用する

おなじみの matplotlib を使用します。

ちなみに、グレー画像を表示させる場合は plt.imshow( ) のカッコの中に cmap = ’gray’ を追記すればOKです。

カラー画像(RGB)を表示させる場合は cmap は不要です。

表示結果

ラベル 0
ラベル 1

各画像にラベル 0 とラベル 1 がタイトルとして付与されていることが分かります。

pickle ファイルに画像とラベルがセットで保存されていることが確認できました。

まとめ

  • pickle ファイルを保存する際は、pickle.dump( ) を使用する
  • 画像をランダムに読み込む際は、random.shuffle( ) を使用する
  • pickle ファイルを読み込む際は、pickle.load( ) を使用する
  • ラベルデータと画像データを扱いやすくするため分離する
  • 画像表示は matplotlib の plt を使用する
  • グレー画像なら plt.imshow( ) のカッコ内に cmap=’gray’ を追記する