🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Flask

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

OpenCV

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

Python

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

Q&A

解決済

1回答

4654閲覧

OpenCVで加工した画像をリアルタイムでストリーミング配信する方法

tasojiro

総合スコア16

Flask

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

OpenCV

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

Python

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

0グッド

0クリップ

投稿2020/12/05 07:38

前提・実現したいこと

Flaskで、Webカメラから取得した画像をリアルタイムでOpenCVで加工して、その画像をWebブラウザで確認する、
といったプログラムを作成しています。
実現したい動作は、Webカメラの映像を加工された状態でブラウザから見る、という動作です。

しかし、加工した画像を返す段階でエラーが発生しました。
どのようなエラーかは、ある程度把握しているつもりですが、修正の仕方が分かりません。
よろしくお願いいたします。

※加工内容は、動体検知を行うサイトを参考に「動いているものに輪郭線を描く」という加工をしています。

該当のソースコード

※エラーが発生した個所はコメントで記しています。

python

1# -*- coding: utf-8 -*- 2from flask import Flask, Blueprint, render_template, Response 3import time 4import datetime 5import cv2 6 7app = Flask(__name__) 8 9class Camera(object): 10 def __init__(self): 11 self.image = None 12 13 def create_frame(self): 14 DELTA_MAX = 255 15 DOT_TH = 20 16 MOTHON_FACTOR_TH = 0.03 17 18 #カメラの登録 19 capture = cv2.VideoCapture(-1) 20 avg = None 21 22 while True: 23 motion_detected = False # 動きが検出されたかどうかを示すフラグ 24 25 # フレーム取得 26 ret, frame = capture.read() 27 if not ret: 28 break 29 30 # グレースケールに変換 31 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 32 # 比較用のフレームを取得する 33 if avg is None: 34 avg = gray.copy().astype("float") 35 continue 36 37 # 現在のフレームと移動平均との差を計算 38 cv2.accumulateWeighted(gray, avg, 0.6) 39 frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg)) 40 41 # デルタ画像を閾値処理を行う 42 thresh = cv2.threshold(frameDelta, DOT_TH, DELTA_MAX, cv2.THRESH_BINARY)[1] 43 44 #全体としてどれくらいの割合が変化したか。 45 motion_factor = thresh.sum() * 1.0 / thresh.size / DELTA_MAX 46 motion_factor_str = '{:.08f}'.format(motion_factor) 47 48 if motion_factor > MOTHON_FACTOR_TH: 49 motion_detected = True 50 51 # 画像の閾値に輪郭線を入れる 52 contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 53 frame = cv2.drawContours(frame, contours, -1, (0, 255, 0), 3) 54 55 # 結果を出力 56 self.image = frame #ここの文でエラーが発生 57 key = cv2.waitKey(5) 58 if key == 27: 59 break 60 61 capture.release() 62 cv2.destroyAllWindows() 63 64 def get_frame(self): 65 frame = self.image 66 ret, img = cv2.imencode('.jpg', frame) 67 return img 68 69@app.route('/camera') 70def index_camera(): 71 return render_template('camera.html', title='Camera') 72 73@app.route('/predict') 74def predict(): 75 return Response(gen(Camera()), mimetype='multipart/x-mixed-replace; boundary=frame') 76 77def gen(camera): 78 while True: 79 frame = camera.get_frame() 80 yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n') 81 82if __name__ == '__main__': 83 app.run(host='0.0.0.0', debug=True)

発生している問題・エラーメッセージ

恐らく、「frame」に画像が格納されていないのかな、と。。。

cv2.error: OpenCV(4.4.0) /tmp/pip-wheel-2l8ccy47/opencv-python/opencv/modules/imgcodecs/src/loadsave.cpp:919: error: (-215:Assertion failed) !image.empty() in function 'imencode'

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

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

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

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

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

guest

回答1

0

ベストアンサー

参考にした別サイトのソースコードから変えなければならない部分をいくつか見落とされてると思います。

get_frame()関数内のimageは最初からNoneであるため、そのエラーが発生しています。
自前関数create_frameの内容を呼び出さなければいけません。

diff

1def gen(camera): 2 while True: 3- frame = camera.get_frame() 4+ frame = camera.create_frame() 5 yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n') 6

create_frame内で適切なデータ形式に直してブラウザに渡す必要があります。

diff

1class Camera(object): 2(略) 3 # 画像の閾値に輪郭線を入れる 4 contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 5 frame = cv2.drawContours(frame, contours, -1, (0, 255, 0), 3) 6 7 # 結果を出力 8- self.image = frame #ここの文でエラーが発生 9+ _, img = cv2.imencode('.jpg', frame) 10 key = cv2.waitKey(5) 11 if key == 27: 12 break 13 14+ return img.tobytes() 15 16 capture.release() 17 cv2.destroyAllWindows() 18(略)

投稿2020/12/05 08:56

sfdust

総合スコア1137

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

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

tasojiro

2020/12/05 09:53

なるほど! 以前は、get_frame()単体で呼び出していたので「create_frame()」が適応されていない状態だけど、 本来はクラスから呼び出してやる必要があるのですね。 解決しました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問