3-20 Flask Opencv 웹캠에 의한 웹서버에서 안면인식 결과 비데오 파일 저장

댓글 0

Flask

2020. 5. 13.

Flask에 의한 웹서버에서 OpencvVideoCaptue(0) 명령을 사용하면 윈도우즈에 설치된 Default 카메라에 의해 영상을 찍을 수 있으며 이 영상을 imencode 하여 웹상에서 출력이 가능하다. 한편 imencode 작업 이전에 Haarcascade에 의한 안면 인식이 이루어지면 아래의 코드 사례에서처럼 그 결과를 원(cv2.circle())이나 직사각형(cv2.rectangle()) 형태로 영상에 표현할 수 있으며 텍스트 정보(putText())나 시간 정보도 영상에 출력이 가능하다. 한편 도형 및 텍스트 정보기 추기된 이미지 정보를 웹상에 올림과 아울러 비데오 이미지를 저장하도록 하자. Opencv에서 비데오 이미지 저장 명령은 cv2.VideoWriter_fourcc() cv2.VideoWrite() 이다. cv2.VideoWriter_fourcc()에서는 비데오 코덱을 설정한다. XVID 가 가장 보편적으로 많이 사용되고 MJPG는 비데오 크기가 커지며 반면에 X264는 작은 크기에 적합하다. 비데오 이미지를 구성하는 개별 이미지가 준비되면 .write() 명령을 사용하여 출력한다.


현재의 코드는 Flask Workframe 이므로 비데오 영상이 url 127.0.0.1:5000 에 출력되지만 저장은 현재 실행 중인 코드가 위치한 폴더에 저장된다.



현재의 Flask 파이선 코드는 윈도우즈10에서 충분히 빠르게 실행이 된다. 아울러 현재의 PC에 소속된 기관 내부의 ip 가 있으나 무선 공유기 iptime을 설치하였기 때문에 그 local ip 192.168.0.3 으로 설정되었다. 따라서 함께 네트워크 된 라즈베리 파이에서 웹 서빙을 받을 수 있는데 url192.168.0.3:5000을 입력해 보자. 원활한 속도로 영상을 모니터링 할 수 있다. 하지만 역으로 라즈베리 파이에서 현재의 코드가 실행은 가능하지만 실행 속도가 현저히 느려 원활한 영상을 보기는 어렵다.


Flask 파이선 코드에서는 파이선 실행코드가 위치한 폴더에 templates 폴더가 있어야 하며 그 안에 index.html 파일이 있어야 한다.

#face_detect_web_video_save.py

    app.run(host='0.0.0.0') 
import cv2
import numpy as np
import time
import datetime
import sys

faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
num = 3
app = Flask(__name__)

@app.route('/')
def index():
    """Video streaming home page."""
    now = datetime.datetime.now()
    timeString = now.strftime("%Y-%m-%d %H:%M")
    templateData = {
            'title':'Image Streaming',
            'time': timeString
            }
    return render_template('index.html', **templateData)

def gen_frames():

    camera = cv2.VideoCapture(0)
    width = camera.get(cv2.CAP_PROP_FRAME_WIDTH) 
    height = camera.get(cv2.CAP_PROP_FRAME_HEIGHT)   
    fourcc = cv2.VideoWriter_fourcc(*"XVID")
    fps = 30
    out = cv2.VideoWriter('video.avi', fourcc, fps, (int(width), int(height)))

   
    time.sleep(0.2)
    lastTime = time.time()*1000.0

    while True:
        ret, image = camera.read()
       
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
       
        faces = faceCascade.detectMultiScale(gray,scaleFactor=1.1,minNeighbors=6)
        delt = time.time()*1000.0-lastTime
        s = str(int(delt))
        #print (delt," Found {0} faces!".format(len(faces)) )
        lastTime = time.time()*1000.0
        # Draw a rectangle around the faces
        for (x, y, w, h) in faces:
            cv2.circle(image, (int(x+w/2), int(y+h/2)), int((w+h)/3), (255, 255, 255), 3)
        cv2.putText(image, s, (10, 25),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
        now = datetime.datetime.now()
        timeString = now.strftime("%Y-%m-%d %H:%M")
        cv2.putText(image, timeString, (10, 45),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)
        #cv2.imshow("Frame", image)
        out.write(image)
      
        key = cv2.waitKey(1) & 0xFF
     # if the `q` key was pressed, break from the loop
        if key == ord("q"):
            break
   
        ret, buffer = cv2.imencode('.jpg', image)
        frame = buffer.tobytes()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
    camera.release()
    out.realease()
    cv2.destroyAllWindows()
       
 
@app.route('/video_feed')

def video_feed():
    """Video streaming route. Put this in the src attribute of an img tag."""
    return Response(gen_frames(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

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



#index.html

<!doctype html>
<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
          integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

    <title>{{title}}</title>
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-lg-8  offset-lg-2">
            <h3 class="mt-5">{{time}}</h3>
            <img src="{{ url_for('video_feed') }}" width="100%">
        </div>
    </div>
</div>
</body>
</html>