프로그래밍/Developer Student Clubs

[Back-end] Flask-Darkflow-web-streaming 비동기 처리

지누; 2020. 3. 1. 16:54

[목표 🎯]

cv2, darkflow 로 분석한 prediction 결과를 페이지 위에 띄워주기

(cv2.putText() 로 영상 위에 띄우는 거는 우리가 만드는 서비스에 의미가 없기 때문)

 

[생각 🤔]

 

1. 서버 - 클라이언트 간에 비동기 통신이 가능해야 한다.

 👉채팅 구현한 것에서 가져와보자

 👉socketio, websocket 조사 (websocket ㅂ2ㅂ2)

 👉socketio 이용해서 백엔드 내에서 분석한 결과를 클라이언트의 호출 없이 보내는 방법 시도

 👉실패 😭

 

2. 다시 처음부터 생각

 👉html 자체는 정적인 페이지 밖에 만들 수 없다

 👉동적 페이지를 만들기 위해서는 자바스크립트 사용

 👉조사 => ajax ?

 👉ajax setInterval 함수로 1초마다 백엔드로 request를 보내 결과값 전송받으면?

      => setInterval() 그냥 jquery 에 있는 함수다..

 👉일단 성공.. 근데 더 나은 방법이 있을 것 같으니 이번주는 계속 조사해 보자

 

[코드 구현]

 - webcam.html

<html>
  <head>
    <meta charset="UTF-8">
    <title>Flask-darkflow-web-streaming</title>
    <script src="../static/js/jquery-3.4.1.js"></script>
    <script>

      $(document).ready(function()  {
        setInterval("ajaxd()", 1000); // call every 1 seconds
      });

      function ajaxd()  {
        // reload result into element with id "resultReceived"
        $("#resultReceived").load("/sendResult")
      }
    </script>
  </head>

  <body>
    <h1>Video Streaming Demonstration</h1>
    <img id="bg" src="{{ url_for('video_feed') }}">
    <h2> Predict Result </h2>
    <textarea id="resultReceived" rows="10" cols="50">{{ resultReceived }}</textarea>
  </body>
</html>

 

- server.py

from flask import Flask, url_for, render_template, Response
from darkflow.net.build import TFNet
import cv2
import tensorflow as tf
import threading
import numpy

app = Flask(__name__)

# ajax 통신 변수
tem_message = "temporary"
final_message = "prediction result"

options = {"model": "./cfg/yolo.cfg", "load": "./bin/yolo.weights", "threshold": 0.4}

tfnet = TFNet(options)

def gen(camera):
    sess = tf.Session()
    with sess.as_default():
        while True:
            success, img = camera.read()
            if success:
                    results = tfnet.return_predict(img)

                    for result in results:
						# 생략
                        
                        # ajax 통신 함수 변수 reset (나중에 dictionary 형태로도)
                        global tem_message
                        tem_message = label
                        
                        # log 체크
                        print("result: ", label, "| confidence: ", confidence)

                    #cv2.imshow('frame',img)

                    ret, jpeg = cv2.imencode('.jpg', img)
                    frame = jpeg.tobytes()

                    yield (b'--frame\r\n'
                           b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

            else:
                print("Status of camera.read()\n", success, img, "\n=======================")

# ajax 통신 함수
@app.route("/sendResult")
def sendResult():
    global tem_message, final_message

    if tem_message == "temporary":
        final_message = "no prediction yet"

    else:
        final_message = tem_message

    return final_message

# 생략

# ajax 통신 함수 반영 sendResult()
@app.route('/')
def webcam():
    return render_template('webcam.html', resultReceived=sendResult())

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

 

[실행영상]

 

 

[final result 띄우기 추가]

=> input 란에 focus 된 상태에서 엔터키를 누르면 setInterval 함수를 중단하고 textarea 안에 있는 값을 가져온다

=> 수정할 수 없도록 readonly 속성 추가

 

-- 코드 올릴 예정 --