※파이선 코딩 초보자를 위한 텐서플로우∙OpenCV 머신 러닝 2차 개정판 발행
http://blog.daum.net/ejleep1/1175
-------------------------------------------------------------------------------------------------
라즈베리 파이 보드에서 네트워킹 된 외부의 사용자가 특정한 웹 주소의 컨텐츠를 공유할 수 있도록 해 주는 웹서버 구축에 대단히 편리한 Workframe 중의 하나가 Flask 이다.
라즈베리 파이 보드에서 Flask Workframe을 사용하여 웹캠을 사용하는 실시간 웹서버를 파이선 코드를 구성해 보자. 웹서버란 웹의 url 을 통해 request를 보낼 경우 특별하게 지정된 ip 번호인 0.0.0.0:5000 또는 127.0.0.1:500에 출력을 공유하는 시스템이다. 특히 파이선 Flask에서 host=’0.0.0.0’ 으로 설정할 경우 이는 Flask 코드가 실행되며 자체 로컬 ip를 가지는 컴퓨터 웹에서 출력 확인도 가능하지만 아울러 로컬 ip를 끈 상태에서 연결된 네트워킹된 컴퓨터에서 ‘로컬 ip:’ +‘5000’ 으로 request 하여 출력 공유가 가능해진다.
라즈베리 파이 보드를 사용하여 비데오 스트리밍 데이터를 네트워킹 된 컴퓨터에서 웹서빙 받기 위해서 사용하는 카메라는 PiCamera 와 웹캠 2종이 있을 수 있다. PiCamera를 사용할 경우에는 지원 라이브러리인 PiCamera 와 PiRGBArray를 사용하여 코드를 작성이 가능하겠지만 반면에 일반 usb 웹캠을 사용할 경우에는 별도의 지원 라이브러리가 없어 곤란해진다. 한편 인텔의 Opencv 라이브러리를 사용하면 PiCamera든 C270 로지텍 웹캠이든 비데오 영상 스트리밍이 가능해지며 이 기법을 Flask Workframe 에 적용해 보기로 한다.
Opencv에서 웹캠이나 PiCamera를 공통적으로 사용하기 위해서는 Rasberry Pi Configuration 의 Interface에서 Camera 기능을 Disable 로 처리해 두어야 카메라가 웹캠이든 PiCamera이든 VideoCature(0) 명령에 의해 비데오 카메라로 인식된다. 물론 Opencv 카메라로 인식 될 경우 frame rate 이 일정한 값인 30 으로 고정되는 듯하지만 그다지 문제가 되는 않는다. 아울러 SSH(Secure Shell)는 Enable 로 설정해야 네트워킹 된 컴퓨터에서 웹서빙을 받을 수 있게 된다. Real VNC 에 네트워크된 디바이스에서의 모니터링 기능도 마찬가지로 웹서버 이상의 기능을 보여 주지만 화면 캡춰가 되지 않아 진정한 공유가 불가능한 단점이 있음에 유의하자.
Flask_webcam.py 의 코드 구조를 살펴보자. 라이브러리 영역에서 Flask 와 한 세트인 render_template, Response 와 함께 Opencv에 해당하는 cv2를 import 하자. Opencv를 사용하면 PiCamera 와 같은 특정한 카메라의 특정 라이브러리 사용을 피할 수도 있으나 PiCamera 특유의 기능을 사용하지 못하게 됨에 유의하자.
Flask 코드의 특징 적인 구조는 Flask 선언, root 즉 ‘/’에서 index.html을 사용하는 @app.route(‘/’) , root 의 하부 폴더 위치에 해당하는 즉 ‘/video_feed’, 웹의 host 로컬 ip 와 port 설정 영역으로 구성된다. 현재의 코드에서처럼 port 설정이 생략되어 있으면 Default인 5000 이 된다. 이 port 넘버는 반드시 4자리라야 하며 예를 들어 2자리 수는 안된다. 한편 host 로컬 ip 는 0.0.0.0 으로설정할 경우 네트워킹된 외부 컴퓨터의 웹에서 현재 Flask 코드 실행 중인 컴퓨터의 로컬 ip + ‘:5000’ 을 웹 url에 입력하여 request를 보낼 수 있으나 로컬 ip를 127.0.0.1 로 설정하는 경우에는 외부네트워크로부터 request를 받을 수 없음에 유의하자. 아울러 외부로부터 네트워킹을 위해서는 Flask 코드를 실행하는 컴퓨터의 웹을 반드시 꺼야 함에도 유의하자.
한편 실행코드인 Flask_webcam.py 가 위치한 폴더에 templates폴더가 함께 위치해야 하며 그 안에 index.html 있어야 한다.
아래의 index.html 코드 구조에는 헤드, CSS 및 title에 이어 Live Streaming 텍스트 문자열과 함께 지정된 url로 대표되는 image source 즉 img src=∙∙∙로 정의되는 스트림 영상 주소가 코딩된다.
코드를 실행하면서 파이선 셸에서 웹 url 과 연결 상태를 모니터링 해 보자. /HTTP/1.1 200 은 제대로 네트워크 연결이 성공적으로 되었다는 의미이며 404 는 에러호서 통신연결 불능 상태이거나 인위적으로 차단했다는 의미이다. 현재 코드에서 host=0.0.0.0 오로 설정했지만 섈에서의 Flask Workframe 의 반응은 자동적으로 127.0.0.1 로 처리 되고 있음을 알 수 있다. 한편 네트워킹 된 외부 컴퓨터의 웹에서 통신 연결을 하려면 라즈베리 파이 보드 터미널에서 ifconfig 명령에 의해 확인 가능한 로컬 ip 번호를 알고 있어야 request를 전송할 수 있다.
첨부된 코드를 다운받아 Flask 웹서버를 실행해 보자.
#Flask_webserver.py
from flask import Flask, render_template, Response
import cv2
app = Flask(__name__)
camera = cv2.VideoCapture(0) # use 0 for web camera
def gen_frames(): # generate frame by frame from camera
while True:
# Capture frame-by-frame
success, frame = camera.read() # read the camera frame
if (not success):
break
else:
ret, buffer = cv2.imencode('.jpg', frame)
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
# concat frame one by one and show result
@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')
@app.route('/')
def index():
"""Video streaming home page."""
return render_template('index.html')
if (__name__ == '__main__'):
app.run(host='0.0.0.0', port=8080)
<!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>Live Streaming Demonstration</title> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-lg-8 offset-lg-2"> | |
<h3 class="mt-5">Live Streaming</h3> | |
<img src="{{ url_for('video_feed') }}" width="100%"> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> |
'라즈베리' 카테고리의 다른 글
라즈베리 파이 3 Flask 웹서버 코딩에 의한 웹 출력 예제 (0) | 2020.04.28 |
---|---|
7-3-6 보조 리튬배터리로 라즈베리파이3 파워 ON 시험 (0) | 2019.12.30 |
1-240 Ubuntu Mate 라즈베리파이+3에서 OpenCV 4 설치 (0) | 2019.09.20 |
1-239 Ubuntu Mate 라즈베리파이+3에서 Pi camera를 설치하자. (0) | 2019.09.11 |
1-238 Ubuntu Mate 라즈베리파이+3에서 Adafruit DHT11 로 온습도 측정 (0) | 2019.09.10 |