HeshamAI commited on
Commit
b33fa92
·
verified ·
1 Parent(s): e68cfea

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -65
app.py CHANGED
@@ -122,75 +122,76 @@ class DicomAnalyzer:
122
  print(f"Error handling keyboard input: {str(e)}")
123
  return self.display_image
124
 
125
- def analyze_roi(self, evt: gr.SelectData):
126
- try:
127
- if self.current_image is None:
128
- return None, "No image loaded"
129
 
130
- # Get clicked coordinates
131
- clicked_x, clicked_y = evt.index[0], evt.index[1]
132
-
133
- # Transform coordinates to match ImageJ
134
- x = (clicked_x + self.pan_x) / self.zoom_factor
135
- y = (clicked_y + self.pan_y) / self.zoom_factor
136
-
137
- # Get image dimensions
138
- height, width = self.current_image.shape[:2]
139
-
140
- # Create precise circular mask (ImageJ method)
141
- y_coords, x_coords = np.ogrid[:height, :width]
142
-
143
- # ImageJ uses diameter/2 for radius calculation
144
- radius = (self.circle_diameter - 1) / 2.0 # Adjust radius calculation
145
-
146
- # Calculate distances using ImageJ method
147
- dist_squared = (x_coords - x)**2 + (y_coords - y)**2
148
- mask = dist_squared <= radius**2
149
-
150
- # Get ROI pixels
151
- roi_pixels = self.current_image[mask]
152
-
153
- if len(roi_pixels) == 0:
154
- return self.display_image, "Error: No pixels selected"
 
155
 
156
- # Get pixel spacing (mm/pixel)
157
- pixel_spacing = float(self.dicom_data.PixelSpacing[0])
158
-
159
- # Calculate area using ImageJ method
160
- n_pixels = np.sum(mask) # Count of pixels in mask
161
- area = n_pixels * (pixel_spacing ** 2)
162
-
163
- # Calculate other statistics
164
- mean_value = np.mean(roi_pixels)
165
- std_dev = np.std(roi_pixels, ddof=1) # ImageJ uses n-1
166
- min_val = np.min(roi_pixels)
167
- max_val = np.max(roi_pixels)
168
 
169
- # Store results
170
- result = {
171
- 'Area (mm²)': f"{area:.3f}",
172
- 'Mean': f"{mean_value:.3f}",
173
- 'StdDev': f"{std_dev:.3f}",
174
- 'Min': f"{min_val:.3f}",
175
- 'Max': f"{max_val:.3f}",
176
- 'Point': f"({x:.1f}, {y:.1f})"
177
- }
178
-
179
- print(f"ROI Analysis Results:")
180
- print(f"Area: {area:.3f} mm²")
181
- print(f"Mean: {mean_value:.3f}")
182
- print(f"StdDev: {std_dev:.3f}")
183
- print(f"Min: {min_val:.3f}")
184
- print(f"Max: {max_val:.3f}")
185
- print(f"Position: ({x:.1f}, {y:.1f})")
186
-
187
- self.results.append(result)
188
- self.marks.append((x, y, self.circle_diameter))
189
 
190
- return self.update_display(), self.format_results()
191
- except Exception as e:
192
- print(f"Error analyzing ROI: {str(e)}")
193
- return self.display_image, f"Error analyzing ROI: {str(e)}"
194
  def update_display(self):
195
  try:
196
  if self.original_display is None:
 
122
  print(f"Error handling keyboard input: {str(e)}")
123
  return self.display_image
124
 
125
+ def analyze_roi(self, evt: gr.SelectData):
126
+ try:
127
+ if self.current_image is None:
128
+ return None, "No image loaded"
129
 
130
+ # Get clicked coordinates
131
+ clicked_x, clicked_y = evt.index[0], evt.index[1]
132
+
133
+ # Transform coordinates to match ImageJ
134
+ x = (clicked_x + self.pan_x) / self.zoom_factor
135
+ y = (clicked_y + self.pan_y) / self.zoom_factor
136
+
137
+ # Get image dimensions
138
+ height, width = self.current_image.shape[:2]
139
+
140
+ # ImageJ-style circle creation
141
+ Y, X = np.ogrid[:height, :width]
142
+
143
+ # ImageJ uses a specific method for radius calculation
144
+ radius = self.circle_diameter / 2.0
145
+
146
+ # Create the circular ROI mask using ImageJ's method
147
+ # ImageJ considers pixels as 1x1 squares centered on integer coordinates
148
+ dist_squared = (X - x)**2 + (Y - y)**2
149
+ mask = dist_squared <= (radius * radius)
150
+
151
+ # Get ROI pixels
152
+ roi_pixels = self.current_image[mask]
153
+
154
+ if len(roi_pixels) == 0:
155
+ return self.display_image, "Error: No pixels selected"
156
 
157
+ # Get pixel spacing (mm/pixel)
158
+ pixel_spacing = float(self.dicom_data.PixelSpacing[0])
159
+
160
+ # Calculate area exactly as ImageJ does
161
+ n_pixels = np.sum(mask) # Total number of pixels in ROI
162
+ area = n_pixels * (pixel_spacing * pixel_spacing) # Area in mm²
163
+
164
+ # Calculate other statistics
165
+ mean_value = np.mean(roi_pixels)
166
+ std_dev = np.std(roi_pixels, ddof=1) # ImageJ uses n-1 for standard deviation
167
+ min_val = np.min(roi_pixels)
168
+ max_val = np.max(roi_pixels)
169
 
170
+ # Store results
171
+ result = {
172
+ 'Area (mm²)': f"{area:.3f}",
173
+ 'Mean': f"{mean_value:.3f}",
174
+ 'StdDev': f"{std_dev:.3f}",
175
+ 'Min': f"{min_val:.3f}",
176
+ 'Max': f"{max_val:.3f}",
177
+ 'Point': f"({x:.1f}, {y:.1f})"
178
+ }
179
+
180
+ print(f"ROI Analysis Results:")
181
+ print(f"Number of pixels: {n_pixels}")
182
+ print(f"Pixel spacing: {pixel_spacing} mm")
183
+ print(f"Area: {area:.3f} mm²")
184
+ print(f"Mean: {mean_value:.3f}")
185
+ print(f"StdDev: {std_dev:.3f}")
186
+ print(f"Position: ({x:.1f}, {y:.1f})")
187
+
188
+ self.results.append(result)
189
+ self.marks.append((x, y, self.circle_diameter))
190
 
191
+ return self.update_display(), self.format_results()
192
+ except Exception as e:
193
+ print(f"Error analyzing ROI: {str(e)}")
194
+ return self.display_image, f"Error analyzing ROI: {str(e)}"
195
  def update_display(self):
196
  try:
197
  if self.original_display is None: