Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
from flask import Flask, request, jsonify, render_template
|
| 2 |
import numpy as np
|
| 3 |
from PIL import Image, ImageOps, ImageFilter
|
| 4 |
import tensorflow as tf
|
|
@@ -9,7 +9,7 @@ from io import BytesIO
|
|
| 9 |
import sqlite3
|
| 10 |
from datetime import datetime
|
| 11 |
|
| 12 |
-
# டேட்டாபேஸ் உருவாக்கும் கோடு
|
| 13 |
def init_db():
|
| 14 |
conn = sqlite3.connect('reticheck_patients.db')
|
| 15 |
c = conn.cursor()
|
|
@@ -22,7 +22,7 @@ def init_db():
|
|
| 22 |
conn.commit()
|
| 23 |
conn.close()
|
| 24 |
|
| 25 |
-
init_db()
|
| 26 |
|
| 27 |
app = Flask(__name__)
|
| 28 |
|
|
@@ -41,33 +41,30 @@ cdss_data = {
|
|
| 41 |
"Glaucoma": {"status": "Glaucoma Suspect", "triage": "REFERRAL", "advice": "Optic nerve damage detected.", "action": "Refer for IOP Test."}
|
| 42 |
}
|
| 43 |
|
| 44 |
-
# 2. XAI Heatmap Functions
|
| 45 |
def generate_robust_heatmap(img_array, model, class_index, patch_size=16, step=8):
|
| 46 |
try:
|
| 47 |
base_pred = model.predict(img_array, verbose=0)[0][class_index]
|
| 48 |
patches, coords = [], []
|
| 49 |
img_size = 224
|
| 50 |
|
| 51 |
-
# Scanning the image with a smaller, finer box
|
| 52 |
for y in range(0, img_size, step):
|
| 53 |
for x in range(0, img_size, step):
|
| 54 |
y_end, x_end = min(y + patch_size, img_size), min(x + patch_size, img_size)
|
| 55 |
if (y_end - y) < 4 or (x_end - x) < 4: continue
|
| 56 |
|
| 57 |
occ_img = img_array.copy()
|
| 58 |
-
occ_img[0, y:y_end, x:x_end, :] = -1
|
| 59 |
patches.append(occ_img[0])
|
| 60 |
coords.append((y, y_end, x, x_end))
|
| 61 |
|
| 62 |
if not patches: return None
|
| 63 |
|
| 64 |
-
# Predict all patches
|
| 65 |
preds = model.predict(np.array(patches), batch_size=32, verbose=0)[:, class_index]
|
| 66 |
|
| 67 |
heatmap = np.zeros((img_size, img_size))
|
| 68 |
for i, (y, y_end, x, x_end) in enumerate(coords):
|
| 69 |
drop = base_pred - preds[i]
|
| 70 |
-
# STRICT ACCURACY: Only mark regions where hiding it drops confidence significantly (>2%)
|
| 71 |
if drop > 0.02:
|
| 72 |
heatmap[y:y_end, x:x_end] += drop
|
| 73 |
|
|
@@ -76,11 +73,9 @@ def generate_robust_heatmap(img_array, model, class_index, patch_size=16, step=8
|
|
| 76 |
if max_val > 0:
|
| 77 |
heatmap /= max_val
|
| 78 |
|
| 79 |
-
# Smooth the heatmap so it looks like medical imaging, not blocky pixels
|
| 80 |
heatmap_img = Image.fromarray(np.uint8(255 * heatmap)).filter(ImageFilter.GaussianBlur(radius=6))
|
| 81 |
return np.array(heatmap_img) / 255.0
|
| 82 |
except Exception as e:
|
| 83 |
-
print("Heatmap Error:", e)
|
| 84 |
return None
|
| 85 |
|
| 86 |
def overlay_heatmap(img, heatmap, alpha=0.5):
|
|
@@ -104,16 +99,35 @@ def upload(): return render_template('upload.html')
|
|
| 104 |
@app.route('/result')
|
| 105 |
def result(): return render_template('result.html')
|
| 106 |
|
| 107 |
-
# DATABASE க்கான புது ரூட் (NEW ROUTE FOR DATABASE)
|
| 108 |
@app.route('/database')
|
| 109 |
def database():
|
| 110 |
conn = sqlite3.connect('reticheck_patients.db')
|
| 111 |
c = conn.cursor()
|
| 112 |
-
c.execute("SELECT * FROM history ORDER BY id DESC")
|
| 113 |
records = c.fetchall()
|
| 114 |
conn.close()
|
| 115 |
return render_template('database.html', records=records)
|
| 116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
@app.route('/predict', methods=['POST'])
|
| 118 |
def predict():
|
| 119 |
file = request.files['image']
|
|
@@ -136,7 +150,6 @@ def predict():
|
|
| 136 |
|
| 137 |
report = cdss_data[disease]
|
| 138 |
|
| 139 |
-
# --- DATABASE ல் சேமிப்பதற்கான கோடு (NEW CODE) ---
|
| 140 |
try:
|
| 141 |
conn = sqlite3.connect('reticheck_patients.db')
|
| 142 |
c = conn.cursor()
|
|
@@ -147,14 +160,11 @@ def predict():
|
|
| 147 |
conn.close()
|
| 148 |
except Exception as db_error:
|
| 149 |
print(f"Database Save Error: {db_error}")
|
| 150 |
-
# ------------------------------------------------
|
| 151 |
|
| 152 |
-
# Convert Original Image to Base64
|
| 153 |
buf = BytesIO()
|
| 154 |
image_resized.save(buf, format="JPEG")
|
| 155 |
orig_b64 = base64.b64encode(buf.getvalue()).decode('utf-8')
|
| 156 |
|
| 157 |
-
# Generate Heatmap (Only if Disease)
|
| 158 |
heat_b64 = ""
|
| 159 |
heatmap_generated = False
|
| 160 |
if disease != "Normal":
|
|
|
|
| 1 |
+
from flask import Flask, request, jsonify, render_template, Response
|
| 2 |
import numpy as np
|
| 3 |
from PIL import Image, ImageOps, ImageFilter
|
| 4 |
import tensorflow as tf
|
|
|
|
| 9 |
import sqlite3
|
| 10 |
from datetime import datetime
|
| 11 |
|
| 12 |
+
# டேட்டாபேஸ் உருவாக்கும் கோடு
|
| 13 |
def init_db():
|
| 14 |
conn = sqlite3.connect('reticheck_patients.db')
|
| 15 |
c = conn.cursor()
|
|
|
|
| 22 |
conn.commit()
|
| 23 |
conn.close()
|
| 24 |
|
| 25 |
+
init_db()
|
| 26 |
|
| 27 |
app = Flask(__name__)
|
| 28 |
|
|
|
|
| 41 |
"Glaucoma": {"status": "Glaucoma Suspect", "triage": "REFERRAL", "advice": "Optic nerve damage detected.", "action": "Refer for IOP Test."}
|
| 42 |
}
|
| 43 |
|
| 44 |
+
# 2. XAI Heatmap Functions
|
| 45 |
def generate_robust_heatmap(img_array, model, class_index, patch_size=16, step=8):
|
| 46 |
try:
|
| 47 |
base_pred = model.predict(img_array, verbose=0)[0][class_index]
|
| 48 |
patches, coords = [], []
|
| 49 |
img_size = 224
|
| 50 |
|
|
|
|
| 51 |
for y in range(0, img_size, step):
|
| 52 |
for x in range(0, img_size, step):
|
| 53 |
y_end, x_end = min(y + patch_size, img_size), min(x + patch_size, img_size)
|
| 54 |
if (y_end - y) < 4 or (x_end - x) < 4: continue
|
| 55 |
|
| 56 |
occ_img = img_array.copy()
|
| 57 |
+
occ_img[0, y:y_end, x:x_end, :] = -1
|
| 58 |
patches.append(occ_img[0])
|
| 59 |
coords.append((y, y_end, x, x_end))
|
| 60 |
|
| 61 |
if not patches: return None
|
| 62 |
|
|
|
|
| 63 |
preds = model.predict(np.array(patches), batch_size=32, verbose=0)[:, class_index]
|
| 64 |
|
| 65 |
heatmap = np.zeros((img_size, img_size))
|
| 66 |
for i, (y, y_end, x, x_end) in enumerate(coords):
|
| 67 |
drop = base_pred - preds[i]
|
|
|
|
| 68 |
if drop > 0.02:
|
| 69 |
heatmap[y:y_end, x:x_end] += drop
|
| 70 |
|
|
|
|
| 73 |
if max_val > 0:
|
| 74 |
heatmap /= max_val
|
| 75 |
|
|
|
|
| 76 |
heatmap_img = Image.fromarray(np.uint8(255 * heatmap)).filter(ImageFilter.GaussianBlur(radius=6))
|
| 77 |
return np.array(heatmap_img) / 255.0
|
| 78 |
except Exception as e:
|
|
|
|
| 79 |
return None
|
| 80 |
|
| 81 |
def overlay_heatmap(img, heatmap, alpha=0.5):
|
|
|
|
| 99 |
@app.route('/result')
|
| 100 |
def result(): return render_template('result.html')
|
| 101 |
|
|
|
|
| 102 |
@app.route('/database')
|
| 103 |
def database():
|
| 104 |
conn = sqlite3.connect('reticheck_patients.db')
|
| 105 |
c = conn.cursor()
|
| 106 |
+
c.execute("SELECT * FROM history ORDER BY id DESC")
|
| 107 |
records = c.fetchall()
|
| 108 |
conn.close()
|
| 109 |
return render_template('database.html', records=records)
|
| 110 |
|
| 111 |
+
# --- PUDHU CODE: EXCEL DOWNLOAD MAGIC 👇 ---
|
| 112 |
+
@app.route('/export_csv')
|
| 113 |
+
def export_csv():
|
| 114 |
+
conn = sqlite3.connect('reticheck_patients.db')
|
| 115 |
+
c = conn.cursor()
|
| 116 |
+
c.execute("SELECT * FROM history ORDER BY id DESC")
|
| 117 |
+
records = c.fetchall()
|
| 118 |
+
conn.close()
|
| 119 |
+
|
| 120 |
+
def generate():
|
| 121 |
+
# எக்செல் சீட்டில் மேல வரும் தலைப்புகள் (Headings)
|
| 122 |
+
yield 'Patient ID,Date & Time,Predicted Disease,AI Confidence,Triage Status\n'
|
| 123 |
+
# டேட்டாபேஸில் உள்ள ஒவ்வொரு ரிசல்ட்டும் வரியாக மாறும்
|
| 124 |
+
for row in records:
|
| 125 |
+
yield f"{row[0]},{row[1]},{row[2]},{row[3]},{row[4]}\n"
|
| 126 |
+
|
| 127 |
+
# இதை ஒரு ஃபைலாக போனுக்கு அனுப்பும் கமாண்ட்
|
| 128 |
+
return Response(generate(), mimetype='text/csv', headers={'Content-Disposition': 'attachment; filename=RetiCheck_Patients_Report.csv'})
|
| 129 |
+
# --- PUDHU CODE END 👆 ---
|
| 130 |
+
|
| 131 |
@app.route('/predict', methods=['POST'])
|
| 132 |
def predict():
|
| 133 |
file = request.files['image']
|
|
|
|
| 150 |
|
| 151 |
report = cdss_data[disease]
|
| 152 |
|
|
|
|
| 153 |
try:
|
| 154 |
conn = sqlite3.connect('reticheck_patients.db')
|
| 155 |
c = conn.cursor()
|
|
|
|
| 160 |
conn.close()
|
| 161 |
except Exception as db_error:
|
| 162 |
print(f"Database Save Error: {db_error}")
|
|
|
|
| 163 |
|
|
|
|
| 164 |
buf = BytesIO()
|
| 165 |
image_resized.save(buf, format="JPEG")
|
| 166 |
orig_b64 = base64.b64encode(buf.getvalue()).decode('utf-8')
|
| 167 |
|
|
|
|
| 168 |
heat_b64 = ""
|
| 169 |
heatmap_generated = False
|
| 170 |
if disease != "Normal":
|