PythonとOpenCVを使って物体検出をやってみた

# はじめに
こちらで顔の検出と抽出を行いましたが、あまり何も考えることなくコピペで実現できたのと、
今度は顔以外の物体の検出をやってみたくなったので、色々知識がないながらも見よう見まねで作ってみました。

[TensorFlowを使ってDir en greyの顔分類器を作ってみた - ④顔抽出編](http://qiita.com/neriai/items/cedc0de9e3722f53287a)

# 参考
[opencv チュートリアル チャレンジ９ OpenCVにおける輪郭(領域)](http://pongsuke.hatenadiary.jp/entry/2017/05/19/171130)

# 環境
こちらをご覧ください。

[TensorFlowを使ってDir en greyの顔分類器を作ってみた - ②環境構築編](http://qiita.com/neriai/items/c0114af9c2eae627b6ce)

# 使用する画像
あぽーです。

![1401205top.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/0289e3ab-0064-5b36-7dd9-f19df1785243.jpeg)

# 結果
以下の３つが検出されます。

<img width="422" alt="スクリーンショット 2017-06-01 9.48.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/137d45d2-b193-71a8-01f4-ff88a62a851c.png">

以下の３つの矩形画像が出力されます。

![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/af2199cd-740c-a3b7-53c8-f3f32301f2a4.jpeg)

![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/4fd92240-7a01-c604-dc55-9ca315dbf942.jpeg)

![0.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/905e5cbc-3476-9272-85fd-725e77829cb0.jpeg)

# ソースコード
```py:contour_detect.py
#!/usr/local/bin/python
#! -*- coding: utf-8 -*-

import cv2
import numpy as np

# 指定した画像(path)の物体を検出し、外接矩形の画像を出力します
def detect_contour(path):

  # 画像を読込
  src = cv2.imread(path, cv2.IMREAD_COLOR)

  # グレースケール画像へ変換
  gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)

  # 2値化
  retval, bw = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

  # 輪郭を抽出
  #   contours : [領域][Point No][0][x=0, y=1]
  #   cv2.CHAIN_APPROX_NONE: 中間点も保持する
  #   cv2.CHAIN_APPROX_SIMPLE: 中間点は保持しない
  contours, hierarchy = cv2.findContours(bw, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

  # 矩形検出された数（デフォルトで0を指定）
  detect_count = 0

  # 各輪郭に対する処理
  for i in range(0, len(contours)):

    # 輪郭の領域を計算
    area = cv2.contourArea(contours[i])

    # ノイズ（小さすぎる領域）と全体の輪郭（大きすぎる領域）を除外
    if area < 1e2 or 1e5 < area:
      continue

    # 外接矩形
    if len(contours[i]) > 0:
      rect = contours[i]
      x, y, w, h = cv2.boundingRect(rect)
      cv2.rectangle(src, (x, y), (x + w, y + h), (0, 255, 0), 2)

      # 外接矩形毎に画像を保存
      cv2.imwrite('{ファイルパス}' + str(detect_count) + '.jpg', src[y:y + h, x:x + w])

      detect_count = detect_count + 1

  # 外接矩形された画像を表示
  cv2.imshow('output', src)
  cv2.waitKey(0)

  # 終了処理
  cv2.destroyAllWindows()

if __name__ == '__main__':
  detect_contour('｛ファイルパス｝/{ファイル名}.jpg')
```

# ほかに試して上手くいかなかったもの

<img width="601" alt="スクリーンショット 2017-06-01 9.45.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/62f84b6c-9b7c-f7b7-081b-8efa4d737680.png">

<img width="480" alt="スクリーンショット 2017-06-01 9.50.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/258bdbd2-471c-4b4d-027c-b580f114f4fa.png">

# まとめ

- 矩形を「タンケイ」ではなく、「クケイ」と読むこと。
- 複数の物体が複数すぎると抽出の限界がでてくる（？）。
- 切り取る際に重なっている輪郭線消せないのだろうか...。

# 次のステップ

- 輪郭線消す方法を調べる。
- もう少し検出精度を上げる計算式を調べる。
- 物体をTensorFlowにかけて学習させてみる。

# 全ページリンク
- [PythonとOpenCVを使って物体検出をやってみた](http://qiita.com/neriai/items/448a36992e308f4cabe2)
- [ステーキ定食の画像から物体を選別できないかやってみた - ①物体検出編](http://qiita.com/neriai/items/d420b78f35033408ccda)
- [ステーキ定食の画像から物体を選別できないかやってみた - ②オーバーラップ数選別編](http://qiita.com/neriai/items/e718290e8b14b0594008)
- [ステーキ定食の画像から物体を選別できないかやってみた - ③類似画像ヒートマップ検出編](http://qiita.com/neriai/items/615c9233582a91a1396a)
- [ステーキ定食の画像から物体を選別できないかやってみた - ④クラスタリング編](http://qiita.com/neriai/items/6df233918513a51a7147)
- [ステーキ定食の画像から物体を選別できないかやってみた - ⑤類似画像特徴点検出編](http://qiita.com/neriai/items/e96d70fc3b89f050daa5)