Streamlit + Web Cam

# はじめに

WebCamの映像をStreamlitで移す方法について、ご紹介いたします。

# streamlit_webrtc 

streamlit以外にstreamlit-webrtcのパッケージを設置します。
streamlit-webrtcは、Tachibana Yuichiroさんが作ってくださいました。
TachibanaさんのTwitter : https://twitter.com/whitphx_ja

```
pip install streamlit
pip install streamlit-webrtc
```
Github

https://github.com/whitphx/streamlit-webrtc


# 01. Web CamのみStreaming

まず、Web CamのStreamlingを実装します。この短いコードでWebCAMのWeb Streamingが可能になります。素晴らしい。

```python
import streamlit as st
from streamlit_webrtc import webrtc_streamer
import cv2
import av #strealing video library

st.title('Streamlit App Test')
st.write('Hello world')

webrtc_streamer(key='example')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/2025bf92-5a5d-29de-89ed-c046eed4ca96.png)


# 02. Web Camでグレースケール変換

次に、Web Camの画像をグレースケールに変換するコードを付け加えてみます。
やり方として、VideoProcessorというクラスを用意します。
このクラスにrecv()というメソッドを用意し、その中に変換するOpenCVコードを入れます。
OpenCVで、WebCamのフレームを処理するとき、While文を使いますが、そのWhile文に相当するのが、このrecv()と覚えるといいかと思います。

そして、OpenCVのinput, output部位には、avのframe.to_ndrray()とVideoFrame.from_ndarray()を利用します。（Web streamingのffmpegを利用するため)

```python
import av

class VideoProcessor:
    def recv(self,frame):

        img = frame.to_ndarray(format = 'bgr24')
        img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        img = av.VideoFrame.from_ndarray(img, format='gray')

        return img
```

そして、webtrc_streamer()のvideo_process_factoryの引数として、用意したクラスを渡します。

```python
webrtc_streamer(key='example', video_processor_factory=VideoProcessor)
```

コードです。

```python
# https://twitter.com/whitphx
# https://www.whitphx.info/posts/20211231-streamlit-webrtc-video-app-tutorial/

import streamlit as st
from streamlit_webrtc import webrtc_streamer
import cv2
import av #strealing video library

st.title('Streamlit App Test')
st.write('Gray Scale')

#Class
class VideoProcessor:
    def recv(self,frame):

        img = frame.to_ndarray(format = 'bgr24')
        img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        img = av.VideoFrame.from_ndarray(img, format='gray')

        return img

webrtc_streamer(key='example', video_processor_factory=VideoProcessor)

```

グレースケールに変換されることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/d0dc1be7-bbe8-0594-839b-3cab90537206.png)


# 03. Web Camでグレースケール変換をCheckboxで制御
今度は、Checkboxを用意し、
Checkboxがチェックされる　→グレースケールに変換を行う。
Checkboxがチェックされない　→カラー表示を行う。
動作をやってみます。

Checkboxがチェックされた結果を入れる変数を用意し、VideoProcessorクラス変数にして、下記のようにコードを構成します。

```python
#Class
class VideoProcessor:

    def __init__(self) -> None:
        self.test_state = None

    def recv(self,frame):

        img = frame.to_ndarray(format = 'bgr24')
        if self.test_state == True:
            img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
            img = av.VideoFrame.from_ndarray(img, format='gray')
        else:
            img = av.VideoFrame.from_ndarray(img, format='bgr24')

        return img

```
そして、webtrc_streamer()をctxにし、下記のコードを加えます。
若干、難しいですが、streamlit_webrtc()のルールだと思い、まず慣れることにしましょう。

```python
ctx = webrtc_streamer(key='example', video_processor_factory=VideoProcessor)

if ctx.video_processor:
    ctx.video_processor.test_state = st.checkbox('Gray Scale -> Color ')

```
全体コードです。

```python
# https://twitter.com/whitphx
# https://www.whitphx.info/posts/20211231-streamlit-webrtc-video-app-tutorial/

import streamlit as st
from streamlit_webrtc import webrtc_streamer
import cv2
import av #strealing video library

st.title('Streamlit App Test')
st.write('Gray Scale -> Color')


#Class
class VideoProcessor:

    def __init__(self) -> None:
        self.test_state = None

    def recv(self,frame):

        img = frame.to_ndarray(format = 'bgr24')
        if self.test_state == True:
            img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
            img = av.VideoFrame.from_ndarray(img, format='gray')
        else:
            img = av.VideoFrame.from_ndarray(img, format='bgr24')

        return img

ctx = webrtc_streamer(key='example', video_processor_factory=VideoProcessor)

if ctx.video_processor:
    ctx.video_processor.test_state = st.checkbox('Gray Scale -> Color ')

```
Checkboxがチェックされる　→グレースケールに変換を行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/6ec92f93-84a6-90df-ca3f-08d90969fb2b.png)
Checkboxがチェックされない　→カラー表示を行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/ed8a2837-09e8-7b47-d33f-26c9a01aa66e.png)


# 参考資料

https://zenn.dev/whitphx/articles/streamlit-realtime-cv-app

https://whitphx.info/posts/20211231-streamlit-webrtc-video-app-tutorial/