はじめに
本記事は Qiita AdventCalendar2022 Elixir vol9 7日目の記事です
Evisionシリーズの3つ目の記事になります
このシリーズは技術評論社のOpenCVではじめよう ディープラーニングによる画像認識の7章の内容を参考にElixirとEvisionで書き換えて行っています
- Livebook + Evision基本編
- EvisionのCascadeClassifierで顔認識
- EvisionのDNN.ClassificationModelを使ってクラス分類
- EvisionのDNN.TextDetectionModelDBでテキスト検出
- EvisionのDNN.DetectionModelでYOLOv4を使って物体検知 12/14公開
- EvisionのDNN.SegmentationModelでセグメンテーション 12/14公開
- YOLOv4の結果を切り取ってEfficientnetで更に分類するシステムをEvisionで書く 12/18公開
この記事ではLivebook上で画像処理ライブラリOpenCVのElixirラッパーのEvisionのCascadeClassifierを使って顔認識を行う方法を紹介します
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分野の多くの学習済みモデルを使用できる
setup
実行環境は以下で行いました
OS macOS monterey
Hard apple m1 max
elixir 1.14.1-otp-25
erlang 25.0.4
livebook 0.7.2
evision 0.1.16
Livebookの環境は本家のgithubからクローンしたものを使っています
Evision(OpenCV)ができること
画像処理 Evision Module
キャプチャ Evision.VideoCapture
行列処理 Evision.Mat (Evision独自実装)
AI/ML
- ML(機械学習) module
- DNN(深層学習) module
- CascadeClassifier
- FaceDetector
....
今回やること
色々できますが、今回は以下に絞って紹介します
- Livebook上でeivison環境のセットアップ
- 画像の読み込み
- 画像のグレースケール変換
- CascadeClassifierで顔認識
Livebook上でeivison環境のセットアップ
READMEに沿って最新版のlivebookを起動させます
git clone https://github.com/livebook-dev/livebook.git
cd livebook
mix deps.get --only prod
MIX_ENV=prod mix phx.server
起動すると認証トークン付きのurlが表示されるのでそれにアクセスします
[Livebook] Application running at http://localhost:8080/?token=[your token]
アクセスしたら
setupのところに以下のMix.installを追加します
Mix.install([
{:evision, "~> 0.1.21"},
{:kino, "~> 0.7.0"}
])
次にEvisionが頻繁に打つには長いので aliasと
現在実行しているlivebookのフォルダが作業ディレクトリなので、画像等を置いてあるフォルダのパスを指定します
2つ目はlivebookのフォルダに直接置くのであれば不要です
alias Evision, as: Ev
base = "/Users/shou/livebook_samples/"
画像の読み込み
画像の読み込みは Evision Moduleにimreadがあるのでそちらを使います
Ev.imread(base <> "images/dog.jpg")
これを実行すると3つのタブがついたセルが表示されます
こちらは最近実装された機能で、本来はimencode で画像形式に変換した後に Kino.Image.new しなければ画像を出力できなかったのですが、
Evision.Mat構造体が最後に出力される場合に以下のようなセルが表示されるようになりました
Imageはそのまま画像で、Rawはデータ構造、NumericalはNxのテンソルがそれぞれ表示されます
imread/2はオプションを指定でき、画像処理でよく使われるのはグレースケールでの読み込みになります
Ev.imread(base <> "images/dog.jpg", flags: Ev.cv_IMREAD_GRAYSCALE())
画像のグレースケール変換
先のほどの imreadのオプションでグレースケールで読み込めましたが、今度はもとはカラーのものをグレースケール変換していきます
関数は Evision.cvtColor/2を使います
Ev.imread(base <> "images/dog.jpg")
|> Ev.cvtColor(Ev.cv_COLOR_BGR2GRAY())
第2引数は Evision.cv_COLOR_
でいくつか定数が定義されているので、気になる方は livebookの補完かドキュメントで調べてみてください
CascadeClassifierで顔認識
カスケードは複数の分類器を繋げて行うアンサンブル学習の一種です。 画像が与えられたとき、まず特徴抽出器で画像から特徴量を抽出します。 その特徴量がカスケード分類器に与えられ、分類結果 (positive または negative) が出力されます。
from https://pystyle.info/opencv-cascade-classifier/
今回は顔か顔でないかを判別するデータを使います
データはこちら
使う関数は分類器を作成する cascadeClassifierと検知する DetectMultiScale2 です
https://hexdocs.pm/evision/Evision.CascadeClassifier.html#cascadeClassifier/1
https://hexdocs.pm/evision/Evision.CascadeClassifier.html#detectMultiScale2/3
image = base <> "images/face.jpg"
path = base <> "opencv_file/hararcascade_frontalface_default.xml"
mat = Ev.imread(image)
gray_image = Ev.cvtColor(mat, Ev.cv_COLOR_BGR2GRAY())
cascade = Ev.CascadeClassifier.cascadeClassifier(path)
{boxes, _numDetections} = Ev.CascadeClassifier.detectMultiScale2(cascade, gray_image)
実行すると2つ座標が返ってきます
タプルの2要素目は numDetectionsとなっていますがよくわかりませんが、今回は使わないので無視します
{[{260, 36, 47, 47}, {296, 129, 81, 81}], [5, 5]}
座標データをもとに Evision.rectangleで短形を描画します
引数はそれぞれ
- Matrix
- x,y座標
- width,height
- 線の色(今回は赤)
- 先の太さ
となっています
Enum.reduce(boxes, mat, fn {x, y, w, h}, mat ->
Ev.rectangle(
mat,
{x, y},
{x + w, y + h},
{0, 0, 255},
thickness: 2
)
end)
実行すると元画像に検知した範囲を囲んだ以下のような画像が出力されます
最後に
書籍の内容に沿って画像の読み込み、グレースケール変換、顔認識といったことをやっていきました
書籍が手元にあれば各メソッドや処理の解説を読むこともできますので、興味が出た方は以下でElixirで書き直したコードを載せていますので試してみてください