【VR空間サービス Spatial.io】#7 来場カウンタ

# サマリ
Spatialのスペースに来た人を認識して以下のようなログをファイルに出力します。
```
2023-04-03 01:07:36 - mayo32 has joined the space.
```
スペースに人が入ってきた時に表示されるメッセージを画像認識してログ書き出しのトリガーとします。

★以下の点未確認です。。
- 日本語のユーザー名
- ユーザー名に絵文字を含む場合


## 動作確認環境
- Windows 11 Home 22H2
- python 3.11.1
- OBS studio 29.0.2
- obs-virtualcam 3.0.0
- Tesseract OCR 5.3.1.20230401

## 目次
1. pythonのインストール
1. OBS studioのインストール
1. obs-virtualcamのインストール
1. Tesseract OCRのインストール
1. OBSの準備
1. pythonアプリの実行

## 1. pythonのインストール
pythonでプログラムを記述します。
pythonをインストールします。
→[python.org](https://www.python.org/)

使用するパッケージをインストールします。
```
pip install opencv-python
pip install pytesseract
```

## 2. OBS studioのインストール
OBSを使ってSpatialの画面を仮想カメラに流します。
OBS studioをインストールします。
→[OBS studio](https://obsproject.com/ja/download)

## 3. obs-virtualcamのインストール
OBS仮想カメラの画像をpythonで取り込むため、obs virtualcamをインストールします。
→[obs-virtualcam](https://github.com/Avasam/obs-virtual-cam/releases)

## 4. Tesseract OCRのインストール
文字認識のため、Tesseract OCRをインストールします。
→[Tesseract OCR](https://github.com/UB-Mannheim/tesseract/wiki)

## 5. OBSの準備
OBSを起動し、Spatialのブラウザ画面を仮想カメラとして設定します。
人が入ってきた時に出るメッセージ以外を認識しないように仮想カメラの範囲をメッセージが出るあたりだけになるようにクロップします。
![vlcsnap-2023-04-03-03h54m41s798.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/f9c8a5bb-ac01-6d64-3906-88a0cf79366b.png)

## 6. pythonアプリの実行
下記のpythonアプリを実行します。
- camera_device_indexは実行環境でOBS仮想カメラの番号を指定します。
- プログラムを実行したカレントディレクトリにLog-YYYYMMDD.txtのファイル名でログを出力します。日付ごとにログファイルができます。
- SpatialVisitorCounterの画面に仮想カメラの画像が正常に表示されない場合はOBSのツールメニューから"VirtualCam"を起動します。
```python
import cv2
import pytesseract
from difflib import SequenceMatcher
import time

LOG_FILE_PREFIX = "Log"

def string_similarity(a, b):
    return SequenceMatcher(None, a, b).ratio()

def get_log_filename():
    return f"{LOG_FILE_PREFIX}-{time.strftime('%Y%m%d')}.txt"

def capture_and_recognize_text():
    # OBSの仮想カメラを選択
    camera_device_index = 1

    cap = cv2.VideoCapture(camera_device_index)

    prev_recognized_text = ""
    prev_date = time.strftime('%Y%m%d')

    while True:
        ret, frame = cap.read()
        if not ret:
            break

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        recognized_text = pytesseract.image_to_string(gray, lang="eng")

        similarity = string_similarity(prev_recognized_text, recognized_text)

        if similarity < 0.9:
            current_date = time.strftime('%Y%m%d')
            if current_date != prev_date:
                prev_date = current_date

            with open(get_log_filename(), "a", encoding="utf-8") as log_file:
                for line in recognized_text.splitlines():
                    if "joined" in line:
                        log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {line}\n")
                        prev_recognized_text = recognized_text

        cv2.imshow("SpatialVisitorCounter", gray)

        if cv2.waitKey(1) & 0xFF == ord("q"):
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    capture_and_recognize_text()

```
# 
チームハイエナ <img width="120" alt="hyaeninae_tomei.png"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/99b448d3-7ff0-58f3-302b-8528cf339b8d.png">