OpenCVでドロップ認識 -課題2-

#前書き
OpenCVの開発環境は作ったので、実際になにか動かしてみます。
今回はOpenCV-Pythonのチュートリアル、[OpenCV-Python Tutorials](https://opencv-python-tutroals.readthedocs.io/en/latest/)の**[日本語版](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/index.html)**をやっていきます。
多少アレンジすると思う。

物体認識をやっていきたいので、とりあえず簡単なところから練習していきます。
今回は「丸ドロップが別物として認識する(5パターン:6×5盤面)」をやっていきます。

# シリーズ
* [pythonでOpenCV使うための環境づくり](https://qiita.com/Ryo87/items/939b370c06c60c9d63c8)
* [OpenCVのチュートリアルをやる](https://qiita.com/Ryo87/items/c20be948d261f1be2f22)
* [OpenCVのチュートリアルをやる -その2 変換系-](https://qiita.com/Ryo87/items/6f367bf1eb69c4f3c80e)
* [OpenCVのチュートリアルをやる -その3 -](https://qiita.com/Ryo87/items/0ffc633fb918cb704566)

#開発環境
機種名 : MacBook Pro
OS : Mojave 10.14.2
プロセッサ名 : Intel Core i5 2.6 GHz
メモリ : 16 GB
グラフィック : Intel Iris 1536MB

## python系
```
% pip freeze
numpy==1.15.4
opencv-python==4.0.0.21
```

## 画像データ
今回はこの画像を使っていきます。

<img width="375" alt="IMG_0451.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/35860/44c1a394-7fa2-dc06-0885-d9c3ee9ad7c6.png">

#本題
画面下部のそれぞれのドロップを認識することを目標とします。
5色を別物として認識したい。

## 課題
1. 丸ドロップと四角ドロップを別物として認識する(2パターン:6×5盤面)
2. 丸ドロップが別物として認識する(5パターン:6×5盤面):今回やるやつ
3. 5×4盤面、6×5盤面、7×6盤面で認識する(2019/02/03 追記:しばらく手をつけられないかも)

## 丸ドロップが別物として認識する(5パターン:6×5盤面)
[Watershedアルゴリズムを使った画像の領域分割](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_watershed/py_watershed.html#watershed)このあたりのやり方を参考になにかできるんじゃないかと思っているんだけど、、、、。

```sample.py
    img = cv2.imread('6_5.PNG')
    img = getBoard(img)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    cv2.imshow('thresh', thresh)
    cv2.imwrite('thresh.png', thresh)

    # ノイズ除去
    kernel = np.ones((3, 3), np.uint8)
    opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
    cv2.imshow('opening', opening)
    cv2.imwrite('opening.png', opening)

    # 背景 確信領域
    sure_bg = cv2.dilate(opening, kernel, iterations=3)
    cv2.imshow('sure_bg', sure_bg)
    cv2.imwrite('sure_bg.png', sure_bg)

    # 前景 確信領域
    dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
    ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
    cv2.imshow('sure_fg', sure_fg)
    cv2.imwrite('sure_fg.png', sure_fg)

    # 未知の領域
    sure_fg = np.uint8(sure_fg)
    unknown = cv2.subtract(sure_bg, sure_fg)
    cv2.imshow('unknown', unknown)
    cv2.imwrite('unknown.png', unknown)

    cv2.waitKey(0)
    cv2.destroyAllWindows()
```

**大津の二値化**
![thresh.png](https://qiita-image-store.s3.amazonaws.com/0/35860/3541bb68-91cf-7efe-41d2-38f7bea8c80a.png)

**ノイズ除去後**
![opening.png](https://qiita-image-store.s3.amazonaws.com/0/35860/6385e7db-c70d-cdd0-aeda-436e951b33bc.png)

**背景 確信領域**
![sure_bg.png](https://qiita-image-store.s3.amazonaws.com/0/35860/e85abf5b-e534-eccc-7d65-91d37989f404.png)

**前面 確信領域**
![sure_fg.png](https://qiita-image-store.s3.amazonaws.com/0/35860/63c9498c-884d-634e-a73c-ac98b90d7c90.png)

**未知領域**
![unknown.png](https://qiita-image-store.s3.amazonaws.com/0/35860/cf100c92-8ce9-a4c1-20bb-46dd0175a662.png)

んーなかなか思ったように行きません。

## 色狙い撃ちで取り出してみる
[「pythonで赤い物体を認識しよう」](https://qiita.com/odaman68000/items/ae28cf7bdaf4fa13a65b)を参考に、特定色だけ狙い撃ちでピックアップしてみる。

1. 特定色をピックアップ
2. その色だけうまく輪郭抽出
3. [前回](https://qiita.com/Ryo87/items/8b4e369d598222e9d719)の手法で、特定色のドロップに縁つけて特定してみる。

### 特定色をピックアップしてみる
![red.png](https://qiita-image-store.s3.amazonaws.com/0/35860/dd486d05-0323-7bfd-81b4-d135ddc5b99e.png)

赤ドロップ結構大きく捉えてくれてるけど、背景色だったり、回復ドロップだったりにも反応していまいちうまく取り出せてない。

### 輪郭抽出、特定
```sample.py
    img = cv2.imread('6_5.PNG')
    img = getBoard(img)
    # 円形取得
    circles = houghCircles(img)
    # 矩形取得
    rects = find_rect_of_target_color(img)

    for i in circles[0, :]:
        for rect in rects:
            # cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness=2)
            # cv2.circle(img, (i[0], i[1]), 2, (0, 255, 0), -1)

            x1, y1 = tuple(rect[0:2])
            x2, y2 = tuple(rect[0:2] + rect[2:4])
            polygon = np.array([[x1, y1], [x1, y2], [x2, y1], [x2, y2]])
            # 矩形の内側に円の中心点が含まれている場合
            if cv2.pointPolygonTest(polygon, (i[0], i[1]), False) >= 0:
                cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2)
                cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), thickness=2)
                print((i[0], i[1]), (x1, y1), (x2, y2))

    cv2.imshow('red', img)
    cv2.imwrite('red.png', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
```

![red.png](https://qiita-image-store.s3.amazonaws.com/0/35860/0432e69f-f24a-67c8-3d82-275387edd2b9.png)

紫が取れてる。ただ、全部の紫が取得されているわけではないのよね。
難しい。
あとは、色指定がうまく行けば対象の特定ができそう。

### 後日やりますーー
多分、色相をいい感じに定義してあげればうまくいくと思うので時間あるときにまた調整します。

#感想
なかなか画像処理は、奥が深く思ったように欲しいデータ取ることができないな。
もう少しやってればなれてきてイメージ通りに切り抜いたり、複雑な形扱ったりもできるかな。