python,OpenCVでハムスター(キンクマ)と床材を見分けたい

# はじめに
キンクマハムスターと床材の色が似すぎているのでなんとかして切り分けたいと思います。

# 環境
windows10
python3.9.4
opencv-python 4.5.5.62
numpy 1.20.2

# HSVで色抽出してみる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/3fce22af-35d9-a4d1-8de0-14656d429d39.jpeg" width="30%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/ab91160b-9d1c-d387-11dd-9f39428168b0.jpeg" width="30%">

とりあえず我が家のハムスターを適当に画像処理します。
ここではOpenCVを使いました。

## 詳細
### インポート
```python
import numpy as np
import cv2

```
ライブラリのインポートをします。
### 画像読み込み
```python
# ファイル読み込み
    filename = 'あなたのハムスター.jpg'
    imageOriginal = cv2.imread(filename)


    # リサイズ 
    imageResize = scaleToWidth(imageOriginal, 500)

```

```python

# 横幅を基準に画像をリサイズ　アスペクト比はかわらない
def scaleToWidth(img, width):
    h, w = img.shape[:2]
    height = round(h*(width/w))
    dst = cv2.resize(img, dsize=(width, height))

    return dst

```
画像を読み込みます。ついでにリサイズもしておきます。

### 色の抽出
```python

    # ぼかし
    imageBlur = cv2.GaussianBlur(imageResize, (15, 15), 3)


    #ハムスター色のマスクを作る
    hsvLower = np.array([0/2, 0*2.55, 0*2.55])  # 抽出色の下限
    hsvUpper = np.array([80/2, 50*2.55, 100*2.55])  # 抽出色の上限

    #imageBlurを対象に色抽出
    hamster = hsvExtraction(imageBlur, hsvLower, hsvUpper)

```

```python
# HSVで特定の色を抽出する関数
def hsvExtraction(image, hsvLower, hsvUpper):
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)  # 画像をHSVに変換
    hsv_mask = cv2.inRange(hsv, hsvLower, hsvUpper)    # HSVからマスクを作成
    result = cv2.bitwise_and(image, image, mask=hsv_mask)  # 元画像とマスクを合成
    return result

```

画像をぼかした後、ハムスターっぽい色のみを抽出します。
### 抽出されたハムスター達
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/923290bf-9e4f-e12c-9425-681d9eb70ae6.jpeg" width="30%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/ab91160b-9d1c-d387-11dd-9f39428168b0.jpeg" width="30%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/23918987-5d31-55eb-b7b0-d78a272ade36.jpeg" width="30%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/3fce22af-35d9-a4d1-8de0-14656d429d39.jpeg" width="30%">



抽出されたハムスタ―達がこちらです。
適当にクリーム色で抽出したのハムスターの耳が消えてしまいました。
よくみると目も消えて~~ドキドキ文芸部のようになってしまって~~います。


## ネガポジ反転して二値化してみる
### ネガ画像にする
```python
imageNega = cv2.bitwise_not(hamster)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/c30faaec-a709-b8dc-463b-e89203661fd4.jpeg" width="30%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/3402c944-20bd-60a5-b3dc-7065e386f10d.jpeg" width="30%">
ネガ画像になりました。


### グレースケールにして二値化する
```python
    imageGray=cv2.cvtColor(imageNega,cv2.COLOR_BGR2GRAY)
    ret,imageBinary=cv2.threshold(imageGray,90,255,cv2.THRESH_BINARY)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/6e0fba05-88df-e20e-93c1-d293715138fa.jpeg" width="30%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/abf54435-7114-c49b-c18b-ed46c70ebf0c.jpeg" width="30%">
一度グレースケールにした後二値化したものがこちらです。
なんだか<font color="dcdcdc">**ハムスターの概念**</font>的な物が見えてきました。

## 輪郭を検出する
```python
    contours, hierarchy = cv2.findContours(
        imageBinary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    img_contour = cv2.drawContours(imageResize, contours, -1, (0, 0, 255), 2)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/95d15c34-dd1d-5599-47b9-286e1496d8f0.jpeg" width="30%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/cc63a97b-c4bc-4b3b-10d8-39162f25d32b.jpeg" width="30%">
寝ているハムスターはギリギリ検出できていると言えそうな輪郭ですが、起きているハムスターの輪郭はかなりボロボロです。
背景の棚がかなり悪さをしている感じがします。

# 結果
床材とハムスターの境界をうまく生成できませんでした。
先に黒目や赤い鼻を色抽出して、その周辺を再びハムスター色で抽出するなど、もう一工程挟む必要がありそうです。

## 参考記事
[Python, OpenCVで輪郭検出をしてみる](https://qiita.com/applepieqiita/items/3fd557c4ebaf8ca542d6)