Google Colabratoryでネコ検出器を作る（後編）【Python】〜OpenCVを使う〜

#はじめに
この記事は私がある企業が主催した画像系のハッカソンに参加した時に使った「顔認識」の技術を応用してネコの画像で学習させることで「ネコ検出器」を作りました。記録として残すためQiitaにまとめています。
全編は12/14に投稿しました。『[Google Colabratoryでネコ検出器を作る（前編）【Python】〜スクレイピングについて〜](https://qiita.com/konan/items/320dd0ecfe03246b4f5d)』こちらの記事では主に前処理で使った技術である「スクレイピング」についてまとめています。この記事が初めてご覧になる方は先に前編からみることでより知識が深められておすすめです！！(20201216-3)

#OpenCVとは
OpenCVとは略語で正式名称は"Open Source Computer Vision Library"と呼ばれています。つまりコンピュータで画像や動画を処理する時に必要な様々な機能が実装されており、目的が趣味でも商用でも学術でも利用できるライブラリになっています。(もっと詳しく:[第1回　OpenCVとは？ 最新3.0の新機能概要とモジュール構成 (1/2)](https://www.atmarkit.co.jp/ait/articles/1507/27/news154.html))

#早速OpenCVを使ってみよう！
全編で使ったGoogleColabを用意します。前編でスクレイピングした方は、「ねこ」の画像をzip形式でPCにダウンロードできたているかと思います。できていない方は[前編](https://qiita.com/konan/items/320dd0ecfe03246b4f5d)をみてスクレイピングしていただくか使いたいネコの画像を自分で取得していただくか本記事下部に今回用いたネコの画像を掲載しておいておきますのでそちらをダウンロードしてお使いください！

Google Colaboratoryを新規で開いてください。開き方は前回示した通りです。
>1)Googleドライブにアクセスする
2)右クリックを押し「その他」をクリック
3)Google Colaboratryをクリックしたら立ち上がります。

コードを書く準備が整いました。

#必要なファイルをダウンロードする。
今回はcascadeファイルというものを使います。このcascadeファイルも自作することができ試しに自作してみましたがこの作り方については後日作り方メインで投稿させていただきます。お待ちください。

今回は下のファイルの中にある`cascade.xml`が必要なのでそちらをダウンロードしてお使いください。また今回使用したネコの画像もこのファイルの中に入れていますのでネコの画像が手元になかったり私の結果を再現してみたい方は適宜画像をダウンロードしてお使いください。
[こちらからダウンロード](https://drive.google.com/drive/folders/1PiMM-8qG-zTHegX-QIVTYSQ1l7brgNIw?usp=sharing)

#プログラム
###1)画像をGCで使うため読み込み

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/dd98f635-c84b-caf8-b996-25717e83b36b.png" width=60%>
こちらの左のアイコンをクリックして画像を読み込みます。(下の画像です。)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/abba6354-ca55-1045-c589-fc69b55dcad0.png" width=20%>!

画像を読み込むと読み込んだ画像の名前が左に並んで表示されていたら成功です。次のステップに進みます。

###2)cascade.xmlを読み込み
cascade.xmlも同じ要領で読み込みます。`2)`で読み込んだ画像と同じように左に表示されたら準備完了です。

###3)必要なモジュールをインストールする
前回と同じように今回必要なモジュールを紹介します。

```python
#必要なモジュールを読み込み
import sys
import cv2 as cv # opencvの読み込み
```
>前回と同じようにエラーがでた場合は`!pip install モジュール名(importの次の単語)`でインストールしてください。

###4)ネコ検出器の関数を作成する
いよいよ学習器の生成です。やっと機械学習っぽいことを行います！！
プログラムは以下になります。

```python
def detect(imagefilename, cascadefilename):
    srcimg = cv2.imread(imagefilename) #イメージファイルを読み込む
    if srcimg is None:
        print('画像がロードできません')
        sys.exit(-1)
    dstimg = srcimg.copy()
    cascade = cv2.CascadeClassifier(cascadefilename) #カスケードファイルを読み込む
    if cascade.empty():
        print('カスケードファイルをロードできません')
        sys.exit(-1)
    objects = cascade.detectMultiScale(srcimg, 1.1, 3)
    for (x, y, w, h) in objects:
        print(x, y, w, h)
        cv2.rectangle(dstimg, (x, y), (x + w, y + h), (0, 0, 255), 2)
    return dstimg

if __name__ == '__main__':  
    result = detect('画像_cat.jpg', 'cascade.xml')
    cv2.imwrite('result.jpg', result)

    result2 = detect('画像_cat2.jpg', 'cascade.xml')
    cv2.imwrite('result2.jpg', result2)

    result3 = detect('画像_cat3.jpg', 'cascade.xml')
    cv2.imwrite('result3.jpg', result3)
    
    #上記のように読み込んだ画像ファイルの名前を入れていきます。
```
プログラムの全体です。与えられた画像の中でネコを見つけてネコに<font color="Red">□</font>を埋め込みます。
では結果をみていきましょう！

#結果
###うまくいっている例
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/45f7b349-78f9-3585-4d37-6ee00ccbdc2f.jpeg" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/6f2fc756-a0fa-4fe6-0e15-03dbe8704f61.jpeg" width = 45%>

ど正面ピントあってるネコは精度良いですね！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/2e051a22-3d71-4c4a-525e-b368c14bf597.jpeg" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/d7885ca7-5eff-f1a3-b2e8-eaed4cb95ea4.jpeg" width = 45%>
こちら向いてる複数匹のネコも精度よくうまくいっています！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/0f324015-a21c-4989-30f9-322ec79a4d6c.jpeg" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/48b61004-ef91-da39-aec2-03fcd1327f75.jpeg" width = 45%>
こちらの画像は上の画像と少し違って顔のあたりがカゲになっていますがしっかりと検出できています！


###うまくいかなかった例
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/90fc8eff-5b5f-0b2e-874a-4ff3552cc1bf.jpeg" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/90fc8eff-5b5f-0b2e-874a-4ff3552cc1bf.jpeg" width = 45%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/c30629db-09b1-ff77-2623-9f90dd09d459.jpeg" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/c30629db-09b1-ff77-2623-9f90dd09d459.jpeg" width = 45%>
上記2つの画像を見ると正面向いていないと反応してくれないそうです。。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/01fab658-3400-6eba-2aa4-d3b8e8711676.jpeg" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/ef2eba5c-6aba-a5b0-ad76-d1c5a44fc88b.jpeg" width = 45%>

寝ているネコは精度が悪かったです。(目で検出しているのかも？)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/1d2b6bdb-93ee-0357-d459-cc3c24b1e7c1.jpeg" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/31b88577-3a39-abaf-e633-6015160af199.jpeg" width = 45%>

2匹しかいないのに3匹判定してしまっています。。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/827be5e2-c671-d25c-1ba5-11f9a98eeaa9.jpeg" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/c27db806-a92f-69e1-23a2-a5541273559f.jpeg" width = 45%>
画像が暗いと検出精度悪かったです。。

###番外編
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/2a9227e1-19eb-9644-165a-20fd9634537e.jpeg" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328847/2a9227e1-19eb-9644-165a-20fd9634537e.jpeg" width = 45%>
ネコのみ学習データに入れていないのですが、ネコはネコでもキーホルダーのようなもので反応するか番外編でしてみました。反応してくれませんでした。

このようにまだ精度が悪くとてもネコ検出器としてはまだまだ未熟だと思いますが一応ネコは検出できました。簡単ですので色々試してみてください！！

#考察・展望
正しく検出できた画像と検出できなかった画像を見比べて見ると大きな違いとして「目」がしっかりと分かるかどうかがキーになっているようだと思いました。私が参加したハッカソンでも痛感したことですが「顔認証」において「目」はとても重要な要素だと私は痛感しました。ですので「顔認証」は至近距離の画像においてはとても精度良く反応すると思っています。

離れた距離で認識させるためには「全身認証」が必要だと私は思っています。参加したハッカソンでも「顔認証」「全身認証」「骨格認証」の3つを作り精度比較して同じような結論になってネコのような動物でも同じような結論に至りました。

今後の展望としては、cascade.xmlに含めた画像をもっと増やしたり全身に変更したり一部分写っているものを含めてみたり色々なバリエーションの画像を含めることで少しは頭のいい検出器になるかと思います。時間があればやってみようと思います。

ここまで読んでいただきありがとうございます。フォロー・LGTMよろしくお願いいたします！！
またご指摘・アドバイス・質問いつでも受け付けております。私もまだ勉強しているのでとても助かります！

========================================
今まで投稿した記事もしよければ読んでみてください
[画像系]
[ねこ検出器(前編)](https://qiita.com/konan/items/320dd0ecfe03246b4f5d)
[自然言語処理系]
[自然言語処理を用いたデータの分類](https://qiita.com/konan/items/17ccc1c86f76ba925147)

========================================