Spaces:
Runtime error
Runtime error
Download app.py from vaithi663/RetiCheck-AI: direct link, hf CLI and curl.
- Browser
- Download file 7.17 kB
-
https://huggingface.co/spaces/vaithi663/RetiCheck-AI/resolve/main/app.py
- Command line
-
hf download hf://spaces/vaithi663/RetiCheck-AI/app.py
-
curl -L -o app.py https://huggingface.co/spaces/vaithi663/RetiCheck-AI/resolve/main/app.py
7.17 kB
| from flask import Flask, request, jsonify, render_template, Response | |
| import numpy as np | |
| from PIL import Image, ImageOps, ImageFilter | |
| import tensorflow as tf | |
| from tensorflow.keras.models import load_model | |
| import matplotlib.cm as cm | |
| import base64 | |
| from io import BytesIO | |
| import sqlite3 | |
| from datetime import datetime | |
| def init_db(): | |
| conn = sqlite3.connect('reticheck_patients.db') | |
| c = conn.cursor() | |
| c.execute('''CREATE TABLE IF NOT EXISTS history | |
| (id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| date TEXT, | |
| disease TEXT, | |
| confidence TEXT, | |
| status TEXT)''') | |
| conn.commit() | |
| conn.close() | |
| init_db() | |
| app = Flask(__name__) | |
| try: | |
| model = load_model("models/keras_model.h5", compile=False) | |
| class_names = open("models/labels.txt", "r").readlines() | |
| print("✅ Chef (AI Model) is ready!") | |
| except Exception as e: | |
| print(f"⚠️ Chef is missing: {e}") | |
| model = None | |
| cdss_data = { | |
| "Normal": {"status": "Healthy Retina", "triage": "SAFE", "advice": "No major diseases detected.", "action": "General drops."}, | |
| "Diabetic": {"status": "Diabetic Retinopathy", "triage": "URGENT", "advice": "High risk of vision loss.", "action": "Check Sugar/BP."}, | |
| "Glaucoma": {"status": "Glaucoma Suspect", "triage": "REFERRAL", "advice": "Optic nerve damage detected.", "action": "Refer for IOP Test."} | |
| } | |
| def generate_robust_heatmap(img_array, model, class_index, patch_size=16, step=8): | |
| try: | |
| base_pred = model.predict(img_array, verbose=0)[0][class_index] | |
| patches, coords = [], [] | |
| img_size = 224 | |
| for y in range(0, img_size, step): | |
| for x in range(0, img_size, step): | |
| y_end, x_end = min(y + patch_size, img_size), min(x + patch_size, img_size) | |
| if (y_end - y) < 4 or (x_end - x) < 4: continue | |
| occ_img = img_array.copy() | |
| occ_img[0, y:y_end, x:x_end, :] = -1 | |
| patches.append(occ_img[0]) | |
| coords.append((y, y_end, x, x_end)) | |
| if not patches: return None | |
| preds = model.predict(np.array(patches), batch_size=32, verbose=0)[:, class_index] | |
| heatmap = np.zeros((img_size, img_size)) | |
| for i, (y, y_end, x, x_end) in enumerate(coords): | |
| drop = base_pred - preds[i] | |
| if drop > 0.02: | |
| heatmap[y:y_end, x:x_end] += drop | |
| heatmap = np.maximum(heatmap, 0) | |
| max_val = np.max(heatmap) | |
| if max_val > 0: | |
| heatmap /= max_val | |
| heatmap_img = Image.fromarray(np.uint8(255 * heatmap)).filter(ImageFilter.GaussianBlur(radius=6)) | |
| return np.array(heatmap_img) / 255.0 | |
| except Exception as e: | |
| return None | |
| def overlay_heatmap(img, heatmap, alpha=0.5): | |
| heatmap = np.uint8(255 * heatmap) | |
| jet = cm.get_cmap("jet") | |
| jet_heatmap = tf.keras.preprocessing.image.array_to_img(jet(np.arange(256))[:, :3][heatmap]).resize((img.size[0], img.size[1])) | |
| superimposed_img = tf.keras.preprocessing.image.img_to_array(jet_heatmap) * alpha + tf.keras.preprocessing.image.img_to_array(img) | |
| return tf.keras.preprocessing.image.array_to_img(superimposed_img) | |
| def login(): return render_template('index.html') | |
| def patient(): return render_template('patient.html') | |
| def upload(): return render_template('upload.html') | |
| def result(): return render_template('result.html') | |
| def database(): | |
| conn = sqlite3.connect('reticheck_patients.db') | |
| c = conn.cursor() | |
| c.execute("SELECT * FROM history ORDER BY id DESC") | |
| records = c.fetchall() | |
| conn.close() | |
| # --- PUDHU CODE: CHART-க்காக வியாதியை எண்ணும் மேஜிக் 👇 --- | |
| normal_count = sum(1 for row in records if "Normal" in row[2]) | |
| diabetic_count = sum(1 for row in records if "Diabetic" in row[2]) | |
| glaucoma_count = sum(1 for row in records if "Glaucoma" in row[2]) | |
| # --- PUDHU CODE END 👆 --- | |
| return render_template('database.html', records=records, | |
| n_count=normal_count, | |
| d_count=diabetic_count, | |
| g_count=glaucoma_count) | |
| def export_csv(): | |
| conn = sqlite3.connect('reticheck_patients.db') | |
| c = conn.cursor() | |
| c.execute("SELECT * FROM history ORDER BY id ASC") | |
| records = c.fetchall() | |
| conn.close() | |
| def generate(): | |
| yield 'Patient ID,Date & Time,Predicted Disease,AI Confidence,Triage Status\n' | |
| for row in records: | |
| yield f"{row[0]},{row[1]},{row[2]},{row[3]},{row[4]}\n" | |
| return Response(generate(), mimetype='text/csv', headers={'Content-Disposition': 'attachment; filename=RetiCheck_Patients_Report.csv'}) | |
| def predict(): | |
| file = request.files['image'] | |
| image = Image.open(file.stream).convert("RGB") | |
| size = (224, 224) | |
| image_resized = ImageOps.fit(image, size, Image.Resampling.LANCZOS) | |
| data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32) | |
| data[0] = (np.asarray(image_resized).astype(np.float32) / 127.5) - 1 | |
| prediction = model.predict(data, verbose=0) | |
| index = np.argmax(prediction) | |
| raw_class = class_names[index].strip() | |
| class_name = raw_class[2:] if raw_class[0].isdigit() else raw_class | |
| confidence = float(prediction[0][index]) * 100 | |
| disease = "Normal" | |
| if "Diabetic" in class_name: disease = "Diabetic" | |
| elif "Glaucoma" in class_name: disease = "Glaucoma" | |
| report = cdss_data[disease] | |
| try: | |
| conn = sqlite3.connect('reticheck_patients.db') | |
| c = conn.cursor() | |
| current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| c.execute("INSERT INTO history (date, disease, confidence, status) VALUES (?, ?, ?, ?)", | |
| (current_time, class_name, f"{confidence:.1f}%", report['triage'])) | |
| conn.commit() | |
| conn.close() | |
| except Exception as db_error: | |
| print(f"Database Save Error: {db_error}") | |
| buf = BytesIO() | |
| image_resized.save(buf, format="JPEG") | |
| orig_b64 = base64.b64encode(buf.getvalue()).decode('utf-8') | |
| heat_b64 = "" | |
| heatmap_generated = False | |
| if disease != "Normal": | |
| heatmap = generate_robust_heatmap(data, model, index) | |
| if heatmap is not None: | |
| final_heatmap = overlay_heatmap(image_resized, heatmap) | |
| buf2 = BytesIO() | |
| final_heatmap.save(buf2, format="JPEG") | |
| heat_b64 = base64.b64encode(buf2.getvalue()).decode('utf-8') | |
| heatmap_generated = True | |
| return jsonify({ | |
| 'disease': class_name, | |
| 'confidence': f"{confidence:.1f}%", | |
| 'status': report['status'], | |
| 'triage': report['triage'], | |
| 'advice': report['advice'], | |
| 'action': report['action'], | |
| 'orig_img': orig_b64, | |
| 'heat_img': heat_b64, | |
| 'heat_gen': heatmap_generated | |
| }) | |
| if __name__ == '__main__': | |
| app.run(debug=True, port=5000) |