データサイエンスの画像コンペでは、画像データがzip形式で圧縮されています。
画像データの数がそんなに多くなければ、zipを解凍して画像を読み込んだりもしますが、大量にある場合はzipのまま、画像データを読み込めればと思い、備忘録的に投稿します。
使うデータはSIGNATEの【練習問題】**画像ラベリング(10種類)**を使います。
まずは、ライブラリをインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import zipfile
import io
zipファイル内の画像ファイルを確認
zipファイルのパスを指定して、中身を確認してみます。
with構文を使って**ZipFile()**でzipファイルを読み込み、**infolist()**で読み込んだzipファイル内のすべてのファイル名を取得します。
# zipファイルのパス
zip_path = './data/train_images.zip'
# zipの中身を確認
with zipfile.ZipFile(zip_path, 'r') as zip_file:
for info in zip_file.infolist():
print(info)
出力
(...略...)
<ZipInfo filename='train_images/train_989.jpg' compress_type=deflate external_attr=0x20 file_size=3334 compress_size=3203>
<ZipInfo filename='train_images/train_99.jpg' compress_type=deflate external_attr=0x20 file_size=2873 compress_size=2737>
<ZipInfo filename='train_images/train_990.jpg' compress_type=deflate external_attr=0x20 file_size=2743 compress_size=2606>
<ZipInfo filename='train_images/train_991.jpg' compress_type=deflate external_attr=0x20 file_size=3005 compress_size=2869>
<ZipInfo filename='train_images/train_992.jpg' compress_type=deflate external_attr=0x20 file_size=2031 compress_size=1894>
<ZipInfo filename='train_images/train_993.jpg' compress_type=deflate external_attr=0x20 file_size=3064 compress_size=2910>
<ZipInfo filename='train_images/train_994.jpg' compress_type=deflate external_attr=0x20 file_size=2858 compress_size=2723>
<ZipInfo filename='train_images/train_995.jpg' compress_type=deflate external_attr=0x20 file_size=3016 compress_size=2882>
<ZipInfo filename='train_images/train_996.jpg' compress_type=deflate external_attr=0x20 file_size=2631 compress_size=2495>
<ZipInfo filename='train_images/train_997.jpg' compress_type=deflate external_attr=0x20 file_size=2315 compress_size=2170>
<ZipInfo filename='train_images/train_998.jpg' compress_type=deflate external_attr=0x20 file_size=3012 compress_size=2877>
<ZipInfo filename='train_images/train_999.jpg' compress_type=deflate external_attr=0x20 file_size=2488 compress_size=2348>
zipファイル内の画像ファイルを読み込み
ここで注意したいのは、infolist()
をそのままループして読み込むと、ラベルデータのファイル順で読み込むことができません。
(... → train_989 → train_99 → train_990 → train_991 → ...)
必ず画像のラベルデータのファイル順に読み込みます。
というわけでラベルデータを読み込んで中身を確認します。
# ラベルデータの読み込み
train_labels = pd.read_csv('./data/train_master.tsv', sep='\t')
print(train_labels.head())
読み込んだ画像データを格納するリストをあらかじめ作っておき、続いてwith構文を使って**ZipFile()**でzipファイルを読み込みます。
そして、ラベルデータのファイル順にループして読み込み、**zip_file.open()**に対象のファイル名を指定し、img_fileに読み込んでいきます。
対象のファイル名がtrain_images/train_〇〇.jpg
となっているのをすでに確認しているため、train_labels['file_name']
の要素(train_〇〇.jpg
)をループしてtrain_images/ +i
とします。
画像のバイナリデータをIOライブラリの**BytesIO()関数で読み込み、PillowのImage.open()**で開き、Numpy配列に変換したものを格納リストに追加していきます。
# zipの読み込み
with zipfile.ZipFile(zip_path, 'r') as zip_file:
for i in train_labels['file_name']:
with zip_file.open('train_images/'+i) as img_file:
# 画像のバイナリデータを読み込む
img_bin = io.BytesIO(img_file.read())
# バイナリデータをPillowで開く
img = Image.open(img_bin)
# 画像データを配列化
img_array = np.array(img)
# 格納リストに追加
X_train.append(img_array)
読み込んだ画像データの確認
zipファイルからちゃんと画像データを読み込めたか確認して、さらにラベル名と一致しているか確認していきます。
このデータは画像データのファイル名とラベルIDが対応していて(train_master.tsv)、さらにラベルIDとラベル名が対応(label_master.tsv)しているため、画像データとラベル名を対応させたものを表示させます。
まずはラベルマスタを読み込みます。
# ラベルマスタの読み込み
label_master = pd.read_csv('./data/label_master.tsv', sep='\t')
print(label_master.head())
続いて、ラベルマスタからラベル名を抽出します。
# ラベル名を抽出
labels = label_master['label_name']
以下のコードを実行すると、画像とそれが何を表すのか、40個のサンプルを表示します。
# 画像の確認
plt.figure(figsize=(10,10))
for i in range(0,40):
plt.subplot(5,8,i+1)
plt.title(labels[train_labels.iloc[i, 1]]) # train_labelsのラベルID抽出後、IDに対応するラベル名を抽出
plt.axis('off') # 軸と目盛りをオフ
plt.imshow(X_train[i])
プログラムを実行すると以下のように表示されます。
ちゃんと、画像に写っているものと、ラベルが一致しているのが確認できました。
学習に進む場合は、画像を格納したリストをNumpy配列に変換すればOKです。
最終スクリプト
'''
zipファイル内の画像ファイルを確認
'''
# ライブラリのインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import zipfile
import io
# zipファイルのパス
zip_path = './data/train_images.zip'
# zipの中身を確認
with zipfile.ZipFile(zip_path, 'r') as zip_file:
for info in zip_file.infolist():
print(info)
'''
zipファイル内の画像ファイルの読み込み
'''
# ラベルデータの読み込み
train_labels = pd.read_csv('./data/train_master.tsv', sep='\t')
print(train_labels.head())
# 画像データの格納リスト
X_train = [] # 画像のピクセル値とラベルを格納するリストを生成(説明変数)
# zipの読み込み
with zipfile.ZipFile(zip_path, 'r') as zip_file:
for i in train_labels['file_name']:
with zip_file.open('train_images/'+i) as img_file:
# 画像のバイナリデータを読み込む
img_bin = io.BytesIO(img_file.read())
# バイナリデータをpillowで開く
img = Image.open(img_bin)
# 画像データを配列化
img_array = np.array(img)
# 格納リストに追加
X_train.append(img_array)
# ラベルマスタの読み込み
label_master = pd.read_csv('./data/label_master.tsv', sep='\t')
print(label_master.head())
# ラベル名を抽出
labels = label_master['label_name']
# 画像の確認
plt.figure(figsize=(10,10))
for i in range(0,40):
plt.subplot(5,8,i+1)
plt.title(labels[train_labels.iloc[i, 1]]) # train_labelsのラベルID抽出後、IDに対応するラベル名を抽出
plt.axis('off') # 軸と目盛りをオフ
plt.imshow(X_train[i])
# np.arrayに変換
X_train = np.array(X_train)