Yash goyal commited on
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,6 +3,7 @@ os.environ['MPLCONFIGDIR'] = '/tmp/matplotlib'
|
|
| 3 |
from flask import Flask, render_template, request, redirect, url_for, session, send_file, jsonify
|
| 4 |
from flask_sqlalchemy import SQLAlchemy
|
| 5 |
from flask_migrate import Migrate
|
|
|
|
| 6 |
import tensorflow as tf
|
| 7 |
import numpy as np
|
| 8 |
from PIL import Image
|
|
@@ -151,6 +152,25 @@ def preprocess_image(image_bytes):
|
|
| 151 |
image_array = tf.keras.utils.img_to_array(image)
|
| 152 |
return np.expand_dims(image_array, axis=0) / 255.0
|
| 153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
def generate_pdf(report, filepath):
|
| 155 |
c = canvas.Canvas(filepath, pagesize=A4)
|
| 156 |
width, height = A4
|
|
@@ -236,6 +256,7 @@ def form():
|
|
| 236 |
def training_plot():
|
| 237 |
return send_file(PLOT_PATH, mimetype="image/png") if os.path.exists(PLOT_PATH) else ("", 404)
|
| 238 |
|
|
|
|
| 239 |
@app.route("/uploads/<filename>")
|
| 240 |
def uploaded_file(filename):
|
| 241 |
upload_folder = "/tmp/uploads"
|
|
@@ -244,23 +265,18 @@ def uploaded_file(filename):
|
|
| 244 |
@app.route("/predict", methods=["POST"])
|
| 245 |
def predict():
|
| 246 |
try:
|
| 247 |
-
if model_load_error or not model:
|
| 248 |
-
raise ValueError(f"Model not loaded: {model_load_error}")
|
| 249 |
-
if "image" not in request.files or not request.files["image"].filename:
|
| 250 |
-
raise ValueError("No image uploaded.")
|
| 251 |
-
|
| 252 |
image_file = request.files["image"]
|
| 253 |
image_bytes = image_file.read()
|
| 254 |
|
| 255 |
-
#
|
| 256 |
img_array = preprocess_image(image_bytes)
|
| 257 |
prediction = model.predict(img_array)[0]
|
| 258 |
predicted_index = int(np.argmax(prediction))
|
| 259 |
confidence = float(prediction[predicted_index])
|
| 260 |
label = label_map.get(predicted_index, "Unknown") if confidence >= CONFIDENCE_THRESHOLD else "Low confidence"
|
| 261 |
-
msg = "This image is not confidently recognized.
|
| 262 |
|
| 263 |
-
# Database
|
| 264 |
email = request.form.get("email")
|
| 265 |
user = User.query.filter_by(email=email).first()
|
| 266 |
if not user:
|
|
@@ -268,6 +284,7 @@ def predict():
|
|
| 268 |
db.session.add(user)
|
| 269 |
db.session.commit()
|
| 270 |
|
|
|
|
| 271 |
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
| 272 |
image_filename = f"scan_{user.id}_{timestamp}.jpg"
|
| 273 |
upload_folder = "/tmp/uploads"
|
|
@@ -276,6 +293,7 @@ def predict():
|
|
| 276 |
with open(image_path, "wb") as f:
|
| 277 |
f.write(image_bytes)
|
| 278 |
|
|
|
|
| 279 |
scan = Scan(
|
| 280 |
user_id=user.id, patient_name=request.form.get("name"),
|
| 281 |
patient_gender=request.form.get("gender"), patient_age=int(request.form.get("age")),
|
|
@@ -284,44 +302,25 @@ def predict():
|
|
| 284 |
db.session.add(scan)
|
| 285 |
db.session.commit()
|
| 286 |
|
| 287 |
-
# Prepare
|
| 288 |
report = {
|
| 289 |
"name": request.form.get("name"), "email": email, "gender": request.form.get("gender"),
|
| 290 |
"age": request.form.get("age"), "prediction": label, "confidence": f"{confidence * 100:.2f}%",
|
| 291 |
-
"message": msg, "scan_id": scan.id
|
|
|
|
| 292 |
}
|
| 293 |
|
| 294 |
-
#
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
raise ValueError("Mail server credentials are not configured.")
|
| 298 |
-
|
| 299 |
-
pdf_path = f"/tmp/report_{scan.id}.pdf"
|
| 300 |
-
generate_pdf(report, pdf_path)
|
| 301 |
-
|
| 302 |
-
email_msg = Message('Your SnapSkin Diagnostic Report', sender=app.config['MAIL_USERNAME'], recipients=[email])
|
| 303 |
-
email_msg.body = f"Dear {report['name']},\n\nPlease find your diagnostic report attached.\n\nThank you for using SnapSkin."
|
| 304 |
-
with app.open_resource(pdf_path) as fp:
|
| 305 |
-
email_msg.attach(f"SnapSkin_Report_{scan.id}.pdf", "application/pdf", fp.read())
|
| 306 |
-
mail.send(email_msg)
|
| 307 |
-
|
| 308 |
-
os.remove(pdf_path)
|
| 309 |
-
report["email_status"] = "Success! The report has been sent to your email."
|
| 310 |
-
logger.info(f"Report sent to {email} for scan ID {scan.id}")
|
| 311 |
-
|
| 312 |
-
except Exception as e:
|
| 313 |
-
logger.error(f"Failed to send email for scan ID {scan.id}: {e}")
|
| 314 |
-
report["email_status"] = "Failed to send the report to your email. You can download it directly."
|
| 315 |
|
| 316 |
session["report"] = report
|
| 317 |
return redirect(url_for("result"))
|
| 318 |
|
| 319 |
except Exception as e:
|
| 320 |
logger.error(f"Prediction error: {e}")
|
| 321 |
-
return render_template(
|
| 322 |
-
"prediction": "Error", "
|
| 323 |
-
"message": f"An error occurred during prediction: {e}",
|
| 324 |
-
"email_status": "N/A"
|
| 325 |
})
|
| 326 |
|
| 327 |
@app.route("/result")
|
|
@@ -329,8 +328,6 @@ def result():
|
|
| 329 |
report = session.get("report")
|
| 330 |
if not report:
|
| 331 |
return redirect(url_for("form"))
|
| 332 |
-
# Change this line to render your result.html page
|
| 333 |
-
# The **report unpacks the dictionary into template variables
|
| 334 |
return render_template("result.html", **report)
|
| 335 |
|
| 336 |
@app.route("/download-report")
|
|
|
|
| 3 |
from flask import Flask, render_template, request, redirect, url_for, session, send_file, jsonify
|
| 4 |
from flask_sqlalchemy import SQLAlchemy
|
| 5 |
from flask_migrate import Migrate
|
| 6 |
+
import threading
|
| 7 |
import tensorflow as tf
|
| 8 |
import numpy as np
|
| 9 |
from PIL import Image
|
|
|
|
| 152 |
image_array = tf.keras.utils.img_to_array(image)
|
| 153 |
return np.expand_dims(image_array, axis=0) / 255.0
|
| 154 |
|
| 155 |
+
# NEW: Function to send email in a background thread
|
| 156 |
+
def send_email_async(app_context, report_data):
|
| 157 |
+
with app_context:
|
| 158 |
+
try:
|
| 159 |
+
pdf_path = f"/tmp/report_{report_data['scan_id']}.pdf"
|
| 160 |
+
generate_pdf(report_data, pdf_path)
|
| 161 |
+
|
| 162 |
+
msg = Message('Your SnapSkin Diagnostic Report', sender=app.config['MAIL_USERNAME'], recipients=[report_data['email']])
|
| 163 |
+
msg.body = f"Dear {report_data['name']},\n\nPlease find your diagnostic report attached."
|
| 164 |
+
|
| 165 |
+
with app.open_resource(pdf_path) as fp:
|
| 166 |
+
msg.attach(f"SnapSkin_Report_{report_data['scan_id']}.pdf", "application/pdf", fp.read())
|
| 167 |
+
|
| 168 |
+
mail.send(msg)
|
| 169 |
+
os.remove(pdf_path)
|
| 170 |
+
logger.info(f"Report sent successfully to {report_data['email']}")
|
| 171 |
+
except Exception as e:
|
| 172 |
+
logger.error(f"Failed to send email in background: {e}")
|
| 173 |
+
|
| 174 |
def generate_pdf(report, filepath):
|
| 175 |
c = canvas.Canvas(filepath, pagesize=A4)
|
| 176 |
width, height = A4
|
|
|
|
| 256 |
def training_plot():
|
| 257 |
return send_file(PLOT_PATH, mimetype="image/png") if os.path.exists(PLOT_PATH) else ("", 404)
|
| 258 |
|
| 259 |
+
|
| 260 |
@app.route("/uploads/<filename>")
|
| 261 |
def uploaded_file(filename):
|
| 262 |
upload_folder = "/tmp/uploads"
|
|
|
|
| 265 |
@app.route("/predict", methods=["POST"])
|
| 266 |
def predict():
|
| 267 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
image_file = request.files["image"]
|
| 269 |
image_bytes = image_file.read()
|
| 270 |
|
| 271 |
+
# --- Prediction Logic ---
|
| 272 |
img_array = preprocess_image(image_bytes)
|
| 273 |
prediction = model.predict(img_array)[0]
|
| 274 |
predicted_index = int(np.argmax(prediction))
|
| 275 |
confidence = float(prediction[predicted_index])
|
| 276 |
label = label_map.get(predicted_index, "Unknown") if confidence >= CONFIDENCE_THRESHOLD else "Low confidence"
|
| 277 |
+
msg = "This image is not confidently recognized." if confidence < CONFIDENCE_THRESHOLD else ""
|
| 278 |
|
| 279 |
+
# --- Database Operations ---
|
| 280 |
email = request.form.get("email")
|
| 281 |
user = User.query.filter_by(email=email).first()
|
| 282 |
if not user:
|
|
|
|
| 284 |
db.session.add(user)
|
| 285 |
db.session.commit()
|
| 286 |
|
| 287 |
+
# --- Save image to /tmp to fix permission error ---
|
| 288 |
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
| 289 |
image_filename = f"scan_{user.id}_{timestamp}.jpg"
|
| 290 |
upload_folder = "/tmp/uploads"
|
|
|
|
| 293 |
with open(image_path, "wb") as f:
|
| 294 |
f.write(image_bytes)
|
| 295 |
|
| 296 |
+
# --- Save Scan to DB ---
|
| 297 |
scan = Scan(
|
| 298 |
user_id=user.id, patient_name=request.form.get("name"),
|
| 299 |
patient_gender=request.form.get("gender"), patient_age=int(request.form.get("age")),
|
|
|
|
| 302 |
db.session.add(scan)
|
| 303 |
db.session.commit()
|
| 304 |
|
| 305 |
+
# --- Prepare Report ---
|
| 306 |
report = {
|
| 307 |
"name": request.form.get("name"), "email": email, "gender": request.form.get("gender"),
|
| 308 |
"age": request.form.get("age"), "prediction": label, "confidence": f"{confidence * 100:.2f}%",
|
| 309 |
+
"message": msg, "scan_id": scan.id,
|
| 310 |
+
"email_status": "Your report will be sent to your email shortly." # Neutral message
|
| 311 |
}
|
| 312 |
|
| 313 |
+
# --- Send email in background to prevent loading freeze ---
|
| 314 |
+
thread = threading.Thread(target=send_email_async, args=(app.app_context(), report))
|
| 315 |
+
thread.start()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 316 |
|
| 317 |
session["report"] = report
|
| 318 |
return redirect(url_for("result"))
|
| 319 |
|
| 320 |
except Exception as e:
|
| 321 |
logger.error(f"Prediction error: {e}")
|
| 322 |
+
return render_template("form.html", result={
|
| 323 |
+
"prediction": "Error", "message": f"An error occurred: {e}"
|
|
|
|
|
|
|
| 324 |
})
|
| 325 |
|
| 326 |
@app.route("/result")
|
|
|
|
| 328 |
report = session.get("report")
|
| 329 |
if not report:
|
| 330 |
return redirect(url_for("form"))
|
|
|
|
|
|
|
| 331 |
return render_template("result.html", **report)
|
| 332 |
|
| 333 |
@app.route("/download-report")
|