HeshamAI commited on
Commit
a82c6bf
·
verified ·
1 Parent(s): afa65ec

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -67
app.py CHANGED
@@ -139,76 +139,89 @@ class DicomAnalyzer:
139
  print(f"Error handling keyboard input: {str(e)}")
140
  return self.display_image
141
 
142
- def analyze_roi(self, evt: gr.SelectData):
143
- try:
144
- if self.current_image is None:
145
- return None, "No image loaded"
146
 
147
- # Transform coordinates using ImageJ method
148
- x, y = self.transform_coordinates(evt.index[0], evt.index[1])
149
-
150
- # Get image dimensions
151
- height, width = self.current_image.shape[:2]
152
-
153
- # Create precise circular mask using ImageJ's method
154
- Y, X = np.ogrid[:height, :width]
155
-
156
- # ImageJ's circle creation method
157
- radius = (self.circle_diameter - 1) / 2.0
158
-
159
- # Calculate distances using ImageJ's method
160
- dx = X - x
161
- dy = Y - y
162
- dist_squared = dx*dx + dy*dy
163
- mask = dist_squared <= radius*radius
164
-
165
- # Get ROI pixels using the exact same mask
166
- roi_pixels = self.current_image[mask]
167
-
168
- if len(roi_pixels) == 0:
169
- return self.display_image, "Error: No pixels selected"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
- # Get pixel spacing (mm/pixel)
172
- pixel_spacing = float(self.dicom_data.PixelSpacing[0])
173
-
174
- # Calculate area exactly as ImageJ does
175
- n_pixels = np.sum(mask)
176
- area = n_pixels * (pixel_spacing * pixel_spacing)
177
-
178
- # Calculate statistics exactly as ImageJ does
179
- mean_value = np.mean(roi_pixels)
180
- std_dev = np.std(roi_pixels, ddof=1) # ImageJ uses n-1
181
- min_val = np.min(roi_pixels)
182
- max_val = np.max(roi_pixels)
183
-
184
- # Debug print
185
- print(f"\nImageJ-compatible Analysis:")
186
- print(f"Position: ({x}, {y})")
187
- print(f"Radius: {radius}")
188
- print(f"Pixel count: {n_pixels}")
189
- print(f"Area: {area:.3f} mm²")
190
- print(f"Mean: {mean_value:.3f}")
191
- print(f"StdDev: {std_dev:.3f}")
192
- print(f"Min: {min_val}")
193
- print(f"Max: {max_val}")
194
-
195
- # Store results
196
- result = {
197
- 'Area (mm²)': f"{area:.3f}",
198
- 'Mean': f"{mean_value:.3f}",
199
- 'StdDev': f"{std_dev:.3f}",
200
- 'Min': f"{min_val:.3f}",
201
- 'Max': f"{max_val:.3f}",
202
- 'Point': f"({x}, {y})"
203
- }
204
-
205
- self.results.append(result)
206
- self.marks.append((x, y, self.circle_diameter))
207
 
208
- return self.update_display(), self.format_results()
209
- except Exception as e:
210
- print(f"Error analyzing ROI: {str(e)}")
211
- return self.display_image, f"Error analyzing ROI: {str(e)}"
212
  def update_display(self):
213
  try:
214
  if self.original_display is None:
 
139
  print(f"Error handling keyboard input: {str(e)}")
140
  return self.display_image
141
 
142
+ def analyze_roi(self, evt: gr.SelectData):
143
+ try:
144
+ if self.current_image is None:
145
+ return None, "No image loaded"
146
 
147
+ # Get clicked coordinates
148
+ clicked_x = evt.index[0]
149
+ clicked_y = evt.index[1]
150
+
151
+ # Transform coordinates to match ImageJ exactly
152
+ x = clicked_x + self.pan_x
153
+ y = clicked_y + self.pan_y
154
+ if self.zoom_factor != 1.0:
155
+ x = x / self.zoom_factor
156
+ y = y / self.zoom_factor
157
+
158
+ # ImageJ uses integer coordinates
159
+ x = int(round(x))
160
+ y = int(round(y))
161
+
162
+ # Get image dimensions
163
+ height, width = self.current_image.shape[:2]
164
+
165
+ # Create mask exactly as ImageJ does
166
+ Y, X = np.ogrid[:height, :width]
167
+ center_x = x
168
+ center_y = y
169
+
170
+ # ImageJ uses a specific radius calculation
171
+ radius = self.circle_diameter / 2.0
172
+
173
+ # Create the mask using ImageJ's method
174
+ dx = X - center_x
175
+ dy = Y - center_y
176
+ dist_squared = dx * dx + dy * dy
177
+ mask = dist_squared <= (radius * radius)
178
+
179
+ # Get ROI pixels
180
+ roi_pixels = self.current_image[mask]
181
+
182
+ if len(roi_pixels) == 0:
183
+ return self.display_image, "Error: No pixels selected"
184
 
185
+ # Get pixel spacing (mm/pixel)
186
+ pixel_spacing = float(self.dicom_data.PixelSpacing[0])
187
+
188
+ # Calculate statistics exactly as ImageJ does
189
+ n_pixels = np.sum(mask)
190
+ area = n_pixels * (pixel_spacing ** 2)
191
+
192
+ # Use ImageJ's statistical calculations
193
+ mean_value = np.mean(roi_pixels)
194
+ std_dev = np.std(roi_pixels, ddof=1) # ImageJ uses n-1
195
+ min_val = np.min(roi_pixels)
196
+ max_val = np.max(roi_pixels)
197
+
198
+ # Print debug information
199
+ print(f"\nDetailed Analysis:")
200
+ print(f"Coordinates: ({x}, {y})")
201
+ print(f"Pixel count: {n_pixels}")
202
+ print(f"Area: {area:.3f} mm²")
203
+ print(f"Mean: {mean_value:.3f}")
204
+ print(f"StdDev: {std_dev:.3f}")
205
+ print(f"Min: {min_val}")
206
+ print(f"Max: {max_val}")
207
+
208
+ # Store results
209
+ result = {
210
+ 'Area (mm²)': f"{area:.3f}",
211
+ 'Mean': f"{mean_value:.3f}",
212
+ 'StdDev': f"{std_dev:.3f}",
213
+ 'Min': f"{min_val:.3f}",
214
+ 'Max': f"{max_val:.3f}",
215
+ 'Point': f"({x}, {y})"
216
+ }
217
+
218
+ self.results.append(result)
219
+ self.marks.append((x, y, self.circle_diameter))
 
220
 
221
+ return self.update_display(), self.format_results()
222
+ except Exception as e:
223
+ print(f"Error analyzing ROI: {str(e)}")
224
+ return self.display_image, f"Error analyzing ROI: {str(e)}"
225
  def update_display(self):
226
  try:
227
  if self.original_display is None: