matplotlib 入門 (7) nitta@tsuda.ac.jp

7章: 画像の保存・読み込み・表示

「画像ファイルへの保存」

画像データは、tensorflow.keras のデータベースにあるものを利用することにする。 Google Colab では標準で tensorflow が使えるが、手元の jupyter notebook の環境で tensorflow がインストールしてなければ、pip コマンドで導入すること。

鉄則[7-1]: Numpy配列形式の画像データを表示するときは、グレースケール画像は[0,255]のuint8型配列に、カラー画像は[0,1]のfloat32型配列に変換してから、Axes.imshow() を適用する。

グレースケール画像(channel数=1)の場合は要素値の範囲が [0, 255] の 'uint8' 型 Numpy 配列に変換してから、カラー画像(channel数=3 or 4)の場合は要素値の範囲が [0, 1] の 'float32' 型 Numpy 配列に変換してから、この関数を適用する。

7-1: グレースケールの画像をプロットする (Axes.imshow())

表示できる画像は2次元配列である必要がある。 配列の要素が整数の場合は[0, 255] の範囲で輝度(0:黒, 255: 白)を表す。 配列の要素が浮動小数の場合は[0.0, 1.0]の範囲で輝度(0.0:黒, 1.0: 白)を表す。

7-2: カラー画像を表示する (Axes.imshow())

カラー画像のデータは (Rows, Cols, Channels)形式のテンソル、 または (Channels, Rows, Cols) 形式のテンソルである。 Channels の要素数は 3 でRGB の輝度を表す。

ここで利用する CIFAR10 では (Rows, Cols, Channels) という形式である。

RGBの各要素が整数の場合は[0, 255]の範囲で輝度(0:暗い, 255: 明るい)を表す。 RGBの各要素が浮動小数の場合は[0.0, 1.0]の範囲で輝度(0.0:暗い, 1.0: 明るい)を表す。

7-3 の準備: 画像ファイルをネットワークからダウンロードして展開する

7-3 の準備として、VidTIMIT datasetの顔画像ファイル(の一部)をネットワークからダウンロードして展開する。

Official WWW of VidTIMIT dataset:
http://conradsanderson.id.au/vidtimit/

zip files of 2 persons of VidTIMIT dataset:
https://zenodo.org/record/158963/files/fadg0.zip
https://zenodo.org/record/158963/files/faks0.zip

7-3: ファイルから画像の読み込み

画像ファイルが次の場所にあるものとする。

./data/fadg0/video/head/[0-9]*

鉄則[7-2]: 画像ファイルから画像データを読み込む時は tensorflow.keras の下にある load_img() 関数を使う。

tensorflow.keras の load_img() / img_to_array() / array_to_img() / save_img() 関数は

のどちらか(tensorflowのバージョンで異なる)にある。

load_img() 関数の返り値は PIL形式の画像データなので、Numpy の配列に変換しておいた方が後々使いやすい。

    image_pil = load_img(path)

鉄則[7-3]: load_img() で読み込んだ画像データは PIL形式なので、ただちに Numpy Array に変換する。

tensorflow.keras の load_img() / img_to_array() / array_to_img() / save_img() 関数は

のどちらか(tensorflowのバージョンで異なる)にある。 load_img() 関数の返り値は PIL形式の画像データなので、Numpyの配列に変換した方が後々使いやすい。 この変換は、img_to_array()関数を使ってもよいが、numpy.array()関数の方がよく利用されているようだ。

img_to_array() 関数は、 各要素の範囲が[0, 255]の 'uint8' 型 Numpy 配列を返す。 PIL形式のデータに dtype パラメータの指定なしで np.array() を適用した場合も 'uint8' 型 Numpy 配列を返す。

    image_uint8 = np.array(imgage_pil)

鉄則[7-4]: 画像データをニューラルネットワークに通すときは、要素値の範囲が [0, 1] または [-1, 1] の 'float32' 型の Numpy 配列に変換する。

要素値の範囲が [0, 255] で型が 'uint8' の Numpy 配列を、要素値の範囲が[0, 1] または [-1, 1] で型が 'float32' の Numpy 配列に変換するには次のコードを使う。

  image = image_uint8.astype('float32') / 255.   # [0, 255] --> [0, 1]
or
  image = image_uint8.astype('float32') / 127.5 - 127.5  # [0, 255] --> [-1, 1]

ちなみに、逆変換のコードは次の通り。

    image_uint8 = (image * 255).astype('uint8')   # [0, 1] ---> [0, 255]
または
    image_uint8 = ((image + 1) * 127.5).astype('uint8') # [-1, 1] --> [0, 255]

鉄則[7-5]: Numpy配列形式のカラー画像データを表示したり保存したりするときは、要素値の範囲が[0, 1] の'float32'型Numpy配列に変換する。

要素値の範囲が [0, 1] で型が 'float32' の Numpy 配列と、要素値の範囲が[-1, 1] で型が 'float32' の Numpy 配列を相互に変換するには次のコードを使う。

    image = image * 2 - 1      # [0, 1] ---> [-1, 1]
    image = (image + 1) / 2    # [-1, 1] --> [0, 1]

要素値の範囲を保証するには numpy.clip() 関数を使う。

    image = np.clip(image, 0, 1)    # [0, 1] を保証する

7-4: 画像データの要素値の範囲の変換

鉄則[7-6]: Numpy 配列形式の画像データをファイルに保存するときは tensorflow.keras の下にある save_img() 関数を使う。

tensorflow.keras の load_img() / img_to_array() / array_to_img() / save_img() 関数は

のどちらか(tensorflowのバージョンで異なる)にある。

保存される画像ファイルのフォーマットは、file_format パラメータで指定できるが、省略された場合はファイル名の拡張子から決定される。

    image_pil = load_img(path)

7-5 画像の保存

画像データは、要素値の範囲が [0, 1] または [-1, 1] の 'float32'型 Numpy 配列として扱う。 要素の範囲が[-1, 1] の場合は、画像を表示や保存するときは一旦 [0, 1] の範囲に変換する必要がある。

保存する場合は,tensorflow.keras の下のsave_img()関数を使う。