8
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

株式会社エイアイ・フィールドAdvent Calendar 2021

Day 7

【python】Mediapipe&OpenCV&OBSを使って、WEB会議でのフィルターを作った

Last updated at Posted at 2021-12-06

TL;DR

ソースコードはこちら!

はじめに

今回は以前のこの記事を使って、実際にWEB会議などで自前で実装したフィルターをかけた状態の画像を使ってみよう!

前のものに数行追加すればできる話ではあるが、今回は別のソフトが必要になってくるので、別途インストールが必要。

考え方としては画像処理を行った結果を仮想カメラに渡し、WEB会議ではその仮想カメラを利用すること。

手順

今回のフォルダ構成は以前の記事と同じで、プログラムの大まかな処理は下記の通り:

  1. Configの読み込む
  2. Mediapipeのインスタンス化
  3. カメラからの画像取得
  4. フィルター適用
  5. 結果を仮想カメラへ送信する

OBSについて

OBSとはオーペンソースの仮想カメラのソフトで、ゲーム中継や動画配信によく使われている。使い方は様々だが、今回は「仮想カメラ」として利用する。

まずはダウンロードして、インストールしよう!

ツール

OBSとpythonを連携させるため、pyvirtualcamというライブラリーを利用する。

まずはインストール

$ pip install pyvirtualcam

この記事は非常に参考になったので、ぜひご参考まで!

ソースコード

ソースコードはほとんど前回と同じだが、今回は仮想カメラを利用するので、それをクラス化しよう

import pyvirtualcam

class VirtualCamera():
    def __init__(self, width, height, fps) -> None:
        self.v_cam = pyvirtualcam.Camera(width=width, height=height, fps=fps)

    def _send(self, image):
        self.v_cam.send(image)
        self.v_cam.sleep_until_next_frame()

次に既存カメラクラス(class Camera)の中に仮想カメラを起動しする。

class Camera():
    # 画像サイズを同調させるため、予め横軸を定義する。
    def __init__(self, index, config, detector, width:int=1920, height:int=1080, fps:int=30) -> None:
        self.config = config
        self.detector = detector

        self.width = width
        self.height = height
        self.fps = fps

        self.start(index)

    def start(self, index) -> None:
        self.cap = cv2.VideoCapture(index)
        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
        self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
        success, frame = self.cap.read()
        if not success:
            logger.error(f"Camera not successful: video input: {index}")
            sys.exit()
        self.mask = np.zeros((frame.shape[0], frame.shape[1], 3), dtype=np.uint8)
        
        # 仮想カメラを始動する。
        self.v_cam = VirtualCamera(width=self.width, height=self.height, fps=self.fps)

最後に画像処理の結果を送信する。

    def capture(self) -> None:
        logger.info("Catpuring images from video input... (press 'q' to exit.)")
        while True: 
            _, frame = self.cap.read()
            frame.flags.writeable = False
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            self.detector(frame)
            
            frame.flags.writeable = True
            frame, mask = self.detector.post_processing(self.mask, self.config.yaml_cfg)
            mask = cv2.flip(mask, 1)
            
            # 結果を送信する。
            self.v_cam._send(frame)
            
            # マスクを表示する。
            mask = cv2.resize(mask, dsize=(400, 320))
            cv2.imshow("mask", cv2.cvtColor(mask, cv2.COLOR_BGR2RGB))
            
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

修正はこれだけ!

これでフィルターをかけた画像が仮想カメラへ送信され、あとは実際のWEB会議でその仮想カメラを選択するのみ!

詳細なやり方は割愛させていただくが、USBカメラを利用する時と同じである。

デモ

WEB会議で仮想カメラ(OBSカメラ)を選択する。

image.png

プログラムを実行する。

face_filter_web.gif

あとがき

今回は単純に前回のものに加え、仮想カメラを利用することで、WEB会議などで自前のフィルターを使えるようになった。

ぜひ既存するものを活かして、身の回りのことをスマートかつ面白くしよう

8
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?