관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

컴퓨터 비전 5 - 플라스크 실습해보기 본문

인공지능/컴퓨터 비전

컴퓨터 비전 5 - 플라스크 실습해보기

huenuri 2024. 11. 14. 04:14

5일 전에 컴퓨터 비전 수업을 듣다가 말았는데 오늘 이 수업들을 모두 듣고 정리하려고 한다. 그동안 책으로 학습했었는데 책이 너무 어렵기도 하고 지금의 수준에서 공부를 하는 건 별 의미가 없는 것 같아 여기서 멈추고 12월 말까지 웹 개발 공부를 어느 정도 끝내놓고 다시 컴퓨터 비전으로 돌아와 나머지 공부를 이어가기로 했다.

사실 몇 개의 수업 영상이 빠져있어 인사교에서 진행했던 컴퓨터 비전 수업은 더이상 듣지 않으려고 했었다. 근데 오늘 자료를 살펴보다 선생님이 마지막날 자료를 올려주셨다는 걸 알게 되었다. 부족한대로 이 자료만 보면서 코드를 예측하며 실습을 진행할 생각이다.

 

조금 전에 다른 선생님이 하시는 컴퓨터 비전 수업을 들어보다가 먼저 이 실습부터 진행하는 것이 학습 진도에 맞을 것 같아 플라스크 실습부터 시작해보겠다.


 

 

 

플라스크 실습해보기

 

 

 

 

 

 

 

내용 설명

  1. app = Flask(__name__)
    • Flask 클래스의 인스턴스인 app을 생성하는 코드이다. __name__은 파이썬에서 현재 모듈의 이름을 나타내며, Flask 애플리케이션을 생성하고 초기화하는 데 사용된다.
    • app = Flask(__name__) 코드를 통해 Flask 애플리케이션을 초기화하고 기본 설정을 한다.
    • 이 파일을 보통 app.py라는 이름으로 저장하고 실행하여 애플리케이션을 구동시킨다.
  2. @app.route('/')
    • @app.route는 Flask의 라우트 데코레이터로, 특정 URL에 대해 함수가 실행되도록 연결해주는 역할을 한다.
    • @app.route('/')는 루트 경로, 즉 기본 경로를 설정한다. 예를 들어, http://localhost:5000/으로 접속했을 때 연결된 함수가 실행된다.
    • @app.route('/mail')과 같이 다른 경로를 설정할 수도 있다. 예를 들어, http://localhost:5000/mail로 접속했을 때 메일 관련 함수가 실행되도록 할 수 있다.

 

예시 설명

  • @app.route('/mail')이 있을 경우:
    • http://www.naver.com/mail과 같은 주소로 접근하면, /mail 경로에 해당하는 함수를 실행하여 메일 관련 처리를 하게 된다.
    • 이처럼 특정 URL 경로에 따라 다른 함수를 연결하여 웹 애플리케이션에서 다양한 페이지와 기능을 제공할 수 있다.

 

 

코드 실습해보기

 

이상한 코드가 뜨는데 해당 메시지는 사용 중인 환경(특히 Windows)에서 mkdir와 touch 명령어가 작동하지 않을 때 나타나는 오류 메시지다. 이 명령어들은 일반적으로 리눅스와 맥에서 사용되며, 윈도우 환경에서는 동작하지 않는다.

 

 

해결 방법 (Windows 환경)

Windows에서는 mkdir은 그대로 사용할 수 있지만, touch 명령어는 사용할 수 없으므로 다른 방법으로 파일을 생성해야 한다.

명령어를 수정하여 사용하기

 

  • mkdir: Windows에서도 폴더를 생성하는 데 사용할 수 있다.
  • echo. > filename: 빈 파일을 생성하는 Windows 명령어이다. 이 명령어로 app.py와 profile.html 파일을 생성할 수 있다.

하지만 빨간 줄이 잔뜩 떴다. VS Code에서 mkdir 및 echo 명령어를 Python 코드가 아닌 터미널에서 직접 실행해야 한다. 이 명령어들은 운영 체제의 명령 프롬프트나 쉘 명령어이며, Python 코드로 인식되지 않기 때문에 코드 편집기에서 작성할 때 빨간줄이 나타난다.

 

 

 

 

터미널 창에서 다음과 같이 작성해주었다. 터미널 창에 입력한 명령어가 성공적으로 실행되었다면, 필요한 폴더와 파일들이 생성된 상태이다. 이제 프로젝트 구조가 준비되었으므로 Flask 애플리케이션을 작성하고 실행할 준비가 되었다.


 

 

 

생성된 디렉토리와 파일 구조

입력한 명령어들로 인해 아래와 같은 폴더와 파일 구조가 생성된다.

Computer Vision/
├── flask/
│   ├── static/             # 정적 파일(CSS, JS, 이미지)을 저장할 폴더
│   ├── templates/          # HTML 템플릿을 저장할 폴더
│   │   └── profile.html    # HTML 파일 (빈 파일로 생성됨)
│   └── app.py              # Flask 애플리케이션 파일 (빈 파일로 생성됨)

 

 

1. app.py 파일 작성

 

flask/app.py 파일을 열고 Flask 애플리케이션 코드를 작성하자.

 

이 코드에 대해서 설명해보겠다. 선생님은 코드를 어디서 제공한 것을 그대로 복사했나보다. 코드 설명이 영어로 되어 있다. 난 이것을 다음과 같이 수정해보았다.

 

 

 

 

이 코드에서 Flask 애플리케이션은 카메라로부터 프레임을 실시간으로 가져와 웹 브라우저에 스트리밍한다. /video_feed 경로는 생성된 프레임을 계속해서 제공하며, / 경로는 index.html 템플릿을 렌더링하여 웹 페이지를 표시하는 역할을 한다.

 

코드 설명

1. 라이브러리 임포트

from flask import Flask, render_template, Response
import cv2

 

  • Flask : Flask는 파이썬 기반의 웹 프레임워크로, 이 코드에서 웹 서버 역할을 한다.
  • render_template : HTML 템플릿을 렌더링하는 함수로, 여기서는 웹 페이지를 표시하는 데 사용된다.
  • Response : 비디오 프레임을 HTTP 응답으로 전송하기 위해 사용된다.
  • cv2 : OpenCV 라이브러리로, 웹캠에서 비디오를 캡처하고 이미지를 처리하는 데 사용된다.

 

2. Flask 애플리케이션 및 웹캠 초기화

app = Flask(__name__)
camera = cv2.VideoCapture(0)  # 0번 웹캠을 사용

 

 

  • app = Flask(__name__): Flask 애플리케이션 인스턴스를 생성한다.
  • camera = cv2.VideoCapture(0): 웹캠 객체를 초기화한다. 0은 기본 웹캠을 나타내며, 외장 웹캠을 사용할 경우 1이나 다른 번호를 입력하면 된다.

 

 

3. 프레임 생성 함수 gen_frames()

def gen_frames():
    while True:
        _, frame = camera.read()  # 카메라로부터 프레임을 읽음
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 프레임을 흑백으로 변환
        ret, buffer = cv2.imencode('.jpg', frame)  # 프레임을 JPG 형식으로 인코딩
        frame = buffer.tobytes()  # 바이트로 변환
        yield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

 

  • camera.read(): 카메라로부터 프레임을 한 장 읽어온다.
  • cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY): 프레임을 흑백으로 변환한다.
  • cv2.imencode('.jpg', frame): 프레임을 JPG 형식으로 인코딩한다.
  • yield 구문을 통해 프레임을 스트리밍 방식으로 반환한다. HTTP multipart 형식을 사용해 프레임을 연속해서 전송한다.

 

4. 비디오 피드 경로 /video_feed

@app.route('/video_feed')
def video_feed():
    return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')

 

 

  • /video_feed 경로는 gen_frames() 함수에서 생성된 프레임을 HTTP 응답으로 전송하는 엔드포인트이다.
  • mimetype='multipart/x-mixed-replace; boundary=frame'를 사용해 비디오 스트리밍을 위한 MIME 타입을 지정한다. 이 타입을 사용하면 여러 프레임을 하나의 응답으로 스트리밍할 수 있다.

 

5. 홈페이지 경로 /

 

@app.route('/')
def index():
    return render_template('index.html')

 

  • / 경로는 홈페이지로, index.html 템플릿 파일을 렌더링하여 사용자가 웹 페이지에 접속할 때 기본 화면을 보여준다.
  • index.html에는 <img src="/video_feed"> 태그를 사용해 /video_feed 경로에서 제공하는 실시간 비디오 스트림을 표시할 수 있다.

 

6. 애플리케이션 실행

if (__name__ == '__main__'):
    app.run(host='localhost', port=7999)

 

 

  • app.run(host='localhost', port=7999): Flask 애플리케이션을 localhost:7999에서 실행한다.
  • 브라우저에서 http://localhost:7999/로 접속하면 웹 페이지가 표시되며, 실시간 비디오 피드가 시작된다.

 


 

 

 

2. index.html 파일 작성

이제 templates 폴더 안에 index.html 파일을 작성해야 한다. 이 파일은 웹 브라우저에서 /video_feed 경로로부터 스트리밍된 비디오를 표시하는 역할을 한다.

 

 

이 index.html 파일은 Flask 애플리케이션에서 웹캠 비디오 스트리밍을 표시하는 웹 페이지 템플릿이다. 

 

  1. <!DOCTYPE html>: HTML5 문서임을 선언한다.
  2. <html>, <head>, <body>: HTML 문서의 구조를 정의하는 태그이다.
  3. <title>Video Streaming</title>: 브라우저 탭에 표시될 제목을 설정한다. 여기서는 "Video Streaming"이라는 제목이 표시된다.
  4. <h1>Video Streaming</h1>: 페이지의 제목을 표시하는 <h1> 태그이다.
  5. <img src="{{ url_for('video_feed') }}" width="640" height="480" />
    • <img> 태그를 사용해 비디오 스트림을 표시한다.
    • src="{{ url_for('video_feed') }}"는 Flask에서 /video_feed 경로로 연결된 비디오 스트리밍을 가져온다.
    • width="640" height="480" 속성은 이미지의 크기를 설정한다.

 

 

 

Flask 애플리케이션 실행

VS Code 터미널에서 flask/app.py 파일이 있는 폴더로 이동한 후, 아래 명령어로 Flask 애플리케이션을 실행한다.

 

 

하지만 아무것도 실행되지 않았다. 그리고 코드만 보고 어떤 코드인지 예측하면서 공부하는 건 너무 시간도 많이 걸리고 별 의미가 없는 것 같았다. 대충 플라스크로 이렇게 실습을 진행할 수 있다는 것 정도만 알면 될 것 같다.


 

 

 

학습을 마치고

어제는 저녁에 공부가 정말 하기 싫고 피곤해서 그냥 쉬었다. 오늘 새벽에 2시 반에 일어나서 1시간 정도 진행한 실습이다. 30분 정도는 학습 준비를 하고 다른 프로젝트를 실행하며 자료를 다운 받고 살펴보는데 시간을 보냈다. 하지만 별다른 성과가 없었다. 

선생님이 남은 이틀 동안 진행한 코드를 살펴보았는데 별 게 없었다. 그냥 책에 훨씬 더 자세하고 잘 설명이 되어 있어 더 학습을 진행하는 건 시간 낭비만 될 것 같아 여기서 종료하기로 했다.