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

Update app.py

Browse files

Fixed invalid 'type' parameter in gr.File component

Files changed (1) hide show
  1. app.py +97 -97
app.py CHANGED
@@ -1,97 +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()
 
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="filepath"),
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()