코드 분석
openCV로 카메라 연동해서 로컬 서버를 만드는 코드입니다.
from flask import Flask, Response, redirect, url_for
import cv2
app = Flask(__name__)
def generate():
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
if not cap.isOpened():
print("Error: Could not open video device.")
return
while True:
ret, frame = cap.read()
if not ret:
print("Error: Failed to capture image.")
break
_, jpeg = cv2.imencode('.jpg', frame)
frame = jpeg.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
cap.release()
@app.route('/')
def index():
# 루트 경로에서 /video_feed로 리디렉션
return redirect(url_for('video_feed'))
@app.route('/video_feed')
def video_feed():
return Response(generate(),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
generate 함수
cap = cv2.VideoCapture(0)
- 카메라 장치를 video0 으로 설정합니다.
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
- 카메라 해상도를 설정합니다.
while True:
ret, frame = cap.read()
if not ret:
print("Error: Failed to capture image.")
break
- 무한 루프를 실행하여 계속해서 프레임을 캡처하고 전송합니다.
- ret, frame = cap.read(): 카메라에서 한 프레임을 읽어옵니다.
- ret은 영상 프레임을 읽었는지 성공 여부를 나타내는 Bool 값입니다.
- frame은 실제 영상 데이터(프레임)을 나타냅니다.
_, jpeg = cv2.imencode('.jpg', frame)
frame = jpeg.tobytes()
- _, jpeg = cv2.imencode('.jpg', frame): frame을 JPEG 형식의 이미지로 인코딩합니다. _는 첫 번째 반환값(성공 여부)을 무시하는 것입니다.
- frame = jpeg.tobyptes(): 인코딩된 JPEG 이미지를 바이트 형식으로 변환하여 네트워크 전송에 적합하게 합니다.
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
- yield: 제너레이터 함수에서 값을 반환하고, 다음 호출 때 다시 실행을 재개합니다. 여기서는 MJPEG 형식의 HTTP 응답을 실시간 스트리밍 형식으로 제공합니다.
- b'--frame\r\n': 각 프레임의 시작을 나타내는 MJPEG 경계(boundary)로, 클라이언트가 이미지의 시작과 끝을 인식할 수 있게 합니다.
- b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n': HTTP 헤더와 함께 JPEG 이미지 데이터를 전송합니다.
cap.release()
- 카메라를 해제하여 다른 프로세스가 접근할 수 있도록 합니다.
URL 도메인 설정하기
@app.route('/')
def index():
# 루트 경로에서 /video_feed로 리디렉션
return redirect(url_for('video_feed'))
- @app.route('/'): Flask 애플리케이션의 루트 경로(http://<IP 주소>:5000/)에서 이 함수를 실행하도록 설정합니다.
- def index(): 루트 경로에 대한 핸들러 함수입니다.
- return redirect(url_for('video_feed')): video_feed 엔드포인트로 리디렉션하여 실시간 스트림이 표시되도록 합니다.
@app.route('/video_feed')
def video_feed():
return Response(generate(),
mimetype='multipart/x-mixed-replace; boundary=frame')
- @app.route('/video_feed'): /video_feed 경로에서 이 함수를 실행하도록 설정합니다.def video_feed(): /video_feed 경로에 대한 핸들러 함수입니다.
- return Response(generate(), mimetype='multipart/x-mixed-replace; boundary=frame'): generate 함수를 호출하여 반환된 스트림을 HTTP 응답으로 보냅니다.
- mimetype='multipart/x-mixed-replace; boundary=frame'은 MJPEG 스트리밍을 위해 필요한 MIME 타입으로, 클라이언트가 여러 이미지를 스트리밍 형식으로 처리할 수 있게 합니다.