Flask+TensorFlow飞蝇识别应用:上传文件为空、图片无法显示求助
飞蝇钓假饵识别Flask应用问题排查
我是一名技术新手,同步学习Python、TensorFlow与Flask,开发了飞蝇钓假饵的TensorFlow图像识别模型,本地运行正常,但迁移到Flask Web应用后遇到两个问题:
- 上传的图片文件被保存为0字节文件,文件名正确但内容为空;
- 识别完成后无法正常显示上传的图片,仅显示通用“已上传图片”图标。
识别功能本身可正常运行,以下是我的代码:
FlyFinderWeb.py
from flask import Flask, render_template, request, redirect, url_for, send_from_directory import numpy as np import tensorflow as tf import matplotlib.pyplot as plt import os from io import BytesIO class_names = ['Pheasant Tail Nymph', 'Wooly Bugger', 'adams dry fly', 'elk hair caddis'] img_height = 180 img_width = 180 # Load the saved Keras model keras_model = tf.keras.models.load_model('Fly_classifer_keras_model') app = Flask(__name__) UPLOAD_FOLDER = 'uploads' app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER @app.route('/', methods=['GET', 'POST']) def upload_photo(): if request.method == 'POST': if 'photo' not in request.files: return redirect(request.url) photo = request.files['photo'] if photo.filename == '': return redirect(request.url) if photo: filename = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename) photo.save(filename) return redirect(url_for('display_photo', filename=photo.filename)) return render_template('upload.html') @app.route('/download/<path:filename>') def download_photo(filename): return send_from_directory( os.path.abspath(app.config['UPLOAD_FOLDER']), filename ) @app.route('/display/<filename>') def display_photo(filename): print(os.path.join(app.config['UPLOAD_FOLDER'], filename)) return render_template('display.html', filename=filename) @app.route('/recognize', methods=['POST']) def recognize_fly(): if 'photo' not in request.files: return "No file part" photo = request.files['photo'] if photo.filename == '': return "No selected file" # Convert FileStorage to BytesIO photo_bytes = BytesIO(photo.read()) # Load the TensorFlow model model = keras_model img = tf.keras.utils.load_img(photo_bytes, target_size=(img_height, img_width)) img_array = tf.keras.utils.img_to_array(img) img_array = tf.expand_dims(img_array, 0) predictions = model.predict(img_array) class_index = np.argmax(predictions[0]) class_name = class_names[class_index] score = tf.nn.softmax(predictions[0]) recognition_results = f"I think what you have here is a {class_name}. I'm {100*np.max(score):.2f}% sure of this (but I could be wrong!)." filename = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename) print("Photo size:", len(photo.read())) # Print the size of the photo content print("Uploaded File:", photo.filename) photo.save(filename) return render_template('display.html', filename=photo.filename, recognition_results=recognition_results) app.run(debug=True, use_reloader=True) #automatically restart server if changes are detected if __name__ == '__main__': app.run(debug=True)
display.html
<!doctype html> <html> <head> <title>Display Photo</title> <style> .image-container { text-align: center; margin-bottom: 20px; /* Added margin for spacing */ } .image-container img { max-width: 100%; max-height: 400px; } </style> </head> <body> <h1>Uploaded Photo</h1> <div class="image-container"> <img src="{{ url_for('download_photo', filename=filename) }}" alt="Uploaded Photo"> </div> <h2>Fly Recognition Results:</h2> <p>{{ recognition_results }}</p> <p>Would you like to repeat another?</p> <a href="{{ url_for('upload_photo') }}">Upload Another</a> </body> </html>
upload.html
<!doctype html> <html> <head> <title>Upload and Display Photo</title> </head> <body> <h1>Upload a Photo Please 5.0</h1> <form method="POST" enctype="multipart/form-data" action="{{ url_for('recognize_fly') }}"> <input type="file" name="photo" accept=".jpg, .jpeg, .png"> <input type="submit" value="Submit image to my big Machine Learning brain to see if I can figure out what fly it is"> </form> </body> </html>
问题原因及修复方案
1. 0字节文件问题
问题出在recognize_fly函数:你先调用photo.read()把文件内容读取到photo_bytes,此时文件指针移到末尾,后续再调用photo.read()和photo.save()时,已经没有内容可读,导致保存的文件为0字节。
修复方式二选一:
- 先保存文件,再从本地文件加载图像(推荐):
修改recognize_fly函数:
@app.route('/recognize', methods=['POST']) def recognize_fly(): if 'photo' not in request.files: return "No file part" photo = request.files['photo'] if photo.filename == '': return "No selected file" # 先保存文件到本地 filename = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename) photo.save(filename) # 从本地文件加载图像 img = tf.keras.utils.load_img(filename, target_size=(img_height, img_width)) img_array = tf.keras.utils.img_to_array(img) img_array = tf.expand_dims(img_array, 0) predictions = keras_model.predict(img_array) class_index = np.argmax(predictions[0]) class_name = class_names[class_index] score = tf.nn.softmax(predictions[0]) recognition_results = f"I think what you have here is a {class_name}. I'm {100*np.max(score):.2f}% sure of this (but I could be wrong!)." print("Uploaded File:", photo.filename) return render_template('display.html', filename=photo.filename, recognition_results=recognition_results)
- 读取文件后重置指针:
在第一次photo.read()后添加photo.seek(0),把文件指针移回开头:
# Convert FileStorage to BytesIO photo_bytes = BytesIO(photo.read()) photo.seek(0) # 重置文件指针到开头 # ... 中间识别代码 ... # 此时保存文件就能写入完整内容 photo.save(filename)
2. 图片无法显示问题
主要原因可能是uploads目录未创建,或者文件路径处理错误。
修复步骤:
- 应用初始化时自动创建
uploads目录:
app = Flask(__name__) UPLOAD_FOLDER = 'uploads' app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER # 自动创建uploads目录(不存在则创建) os.makedirs(UPLOAD_FOLDER, exist_ok=True)
- 简化
download_photo路由的路径处理:
@app.route('/download/<path:filename>') def download_photo(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
确认display.html中的图片路径{{ url_for('download_photo', filename=filename) }}正确,只要文件正常保存,就能正常显示。
内容的提问来源于stack exchange,提问作者Dave Franchino
相关产品推荐
相关产品推荐

