質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1651閲覧

Flaskで複数の画像をストリーミングしたい

mo256man

総合スコア43

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/05/24 12:48

やりたいこと

カメラ映像を画像処理した上でFlaskでストリーミングする方法をなんとか習得しました。
多くの解説サイトがそうであるように、出力画像が一つのものです。

では、複数の画像を同時にストリーミングさせるにはどうしたらよいのでしょうか。
カメラ映像そのままと画像処理された画像を流したいと考えています。

コード(画像ひとつ版)

Python

1from flask import Flask, render_template, Response 2import cv2 3 4app = Flask(__name__) 5 6class Camera(object): 7 def __init__(self): 8 self.video = cv2.VideoCapture(0) 9 10 def read(self): 11 return self.video.read() 12 13def gen(camera): 14 while True: 15 _, frame = camera.read() 16 17 # 画像処理1 グレースケールにする 18 image1 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 19 _, encoded1 = cv2.imencode('.jpg', image1) 20 bin1 = b"--frame\r\nContent-Type: image/jpeg\r\n\r\n" + encoded1.tobytes() + b"\r\n" 21 22 # 画像処理2 左右反転する 23 image2 = cv2.flip(frame, 1) 24 _, encoded2 = cv2.imencode('.jpg', image2) 25 bin2 = b"--frame\r\nContent-Type: image/jpeg\r\n\r\n" + encoded2.tobytes() + b"\r\n" 26 27 yield (bin1) 28 29@app.route("/") 30def stream(): 31 return render_template("stream.html") 32 33@app.route("/video1") 34def video1(): 35 return Response(gen(Camera()), 36 mimetype="multipart/x-mixed-replace; boundary=frame") 37 38if __name__ == "__main__": 39 app.run(debug=True)

html

1<html> 2<body> 3<img src="{{ url_for('video1') }}"> 4</body> 5</html>

やってみたこと

その1

2個の画像を出力させる一歩前の段階として、

  • gen(camera)bin1でなくリスト[bin1, bin2]を生成する
  • レスポンスを返すところでgen(Camera())でなくgen(Camera())[0]を指定する

をやってみた → generator' object is not subscriptable エラー

その2

  • その1と同じくgen(camera)でリスト[bin1, bin2]を生成する
  • レスポンスを返すところでlist(gen(Camera()))[0]を指定する

をやってみた → 何の反応もなし

と、複数表示させるどころか二つのバイナリを作ってそのうち一つを扱うことすらできていない状態です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

cv2で同じカメラに同時アクセスはできないので、以下のようにすれば同時表示可能です。

  1. Flaskと関係無くカメラにアクセスし画像を取得するアプリを作成する。
  2. Flaskから[1]にアクセスし、画像を取得する。
  3. 通常/処理済みを識別する記号とかを自分で付けてそれを呼び出す。

1のアプリはCameraから画像を取得し、そのまま使うパターンと、画像処理して使うパターンの2通りの処理を行う必要があるはずです。
それぞれでcv2.VideoCapture(0)のようなものを呼び出すと動かないと思うので、画像を取得し続けるものとそれを利用して処理する物で分けるマルチスレッド/マルチプロセスのアプリが必要になります。
これはマルチスレッドで動かせば解決する可能性が高いです。(ハードによる)

2のFlaskから[1]にアクセスする方法はいくつかありますが、例えば以下の様なものです。

  1. Socket通信
  2. プロセス間通信
  3. 中間ストレージ(DBとか)を利用する。

DBは単にDBと書いてありますが、redisやmemcachedみたいな早いやつが良いと思います。(RDBMSはダメと思う)

3の識別する記号を付けては、例えばurlに/video0とか/video1とかわかるヤツで呼び出すだけです。
genを複数作る必要があるか、引数渡して1つで良いかは実装次第になると思います。

もしも、開発したあとに運用する予定がある場合は、OpenCVの処理は意外に重いので実機で動かすのをお勧めします。
開発機では動作しているが、実機(開発機より非力)で動かしたら全く満足に動かなくて設計し直しが発生する可能性があるためです。

そこまでやって実運用にはたえられそうにないのしかできませんでしたが、そんなに同時映像が重要なんでしょうか?

投稿2022/05/24 13:17

FiroProchainezo

総合スコア2401

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mo256man

2022/05/24 15:01

素早い回答ありがとうございます。私のコードでは一つのカメラ映像から複数の画像を作るところまではできていますが(作っただけで送れていないのですけど)、そのやり方では駄目ということでしょうか?
FiroProchainezo

2022/05/25 00:55

はい。 試しにgenを2つ(/video1と/video2とか。<img src="{{ url_for('video1') }}">も2個設置)作ってやってみると良いかもしれません。 それで動けばそれで良いと思います。
mo256man

2022/05/25 12:13

おっと、気持ちが良いほどにきっぱりと断言されてしまいました。これは断念せざるを得ません。 いくつか課題をいただきましたのでそれらの動きを確認しました。なぜそのような挙動になるのかは理解できていませんが。 示していただいた方法は私には難しそうなので第三の方法にしようと思います。 すなわち、np.hstack()を使って二つの画像を一つに合成してhtmlに送る、という。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問