Azure Percept DKで簡単インフラ点検！その１

Azure Percept DKが手に入ったのでEdge AIを体験してみようじゃないかと色々遊んでみました
公式チュートリアルを読めば簡単にAIモデルを作れて試すことができましたが、実際にすぐ仕事で使えるかと言われるともう一工夫自分で作りこむ必要があるかなと感じました

本記事では実際に検証で使うことを考慮し、カスタムモデルで認識した結果を元にさらに画像解析に繋げることをゴールとします

# Azure Perceptとは何か？
Azure Perceptとは何か？については@matsujirushiさんのわかりやすい記事があったので以下を参照
https://qiita.com/matsujirushi/items/407e21a42da561773469
公式のドキュメントもしっかり揃っています
https://docs.microsoft.com/ja-jp/azure/azure-percept/

# 目的

私自身の解釈ではAzure Percept DKは
**AI（特に物体認識）に関する技術検証を素早く実装するツールくん**
です

ただ、実際にチュートリアルでフォローされているのはカスタムモデルを作成までなので、認識した後どうするのかの検証を進めれないなと思いました
例えば、インフラ点検で物体認識を使う検証の場合、対象物を検出した後には対象物の状態の評価が入ってきます
そのため、物体認識だけではシステム全体の検証を進めることができません
AIの結果を何かに繋げる必要があります
そこで本記事ではカスタムモデルで認識した結果を元にさらに画像解析に繋げていきたいと思います

# 何をやるか
家に点検したいインフラ設備がなかったのでゴルフクラブの構えた角度を検出していきたいと思います
本当は計器みたいなものがあれば良かったですが我が家には時計すらなかったことを忘れてました
1. Azure Percept DKでクラブの画像位置を取得
2. 自前の画像処理プログラムでクラブの角度を算出

# まずは物体認識のカスタムモデルの作成
こんな感じで17枚のゴルフクラブの写真を用意しました
![スクリーンショット 2021-12-05 21.11.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478741/4b8082ba-ed64-22ea-4407-d26ebdac2609.png)
アノテーションはこんな範囲で適当に
<img width=600 alt="スクリーンショット 2021-12-05 21.08.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478741/b2daee4a-ed63-17fd-9d24-e6e2ecd1f53b.png">
学習した結果はPrecision, Recall, mAP全て100%となりました
題材が簡単だから当たり前か...
<img width=600 alt="スクリーンショット 2021-12-05 21.28.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478741/97c6f948-e0ce-a2fe-5017-7ce2044f6315.png">

# 推論した結果
Azure Percept DKのネットワーク内であれば推論結果は<http://10.1.1.1:3000>から見ることができます.
大体いい感じですがアノテーションはグリップとヘッドまで覆ってた気が...
データ不足でしょうか
<img width=600 alt="スクリーンショット 2021-12-05 22.27.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478741/3c8b4948-68af-bc31-bb2d-622047c4c71c.png">

# 結果の受け渡し（画像）
次に推論結果（検出位置）と画像の受け渡しについて考えます.
以下はAzure Percept DKのアーキテクチャです.
<img width=800 alt="archi.png" src="https://docs.microsoft.com/ja-jp/azure/azure-percept/media/azureeyemodule-overview/azureeyemodule-architecture.png">
https://docs.microsoft.com/ja-jp/azure/azure-percept/azureeyemodule-overview

まずは画像の受け渡しについてです.
画像はRTSPで8554ポートで受信可能であるため、OpenCVでVideoCaptureすれば解決！と思いきや、
```
[rtsp @ 0x7f9403135a00] method SETUP failed: 461 Unsupported transport
OpenCV: Couldn't read video stream from file "rtsp://10.1.1.1:8554/result"
[ERROR:0] global /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/pip-req-build-tetsazc6/opencv/modules/videoio/src/cap.cpp (162) open VIDEOIO(CV_IMAGES): raised OpenCV exception:
```
とエラーが出てしまいました...（原因はまた調査します）
そのため、今回は３000ポートから閲覧可能なHTMLの動画ストリーム部分のみを抜き取るという荒技で画像の取得を実現します
開発者ツールを使って動画ストリーム部分はid="player0"ということがわかったので以下の実装で抜き取りをします

```python
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import base64

import cv2
import chromedriver_binary
import numpy as np

URL = "http://10.1.1.1:3000"

driver = webdriver.Chrome('chromedriver')
driver.get(URL)

selector = 'body'
WebDriverWait(driver, 30).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, selector))
)

while 1:
    canvas_first = driver.find_element(By.ID,"player0")
    dataURLs = driver.execute_script("return arguments[0].toDataURL('image/png').substring(21);",
                                                canvas_first)
    img_b64 = base64.b64decode(dataURLs)
    img_np = np.frombuffer(img_b64,dtype=np.uint8)
    img = cv2.imdecode(img_np, cv2.IMREAD_COLOR)

    cv2.imshow("image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
```

無事に画像のみを抽出することができました！
<img width=800 alt="スクリーンショット 2021-12-05 23.36.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478741/04597fc8-71af-5d27-49d9-49d418d657e7.png">
後は検出位置を取得できれば、クラブの色から傾き方向を出して角度を出せるはずです.
今回に限れば赤色の枠線取り出せばいいじゃんという話もありますが、検出対象を増やすと検出結果の色が必ずしも赤色になるとも限らないので、
やはりモデルの検出結果を取得する方法を考えたいです.

本日は疲れたので続きはまた後日書きます.