(36)【PyTorchでMNIST #7】自筆画像PNGファイルを自動認識させる。

投稿者: | 2025年4月23日

685 views

この記事は最終更新から 395日 が経過しています。

【1】やりたいこと

GIMPなどの画像エディタを使って自筆の数字を描き、これを学習済みパラメータを使って自動認識させてみたい。
作成する画像は、学習に使用したのと同じ 28×28[pixel]の 1[channel]画像(=モノクロ画像)だ。

【2】やってみる

1) プログラミング

(1) dataset_MNIST.py

1枚の数字画像を読み込み Tensorデータ化する関数 load_one_image を追加した。
変更箇所をハイライト表示する。

from torchvision import datasets, transforms
from PIL import Image

class MyDataset:
    def __init__(self, data_dir='../data'):
        self.transform = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.1307,), (0.3081,))
        ])
        self.data_dir = data_dir

    def get_train_dataset(self):
        return datasets.MNIST(self.data_dir, train=True, download=True, transform=self.transform)

    def get_test_dataset(self):
        return datasets.MNIST(self.data_dir, train=False, download=True, transform=self.transform)

    def load_one_image(self, img_path):
        # 指定された画像ファイルを読み込み、MNIST準拠のTensorに変換して返す。
        # 出力テンソルの shape: [1, 1, 28, 28]
        image = Image.open(img_path).convert('L')         # モノクロに変換
        image = image.resize((28, 28))                    # サイズを28x28に統一
        image = self.transform(image)                     # Tensor化+正規化
        return image.unsqueeze(0)                         # [1, 1, 28, 28] に拡張

(2) control_test_one_img.py

こちらは新規作成したファイルだ。
control_test.pyを流用し、単一画像を入力&自動認識するように改造した。

import torch
from net_model_CNN_01 import Net
from trainer import Trainer
from dataset_MNIST import MyDataset
import argparse

#//////////////////////////////////////////////////////////////////////////
def predict_image(img_path, model_path):
    # 環境設定
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    
    # モデルとパラメータの読み込み
    model = Net()
    trainer = Trainer(model, device)
    trainer.load(model_path)

    # 画像読み込みと前処理
    dataset = MyDataset()
    image_tensor = dataset.load_one_image(img_path).to(device)

    # 推論
    model.eval()
    with torch.no_grad():
        output = model(image_tensor)
        prob = torch.softmax(output, dim=1)
        predicted_label = torch.argmax(prob).item()
        prob_array = prob.cpu().numpy()[0]
        formatted = [f"{p:.1f}" for p in prob_array]
        print(f"予測された数字は: {predicted_label}")
        print(f"各クラスの確率: {formatted}")

#//////////////////////////////////////////////////////////////////////////
def main():
    parser = argparse.ArgumentParser(description="Predict a digit from a single image")
    parser.add_argument('-i', type=str, required=True, help='Path to input image file')
    parser.add_argument('-p', type=str, required=True, help='Path to trained model file')
    args = parser.parse_args()
    predict_image(args.i, args.p)

#//////////////////////////////////////////////////////////////////////////
if __name__ == "__main__":
    main()

2) 画像作成

GIMPで 28×28[pixel]のモノクロ画像を作った。
数字は AIが悩みそうなもの、AIが楽々わかりそうなもの、いろいろな数字画像を混ぜてみた。

3) 実行結果

まずは 10 epochs学習する。
 → 正解率 99.05%のモデルが出来た。

$ python control_train.py -p AAA.pth
[1/10] Epoch complete
[2/10] Epoch complete
[3/10] Epoch complete
[4/10] Epoch complete
[5/10] Epoch complete
[6/10] Epoch complete
[7/10] Epoch complete
[8/10] Epoch complete
[9/10] Epoch complete
[10/10] Epoch complete
Test Accuracy: 99.05%
Model saved to AAA.pth

このモデルを使って、自筆数字画像を自動判読してみる。

$ python control_test_one_img.py -p AAA.pth -i ./Img/t_001_2.png
Model loaded from AAA.pth
予測された数字は: 2
各クラスの確率: ['0.0', '0.0', '1.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0']

$ python control_test_one_img.py -p AAA.pth -i ./Img/t_002_4.png
Model loaded from AAA.pth
予測された数字は: 4
各クラスの確率: ['0.0', '0.0', '0.0', '0.0', '1.0', '0.0', '0.0', '0.0', '0.0', '0.0']

$ python control_test_one_img.py -p AAA.pth -i ./Img/t_003_8.png
Model loaded from AAA.pth
予測された数字は: 8
各クラスの確率: ['0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '1.0', '0.0']

$ python control_test_one_img.py -p AAA.pth -i ./Img/t_004_7.png
Model loaded from AAA.pth
予測された数字は: 7
各クラスの確率: ['0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '1.0', '0.0', '0.0']

$ python control_test_one_img.py -p AAA.pth -i ./Img/t_005_5.png
Model loaded from AAA.pth
予測された数字は: 5
各クラスの確率: ['0.0', '0.0', '0.0', '0.0', '0.0', '1.0', '0.0', '0.0', '0.0', '0.0']


かなり怪しい 6を描いたが、

$ python control_test_one_img.py -p AAA.pth -i ./Img/t_006_6.png
Model loaded from AAA.pth
予測された数字は: 6
各クラスの確率: ['0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.8', '0.0', '0.2', '0.0']

アクセス数(直近7日): ※試験運用中、BOT除外簡易実装済
  • 2026-05-26: 0回
  • 2026-05-25: 0回
  • 2026-05-24: 0回
  • 2026-05-23: 0回
  • 2026-05-22: 0回
  • 2026-05-21: 0回
  • 2026-05-20: 0回
  • コメントを残す

    メールアドレスが公開されることはありません。 が付いている欄は必須項目です