작성
·
137
0
yoloV9과 flask 연동해서 웹 사이트에 객체 탐지한 결과를 출력하는 페이지를 만들고 있는데 결과 사진이 html에 뜨지 않고 새로운 창으로 뜨게 됩니다...ㅜㅜ 그리고 TypeError: 'NoneType' object is not iterable 이런 오류가 발생하는데 관련이 있을까요??? 해결해주시면 너무 감사할 것 같습니다!
#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 속성에 할당해야 하는지를 코드로 어떻게 작성하는지 알려주실 수 있나요?