見出し画像

XRealで自転車用物体認識バックモニター兼コンパス兼時計を作ってみる

AIとXRと自転車で何かできないかというのは実はずっと前から思っていた。

そしてXReal Airがバージョンアップするというので買いましたよ。
これのすごいところは、USB-Cが刺されば画面がなんでも出せるということ。

そこで昔買ったもののあまり使ってなかった余ったAndroid端末にお手軽にブラウザだけでカメラ画像を表示して自転車のシートポストに後ろ向きにつける運用を考えた。

とりあえずAIは後で考えるとして、カメラを表示して時計と方位磁針を表示する。

雑すぎるWebアプリ

まあアプリと呼ぶのも少し申し訳ない気がするが。
これをGalaxyNote9で読ませてダークモードにするとちょうどいい感じになる。

で、まあせっかくだからAIも入れてみるか。
PyScriptを使うとブラウザ上でPythonが動くようになる。
これを使って物体認識を行う。GalaxyNote9は二世代前くらいのスマホだが動くだろう。

動いた

YOLOv8をブラウザで動かしていた人が居たのでそのコードを改変してカメラからの入力をキックするようにする。

PyScriptの情報が案外少なくてどうすればJavaScriptからPyScriptにデータを受け渡せるのかよくわかんなかったので、Canvas経由で情報を渡すことにする。更新のキックはEventを発行して行った。

PyScript側のイベントハンドラをこうしておいて

async def detect_from_canvas(dataURL: str):
        global img
        canvas = document.getElementById("canvasOutput")
        dataURL=canvas.toDataURL("image/jpeg"); 

        binary_data = base64.b64decode(dataURL.split(",")[1])
        img_data = np.frombuffer(binary_data, np.uint8)
        img = cv2.imdecode(img_data, cv2.IMREAD_COLOR)
        print('loaded image')
        await detect(img)

 document.getElementById("data").addEventListener('change',create_proxy(detect_from_canvas))

JavaScript側からはdataというIDのDOMエレメントにchangeイベントを発行して呼び出す。

            framecnt++;
            if(framecnt%10==0){
              var data = document.getElementById("data")
              //console.log(src)
              let e = new Event('change');

              data.dispatchEvent(e);
            }

毎フレームは無茶なので10フレームおきにキックするようにした。
スマホだとこんな感じで動く。
iPad/iPhoneでも動作確認した。

まあでもこんなにタイムラグがあると自転車のバックミラー用途としてはむしろ危険だな。普通にCoreMLとかで書けば物体認識はもっとずっと高速なのでブラウザで作るなどと手を抜かずにネイティブで書くべきだろうな。でも、バックミラーにiPhone使うってのがそもそも贅沢すぎるのではないか(今更?)