HeshamAI commited on
Commit
a072333
·
verified ·
1 Parent(s): 99da8a7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -50
app.py CHANGED
@@ -144,59 +144,131 @@ class DicomAnalyzer:
144
  x = clicked_x
145
  y = clicked_y
146
 
147
- # Apply ImageJ coordinate system correction
148
- # These offset values might need fine-tuning based on testing
149
- x_offset = -2 # Adjust this value
150
- y_offset = -2 # Adjust this value
151
-
152
- x = x + x_offset
153
- y = y + y_offset
154
-
155
- # Ensure coordinates are within bounds
156
- x = max(0, min(x, width-1))
157
- y = max(0, min(y, height-1))
158
-
159
- # Create circular mask with adjusted coordinates
160
- mask = np.zeros_like(raw_image, dtype=np.uint8)
161
- y_indices, x_indices = np.ogrid[:height, :width]
162
- radius = self.circle_diameter / 2
163
- distance_from_center = np.sqrt(
164
- (x_indices - x)**2 + (y_indices - y)**2
165
- )
166
- mask[distance_from_center <= radius] = 1
167
 
168
- # Get ROI pixels using ImageJ-aligned coordinates
169
- roi_pixels = raw_image[mask == 1]
 
170
 
171
- # Calculate statistics using ImageJ scaling
172
- pixel_spacing = float(self.dicom_data.PixelSpacing[0])
173
- area_pixels = np.sum(mask)
174
- area_mm2 = area_pixels * (pixel_spacing ** 2)
175
-
176
- # Apply ImageJ-like scaling to match results
177
- scaling_factor = 1.0 # Adjust this value to match ImageJ scaling
178
- mean = np.mean(roi_pixels) * scaling_factor
179
- stddev = np.std(roi_pixels) * scaling_factor
180
- min_val = np.min(roi_pixels)
181
- max_val = np.max(roi_pixels)
182
-
183
- # Store results
184
- result = {
185
- 'Area (mm²)': f"{area_mm2:.3f}",
186
- 'Mean': f"{mean:.3f}",
187
- 'StdDev': f"{stddev:.3f}",
188
- 'Min': f"{min_val:.3f}",
189
- 'Max': f"{max_val:.3f}",
190
- 'Point': f"({x}, {y})"
191
- }
192
-
193
- self.results.append(result)
194
- self.marks.append((x, y, self.circle_diameter))
195
 
196
- return self.update_display(), self.format_results()
197
- except Exception as e:
198
- print(f"Error analyzing ROI: {str(e)}")
199
- return self.display_image, f"Error analyzing ROI: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
  def format_results(self):
202
  if not self.results:
 
144
  x = clicked_x
145
  y = clicked_y
146
 
147
+ # Apply ImageJ coordinate system correction
148
+ x_offset = -2 # Adjust this value
149
+ y_offset = -2 # Adjust this value
150
+
151
+ x = x + x_offset
152
+ y = y + y_offset
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
+ # Ensure coordinates are within bounds
155
+ x = max(0, min(x, width-1))
156
+ y = max(0, min(y, height-1))
157
 
158
+ # Create circular mask with adjusted coordinates
159
+ mask = np.zeros_like(raw_image, dtype=np.uint8)
160
+ y_indices, x_indices = np.ogrid[:height, :width]
161
+ radius = self.circle_diameter / 2
162
+ distance_from_center = np.sqrt(
163
+ (x_indices - x)**2 + (y_indices - y)**2
164
+ )
165
+ mask[distance_from_center <= radius] = 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
+ # Get ROI pixels using ImageJ-aligned coordinates
168
+ roi_pixels = raw_image[mask == 1]
169
+
170
+ # Calculate statistics using ImageJ scaling
171
+ pixel_spacing = float(self.dicom_data.PixelSpacing[0])
172
+ area_pixels = np.sum(mask)
173
+ area_mm2 = area_pixels * (pixel_spacing ** 2)
174
+
175
+ # Apply ImageJ-like scaling to match results
176
+ scaling_factor = 0.3 # Adjust this value to match ImageJ scaling
177
+ mean = np.mean(roi_pixels) * scaling_factor
178
+ stddev = np.std(roi_pixels) * scaling_factor
179
+ min_val = np.min(roi_pixels)
180
+ max_val = np.max(roi_pixels)
181
+
182
+ # Store results
183
+ result = {
184
+ 'Area (mm²)': f"{area_mm2:.3f}",
185
+ 'Mean': f"{mean:.3f}",
186
+ 'StdDev': f"{stddev:.3f}",
187
+ 'Min': f"{min_val:.3f}",
188
+ 'Max': f"{max_val:.3f}",
189
+ 'Point': f"({x}, {y})"
190
+ }
191
+
192
+ self.results.append(result)
193
+ self.marks.append((x, y, self.circle_diameter))
194
+
195
+ # Debug information
196
+ print(f"Original click: ({clicked_x}, {clicked_y})")
197
+ print(f"Adjusted coordinates: ({x}, {y})")
198
+ print(f"Zoom factor: {self.zoom_factor}")
199
+ print(f"Pan: ({self.pan_x}, {self.pan_y})")
200
+ print(f"ROI Statistics: Mean={mean:.3f}, StdDev={stddev:.3f}")
201
+ print(f"Min={min_val:.3f}, Max={max_val:.3f}")
202
+
203
+ return self.update_display(), self.format_results()
204
+ except Exception as e:
205
+ print(f"Error analyzing ROI: {str(e)}")
206
+ return self.display_image, f"Error analyzing ROI: {str(e)}"
207
+
208
+ def update_display(self):
209
+ try:
210
+ if self.original_display is None:
211
+ return None
212
+
213
+ height, width = self.original_display.shape[:2]
214
+ new_height = int(height * self.zoom_factor)
215
+ new_width = int(width * self.zoom_factor)
216
+
217
+ # Create zoomed image
218
+ zoomed = cv2.resize(self.original_display, (new_width, new_height),
219
+ interpolation=cv2.INTER_CUBIC)
220
+
221
+ # Convert to BGR for drawing
222
+ zoomed_bgr = cv2.cvtColor(zoomed, cv2.COLOR_RGB2BGR)
223
+
224
+ # Draw marks
225
+ for x, y, diameter in self.marks:
226
+ zoomed_x = int(x * self.zoom_factor)
227
+ zoomed_y = int(y * self.zoom_factor)
228
+ zoomed_diameter = int(diameter * self.zoom_factor)
229
+
230
+ # Draw main circle in BGR color space
231
+ cv2.circle(zoomed_bgr,
232
+ (zoomed_x, zoomed_y),
233
+ zoomed_diameter // 2,
234
+ (0, 255, 255), # BGR: Yellow
235
+ 1,
236
+ lineType=cv2.LINE_AA)
237
+
238
+ # Draw dots on circle
239
+ num_points = 8
240
+ for i in range(num_points):
241
+ angle = 2 * np.pi * i / num_points
242
+ point_x = int(zoomed_x + (zoomed_diameter/2) * np.cos(angle))
243
+ point_y = int(zoomed_y + (zoomed_diameter/2) * np.sin(angle))
244
+ cv2.circle(zoomed_bgr,
245
+ (point_x, point_y),
246
+ 1,
247
+ (0, 255, 255), # BGR: Yellow
248
+ -1,
249
+ lineType=cv2.LINE_AA)
250
+
251
+ # Convert back to RGB for display
252
+ zoomed = cv2.cvtColor(zoomed_bgr, cv2.COLOR_BGR2RGB)
253
+
254
+ # Calculate pan limits
255
+ self.max_pan_x = max(0, new_width - width)
256
+ self.max_pan_y = max(0, new_height - height)
257
+
258
+ # Ensure pan values are within bounds
259
+ self.pan_x = min(max(0, self.pan_x), self.max_pan_x)
260
+ self.pan_y = min(max(0, self.pan_y), self.max_pan_y)
261
+
262
+ # Extract visible portion
263
+ visible = zoomed[
264
+ int(self.pan_y):int(self.pan_y + height),
265
+ int(self.pan_x):int(self.pan_x + width)
266
+ ]
267
+
268
+ return visible
269
+ except Exception as e:
270
+ print(f"Error updating display: {str(e)}")
271
+ return self.original_display
272
 
273
  def format_results(self):
274
  if not self.results: