RaspberryPiで機械学習をやってみた
Raspberry Pi Advent Calendar 2019の21日目です。
なんとなく機械学習を触ってみたい方、
画像処理に機械学習を取り入れてみたい方、
ラズパイ4を買ってみたけど特にすることがない方向けに記事を書きます。
画像処理に初めて機械学習を使った時に「dlib」というライブラリを使ったのですが、
これが中身を理解しなくても使いやすかったのでご紹介させていただきます。
概要
ラズパイにwebカメラをつなげ、取得した画像データから任意の物体の位置を検出します。
物体の位置は物体の形状(エッジ)を学習することで検出します。
形状認識で用いられる特徴量にはHOG・SIFT・SURFなどがあるのですが、
dlibではHOG特徴量を用いています。
- 特徴
- HOG(Histograms of Oriented Gradients)…輪郭がはっきりと映っている画像に有効
- SIFT…ぼやけている画像にも有効。回転・スケールの変更にも強く、ロバスト性が高い。
- SURF…ぼやけている画像にも有効。SIFTの高速処理バージョン。
以下にHOG特徴量の例を示します。
(なんとなくエッジが見えると思うのですが、これが輝度の勾配をベクトルで示したものとなります)
これをヒストグラム化して物体の特徴とするのですが、今回は説明しません.
機械学習のフレームワークにはSVM(Support Vector Machine)を用いています。
- 特徴
- SVM…いい感じの判別器(雑)。先ほどの作成したHOG特徴量を元に物体を判別する。
環境
-
ラズパイ4(メモリ4GB)
- OS:Raspbian GNU/Linux 10
- python(3.7.3)…使用言語
- OpenCV(3.2.0)…画像処理用のライブラリ
- dlib(19.0.0)…機械学習用のライブラリ
-
C270n HD Webcam…お手頃なロジクールのカメラですが、USBカメラならなんでもいいです。
作業
- 写真を取る
- 写真からターゲットを学習させる
- 学習させる
- 学習した結果を使う
環境構築
python3のインストール
Raspberry piにPython3.6を入れてみた(Raspberry Pi Advent Calendar 2019 1日目)
上記にもあるように、pythonは3系を入れましょう!!
OpenCV…画像処理用のライブラリ
$ pip install opencv-contrib-python
dlib…機械学習用のライブラリ
$ pip install dlib
確認(重要)
$ python
>import cv2
>import dlib
pythonと打ち込んでインタラクティブモードに入ればOKです。cv2とdlibのimport時もエラーが出なければOKです。
画像を撮影する
# -*- coding: utf-8 -*-
import numpy as np
import cv2
import os # rename用モジュール
i = 0 # 保存した写真名の初期値番号。
cap = cv2.VideoCapture(0)
while(True):
# フレームをキャプチャする
ret, frame = cap.read()
# 画面に表示する
cv2.imshow('frame',frame)
# キーボード入力待ち
key = cv2.waitKey(1) & 0xFF
# [q]が押された場合は終了する
if key == ord('q'):
break
# [s]が押された場合は保存する
if key == ord('s'):
i = i + 1
path = str("{0:06d}".format(i)) + '.jpg'
cv2.imwrite(path,frame)
# キャプチャの後始末と,ウィンドウをすべて消す
cap.release()
cv2.destroyAllWindows()
使い方
1. 写真を撮影するプログラムを実行。
$ python3 webcam_take_picture.py
2. 学習させたい対象にカメラを向け[s]キーで写真を撮る(Save)。撮影枚数は50枚程度でいい。
3. [q]キーでウインドウを閉じる(Quit)。
homeの直下に「/owl」というフォルダを作り、
撮影した画像を「owl」に置く。
物体を選択する
写真中の物体はimglabを使って選択します。
imglabをビルドする
$ cd ~/dlib/tools/imglab/
$ sudo mkdir build
$ cd build
$ sudo cmake ..
$ sudo cmake --build . --config Release
撮影したowl内の写真をxmlにまとめる。
$ ./imglab -c ~/owl/all.xml ~/owl
imglabの起動
$./imglab ~/owl/all.xml
- Labelをつける
- 対象を選択する
- 「training.xml」として保存する。
学習させる
import dlib
if __name__ == "__main__":
TrainingXml = "~/owl/training.xml"
SvmFile = "~/owl/detector.svm"
options = dlib.simple_object_detector_training_options()
options.add_left_right_image_flips = True
options.C = 5
options.num_threads = 4
options.be_verbose = True
dlib.train_simple_object_detector(TrainingXml, SvmFile, options)
1. 学習させる
$ webcam_dlib_learning.py
学習結果はdetector.svmとして出力されます。
今回は学習に150枚の画像を用いたのですが、
ラズパイ4で学習させたら6分15秒で終わりました。
(ちなみにPC(core i7)で学習すると27秒で終わりました。PCで学習させて、学習させたものをラズパイで使うことも可能です)
学習した結果を使う
import dlib
import cv2
if __name__ == "__main__":
SvmFile = "~/owl/detector.svm"
detector = dlib.simple_object_detector(SvmFile)
cap = cv2.VideoCapture(0)
if cap.isOpened() is not True:
raise("IO Error")
WinName = "Capture"
cv2.namedWindow(WinName, cv2.WINDOW_AUTOSIZE)
win_det = dlib.image_window()
win_det.set_image(detector)
while True:
ret, img = cap.read()
if ret:
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
dets = detector(rgb)
if len(dets):
d = dets[0]
cv2.rectangle(img, (d.left(), d.top()), (d.right(), d.bottom()), (0, 0, 255), 2)
x = (d.left()+d.right())/2
y = (d.top()+d.bottom())/2
cv2.putText(img,"Ex:"+str(x),(40,70),2,0.8,(0,255,0))
cv2.putText(img,"Ey:"+str(y),(160,70),2,0.8,(0,255,0))
cv2.imshow(WinName, img)
key = cv2.waitKey(1)
if key & 0x00FF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
1. 学習結果を使って、任意の物体を検出する。
$ python3 webcam_dlib.py
#処理が重すぎる
ラズパイ4で機械学習をやってみた💃💃💃💃
— 星ざめ (@hosizame) December 19, 2019
が処理が重すぎた😇😇😇😇 pic.twitter.com/XVIhkvFwVD