MNIST画像情報を読み込む
MNIST画像情報をPerlで読み込むサンプルプログラムです。MNISTは、ディープラーニングで利用できる画像のサンプルです。
THE MNIST DATABASE of handwritten digitsを読み込むサンプルです。
use strict; use warnings; use FindBin; # MNIST画像情報を読み込む my $mnist_image_file = "$FindBin::Bin/data/train-images-idx3-ubyte"; open my $mnist_image_fh, '<', $mnist_image_file or die "Can't open file $mnist_image_file: $!"; # マジックナンバー my $image_buffer; read($mnist_image_fh, $image_buffer, 4); my $magic_number = unpack('N1', $image_buffer); if ($magic_number != 0x00000803) { die "Invalid magic number expected " . 0x00000803 . "actual $magic_number"; } # 画像数 read($mnist_image_fh, $image_buffer, 4); my $items_count = unpack('N1', $image_buffer); # 画像の行ピクセル数 read($mnist_image_fh, $image_buffer, 4); my $rows_count = unpack('N1', $image_buffer); # 画像の列ピクセル数 read($mnist_image_fh, $image_buffer, 4); my $columns_count = unpack('N1', $image_buffer); # 画像の読み込み my $image_data; my $all_images_length = $items_count * $rows_count * $columns_count; my $read_length = read $mnist_image_fh, $image_data, $all_images_length; unless ($read_length == $all_images_length) { die "Can't read all images"; } # 画像情報 my $image_info = {}; $image_info->{items_count} = $items_count; $image_info->{rows_count} = $rows_count; $image_info->{columns_count} = $columns_count; $image_info->{data} = $image_data;
MNIST画像情報を読み込むプログラムの簡易解説
「data」以下に「train-images-idx3-ubyte」を配置します。
ファイルをオープンしてread関数で読み込んでいきます。
マジックナンバーのチェックを行います。ビッグエンディアンの32bit整数なので、unpackに「N1」を指定します。
画像数を取得します。ビッグエンディアンの32bit整数なので、unpackに「N1」を指定します。
画像の行ピクセル数を取得します。ビッグエンディアンの32bit整数なので、unpackに「N1」を指定します。
画像の列ピクセル数を取得します。ビッグエンディアンの32bit整数なので、unpackに「N1」を指定します。
MNIST画像情報では、すべての画像データで、行ピクセル数と列ピクセル数は共通です。
すべての画像を読み込みます。
訓練用の画像情報である「train-images-idx3-ubyte」を読み込んでいますが、検証用の画像情報「t10k-images-idx3-ubyte」も同様の方法で読み込めます。
MNIST画像情報を出力する方法
メモリ上にMNIST画像情報を読み込みましたが、これを確認する方法を解説します。ビットマップ画像として出力すれば、内容を確認できます。
Imagerというモジュールを使います。CPANモジュールですので、cpanmあるいはcpanでインストールしてください。
以下は、最初の5つの画像をビットマップ画像として出力するサンプルです。
use strict; use warnings; use FindBin; use Imager; # MNIST画像情報を読み込む my $mnist_image_file = "$FindBin::Bin/data/train-images-idx3-ubyte"; open my $mnist_image_fh, '<', $mnist_image_file or die "Can't open file $mnist_image_file: $!"; # マジックナンバー my $image_buffer; read($mnist_image_fh, $image_buffer, 4); my $magic_number = unpack('N1', $image_buffer); if ($magic_number != 0x00000803) { die "Invalid magic number expected " . 0x00000803 . "actual $magic_number"; } # 画像数 read($mnist_image_fh, $image_buffer, 4); my $items_count = unpack('N1', $image_buffer); # 画像の行ピクセル数 read($mnist_image_fh, $image_buffer, 4); my $rows_count = unpack('N1', $image_buffer); # 画像の列ピクセル数 read($mnist_image_fh, $image_buffer, 4); my $columns_count = unpack('N1', $image_buffer); # 画像の読み込み my $image_data; my $all_images_length = $items_count * $rows_count * $columns_count; my $read_length = read $mnist_image_fh, $image_data, $all_images_length; unless ($read_length == $all_images_length) { die "Can't read all images"; } # 画像情報 my $image_info = {}; $image_info->{items_count} = $items_count; $image_info->{rows_count} = $rows_count; $image_info->{columns_count} = $columns_count; $image_info->{data} = $image_data; # 画像情報の出力 for (my $i = 0; $i < 5; $i++) { # 画像オフセット my $offset = $i * $rows_count * $columns_count; # キャンバス(モノクロ) my $img = Imager->new(xsize => $rows_count, ysize => $columns_count, channels => 1); # 画像情報を順番に出力 for (my $row = 0; $row < $rows_count; $row++) { for (my $column = 0; $column < $columns_count; $column++) { # 色(白黒がRGBと逆なので反転) my $pos = $offset + ($column * $rows_count) + $row; my $color_bin = substr($image_data, $pos, 1); my $color_value = unpack('C1', $color_bin); my $color_value_neg = $color_value ^ 0xFF; my $color = Imager::Color->new($color_value_neg, $color_value_neg, $color_value_neg); # ピクセル描画 $img->setpixel(x => $row, y => $column, color => $color); } } # Web表示できるようにPNGとして保存 my $bitmap_file = "$FindBin::Bin/tmp_images/number$i.png"; $img->write(file => $bitmap_file); }
出力した画像です。
MNIST画像情報を出力するプログラムの簡易解説
Imagerオブジェクトを幅と高さとチャンネル数を指定して作成します。モノクロなので1を指定しています。
画像情報を読み込んでいきます。行列の順で色の濃さが並んでいるので、取得します。データは、符号なし8bit整数で格納されているのでunpackに「C1」を指定しています。
MNISTの色の濃さはRGBと逆なので、反転させています。
Imager::Colorオブジェクトを作成しています。
ピクセルに描画します。
最後に、Webで表示できるようにpngで保存しています。拡張子から自動判定されます。
C言語のlibpngライブラリがOSのインストールされていることと、Imager::File::PNGが必要かもしれません。