강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

박예린님의 프로필 이미지
박예린

작성한 질문수

yoloV9, flask 연동 시 오류 발생

작성

·

137

0

yoloV9과 flask 연동해서 웹 사이트에 객체 탐지한 결과를 출력하는 페이지를 만들고 있는데 결과 사진이 html에 뜨지 않고 새로운 창으로 뜨게 됩니다...ㅜㅜ 그리고 TypeError: 'NoneType' object is not iterable 이런 오류가 발생하는데 관련이 있을까요??? 해결해주시면 너무 감사할 것 같습니다!

 

flaskApp.py

#Import All the Required Libraries
from flask import Flask, render_template, Response, jsonify, request, session
from flask_wtf import FlaskForm
from wtforms import FileField, SubmitField
from werkzeug.utils import secure_filename
from wtforms.validators import InputRequired
from detection import objectDetection
import os
import cv2

#Initialize the Flask Application
app = Flask(__name__)
#Configure a secret key
app.config['SECRET_KEY'] = 'muhammadmoin'
#Store the input files uploaded in the application
app.config['UPLOAD_FOLDER'] = 'static/files'

#Use FlaskForm to get the input file form the user
class UploadFileForm(FlaskForm):
    file = FileField('File', validators=[InputRequired()])
    submit = SubmitField('Run')
fpsCount = 0
frameSize = 0
detectedObjects = 0
def generate_frames(path):
    yolov9_output = objectDetection(path)
    for im0, frameRate, frameShape, totalDetection in yolov9_output:
        ret, buffer = cv2.imencode('.jpg', im0)
        global fpsCount
        fpsCount = str(frameRate)
        global frameSize
        frameSize = str(frameShape[0])
        global detectedObjects
        detectedObjects = str(totalDetection)
        frame = buffer.tobytes()
        yield(b'--frame\r\n'
              b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')


@app.route('/', methods=['GET', 'POST'])
def front():
    form = UploadFileForm()
    if form.validate_on_submit():
        file = form.file.data
        filename = secure_filename(file.filename)
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(file_path)
        session['filePath'] = file_path
        return render_template('index.html', form = form, uploaded = True, filename = filename)
    return render_template('index.html', form = form, uploaded = False)


@app.route('/detections', methods = ['GET', 'POST'])
def detections():
    file_path = session.get('filePath', None)
    if file_path:
        return Response(generate_frames(path=file_path), mimetype='multipart/x-mixed-replace; boundary=frame')
    else:
        return "No video uploaded"

@app.route('/fps', methods = ['GET', 'POST'])
def fps():
    global fpsCount
    return jsonify(fpsresult=fpsCount)

@app.route('/dcount', methods = ['GET'])
def dcount():
    global detectedObjects
    return jsonify(dcountresult=detectedObjects)

@app.route('/fsize', methods = ['GET'])
def fsize():
    global frameSize
    return jsonify(fsizeresult=frameSize)

if __name__ == "__main__":
    app.run(debug=True)


index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width", initial-scale="1.0">
    <title>스마트 건설환경 안전관리 시스템</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons"
          rel='stylesheet'>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100..900&display=swap"
          rel="stylesheet">
</head>

<body>
    <!-- main page -->
    <div class="main-page">
        <!-- side line -->
        <div class="side-line"></div>
        <!-- side bar -->
        <div class="side-bar">
            <form id="upload-form" method="POST" enctype="multipart/form-data">
                {{ form.hidden_tag() }}
                {{ form.file(id='file', style='display: none;') }}
                <span class="circle" id="upload-icon"><i class="material-icons" style="font-size: 36px; color: white;">file_upload</i></span>
            </form>
            <span class="circle blue-circle" id="detect-icon"><i class="material-icons" style="font-size: 36px; color: white;">play_arrow</i></span>

            <span class="circle" id="button-rgb-img"><i class="material-icons" style="font-size: 36px; color: white;">palette</i></span>
            <span class="circle" id="button-gray-scale"><i class="material-icons" style="font-size: 36px; color: white;">contrast</i></span>
            <span class="circle" id="button-blur"><i class="material-icons" style="font-size: 36px; color: white;">blur_on</i></span>
            <span class="circle" id="button-canny-image"><i class="material-icons" style="font-size: 36px; color: white;">grade</i></span>
            <span class="circle blue-circle"><i class="material-icons" style="font-size: 36px; color: white;">videocam</i></span>
        </div>
        <!-- right panel -->
        <div class="right-panel">
            <!-- Header -->
            <div class="header">
                    <div class="empty-container"></div>
                    <h1>스마트 건설환경 안전관리 시스템</h1>
<!--                    <div class="logo-container"><img src="{{ url_for('static', filename='logo.png') }}" width="90" height="30" alt=""></div>-->
<!--                 Tablet Container -->
                <div class="tablet-container">
                    <img id="tablet-image" src="{{ url_for('static', filename='tablet.png') }}" width="800" height="600" alt="">
                    <img id="image-main" src="{{ url_for('detections') }}" width="740" height="540" alt="">
                    <canvas id="main-canvas" width="740" height="540">

                    </canvas>
                </div>
            </div>
        </div>

        <script>
            document.getElementById('upload-icon').addEventListener('click', function () {
                document.getElementById('file').click();
            });

            document.getElementById('detect-icon').addEventListener('click', function () {
                document.getElementById('upload-form').submit()
            });
        </script>
    </div>
</body>

</html>

 

답변 1

1

안녕하세요, 인프런 AI 인턴입니다.

박예린님, yoloV9과 flask 연동 시 발생하는 문제 관련하여 도움을 드리고자 합니다.

TypeError: ‘NoneType’ object is not iterable 오류는 대개 반복 가능한 객체가 없는 경우 발생합니다. 이 경우, objectDetection 함수의 path 인자로 전달된 파일 경로에 문제가 있거나 해당 함수 자체에서 예상치 못한 값이 반환되어 발생할 수 있습니다. objectDetection 함수가 정상적으로 반복 가능한 객체(예: 리스트, 튜플 등)를 반환하는지 확인해 보세요.

또한 결과 사진이 HTML에서 뜨지 않고 새 창으로 뜨는 문제는 HTML 태그 내부에서 미디어 리소스를 불러오는 방식에 따라 다를 수 있습니다. 현재 코드에서는 <img id="image-main" src="{{ url_for('detections') }}" width="740" height="540" alt=""> 이 방식을 사용하고 있습니다. 이때, src 속성에 detections 경로를 설정하셨는데, 이 경로가 동영상 스트리밍을 위한 Response 객체를 반환하고 있습니다. 객체 탐지된 결과를 이미지 형태로 웹 페이지 내에 직접 나타내고자 한다면, 각 프레임을 정적 파일로 저장한 뒤 해당 파일의 URL을 src 속성에 할당하는 방식을 고려해볼 수 있습니다.

이러한 문제를 해결하기 위해선 상태 코드에 따른 에러 처리나 정적 파일 및 템플릿 처리 방식을 flask 및 웹 개발 문서에서 추가적으로 확인해보시는 것을 추천드립니다. Flask와 관련된 추가적인 지원이 필요하시면, Flask 공식 문서(http://flask.pocoo.org/docs/)를 참조해 주세요. Flask를 이용한 웹 개발을 진행하실 때 이 문서들이 좋은 참고자료가 될 것입니다.

문제 해결 과정에서 궁금한 사항이 발생하면 언제든지 질문해 주세요. 감사합니다.

박예린님의 프로필 이미지
박예린
질문자

그럼 객체 탐지된 결과를 비디오 형태가 아닌 이미지 형태로 웹 페이지 내에 직접 나타내고자 할 때 어떻게 해당 파일의 URL을 src 속성에 할당해야 하는지를 코드로 어떻게 작성하는지 알려주실 수 있나요?

박예린님의 프로필 이미지
박예린

작성한 질문수

질문하기