チャレンジ!画像認識


目的

画像認識を試したい。
簡単な方法を模索してみます。

使うソフトウェアの整理

  • OpenCV
  • googleimagesdownload

画像認識を簡単にしてくれるソフトウェア
- (探索中)

インストール

  • Ubuntu 16.04
  • OpenCV 4

OpenCV 4

ここに従ってインストール
https://docs.opencv.org/master/d2/de6/tutorial_py_setup_in_ubuntu.html

$ sudo apt-get install python-opencv

これだと、python 2.7向けに入ってしまったので、pip3でやり直し。
python2 だと、numpyが入らないので、opencvがはいったところで、いまいち使えないと思う。

$ pip3 install opencv-python

こちらは、opencvに続いて、numpyをインストールしてくれます。はいったことを確認。

$ python3 -c "import cv2 as cv; print(cv.__version__)"
4.1.0

合わせて、haarcascadeファイルをダウンロード。面倒なので、opencvそのものをダウンロード

$ git clone https://github.com/opencv/opencv.git

googleimagesdownload

googleの画像検索で、学習用のデータを取ってくるために必要。
101枚以上ダウンロードする場合は、chromedriverが必要。

$ pip3 google_images_download

chromedriverのインストールには、chromeのインストールが必要。
本稿では割愛デス。

学習データ収集

googleimagesdownloadで、学習画像をダウンロード。
今回は、ぬいぐるみの判定を考えて、build a bearのぬいぐるみとそうでないぬいぐるみのf画像情報をダウンロードします。

$ googleimagesdownload -cd '/usr/local/bin/chromedriver' -l 5000 -k 'stuffed animal -bear'
$ googleimagesdownload -cd '/usr/local/bin/chromedriver' -l 3000 -k 'build a bear'

ダウンロードしたデータは、それぞれ、正解、不正解に分けて保存します。
ここでは、prosに正解、consに不正解を入れることにします。

学習データ加工

opencv_createsampleを利用して、vecファイルを生成
一つ一つやると骨が折れるので、簡易的にスクリプト的にやります。

$ find ./pros -iname "*.jpg" > positives.txt
$ find ./cons -iname "*.jpg" > negatives.txt
$ cat positives.txt | xargs -I{} sh -c "opencv_createsamples -img {} -num 10 -bg negatives.txt -vec {}.vec -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 || true"

createsamplesの結果、ファイルサイズが"0"になるものがいるので、そいつらは、要削除

$ find ./pros -empty | xargs rm

vecファイルを別に保管し、vecファイル一覧を作成

$ mkdir vecs
$ mv pros/*vec vecs
$ find ./vecs -iname "*vec" > vecs.txt

学習中

open_trancascadeを利用して、cascadeファイルを作成

$ opencv_traincascade -data ./vec -vec vecs.vec -bg negatives.txt

うちの環境では、おおよそ6時間かかりました。(stage-19まで)
だいたい、OKデータが300、NOKデータが600です。

コーディング

いろいろ、ネットにサンプルコードが落ちているので、つなぎ合わせました。

import cv2
import imutils
import numpy
import os
import time

def show_webcam(mirror=False):

    cam = cv2.VideoCapture(0)
    while True:
        ret_val, image = cam.read()
        if mirror: 
            image = cv2.flip(image, 1)

        image = Zoom(image,2)

        #load cascade files
        bear_cascade = cv2.CascadeClassifier('/home/ubuntu/sample/vec/cascade.xml')

        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY )

        bears = bear_cascade.detectMultiScale(gray, 1.1 , 4)
        for (x,y,w,h) in bears:
            cv2.rectangle(image, (x,y), (x+w, y+h), (12,150,100),2)

        cv2.imshow('Now detecting...', image)

        k = cv2.waitKey(1)
        if k == 27: 
            break  # esc to quit
        elif k == ord('q'):
            break  # 'q' to quit

    cv2.destroyAllWindows()


def Zoom(cv2Object, zoomSize):
    cv2Object = imutils.resize(cv2Object, width=(zoomSize * cv2Object.shape[1]))
    center = (int(cv2Object.shape[0]/2), int(cv2Object.shape[1]/2))
    cropScale = (int(center[0]/zoomSize), int(center[1]/zoomSize))
    cv2Object = cv2Object[cropScale[0]:(center[0] + cropScale[0]), cropScale[1]:(center[1] + cropScale[1])]
    return cv2Object


def main():
    #show_webcam(mirror=True)
    show_webcam(mirror=False)


if __name__ == '__main__':
    main()

ライブカメラで実験

クマさん、分身の術をつかってます。そこかしこが、クマさん認定されています。学習失敗です。

学習するとき、もっと丁寧に教えてあげないと、正しく囲えないみたいデス。

まとめ

ありきたりですが、学習データをどうつくるか、どう学習させるか、キーですね。学習させるにも時間がかかりますし、その結果、失敗というのも、残念。

データはあるので、もう少し工夫して、再挑戦します。

おしまい