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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -19
app.py CHANGED
@@ -11,7 +11,7 @@ print("Starting imports completed...")
11
  class DicomAnalyzer:
12
  def __init__(self):
13
  self.results = []
14
- self.circle_diameter = 9
15
  self.zoom_factor = 1.0
16
  self.current_image = None
17
  self.dicom_data = None
@@ -134,18 +134,16 @@ class DicomAnalyzer:
134
  x = (clicked_x + self.pan_x) / self.zoom_factor
135
  y = (clicked_y + self.pan_y) / self.zoom_factor
136
 
137
- # ImageJ coordinate correction
138
- x = x - 0.5 # ImageJ starts from 0.5, not 0
139
- y = y - 0.5
140
-
141
  # Get image dimensions
142
  height, width = self.current_image.shape[:2]
143
 
144
  # Create precise circular mask (ImageJ method)
145
  y_coords, x_coords = np.ogrid[:height, :width]
146
- radius = self.circle_diameter / 2.0
147
 
148
- # Use exact ImageJ distance calculation
 
 
 
149
  dist_squared = (x_coords - x)**2 + (y_coords - y)**2
150
  mask = dist_squared <= radius**2
151
 
@@ -158,28 +156,36 @@ class DicomAnalyzer:
158
  # Get pixel spacing (mm/pixel)
159
  pixel_spacing = float(self.dicom_data.PixelSpacing[0])
160
 
161
- # Calculate statistics exactly like ImageJ
162
- n_pixels = len(roi_pixels)
 
 
 
163
  mean_value = np.mean(roi_pixels)
164
  std_dev = np.std(roi_pixels, ddof=1) # ImageJ uses n-1
165
  min_val = np.min(roi_pixels)
166
  max_val = np.max(roi_pixels)
167
-
168
- # Calculate area using ImageJ method
169
- area = n_pixels * (pixel_spacing ** 2)
170
 
171
- # Store results with ImageJ precision
172
  result = {
173
  'Area (mm²)': f"{area:.3f}",
174
  'Mean': f"{mean_value:.3f}",
175
  'StdDev': f"{std_dev:.3f}",
176
  'Min': f"{min_val:.3f}",
177
  'Max': f"{max_val:.3f}",
178
- 'Point': f"({x+0.5:.1f}, {y+0.5:.1f})" # Add 0.5 back for display
179
  }
180
 
 
 
 
 
 
 
 
 
181
  self.results.append(result)
182
- self.marks.append((x+0.5, y+0.5, self.circle_diameter))
183
 
184
  return self.update_display(), self.format_results()
185
  except Exception as e:
@@ -205,13 +211,13 @@ class DicomAnalyzer:
205
  for x, y, diameter in self.marks:
206
  zoomed_x = int(x * self.zoom_factor)
207
  zoomed_y = int(y * self.zoom_factor)
208
- zoomed_radius = int((diameter/2) * self.zoom_factor)
209
 
210
  # Draw main circle
211
  cv2.circle(zoomed_bgr,
212
  (zoomed_x, zoomed_y),
213
  zoomed_radius,
214
- self.CIRCLE_COLOR, # BGR Yellow (0, 255, 255)
215
  1,
216
  lineType=cv2.LINE_AA)
217
 
@@ -224,7 +230,7 @@ class DicomAnalyzer:
224
  cv2.circle(zoomed_bgr,
225
  (point_x, point_y),
226
  1,
227
- self.CIRCLE_COLOR, # BGR Yellow (0, 255, 255)
228
  -1,
229
  lineType=cv2.LINE_AA)
230
 
@@ -345,7 +351,7 @@ def create_interface():
345
  """)
346
 
347
  def update_diameter(x):
348
- analyzer.circle_diameter = x
349
  print(f"Diameter updated to: {x}")
350
  return f"Diameter set to {x} pixels"
351
 
 
11
  class DicomAnalyzer:
12
  def __init__(self):
13
  self.results = []
14
+ self.circle_diameter = 9.0 # Changed to float for precise calculations
15
  self.zoom_factor = 1.0
16
  self.current_image = None
17
  self.dicom_data = None
 
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
 
 
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:
 
211
  for x, y, diameter in self.marks:
212
  zoomed_x = int(x * self.zoom_factor)
213
  zoomed_y = int(y * self.zoom_factor)
214
+ zoomed_radius = int(((diameter - 1) / 2) * self.zoom_factor) # Adjusted radius calculation
215
 
216
  # Draw main circle
217
  cv2.circle(zoomed_bgr,
218
  (zoomed_x, zoomed_y),
219
  zoomed_radius,
220
+ self.CIRCLE_COLOR, # BGR Yellow
221
  1,
222
  lineType=cv2.LINE_AA)
223
 
 
230
  cv2.circle(zoomed_bgr,
231
  (point_x, point_y),
232
  1,
233
+ self.CIRCLE_COLOR,
234
  -1,
235
  lineType=cv2.LINE_AA)
236
 
 
351
  """)
352
 
353
  def update_diameter(x):
354
+ analyzer.circle_diameter = float(x) # Convert to float
355
  print(f"Diameter updated to: {x}")
356
  return f"Diameter set to {x} pixels"
357