序文
ディープ ラーニング ビデオ ターゲット検出プロジェクトに取り組んでいる場合、ディープ ラーニング ビデオ処理の進行状況に基づいて進行状況バーのパーセンテージを更新する必要があります。
最初はとても簡単だと思いました、ただ使ってください現在のフレーム番号/総ビデオ フレーム番号処理の進行状況のパーセンテージを取得し、それをフロントエンドに返して表示するだけです。
#深度学习代码文件
import cv2
video = cv2.VideoCapture('video.mp4')
#获取总帧数
frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT)
#获取进度比例,当前帧可以自己用while循环自增得到
ratio = current_frame_id/framcount
しかし、実際の実装プロセスでは多くの落とし穴に遭遇したことがわかったので、ここに記録するためにチュートリアルを書きます。
1. バックエンドコード
まず、バックエンドでグローバル変数を定義しましたprogress_bar_ratio現在のパーセンテージを記録するために使用され、ビデオの次のフレームの処理が完了するたびにこれを更新します。progress_bar_ratio価値:
#深度学习代码文件
#将百分比定义全局变量,方便其他函数获取
progress_bar_ratio = 0.
def 视频处理伪代码():
global progress_bar_ratio #函数内加global才能使用全局变量
#用浮点数方法储存数据
progress_bar_ratio = current_frame_id/float(frame_count)
#保留两位小数,乘以100%
progress_bar_ratio = int(round(progress_bar_ratio,2)*100)
次に、フロントエンドの深層学習コード ファイルに追加関数を定義して、バックエンドのプログレス バーの値を取得します。
#将百分比定义全局变量,方便其他函数获取
progress_bar_ratio = 0.
def 视频处理伪代码():
global progress_bar_ratio #函数内加global才能使用全局变量
#用浮点数方法储存数据
progress_bar_ratio = current_frame_id/float(frame_count)
#保留两位小数,乘以100%
progress_bar_ratio = int(round(progress_bar_ratio,2)*100)
#供前端访问
def get_bar_ratio():
global progress_bar_ratio
return progress_bar_ratio
2. Flask とフロントエンド コード
1.フラスコ
progress_bar_ratioの値がストリームされますプログレスバーの値フロントエンドに渡されます。
from 深度学习代码 import get_bar_ratio
from flask import Response, stream_with_context
@app.route('/progress') #随便自己定义,前端javascript要靠这个路由来访问数据
def progress():
@stream_with_context
def generate():
global ratio
ratio = get_bar_ratio() #获取后端进度条数据,最初的时候是0
while ratio < 100: #循环获取,直到达到100%
yield "data:" + str(ratio) + "\n\n"
print("ratio:",ratio)
ratio = get_bar_ratio()
#最好设置睡眠时间,不然后端在处理一帧的过程中前端就访问了好多次
time.sleep(1)
return Response(generate(), mimetype='text/event-stream') #用数据流的方式发送给后端
ここで簡単に説明すると以下のようになります収率yielded の関数は実際には、値を返すために使用される return に似ています。ただし、yield と return の違いは、yield は値を返した後に関数を終了し、次回プログラムが再び関数にアクセスするときは、次の yield ステートメントから実行が開始されることです。
簡単に言うと、yield はゲームのセーブポイントに相当し、初めて関数を呼び出すと、関数が yield ラインに到達した後、関数を終了して を返し、"data:" + str(ratio) + "\n\n"
ファイルを保存します。関数を 2 回目に呼び出すと、関数はprint("ratio:",ratio)
最初から実行されます。これは、ファイルを最後から読み取り、次の yield が見つかるまで関数をループで実行するのと同じです。これはデータ フローの効果を形成するために行き来し、毎回データの一部をフロントエンドに送信します。
コード内のstream_with_context は非常に重要です。!!追加する必要があります。追加しないと、フロントエンドは効果がありません。!!
2.htmlとJavaScript
フロントエンドの進行状況バー スタイルは、bootstrap5 によって提供されます (bootstrap5 パッケージを自分でインポートするか、進行状況バー スタイルを持つ他のパッケージをインポートする必要があります)。
//html文件
<div class="progress" style="margin-bottom:20px;">
<div class="progress-bar" id="flask_progress" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%"> 0%
</div>
</div>
JavaScriptコード:
//加到html代码末尾即可
<script>
var source = new EventSource("/progress"); //前端向flask的/progress路由发送请求
source.onmessage = function(event) {
//获取当前的进度条数值,并对数值进行更改
let div = document.querySelector('#flask_progress')
let text = document.getElementById('flask_progress')
//更改进度条的进度长度以及进度条中的值
div.style.width = event.data+'%'
text.innerHTML = event.data+'%'
if(event.data == 101){
//当进度条超过100%后结束
source.close()
}
}
</script>