Jupyter リモート使用カメラ、WebRTC チャット ルーム、リアルタイムビデオ処理
序文
ipywebrtcコンポーネントを使用してローカル ビデオ ストリームを取得し、リモート Jupyter サーバーに送信します。サーバーがビデオを処理した後、ビデオはローカルに送り返され、最終的にコンポーネントによって表示されますipywidgets.Image
。
効果体験
Chromeブラウザの使用を推奨します
公式の例に移動し、カメラが動作しているのを確認できるようにします。
デモ コードをより深く体験したい場合は、Binderに移動して任意のファイルを開いて.ipynb
、段階的に実行できます。
準備
最初にコンポーネントをインストールする必要がありますipywebrtc
。方法は 2 つあります。簡単な方法はpip
直接インストールすることです (jupyter バージョン 5.3 以降が必要です):
pip install ipywebrtc
2 つ目は、github 経由で最新のプレビュー バージョンをインストールすることです。
git clone https://github.com/maartenbreddels/ipywebrtc
cd ipywebrtc
pip install -e .
jupyter nbextension install --py --symlink --sys-prefix ipywebrtc
jupyter nbextension enable --py --sys-prefix ipywebrtc
jupyter lab を使用している場合は、ターミナルで次のステートメントを実行するだけです。
jupyter labextension install jupyter-webrtc
手順
準備が完了したら、まずipywebrtc
Jupyter ファイル内のライブラリを参照し、ストリームを作成する必要があります。利用可能なストリームについては、以下のコンポーネントの紹介セクションを参照してください。ここでは、ローカル フロント カメラを使用する例を示しますCameraStream
。
from ipywebrtc import CameraStream
camera = CameraStream.facing_user(audio=False)
camera
何も事故がなければ、Chrome ブラウザは Web ページでのカメラの使用を許可するかどうかを尋ねるウィンドウを表示し、許可を選択すると、出力領域にカメラでキャプチャされたビデオが表示されます。
Chrome でプロンプトがポップアップ表示されずに表示される場合は
Error creating view for media stream: Only secure origins are allowed
、ブラウザが現在の Web サイトが安全ではない (接続が使用されていない) と判断しているためhttps
、カメラが無効になっていることを意味します。最も簡単な解決策は、Chrome ショートカットの「ターゲット」列の最後に追加して--unsafely-treat-insecure-origin-as-secure="http://host_ip:port"
再起動することです (host_ip:port
独自のサーバー アドレスに変更します)。
ただし、現時点では、ビデオはローカルでのみ表示され、Python カーネルが配置されているサーバー (リモート サーバーを使用していると仮定) にはアップロードされないため、Python コンテキストでビデオ コンテンツを取得する方法はありません。
次に、ImageRecorder
ストリームを記録し、画像としてサーバー上の Python カーネルに送信するためのストリームを作成する必要があります。
from ipywebrtc import ImageRecorder
image_recorder = ImageRecorder(stream=camera)
image_recorder
このコードを実行すると、コンポーネントが表示されますImageRecorder
。コンポーネント上のカメラ アイコンをクリックしてstream
画面をキャプチャします。
その後、Python で画像にアクセスして形式image_recorder.image.value
に変換することで、Pillow
画像を取得できます。
import PIL.Image
import io
im = PIL.Image.open(io.BytesIO(image_recorder.image.value))
加工する必要がなく、プレビューするだけであれば直接表示することもできますが、それ自体が画像を表示する機能を持つコンポーネントimage_recorder.image
です。画像処理を使用する必要がある場合は、処理可能な画像配列を取得し、処理後に画像を表示できますが、コンポーネントを使用することをお勧めします。ipywidgets.Image
opencv-python
canvas = numpy.array(im)[..., :3]
cv2
matplotlib
ipywidgets.Image
from ipywidgets import Image
out = Image()
out.value = cv2.imencode('.jpg', cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB))[1].tobytes() # canvas出处见上文说明部分
out
または、再度導入したくない場合はcv2
、公式の方法に従うこともできます。
from ipywidgets import Image
out = Image()
im_out = PIL.Image.fromarray(canvas)
f = io.BytesIO()
im_out.save(f, format='png')
out.value = f.getvalue()
out
ビデオを処理する
ここまでは画像の取得、加工、表示方法のみを紹介しましたが、どれも公式ドキュメントで簡単に学ぶことができます。では、ビデオの各フレームを継続的にキャプチャし、処理して 1 つずつ表示するにはどうすればよいでしょうか? 以下に私がまとめたImageRecorder
継続的なクローリングの方法を紹介します。
ImageRecorder
代わりに連続キャプチャが依然として使用されている理由は、VideoRecorder
キャプチャVideoRecorder
されたビデオには開始と終了が必要であり、終了後にのみキャプチャされたビデオ クリップ全体が処理され、「リアルタイム」要件を満たさないためです。
著者のコードを分析したところ、や のような関数は存在せず、フロントエンドが画像の次のフレームを取得しrecorder.record()
た後、属性を に設定するようにPython カーネルに通知し、画像を取得した後に属性を設定することがわかりました。に自動的に変わります。したがって、毎回前のフレームの写真を処理した後、次のフレームを取得するように自動的に設定されるループ メカニズムを試してみたいと思います。ただし、実験した結果、ループやループを使用しても機能しません。これはおそらく、Jupyter のフロントエンドが Javascript によってレンダリングされているためです。フロントエンドに通知せずにバックエンドの Python 環境で属性を変更するだけでは、クロールを続行できません。recorder.take_photo()
ImageRecorder
ImageRecorder
recording
True
recording
False
recording
True
while
for
この理由は私の個人的な推測にすぎません。時間の都合上、フロントエンド ファイルとその基礎となるロジックを注意深く見ていないため、私の理解が間違っている可能性があります。コメント エリアで修正してください。
最後に、Github の martin Renou の投稿を参照して、連続リアルタイムビデオ処理を完了する次のモードを考えました。
import io
import PIL.Image
import numpy as np
from ipywidgets import Image, VBox, HBox, Widget, Button
from IPython.display import display
from ipywebrtc import CameraStream, ImageRecorder
VIDEO_WIDTH = 640 # 窗口宽度,按需调整
VIDEO_HEIGHT = 480 # 窗口高度,按需调整
camera = CameraStream(constraints=
{
'facing_mode': 'user',
'audio': False,
'video': {
'width': VIDEO_WIDTH, 'height': VIDEO_HEIGHT}
}) # 另一种CameraStream创建方式,参考下文组件介绍部分
image_recorder = ImageRecorder(stream=camera)
out = Image(width=VIDEO_WIDTH, height=VIDEO_HEIGHT)
FLAG_STOP = False # 终止标记
def cap_image(_): # 处理ImageRecord抓取到的图片的过程
if FLAG_STOP:
return # 停止处理
im_in = PIL.Image.open(io.BytesIO(image_recorder.image.value))
im_array = np.array(im_in)[..., :3]
canvas = process(im_array) # process是处理图像数组的函数,这里没写出来,各位按处理需要自己写即可
im_out = PIL.Image.fromarray(canvas)
f = io.BytesIO()
im_out.save(f, format='png')
out.value = f.getvalue()
image_recorder.recording = True # 重新设置属性,使ImageRecorder继续抓取
# 注册抓取事件,参考我另一篇Blog:https://qxsoftware.blog.csdn.net/article/details/86708381
image_recorder.image.observe(cap_image, names=['value'])
# 用于停止抓取的按钮
btn_stop = Button(description="Stop",
tooltip='click this to stop webcam',
button_style='danger')
# btn_stop的处理函数
def close_cam(_):
FLAG_STOP= True
Widget.close_all()
btn_stop.on_click(close_cam) # 注册单击事件
# Run this section and Press the Camera button to display demo
display(VBox([HBox([camera, image_recorder, btn_stop]), out]))
ImageRecorder
Jupyter でこのコードを実行すると、ローカル カメラ プレビュー ボックス、グラブ ボックス、赤い停止ボタン、およびImage
まだ画像のないコンポーネントが表示されます。上のカメラボタン
をクリックすると機能が有効になり、処理された画像がコンポーネントに表示され、「停止」をクリックするまでこのプロセスが繰り返されます。カメラをクリックした後でのみ、その後の Jupyter セルに正常にアクセスできます。アクセスできない場合は、エラーが報告されます。ImageRecorder
cap_image
Image
image_recorder.image
OSError: cannot identify image file
ここで最も重要な部分は、イベント登録
ImageRecorder.image
関数に追加されたステートメントです。なぜ登録機能の外にこの文を追加することが無効なのかについては、フロントエンドとバックエンドの接続を検討する必要があります。登録関数のエラーは中断を引き起こさないことに注意してください。そのため、を実行した後にコンポーネントが画像を表示しない場合はエラーである可能性があり、新しいセルの内容を抽出することで確認できます。observer
image_recorder.recording = True
cap_image
Image
cap_image
cap_image
コンポーネントの紹介
ipywebrtc
、利用可能なストリーミング メディアは次のとおりです。
-
VideoStream
:VideoStream.from_file(path)
ローカルビデオを取得することも、VideoStream.from_url(url)
ネットワークビデオを取得することもできます -
CameraStream
: ローカル カメラ デバイスまたは Web カメラ (Web カメラ) を通じてメディア ストリームを取得します。作成方法は 2 つあります。- 最初:
camera = CameraStream(constraints= { 'facing_mode': 'user', # 'user表示前置摄像头,'environment'表示后置摄像头 'audio': False, # 是否同时获取音频(需要硬件支持) 'video': { 'width': 640, 'height': 480 } # 获取视频的宽高 })
- 2 番目のタイプ:
front_camera = CameraStream.facing_user(audio=False)
: フロントカメラ
back_camera = CameraStream.facing_environment(audio=False)
: リアカメラ
-
AudioStream
: オーディオ ストリーム。VideoStream
と同じ方法で作成されます。 -
WidgetStream
: をWidgetStream(widget=target)
指定すると、任意のインスタンスの出力をメディア ストリームとして作成widget
できます。ipywidget
これらのメディア ストリームはすべて
MediaStream
クラスから継承します。
ストリーミング メディア コンポーネントに加えて、フロントエンド Javascript によって取得されたストリームを記録し、Python カーネルに送信するために使用されるレコーダー コンポーネントもあります。これについては、例とその使用法で詳しく紹介されていますImageRecorder
。同様ですので、公式ドキュメントVideoRecorder
を参照してください。最後に、にコンポーネントがあります。テスト後も、まだいくつかのバグがあります。Chatビデオ チャット ルームを参照してください。ipywebrtc.webrtc
ipyvolumn
今後、さらに多くのコンテンツ(シリーズなど)が更新される予定です。
元は CSDN で公開されたものです。転載する場合は出典を明記してください: https://qxsoftware.blog.csdn.net/article/details/89513815。ご質問やアイデアがございましたら、以下にコメントを残してください~~