Added Report
Browse files
app.py
CHANGED
|
@@ -178,12 +178,78 @@ def segment_image(image: Image.Image, model: nn.Module) -> dict:
|
|
| 178 |
'red_area': (np.sum(final_mask == 2) / total_pixels * 100)
|
| 179 |
}
|
| 180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
# ====================== MAIN APP ======================
|
| 182 |
def main():
|
| 183 |
st.set_page_config(layout="wide")
|
| 184 |
st.title("Diabetic Retinopathy Analysis")
|
| 185 |
|
| 186 |
-
uploaded_file = st.file_uploader("
|
| 187 |
if not uploaded_file:
|
| 188 |
st.info("Please upload an image")
|
| 189 |
return
|
|
@@ -244,13 +310,33 @@ def main():
|
|
| 244 |
cols[2].metric("Total Affected",
|
| 245 |
f"{seg_results['bright_area'] + seg_results['red_area']:.2f}%")
|
| 246 |
|
| 247 |
-
# Download
|
| 248 |
-
st.
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
|
| 255 |
except Exception as e:
|
| 256 |
st.error(f"Error processing image: {str(e)}")
|
|
|
|
| 178 |
'red_area': (np.sum(final_mask == 2) / total_pixels * 100)
|
| 179 |
}
|
| 180 |
|
| 181 |
+
# ====================== PDF REPORT GENERATION ======================
|
| 182 |
+
def generate_pdf_report(original_img: Image.Image, mask: np.ndarray, overlay: Image.Image,
|
| 183 |
+
diagnosis: str, grade: str, bright_area: float, red_area: float):
|
| 184 |
+
pdf = FPDF()
|
| 185 |
+
pdf.add_page()
|
| 186 |
+
|
| 187 |
+
# Title
|
| 188 |
+
pdf.set_font("Arial", 'B', 16)
|
| 189 |
+
pdf.cell(0, 10, "Diabetic Retinopathy Diagnosis Report", 0, 1, 'C')
|
| 190 |
+
pdf.ln(10)
|
| 191 |
+
|
| 192 |
+
# Patient Info (placeholder)
|
| 193 |
+
pdf.set_font("Arial", '', 12)
|
| 194 |
+
pdf.cell(0, 10, "Patient: ___________________________", 0, 1)
|
| 195 |
+
pdf.cell(0, 10, "Date: _____________________________", 0, 1)
|
| 196 |
+
pdf.ln(10)
|
| 197 |
+
|
| 198 |
+
# Diagnosis
|
| 199 |
+
pdf.set_font("Arial", 'B', 14)
|
| 200 |
+
pdf.cell(0, 10, "Diagnosis:", 0, 1)
|
| 201 |
+
pdf.set_font("Arial", '', 12)
|
| 202 |
+
pdf.cell(0, 10, f"Stage: {diagnosis}", 0, 1)
|
| 203 |
+
pdf.cell(0, 10, f"UK Grading: {grade}", 0, 1)
|
| 204 |
+
pdf.ln(10)
|
| 205 |
+
|
| 206 |
+
# Lesion Analysis
|
| 207 |
+
pdf.set_font("Arial", 'B', 14)
|
| 208 |
+
pdf.cell(0, 10, "Lesion Analysis:", 0, 1)
|
| 209 |
+
pdf.set_font("Arial", '', 12)
|
| 210 |
+
pdf.cell(0, 10, f"Bright Lesions: {bright_area:.2f}%", 0, 1)
|
| 211 |
+
pdf.cell(0, 10, f"Red Lesions: {red_area:.2f}%", 0, 1)
|
| 212 |
+
pdf.cell(0, 10, f"Total Affected Area: {bright_area + red_area:.2f}%", 0, 1)
|
| 213 |
+
pdf.ln(15)
|
| 214 |
+
|
| 215 |
+
# Convert images to bytes
|
| 216 |
+
def pil_to_bytes(img, format='PNG'):
|
| 217 |
+
img_byte_arr = io.BytesIO()
|
| 218 |
+
img.save(img_byte_arr, format=format)
|
| 219 |
+
return img_byte_arr.getvalue()
|
| 220 |
+
|
| 221 |
+
# Original Image
|
| 222 |
+
pdf.set_font("Arial", 'B', 12)
|
| 223 |
+
pdf.cell(0, 10, "Original Retinal Image:", 0, 1)
|
| 224 |
+
pdf.image(io.BytesIO(pil_to_bytes(original_img)), x=50, w=100)
|
| 225 |
+
pdf.ln(5)
|
| 226 |
+
|
| 227 |
+
# Segmentation Mask
|
| 228 |
+
mask_img = Image.fromarray((mask * 85).astype(np.uint8))
|
| 229 |
+
pdf.set_font("Arial", 'B', 12)
|
| 230 |
+
pdf.cell(0, 10, "Lesion Segmentation Mask:", 0, 1)
|
| 231 |
+
pdf.image(io.BytesIO(pil_to_bytes(mask_img)), x=50, w=100)
|
| 232 |
+
pdf.ln(5)
|
| 233 |
+
|
| 234 |
+
# Overlay Image
|
| 235 |
+
pdf.set_font("Arial", 'B', 12)
|
| 236 |
+
pdf.cell(0, 10, "Lesion Overlay:", 0, 1)
|
| 237 |
+
pdf.image(io.BytesIO(pil_to_bytes(overlay)), x=50, w=100)
|
| 238 |
+
|
| 239 |
+
# Footer
|
| 240 |
+
pdf.ln(15)
|
| 241 |
+
pdf.set_font("Arial", 'I', 10)
|
| 242 |
+
pdf.cell(0, 10, "This report was generated by DR Analysis System", 0, 1, 'C')
|
| 243 |
+
|
| 244 |
+
return pdf.output(dest='S').encode('latin1')
|
| 245 |
+
|
| 246 |
+
|
| 247 |
# ====================== MAIN APP ======================
|
| 248 |
def main():
|
| 249 |
st.set_page_config(layout="wide")
|
| 250 |
st.title("Diabetic Retinopathy Analysis")
|
| 251 |
|
| 252 |
+
uploaded_file = st.file_uploader("", type=["jpg", "jpeg", "png"])
|
| 253 |
if not uploaded_file:
|
| 254 |
st.info("Please upload an image")
|
| 255 |
return
|
|
|
|
| 310 |
cols[2].metric("Total Affected",
|
| 311 |
f"{seg_results['bright_area'] + seg_results['red_area']:.2f}%")
|
| 312 |
|
| 313 |
+
# Download buttons
|
| 314 |
+
col1, col2 = st.columns(2)
|
| 315 |
+
with col1:
|
| 316 |
+
st.download_button(
|
| 317 |
+
"Download Mask",
|
| 318 |
+
cv2.imencode('.png', seg_results['mask'] * 85)[1].tobytes(),
|
| 319 |
+
"dr_mask.png",
|
| 320 |
+
"image/png"
|
| 321 |
+
)
|
| 322 |
+
|
| 323 |
+
with col2:
|
| 324 |
+
# Generate and download PDF report
|
| 325 |
+
pdf_bytes = generate_pdf_report(
|
| 326 |
+
original_image,
|
| 327 |
+
seg_results['mask'],
|
| 328 |
+
overlay,
|
| 329 |
+
predicted_class_name,
|
| 330 |
+
uk_grade,
|
| 331 |
+
seg_results['bright_area'],
|
| 332 |
+
seg_results['red_area']
|
| 333 |
+
)
|
| 334 |
+
st.download_button(
|
| 335 |
+
"Download Full Report",
|
| 336 |
+
data=pdf_bytes,
|
| 337 |
+
file_name="dr_diagnosis_report.pdf",
|
| 338 |
+
mime="application/pdf"
|
| 339 |
+
)
|
| 340 |
|
| 341 |
except Exception as e:
|
| 342 |
st.error(f"Error processing image: {str(e)}")
|