サーバレス練習帳

着眼大局着手小局

pythonで仮想カメラを制御する

◆この記事を参考にします。
qiita.com

OBS Studioという仮想カメラを使うのだそうな。

◆Windowz2064環境
この記事の続きで同じ環境で作っています。
serverless.hateblo.jp

(espo36) C:\python\espo36\src\zd>python --version
Python 3.6.8

(espo36) C:\python\espo36\src\zd>pip freeze
numpy==1.19.4
PyAudio==0.2.11

opencvを動かす
まずはインストールから

(espo36) C:\python\espo36\src\zd>pip install opencv-python
(espo36) C:\python\espo36\src\zd>pip freeze
numpy==1.19.4
opencv-python==4.4.0.46
PyAudio==0.2.11

あとは、冒頭の記事の引用です。まずは自分の顔が映りましたね。
引用通りだと動かなかったのですが「cv2.waitKey(30)」のKを大文字にしたら動きました。
(バージョンによってはk小文字なのだろうか?)

virtualcamTesting01.py

import cv2

# 取得するデータソース(Webカメラ)を選択
cap = cv2.VideoCapture(0)

while True:
    # 各フレームの画像を取得
    ret, frame = cap.read()

    # ここで何らかのエフェクトをかける

    # 画像を表示
    # 表示先を仮想Webカメラにしたい
    cv2.imshow("Window Name", frame)

    # 30フレーム表示して,Enterキーが入力されたら表示を終了する
    if cv2.waitKey(30) == 13:
        break

# 終了処理
cv2.destroyAllWindows()
cap.release()

◆pyvirtualcam
大元になっているgithubも見てみよう。
github.com
インストールします。

(espo36) C:\python\espo36\src\zd>pip install pyvirtualcam

(espo36) C:\python\espo36\src\zd>pip freeze
numpy==1.19.4
opencv-python==4.4.0.46
PyAudio==0.2.11
pyvirtualcam==0.2.0

◆OBS(Open Bloadcast Software)のインストール
そして、最新版のobsである
「OBS-VirtualCam2.0.4-Installer.exe」をインストールしてみました。
コマンドラインじゃなくて、普通にインストールできます。
「カメラを1つ有効にする」みたいな方の選択で大丈夫です。
github.com

Windowsを再起動しないと、仮想カメラを認識してくれません。
ですので、Windowsを再起動してから、Teamsか何かでOBS-Cameraが選択できることを確認しましょう。

ちなみに、別の方法で
上記URLから「OBS-VirtualCam2.0.4.zip」をダウンロードして解凍して、
C:\python\espo36\src\zd配下にフォルダごと格納。
コマンドプロンプト管理者モードで開いて、
次のregsvr32(レジストリ登録)を実行します。
管理者モードじゃないと、dllをインストールできず、
0x80070005というエラーが発生します。

C:\python\espo36\src\zd>regsvr32 /n /i:1 "obs-virtualcam\bin\64bit\obs-virtualsource.dll"

この方法だったとしてもWindows再起動が必要です。

◆グラデーションプログラム
pyvirtualcamのサンプルであるグラデーションを動かしてみましょう。
この画面キャプチャだけでは分かりづらいのですが、
例えば、Teamsでカメラを「OBS-Camera」に設定すると、
グレイスケールの濃さが刻々と変化するアニメーションが
仮想カメラに送りこまれているのを見ることができます。
f:id:urbanplanner:20201213143624p:plain
そのソースコードはこちら。
(というか、pyvirtualcamのサンプルプログラムそのものです)
virtualcamTesting02.py

import pyvirtualcam
import numpy as np
with pyvirtualcam.Camera(width=1280, height=720, fps=30) as cam:
    print('START!')
    while True:
        frame = np.zeros((cam.height, cam.width, 4), np.uint8) # RGBA
        frame[:,:,:3] = cam.frames_sent % 255 # grayscale animation
        frame[:,:,3] = 255
        cam.send(frame)
        cam.sleep_until_next_frame()

◆最後にopencvとつなげる
つながった。良いね。

import cv2
import pyvirtualcam

# 取得するデータソース(Webカメラ)を選択
cap = cv2.VideoCapture(0)

# 最初のフレームから画像のサイズを取得
ret, frame = cap.read()
with pyvirtualcam.Camera(width=frame.shape[1], height=frame.shape[0], fps=30, delay=0) as cam:
    while True:
        # 各フレームの画像を取得
        ret, frame = cap.read()
        # ちなみに私のPCのカメラは、右上がX=0:Y=0で、左下がX=640:y=480になります。
        cv2.rectangle(frame, (50, 150), (125, 200), (0, 0, 255), thickness=-1)
        cv2.rectangle(frame, (50, 200), (125, 250), (255, 255, 0), thickness=-1)
        cv2.rectangle(frame, (50, 250), (125, 300), (0, 255, 255), thickness=-1)

        # 色空間を変更
        # αチャンネルを有効にして,RGB順にする
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)

        # 画像を仮想カメラに流す
        cam.send(frame)

        # 画像をスクリーンに表示しなくなったので,pyvirtualcamの機能を使って次のフレームまで待機する
        cam.sleep_until_next_frame()

# 終了処理
cap.release()

せっかくだから、最後にexe化しておく。

(espo36) C:\python\espo36\src\zd>pip install pyinstaller==4.0
(espo36) C:\python\espo36\src\zd>pyinstaller --onefile --noconsole --icon=logo.ico emoCam.py

◆過去の調査結果はコチラ。
serverless.hateblo.jp