クラッシュオブクラウンと画像解析(2)

# やりたいこと
前回の画像解析の続きです．
前回：[クラッシュオブクラウンと画像解析(1)]
(https://qiita.com/__Bert__/items/4336f92823201c6848b2)

前回はスクリーンショットした画像の配置を正方形に変形し，必要な配置の部分だけの情報を抽出しました．今回はその画像から施設（施設の種類の分別は問わない）が位置しているマス目の情報を取り出そうと思います．

# 1.入力画像
前回は以下のような画像を得ることができました．
![GAKU2020_cut.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/949600/78fc9fae-097e-cd04-542d-0cd5f2965395.png)
この画像からどこのマスに施設があるか判断するのは難しそう…
どうしようか考えたのですが，クラクラには壁だけ表示させることのできる機能があります．
写真でいうとこんな感じ
![GAKU2020_wall.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/949600/56ff2a30-1477-7159-2196-3828c9416d1f.jpeg)
この写真をよく見ると，施設の位置している部分は濃い緑色になっていることがわかります．
この部分を認識できればいいのではと思ったので，今回は下のような画像を入力画像とします．
![GAKU2020_wall_cut.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/949600/cbec3dc2-083c-c7c6-1c99-b2d63c2a3f2e.png)

# 2.施設部分の検出
濃い緑の部分を検出します．
コードは以下の通りです．

```
import numpy as np
import matplotlib.pyplot as plt
import cv2


def main():
    # 入力画像の読み込み
    pictrue = 'reformat_pic/GAKU2020_wall_cut.png'
    img = cv2.imread(pictrue, cv2.IMREAD_COLOR)

    # 高さ，幅の取得
    height, width = img.shape[:2]
    img_resize = cv2.resize(img, 
                            dsize=(440, 440),
                            interpolation=cv2.INTER_LINEAR)

    # 濃い緑の抽出
    green_mask, green_masked_img = detect_darkgreen_color(img_resize)
    cv2.imwrite("./locate_facility_pic/GAKU2020_facilitylocate_original.png", green_mask)    


def detect_darkgreen_color(img):
    # HSV色空間に変換
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    # 緑色のHSVの値域1
    hsv_min = np.array([28, 64, 110])
    hsv_max = np.array([70,150,180])

    # 緑色領域のマスク（255：赤色、0：赤色以外）    
    mask = cv2.inRange(hsv, hsv_min, hsv_max)
    
    # マスキング処理
    masked_img = cv2.bitwise_and(img, img, mask=mask)

    return mask, masked_img

```
これを実行すると以下の画像が得られました．
白く表示されている部分が施設の位置を表しています．
若干ノイズが気になりますが，まあまあいい感じに検出できています．
![GAKU2020_facilitylocate_original.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/949600/eeb92f03-6559-b92f-c597-062dd18fc6a5.png)

# 3.施設の位置検出
先程の処理で施設の大まかな位置を把握することができました．
ここではマス目のどこに配置しているか検出できるようにします．
配置のマス目は$44 \times 44$とわかっているため，まず画像サイズを$440 \times 440$に変更し，$1$マスが$10\times10$ピクセルとなるようにします．その後，$1$マスごとに白か黒かどちらか多いか数え，白が多ければ$1$，黒が多ければ$0$を返すようにします．このときノイズの影響を抑えるために調査領域はマス目の内部のみで行います．このようにすることで，施設があると判断された部分とそうでない部分を分けます．コードは以下の通りです．

```
def main():
    # 入力画像の読み込み
    pictrue = 'reformat_pic/GAKU2020_wall_cut.png'
    img = cv2.imread(pictrue, cv2.IMREAD_COLOR)

    # 高さ，幅の取得
    height, width = img.shape[:2]
    img_resize = cv2.resize(img, 
                            dsize=(440, 440),
                            interpolation=cv2.INTER_LINEAR)

    # 濃い緑の抽出
    green_mask, green_masked_img = detect_darkgreen_color(img_resize)
    cv2.imwrite("./locate_facility_pic/GAKU2020_facilitylocate_original.png", green_mask)    

    # 施設の検出
    mask = facility_mask(green_mask)

    # 図の表示
    draw_map(mask)


def facility_mask(img):
    # 1マスのサイズ
    h_size, w_size = 10, 10

    # 全てのマスの情報を記憶
    mask = []
    for h in range(44):
        for w in range(44):
            w2 = w * w_size
            h2 = h * h_size
            c = img[h2 : h2+h_size, w2 : w2+w_size]

　　　　　　　# 画像のズレ，ノイズの影響の低減

            c = c[2:-3, 2:-3]

            if np.mean(c) > 127:
                mask.append(1)
            else:
                mask.append(0)

    mask = np.array(mask)
    mask = mask.reshape([44, 44])
    return mask
```
得られた画像はこちらです．色が反転していますが，黒色の部分が施設の位置を表しています．入力画像と比較すると，欲しい部分の色がしっかり黒くなっていることが分かります．
![GAKU2020_facilitylocate_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/949600/35014d15-5bf1-cfc2-9183-b3b2431ca3f4.png)

# 4.最後に
壁のみの画像から施設の位置を認識することができました．いよいよどの施設がどこにあるか認識できるようにしていきたいと思いますが，次回はそのための定義について考えていきたいと思います．

今回はここまで