HeshamAI commited on
Commit
6be9f4b
·
verified ·
1 Parent(s): dfc6315

Added app.py and requirements.txt

Browse files
Files changed (2) hide show
  1. app.py +97 -0
  2. requirements.txt +5 -0
app.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pydicom
3
+ import numpy as np
4
+ import cv2
5
+ import pandas as pd
6
+
7
+ def load_dicom(file):
8
+ """Load a DICOM file and extract pixel data with rescale slope and intercept applied."""
9
+ dicom_data = pydicom.dcmread(file)
10
+ image = dicom_data.pixel_array.astype(np.float32)
11
+ rescale_slope = getattr(dicom_data, "RescaleSlope", 1)
12
+ rescale_intercept = getattr(dicom_data, "RescaleIntercept", 0)
13
+ image = (image * rescale_slope) + rescale_intercept
14
+ pixel_spacing = getattr(dicom_data, "PixelSpacing", [1, 1])
15
+ return image, pixel_spacing
16
+
17
+ def analyze_dicom(file, circle_diameter):
18
+ """
19
+ Analyze the DICOM file:
20
+ - Load image and pixel spacing
21
+ - Display the image
22
+ - Analyze a circular region of interest
23
+ """
24
+ try:
25
+ # Load DICOM file
26
+ image, pixel_spacing = load_dicom(file)
27
+ pixel_size_mm = float(pixel_spacing[0]) # Assuming square pixels
28
+
29
+ # Normalize image for display
30
+ image_display = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
31
+
32
+ # Convert to RGB for overlay purposes
33
+ image_rgb = cv2.cvtColor(image_display, cv2.COLOR_GRAY2RGB)
34
+
35
+ # Analyze center of the image as a circular ROI
36
+ h, w = image.shape
37
+ center_x, center_y = w // 2, h // 2
38
+
39
+ # Create a circular mask
40
+ mask = np.zeros_like(image, dtype=np.uint8)
41
+ y_indices, x_indices = np.ogrid[:image.shape[0], :image.shape[1]]
42
+ distance_from_center = np.sqrt((x_indices - center_x) ** 2 + (y_indices - center_y) ** 2)
43
+ mask[distance_from_center <= circle_diameter / 2] = 1
44
+
45
+ # Extract pixel values within the circle
46
+ pixels = image[mask == 1]
47
+
48
+ # Calculate metrics
49
+ area_pixels = np.sum(mask)
50
+ area_mm2 = area_pixels * (pixel_size_mm**2)
51
+ mean = np.mean(pixels)
52
+ stddev = np.std(pixels)
53
+ min_val = np.min(pixels)
54
+ max_val = np.max(pixels)
55
+
56
+ # Save the result
57
+ results = {
58
+ "Area (mm²)": f"{area_mm2:.3f}",
59
+ "Mean Intensity": f"{mean:.3f}",
60
+ "Standard Deviation": f"{stddev:.3f}",
61
+ "Minimum Intensity": f"{min_val:.3f}",
62
+ "Maximum Intensity": f"{max_val:.3f}",
63
+ }
64
+
65
+ # Draw the circle on the image
66
+ cv2.circle(image_rgb, (center_x, center_y), int(circle_diameter / 2), (0, 255, 0), 2)
67
+
68
+ # Convert the image back to BGR for display
69
+ annotated_image = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2BGR)
70
+
71
+ return annotated_image, pd.DataFrame([results]).to_csv(index=False)
72
+ except Exception as e:
73
+ return None, f"Error: {str(e)}"
74
+
75
+ # Define the Gradio interface
76
+ inputs = [
77
+ gr.File(label="Upload DICOM File (.IMA or .dcm)", type="file"),
78
+ gr.Number(label="Circle Diameter (in pixels)", value=50, precision=1),
79
+ ]
80
+
81
+ outputs = [
82
+ gr.Image(label="Annotated DICOM Image"),
83
+ gr.File(label="Analysis Results (CSV)"),
84
+ ]
85
+
86
+ # Launch the app
87
+ gr.Interface(
88
+ fn=analyze_dicom,
89
+ inputs=inputs,
90
+ outputs=outputs,
91
+ title="DICOM Analyzer Tool",
92
+ description=(
93
+ "Upload a DICOM file and analyze a circular region of interest (ROI). "
94
+ "The tool calculates metrics such as mean intensity, standard deviation, and area in mm²."
95
+ ),
96
+ theme="compact",
97
+ ).launch()
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio
2
+ numpy
3
+ pandas
4
+ opencv-python
5
+ pydicom