Hololens2 Node.JSソケット通信


Hollens 2は統一的に開発できますが、MRTKという特殊なツールパッケージを使用しています.
ただし、MRTK Unityキットを使うと制約が多すぎます.
Azure Nuget pkgをインストールできません(最も奇妙です)、
他の各種pkgは取り付けられません.
インストールがNuget pkgの場合、エラーが発生するか、namespaceが追加されていません.
私はHollens 2を用いてAzureの認知OCR技術をunityに追加し、C#で開発するだけでなく、Azureが提供するpkgは使用できないので、元のアクセスを試してみました.
https://westus.dev.cognitive.microsoft.com/docs/services/computer-vision-v3-2/operations/56f91f2e778daf14a499f20d
参考までに、APIを直接呼び出す操作を行ったところ、APIはUrl画像が読みやすいことを発見したが、実際の画像ファイルをバイナリ画像データとしてAPIを呼び出すと(C#に詳しくないので、私が間違っている可能性が高い)、正常に動作しない.時間がかかる
では、Hollens 2からOCRデータを読み取るのではなく、Hollens 2の写真だけをサーバに持ち込み、サーバ上でJavascriptを用いてAzure Cognitive-OCR技術を用いて画像を解析し、結果をソケット通信でHollens 2に再送信する.
幸いにもHollens 2は写真を撮ると自動的にOneDriveに保存され、OneDrive連動のPCでNode.JSサーバを開き、localhostソケット通信でHollens 2とのデータ交換に成功しました.
次は「マイサーバノード」です.JSコード
const async = require("async");
const fs = require("fs");
const https = require("https");
const path = require("path");
const createReadStream = require("fs").createReadStream;
const sleep = require("util").promisify(setTimeout);
const ComputerVisionClient =
  require("@azure/cognitiveservices-computervision").ComputerVisionClient;
const ApiKeyCredentials = require("@azure/ms-rest-js").ApiKeyCredentials;
const WebSocket = require("ws");

const key = "{cognitive Service Privite-Key}";
const endpoint = "{cognitive Service End-point}";

// <snippet_client>
const computerVisionClient = new ComputerVisionClient(
  new ApiKeyCredentials({ inHeader: { "Ocp-Apim-Subscription-Key": key } }),
  endpoint
);

const dir = "./";

fs.readdir(dir, function (err, filelist) {
  // fs모듈의 readdir함수를 사용해
  // 첫번째 인자로 파일 목록을 읽을 폴더(dir)를 가져오고
  // 콜백함수의 두번째 인자로 폴더(dir)의 파일목록(filelist)을 가져옴

  console.log(filelist[0]);
});

const arrayOcr = [];
// <snippet_functiondef_begin>
function computerVision() {
  async.series(
    [
      async function () {
        const STATUS_SUCCEEDED = "succeeded";
        const STATUS_FAILED = "failed";

        const handwrittenImageLocalPath = "ocr.jpg";

        console.log(
          "\nRead handwritten text from local file...",
          handwrittenImageLocalPath
        );
        const handwritingResult = await readTextFromFile(
          computerVisionClient,
          handwrittenImageLocalPath
        );
        printRecText(handwritingResult);

        // Perform read and await the result from local file
        async function readTextFromFile(client, localImagePath) {
          // To recognize text in a local image, replace client.read() with readTextInStream() as shown:
          let result = await client.readInStream(() =>
            createReadStream(localImagePath)
          );
          // Operation ID is last path segment of operationLocation (a URL)
          let operation = result.operationLocation.split("/").slice(-1)[0];

          // Wait for read recognition to complete
          // result.status is initially undefined, since it's the result of read
          while (result.status !== STATUS_SUCCEEDED) {
            //await sleep(1000);
            result = await client.getReadResult(operation);
          }
          return result.analyzeResult.readResults; // Return the first page of result. Replace [0] with the desired page if this is a multi-page file such as .pdf or .tiff.
        }

        // <snippet_read_print>
        // Prints all text from Read result
        function printRecText(readResults) {
          console.log("Recognized text:");
          for (const page in readResults) {
            if (readResults.length > 1) {
              console.log(`==== Page: ${page}`);
            }
            const result = readResults[page];

            if (result.lines.length) {
              for (const line of result.lines) {
                //console.log(line.words.map((w) => w.text).join(" "));
                arrayOcr.push(line.words.map((w) => w.text));
              }
            } else {
              console.log("No recognized text.");
            }
          }
        }
      },
      function () {
        return new Promise((resolve) => {
          resolve();
        });
      },
    ],
    (err) => {
      throw err;
    }
  );
}

function regExp(str) {
  var reg = /[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]/gi;
  //특수문자 검증
  if (reg.test(str)) {
    //특수문자 제거후 리턴
    return str.replace(reg, " ");
  } else {
    //특수문자가 없으므로 본래 문자 리턴
    return str;
  }
}

//WebSocket 서버 오픈
const wss = new WebSocket.Server({ port: 8080 }, () => {
  console.log("server start");
});

// Client에게 메세지를 받으면 data를 통해 OCR 결과값을 전송한다.
wss.on("connection", (ws) => {
  ws.on("message", (data) => {
    console.log("data received : " + data);

    console.log(regExp(arrayOcr.toString()));
    ws.send(regExp(arrayOcr.toString()));
  });
});

wss.on("listening", () => {
  console.log("server is listening on port 8080");
});

computerVision();
次はUnity部分コードです
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using WebSocketSharp;
public class OCR_TEST_Debug : MonoBehaviour
{
    // Start is called before the first frame update
	// e.Data를 통해 데이터를 수신
    WebSocket ws;
    void Start()
    {
        ws = new WebSocket("ws://localhost:8080");
        ws.OnMessage += (sender, e) =>
        {
            Debug.Log("Message received from " + ((WebSocket)sender).Url + ", Data : " + e.Data);

        };
        ws.Connect();
    }

    // Update is called once per frame
    void Update()
    {
        if (ws == null)
        {
            return;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            ws.Send("Hello");
        }
    }

    //왼쪽버튼이 눌렸을때 활성화
    public void Popup_ON()
    {
        Debug.Log("팝업 ON");
    }

    //오른쪽버튼이 눌렸을때 활성화
    public void Popup_OFF()
    {
        Debug.Log("팝업 OFF");
    }
}
Hollens 2は発売されて間もない製品で、開発が大きく制限されているようです.
Azureを使用する技術もUnityに直接接続するのではなく、特殊な方法があります.(Hollolens 2の正式な技術文書に記入)
時間が足りなくて急いでいたので、残念な点が多かったので、後でゆっくり変更するつもりです.