12
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ElixirAdvent Calendar 2022

Day 14

EvisionのDNN.DetectionModelでYOLOv4を使って物体検知

Last updated at Posted at 2022-12-13

はじめに

本記事は Qiita AdventCalendar2022 Elixir vol2 14日目の記事です

Evisionシリーズの5つ目の記事になります
このシリーズは技術評論社のOpenCVではじめよう ディープラーニングによる画像認識の7章の内容を参考にElixirとEvisionで書き換えて行っています

  1. Livebook + Evision基本編
  2. EvisionのCascadeClassifierで顔認識
  3. EvisionのDNN.ClassificationModelを使ってクラス分類
  4. EvisionのDNN.TextDetectionModelDBでテキスト検出
  5. EvisionのDNN.DetectionModelでYOLOv4を使って物体検知 12/14公開
  6. EvisionのDNN.SegmentationModelでセグメンテーション 12/14公開
  7. YOLOv4の結果を切り取ってEfficientnetで更に分類するシステムをEvisionで書く 12/18公開

Livebook上で画像処理ライブラリOpenCVのElixirラッパーのEvisionのDNN.DetectionModelを使って物体検知を行う方法を紹介します

Livebookについて

Livebook is a web application for writing interactive and collaborative code notebooks.

LivebookはコラボレーションもできるElixir対話的実行環境を提供するWebアプリケーションです

Evisionについて

  • OpenCVのElixirラッパー
  • Port等を使わずに直にElixirから使うことができる
  • Nxのバックエンドとして使用でき、行列演算の高速化(CPU,GPU)ができる
  • Nxデータに相互に変換できる
  • 膨大な画像処理の関数を使用できる
  • DNNモジュールでCV分野の多くの学習済みモデルを使用できる

物体検知について

物体検出(ObjectDetection)とは、画像の中から物体らしき領域を検出し、その物体がカップなのかペンなのかといったクラスに分類するタスクです。
OpenCVではじめよう ディープラーニングによる画像認識 p.350

使用するモジュールはDNN.DetectionMoelになります

使用するモデル

YOLOv4
学習済みデータはこちらの7.3をダウンロードしてください

直リンク
https://gihyo.jp/assets/files/book/2022/978-4-297-12775-6/download/7.3.zip

setup

livebookは公式サイトを参考にインストールしてください
livebookを起動してノートブックを作成したらsetupセルに以下を追加して実行してください

Mix.install([
  {:evision, "~> 0.1.21"},
  {:kino, "~> 0.7.0"},
])

データの準備

aliasでモジュール名を短くしています import numpy as npと同じですね
weigthsで学習済みデータのファイルパスを指定します
configでモデル設定のファイルパスを指定します
baseでダウンロードしたフォルダパスを貼っておくと便利です

alias Evision, as: Ev
base = "7.3をダウンロードしたフォルダの絶対パスを貼り付けてください"
weights = base <> "7.3/yolov4/yolov4.weights"
config = base <> "7.3/yolov4/yolov4.cfg"

classesで推論結果のラベル名を取得するためにクラス名のリストを作ります
colorsで推論結果を囲うためにラベル毎にランダムな色のリストを作ります

classes = File.read!(base <> "7.3/yolov4/coco.names") |> String.split("\n")
colors =
  Enum.map(classes, fn _ ->
    {Enum.random(0..255), Enum.random(0..255), Enum.random(0..255)}
  end)

モデルの読み込み

学習済みデータを読み込んで、モデルを構築します
DetectionModel/2で先程の学習済みデータとオプションでネットワークの設定ファイルのパスを渡します

モデルの次はsetInputParams/2でハイパーパラメータを設定します
パラメーターはそれぞれ以下を設定しています

  • scale -> 画像のRGB値を0~1.0の範囲に変換
  • size -> 入力画像サイズを416x416にする
  • swapRB -> BGR形式をRGBに入れ替えない
  • crop -> アスペクト比をせずにリサイズ
model =
  Ev.DNN.DetectionModel.detectionModel(weights, config: config)
  |> Ev.DNN.DetectionModel.setInputParams(
    scale: 1.0 / 255.0,
    size: {416, 416},
    swapRB: true,
    crop: false
  )

推論の実行

画像を読み込みます
YOLOでよく使われる犬の画像を使います

image = Ev.imread(base <> "7.3/yolov4/dog.jpg")

dog.jpg

detect/3で推論を実行します
オプションはそれぞれ

  • confThreshold -> 信頼度0.5以上のみ対象とする
  • nmsTreshhold -> NMS(Non-Maximum Suppression)の信頼度0.4以上のみを対象とする
    としています
{class_ids, confidences, boxes} =
  Ev.DNN.DetectionModel.detect(model, image, confThreshold: 0.5, nmsThreshold: 0.4)

実行すると検出したオブジェクトのクラスID、信頼度、座標のリストがそれぞれ返ってきます

{[1, 7, 16], [0.9896954298019409, 0.912635087966919, 0.9911838173866272],
 [{129, 131, 439, 293}, {465, 75, 227, 96}, {133, 234, 177, 302}]}

推論結果を画像に描画

Enum.zip_reduceで推論結果を描画していきます

zip_reduceは複数のリストを受け取って、各リストの1番目からをまとめて1つのリストにしてループを回してアキュムレータのimageに対して推論結果を描画します

boxはそれぞれ{x,y,w,h}に展開します

短形を描画する関数rectangleの引数はそれぞれ

  1. 画像
  2. 始点座標 {x,y}
  3. 終点座標 {x + w, y + h}
  4. 色(クラス毎にランダム作成した色)
  5. オプション、今回は線の太さ

クラス名のテキストを描画するputTextの引数はそれぞれ

  1. 画像
  2. テキスト(クラス名と信頼度小数点3桁)
  3. 座標(始点ちょっと上)
  4. フォント
  5. 文字の大きさ
  6. オプション、今回は線の太さ

となっています

Enum.zip_reduce([class_ids, confidences, boxes], image, fn [id, conf, {x, y, w, h}], mat ->
  Ev.rectangle(mat, {x, y}, {x + w, y + h}, Enum.at(colors, id), thickness: 2)
  |> Ev.putText(
    "#{Enum.at(classes, id)}:(#{Float.round(conf, 3)})",
    {x, y - 5},
    Ev.cv_FONT_HERSHEY_SIMPLEX(),
    0.5,
    {0, 0, 0},
    thickness: 2
  )
end)

スクリーンショット 2022-12-04 19.00.17.png

最後に

DetectionModelを使用して簡単に物体検出ができました

他のバージョンのYOLOも動くと思うので色々試してみてください
本記事は以上になりますありがとうございました

全コード

alias Evision, as: Ev
base = "/Users/shou/livebook_samples/"
weights = base <> "7.3/yolov4/yolov4.weights"
config = base <> "7.3/yolov4/yolov4.cfg"
classes = File.read!(base <> "7.3/yolov4/coco.names") |> String.split("\n")
colors =
  Enum.map(classes, fn _ ->
    {Enum.random(0..255), Enum.random(0..255), Enum.random(0..255)}
  end)

model =
  Ev.DNN.DetectionModel.detectionModel(weights, config: config)
  |> Ev.DNN.DetectionModel.setInputParams(
    scale: 1.0 / 255.0,
    size: {416, 416},
    swapRB: true,
    crop: false
  )

image = Ev.imread(base <> "7.3/yolov4/dog.jpg")
{class_ids, confidences, boxes} =
  Ev.DNN.DetectionModel.detect(model, image, confThreshold: 0.5, nmsThreshold: 0.4)

Enum.zip_reduce([class_ids, confidences, boxes], image, fn [id, conf, {x, y, w, h}], mat ->
  Ev.rectangle(mat, {x, y}, {x + w, y + h}, Enum.at(colors, id), thickness: 2)
  |> Ev.putText(
    "#{Enum.at(classes, id)}:(#{Float.round(conf, 3)})",
    {x, y - 5},
    Ev.cv_FONT_HERSHEY_SIMPLEX(),
    0.5,
    {0, 0, 0},
    thickness: 2
  )
end)
12
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?