チャレンジ！画像認識

# 目的

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

# 使うソフトウェアの整理

- 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()

```


# ライブカメラで実験

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213097/763ad33c-44b1-9178-93cb-4039bb8e384c.png)

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


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

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

おしまい