| from flask import Flask, render_template, request, url_for
|
| import pickle
|
| import numpy as np
|
| import os
|
| from ocr_utils import extract_keywords_from_report, score_text_for_risk
|
| from image_utils import predict_xray_risk, generate_and_save_gradcam
|
|
|
| app = Flask(__name__)
|
| app.config['UPLOAD_FOLDER'] = 'uploads'
|
| os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
|
|
|
|
|
|
|
| model = None
|
| target_encoder = None
|
| feature_order = None
|
|
|
|
|
| CSV_KEYS = [
|
| 'Age', 'Gender', 'Air Pollution', 'Alcohol use', 'Dust Allergy', 'OccuPational Hazards',
|
| 'Genetic Risk', 'chronic Lung Disease', 'Balanced Diet', 'Obesity', 'Smoking',
|
| 'Passive Smoker', 'Chest Pain', 'Coughing of Blood', 'Fatigue', 'Weight Loss',
|
| 'Shortness of Breath', 'Wheezing', 'Swallowing Difficulty', 'Clubbing of Finger Nails',
|
| 'Frequent Cold', 'Dry Cough', 'Snoring'
|
| ]
|
|
|
|
|
| @app.route('/')
|
| def home():
|
| """Render main interactive UI"""
|
| return render_template('index.html')
|
|
|
|
|
| @app.route('/predict', methods=['POST'])
|
| def predict():
|
| """Handles the prediction request and renders the result page."""
|
|
|
|
|
| global model, target_encoder, feature_order
|
|
|
| if model is None:
|
| try:
|
| model = pickle.load(open("model.pkl", "rb"))
|
| target_encoder = pickle.load(open("target_encoder.pkl", "rb"))
|
| feature_order = pickle.load(open("model_features.pkl", "rb"))
|
| except Exception as e:
|
| return render_template('result.html', final_risk_level="Error", combined_score=0, error_message=f"Initial model loading failed on request: {str(e)}")
|
|
|
|
|
| if not model:
|
| return render_template('result.html', final_risk_level="Error", combined_score=0, error_message="Model loading failed. Please check server logs.")
|
|
|
| try:
|
|
|
| data_dict = {}
|
| for key in CSV_KEYS:
|
| form_key = key.lower().replace(' ', '_')
|
| val = request.form.get(form_key)
|
| data_dict[key] = float(val) if val else 0.0
|
|
|
|
|
| features = [data_dict.get(col, 0.0) for col in feature_order]
|
| X = np.array(features).reshape(1, -1)
|
|
|
| if X.shape[1] != len(feature_order):
|
| raise ValueError("Feature count mismatch. Model features != Form inputs.")
|
|
|
| encoded_pred = model.predict(X)[0]
|
| tabular_proba = model.predict_proba(X)[0]
|
| tabular_confidence = float(np.max(tabular_proba) * 100)
|
|
|
| tabular_classes = target_encoder.classes_
|
| high_idx = np.where(tabular_classes == 'High')[0][0] if 'High' in tabular_classes else -1
|
| tabular_high_prob = float(tabular_proba[high_idx]) if high_idx != -1 else 0.0
|
|
|
|
|
| ocr_risk_score = 0.0
|
| ocr_keywords = []
|
| report_file = request.files.get('report')
|
| if report_file and report_file.filename:
|
| report_path = os.path.join(app.config['UPLOAD_FOLDER'], report_file.filename)
|
| report_file.save(report_path)
|
| extracted_text = extract_keywords_from_report(report_path)
|
| ocr_risk_score, ocr_keywords = score_text_for_risk(extracted_text)
|
|
|
|
|
| cnn_risk_score = 0.0
|
| gradcam_url = None
|
| xray_file = request.files.get('xray')
|
|
|
| if xray_file and xray_file.filename:
|
| xray_path = os.path.join(app.config['UPLOAD_FOLDER'], xray_file.filename)
|
| xray_file.save(xray_path)
|
|
|
| abs_xray_path = os.path.abspath(xray_path)
|
|
|
| cnn_risk_score = float(predict_xray_risk(abs_xray_path))
|
| gradcam_filename = generate_and_save_gradcam(abs_xray_path)
|
|
|
|
|
| if gradcam_filename:
|
| gradcam_url = gradcam_filename
|
|
|
|
|
| WEIGHT_TABULAR = 0.5
|
| WEIGHT_OCR = 0.3
|
| WEIGHT_CNN = 0.2
|
| combined_score = (
|
| WEIGHT_TABULAR * tabular_high_prob +
|
| WEIGHT_OCR * ocr_risk_score +
|
| WEIGHT_CNN * cnn_risk_score
|
| )
|
|
|
| if combined_score >= 0.65:
|
| final_risk = "High"
|
| elif combined_score >= 0.35:
|
| final_risk = "Medium"
|
| else:
|
| final_risk = "Low"
|
|
|
|
|
| return render_template('result.html',
|
| final_risk_level=final_risk,
|
| confidence=round(tabular_confidence, 2),
|
| user_data=data_dict,
|
| ocr_score=round(ocr_risk_score * 100, 2),
|
| ocr_keywords=ocr_keywords,
|
| cnn_score=round(cnn_risk_score * 100, 2),
|
| combined_score=round(combined_score * 100, 2),
|
| gradcam_image_url=gradcam_url)
|
|
|
| except Exception as e:
|
| return render_template('result.html',
|
| final_risk_level="Error",
|
| combined_score=0,
|
| error_message=f"Processing Error: {str(e)}",
|
| user_data={})
|
|
|
|
|
| if __name__ == '__main__':
|
| app.run(debug=True) |