from flask import Flask, request, render_template, redirect, url_for, session, send_file import cv2 import numpy as np import os import pickle import logging from werkzeug.utils import secure_filename from datetime import datetime from reportlab.lib.pagesizes import A4 from reportlab.pdfgen import canvas app = Flask(__name__) app.secret_key = os.getenv("FLASK_SECRET_KEY", "fallback_secret_key") # Set up logging app.logger.setLevel(logging.DEBUG) # Base directory (works when run from project root or Docker /app) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) TEMP_DIR = os.path.join(BASE_DIR, 'temp') model_path = os.path.join(BASE_DIR, 'breast_cancer_detector.pickle') # Load trained cancer detection model cancer_detection_model = None try: if os.path.isfile(model_path): with open(model_path, 'rb') as model_file: cancer_detection_model = pickle.load(model_file) app.logger.info(f"Model loaded successfully from {model_path}") else: app.logger.warning(f"Model file not found at {model_path}. Run: python train_model.py") except Exception as e: app.logger.error(f"Error loading model: {e}") raise # Ensure the temp directory exists for saving uploaded images and PDFs if not os.path.exists(TEMP_DIR): os.makedirs(TEMP_DIR) @app.route('/') def home(): return redirect(url_for('upload')) # Upload page @app.route('/upload') def upload(): app.logger.debug('Upload page accessed') return render_template('upload.html') # Handle image upload and cancer detection @app.route('/detect-cancer', methods=['POST']) def detect_cancer(): app.logger.debug('Detect Cancer page accessed') if request.method == 'POST': user_name = request.form.get('name', '').strip() session['user_name'] = user_name session['upload_date'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') # Get the uploaded image file = request.files.get('image') if file and allowed_file(file.filename): filename = secure_filename(file.filename) filepath = os.path.join(TEMP_DIR, filename) file.save(filepath) session['image_path'] = filepath if cancer_detection_model is None: return render_template('error.html', error_message="Model not loaded. Run train_model.py to create the model.") try: preprocessed_image = preprocess_image(filepath) prediction = cancer_detection_model.predict(preprocessed_image) result_message = 'Cancer Detected' if prediction[0] == 1 else 'No Cancer Detected' session['detection_result'] = result_message # Generate PDF report pdf_path = generate_pdf_report(user_name, session['upload_date'], filepath, result_message) session['pdf_path'] = pdf_path return redirect(url_for('show_result', result=result_message)) except Exception as e: app.logger.error(f"Error during prediction: {e}") return render_template('error.html', error_message="Error processing the image. Try again.") else: app.logger.warning('Invalid file type') return render_template('error.html', error_message="Invalid file type. Upload a valid image.") return redirect(url_for('upload')) # Display the result and provide PDF download link @app.route('/result') def show_result(): result = request.args.get('result', 'No result available') user_name = session.get('user_name', 'User') pdf_path = session.get('pdf_path') return render_template('result.html', result=result, user_name=user_name, pdf_path=pdf_path) # Download the PDF report @app.route('/download-report') def download_report(): pdf_path = session.get('pdf_path') if pdf_path and os.path.exists(pdf_path): session.clear() # Clear session after download return send_file(pdf_path, as_attachment=True) else: return "Report not found." # Preprocess the uploaded image def preprocess_image(image_path): try: image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if image is None: raise ValueError("Could not read image file; file may be corrupt or not a valid image.") resized_image = cv2.resize(image, (5, 6)) flattened_image = resized_image.flatten() reshaped_image = flattened_image.reshape(1, -1) return reshaped_image except Exception as e: app.logger.error(f"Error in preprocessing image: {e}") raise # Generate PDF report def generate_pdf_report(user_name, upload_date, image_path, result): safe_name = "".join(c if c.isalnum() or c in "._- " else "_" for c in (user_name or "User")) pdf_name = f'report_{safe_name}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.pdf' pdf_path = os.path.join(TEMP_DIR, pdf_name) c = canvas.Canvas(pdf_path, pagesize=A4) width, height = A4 # Add content to PDF c.drawString(50, height - 50, "Cancer Detection Report") c.drawString(50, height - 100, f"User Name: {user_name}") c.drawString(50, height - 120, f"Upload Date: {upload_date}") c.drawString(50, height - 140, f"Detection Result: {result}") c.drawString(50, height - 160, "Image Processing Details:") c.drawString(70, height - 180, "- Resized to 5x6 pixels") c.drawString(70, height - 200, "- Converted to grayscale") # Add recommendations if cancer is detected if result == "Cancer Detected": c.drawString(50, height - 240, "Recommendations:") c.drawString(70, height - 260, "- Consult a healthcare provider.") c.drawString(70, height - 280, "- Schedule additional diagnostic tests.") c.showPage() c.save() return pdf_path # Check if the uploaded file is an allowed image ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'} def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS # Custom Error Pages @app.errorhandler(404) def page_not_found(error): return render_template('error.html', error_message="Page not found. Check the URL."), 404 @app.errorhandler(500) def internal_server_error(error): return render_template('error.html', error_message="Unexpected error. Try again."), 500