画像の異常検知AIライブラリ anomalib -推論編- 【Python】

AI
スポンサーリンク
スポンサーリンク

はじめに

前回は anomalib をカスタムデータで学習させる方法について説明しました。

今回は、推論プログラムを使いやすいように変更していきます。

前提条件

前提条件は以下の通りです。

  • torch == 1.12.1+cu113
  • pytorch_lightning == 1.9.5

推論の前に

カメラ映像を OpenCV で読み取り、推論するためには pytorch_lightning ではなく、torch を使用する必要があります。

pytorch_lightning は、推論するためにデータローダーを構築する必要があるので、今回は使用しません。

torch モデルを学習

まずは、src/anomalib/models/padim/config.yaml を編集します。

dataset:
  name: custom
  format: folder
  path: ./datasets/MVTec/custom
  # category: custom
  normal_dir: train/good
  normal_test_dir: test/good
  abnormal_dir: test/defect
  mask_dir: null
  extensions: null
  # task: segmentation
  task: classification
  train_batch_size: 8
  eval_batch_size: 8
  num_workers: 2
  image_size: 256 # dimensions to which images are resized (mandatory)
  center_crop: null # dimensions to which images are center-cropped after resizing (optional)
  normalization: imagenet # data distribution to which the images will be normalized: [none, imagenet]
  transform_config:
    train: null
    eval: null
  test_split_mode: from_dir # options: [from_dir, synthetic]
  test_split_ratio: 0.1 # fraction of train images held out testing (usage depends on test_split_mode)
  val_split_mode: same_as_test # options: [same_as_test, from_test, synthetic]
  val_split_ratio: 0.1 # fraction of train/test images held out for validation (usage depends on val_split_mode)
  tiling:
    apply: false
    tile_size: null
    stride: null
    remove_border_count: 0
    use_random_tiling: False
    random_tile_count: 16

model:
  name: padim
  # backbone: resnet18
  backbone: wide_resnet50_2
  pre_trained: true
  layers:
    - layer1
    - layer2
    - layer3
  normalization_method: min_max # options: [none, min_max, cdf]

metrics:
  image:
    - F1Score
    - AUROC
  pixel:
    - F1Score
    - AUROC
  threshold:
    method: adaptive #options: [adaptive, manual]
    manual_image: null
    manual_pixel: null

visualization:
  show_images: False # show images on the screen
  save_images: True # save images to the file system
  log_images: True # log images to the available loggers (if any)
  image_save_path: null # path to which images will be saved
  mode: full # options: ["full", "simple"]

project:
  seed: 42
  path: ./results

logging:
  logger: [] # options: [comet, tensorboard, wandb, csv] or combinations.
  log_graph: false # Logs the model graph to respective logger.

optimization:
  # export_mode: null # options: torch, onnx, openvino
  export_mode: torch

# PL Trainer Args. Don't add extra parameter here.
trainer:
  enable_checkpointing: true
  default_root_dir: null
  gradient_clip_val: 0
  gradient_clip_algorithm: norm
  num_nodes: 1
  devices: 1
  enable_progress_bar: true
  overfit_batches: 0.0
  track_grad_norm: -1
  check_val_every_n_epoch: 1 # Don't validate before extracting features.
  fast_dev_run: false
  accumulate_grad_batches: 1
  max_epochs: 1
  min_epochs: null
  max_steps: -1
  min_steps: null
  max_time: null
  limit_train_batches: 1.0
  limit_val_batches: 1.0
  limit_test_batches: 1.0
  limit_predict_batches: 1.0
  val_check_interval: 1.0 # Don't validate before extracting features.
  log_every_n_steps: 50
  accelerator: cpu # <"cpu", "gpu", "tpu", "ipu", "hpu", "auto">
  strategy: null
  sync_batchnorm: false
  precision: 32
  enable_model_summary: true
  num_sanity_val_steps: 0
  profiler: null
  benchmark: false
  deterministic: false
  reload_dataloaders_every_n_epochs: 0
  auto_lr_find: false
  replace_sampler_ddp: true
  detect_anomaly: false
  auto_scale_batch_size: false
  plugins: null
  move_metrics_to_cpu: false
  multiple_trainloader_mode: max_size_cycle

74 行目の export_mode を null から torch へ変更しました。

学習コマンド

学習コマンドは同じです。

python .\tools\train.py --model padim

推論コマンド

python tools/inference/torch_inference.py \
 --config src/anomalib/models/padim/config.yaml \
 --weights results/padim/custom/run/weights/torch/model.pt \
 --input ./datasets/MVTec/custom/test/defect/1.png \
 --output results/padim/custom/test/1_result.png \
 --device cpu \
 --task classification \
 --show False \
 --visualization_mode simple

上記を実行すると、pytorch_lightning と同じ結果が得られます。

推論プログラムの作成

torch_inference.py をコピーして custom_inference.py とします。

"""Anomalib Torch Inferencer Script.

This script performs torch inference by reading model weights
from command line, and show the visualization results.
"""

# Copyright (C) 2022 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

from argparse import ArgumentParser, Namespace
import cv2
import torch

from anomalib.deploy import TorchInferencer
# from anomalib.post_processing import Visualizer


def infer(args: Namespace) -> None:
    """Infer predictions.

    Show/save the output if path is to an image. If the path is a directory, go over each image in the directory.

    Args:
        args (Namespace): The arguments from the command line.
    """

    torch.set_grad_enabled(False)

    # Create the inferencer and visualizer.
    inferencer = TorchInferencer(path=args.weights, device=args.device)
    # visualizer = Visualizer(mode=args.visualization_mode, task=args.task)

    image = cv2.imread(args.input)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    predictions = inferencer.predict(image=image)
    print("pred_score: ", predictions.pred_score, "pred_label: ", predictions.pred_label)
    # output = visualizer.visualize_image(predictions)

    # if args.output:
    #     file_path = generate_output_image_filename(input_path=args.input, output_path=args.output)
    #     visualizer.save(file_path=file_path, image=output)

    # Show the image in case the flag is set by the user.
    if args.show:
        # visualizer.show(title="Output Image", image=output)
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
        cv2.imshow("frame", image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

if __name__ == "__main__":
    args = ArgumentParser().parse_args()
    args.input = "./datasets/MVTec/custom/test/defect/1.png"
    args.config = "src/anomalib/models/padim/config.yaml"
    args.weights = "results/padim/custom/run/weights/torch/model.pt"
    # args.output = "results/padim/custom/test/1_result.png"
    args.device = "cpu"
    args.show = True
    args.visualization_mode = "simple"
    args.task = "classification"
    infer(args=args)

上記を実行すると、以下の出力が得られます。

pred_score:  0.5353217090536091 pred_label:  Anomalous

おわりに

今回は anomalib の推論プログラムを変更しました。

これでカメラから取得したデータをそのまま推論し、結果を数値で得ることができるようになりました。

コメント

タイトルとURLをコピーしました