HeshamAI commited on
Commit
0f6d329
·
verified ·
1 Parent(s): aec9c12

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -67
app.py CHANGED
@@ -4,15 +4,16 @@ import numpy as np
4
  import pandas as pd
5
  import pydicom
6
  import tempfile
 
7
 
8
  class DicomAnalyzer:
9
  def __init__(self):
10
  self.results = []
11
  self.circle_diameter = 9
12
- self.current_image = None
13
- self.dicom_data = None
14
- self.image_display = None
15
- self.marks = []
16
 
17
  def load_dicom(self, file):
18
  try:
@@ -27,6 +28,9 @@ class DicomAnalyzer:
27
  rescale_intercept = getattr(dicom_data, 'RescaleIntercept', 0)
28
  image = (image * rescale_slope) + rescale_intercept
29
 
 
 
 
30
  # Normalize for display
31
  image_display = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
32
 
@@ -34,7 +38,7 @@ class DicomAnalyzer:
34
  if len(image_display.shape) == 2:
35
  image_display = cv2.cvtColor(image_display, cv2.COLOR_GRAY2BGR)
36
 
37
- return image, image_display, dicom_data
38
  except Exception as e:
39
  print(f"Error loading DICOM file: {str(e)}")
40
  return None, None, None
@@ -70,72 +74,68 @@ class DicomAnalyzer:
70
  print(f"Error analyzing point: {str(e)}")
71
  return None
72
 
73
- def draw_circle(self, image, x, y, is_image1=True):
74
- try:
75
- image_copy = image.copy()
76
-
77
- # Draw all previous marks
78
- marks = self.marks1 if is_image1 else self.marks2
79
- for mark_x, mark_y in marks:
 
 
 
 
 
 
 
 
 
 
 
80
  cv2.circle(image_copy,
81
- (int(mark_x), int(mark_y)),
82
  int(self.circle_diameter / 2),
83
  (255, 255, 0), 1, # Yellow outer ring (thin)
84
  lineType=cv2.LINE_AA)
85
- cv2.circle(image_copy,
86
- (int(mark_x), int(mark_y)),
87
- int(self.circle_diameter / 2) - 1, # Slightly smaller radius
88
  (255, 255, 255), 1, # White inner ring (thin)
89
  lineType=cv2.LINE_AA)
90
 
91
- # Draw the new mark
92
- cv2.circle(image_copy,
93
- (int(x), int(y)),
94
- int(self.circle_diameter / 2),
95
- (255, 255, 0), 1, # Yellow outer ring (thin)
96
- lineType=cv2.LINE_AA)
97
- cv2.circle(image_copy,
98
- (int(x), int(y)),
99
- int(self.circle_diameter / 2) - 1,
100
- (255, 255, 255), 1, # White inner ring (thin)
101
- lineType=cv2.LINE_AA)
102
-
103
- # Store the new mark
104
- if is_image1:
105
  self.marks1.append((x, y))
106
- else:
107
- self.marks2.append((x, y))
108
-
109
- return image_copy
110
- except Exception as e:
111
- print(f"Error drawing circle: {str(e)}")
112
- return image
113
 
114
  def process_image(self, file):
115
  image, image_display, dicom_data = self.load_dicom(file)
116
- self.current_image = image
117
- self.image_display = image_display
118
- self.dicom_data = dicom_data
119
  return image_display
120
 
121
  def handle_click(self, evt: gr.SelectData):
122
- if self.current_image is None:
123
- return self.image_display, "Please load the DICOM file first"
124
 
125
  try:
126
  x, y = evt.index
127
- marked_image = self.draw_circle(self.image_display, x, y)
128
- self.image_display = marked_image
129
 
130
- results = self.analyze_point(self.current_image, self.dicom_data, x, y)
131
  if results:
132
  results['Point'] = f"({x}, {y})"
133
  self.results.append(results)
134
 
135
- return self.image_display, self.format_results()
136
  except Exception as e:
137
  print(f"Error in handle_click: {str(e)}")
138
- return self.image_display, f"Error: {str(e)}"
139
 
140
  def format_results(self):
141
  if not self.results:
@@ -145,13 +145,13 @@ class DicomAnalyzer:
145
 
146
  def clear_results(self):
147
  self.results = []
148
- self.marks = []
149
- if self.current_image is not None:
150
- self.image_display = cv2.cvtColor(
151
- cv2.normalize(self.current_image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8),
152
  cv2.COLOR_GRAY2BGR
153
  )
154
- return "Results cleared", self.image_display
155
 
156
  def update_circle_diameter(self, value):
157
  self.circle_diameter = value
@@ -183,16 +183,17 @@ def create_interface():
183
  gr.Markdown("# CT DICOM Image Analyzer")
184
 
185
  with gr.Row():
186
- file = gr.File(label="Upload DICOM File")
187
- image = gr.Image(label="DICOM Image", interactive=True, type="numpy")
188
- file.change(fn=analyzer.process_image, inputs=file, outputs=image)
 
189
 
190
  with gr.Row():
191
  circle_diameter = gr.Slider(
192
- minimum=1,
193
- maximum=20,
194
- value=9,
195
- step=1,
196
  label="Circle Diameter"
197
  )
198
 
@@ -206,23 +207,23 @@ def create_interface():
206
 
207
  # Connect events
208
  circle_diameter.change(
209
- fn=analyzer.update_circle_diameter,
210
- inputs=circle_diameter,
211
  outputs=status
212
  )
213
 
214
- image.select(
215
- fn=analyzer.handle_click,
216
- outputs=[image, results]
217
  )
218
 
219
  clear_btn.click(
220
- fn=analyzer.clear_results,
221
- outputs=[status, image]
222
  )
223
 
224
  save_btn.click(
225
- fn=analyzer.save_results,
226
  outputs=[file_output, status]
227
  )
228
 
 
4
  import pandas as pd
5
  import pydicom
6
  import tempfile
7
+ import os
8
 
9
  class DicomAnalyzer:
10
  def __init__(self):
11
  self.results = []
12
  self.circle_diameter = 9
13
+ self.current_image1 = None
14
+ self.image_display1 = None
15
+ self.dicom_data1 = None
16
+ self.marks1 = []
17
 
18
  def load_dicom(self, file):
19
  try:
 
28
  rescale_intercept = getattr(dicom_data, 'RescaleIntercept', 0)
29
  image = (image * rescale_slope) + rescale_intercept
30
 
31
+ # Store original image for analysis
32
+ original_image = image.copy()
33
+
34
  # Normalize for display
35
  image_display = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
36
 
 
38
  if len(image_display.shape) == 2:
39
  image_display = cv2.cvtColor(image_display, cv2.COLOR_GRAY2BGR)
40
 
41
+ return original_image, image_display, dicom_data
42
  except Exception as e:
43
  print(f"Error loading DICOM file: {str(e)}")
44
  return None, None, None
 
74
  print(f"Error analyzing point: {str(e)}")
75
  return None
76
 
77
+ def draw_circle(self, image, x, y):
78
+ try:
79
+ image_copy = image.copy()
80
+
81
+ # Draw all previous marks
82
+ for mark_x, mark_y in self.marks1:
83
+ cv2.circle(image_copy,
84
+ (int(mark_x), int(mark_y)),
85
+ int(self.circle_diameter / 2),
86
+ (255, 255, 0), 1, # Yellow outer ring (thin)
87
+ lineType=cv2.LINE_AA)
88
+ cv2.circle(image_copy,
89
+ (int(mark_x), int(mark_y)),
90
+ int(self.circle_diameter / 2) - 1,
91
+ (255, 255, 255), 1, # White inner ring (thin)
92
+ lineType=cv2.LINE_AA)
93
+
94
+ # Draw the new mark
95
  cv2.circle(image_copy,
96
+ (int(x), int(y)),
97
  int(self.circle_diameter / 2),
98
  (255, 255, 0), 1, # Yellow outer ring (thin)
99
  lineType=cv2.LINE_AA)
100
+ cv2.circle(image_copy,
101
+ (int(x), int(y)),
102
+ int(self.circle_diameter / 2) - 1,
103
  (255, 255, 255), 1, # White inner ring (thin)
104
  lineType=cv2.LINE_AA)
105
 
106
+ # Store the new mark
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  self.marks1.append((x, y))
108
+
109
+ return image_copy
110
+ except Exception as e:
111
+ print(f"Error drawing circle: {str(e)}")
112
+ return image
 
 
113
 
114
  def process_image(self, file):
115
  image, image_display, dicom_data = self.load_dicom(file)
116
+ self.current_image1 = image
117
+ self.image_display1 = image_display
118
+ self.dicom_data1 = dicom_data
119
  return image_display
120
 
121
  def handle_click(self, evt: gr.SelectData):
122
+ if self.current_image1 is None:
123
+ return self.image_display1, "Please load an image first"
124
 
125
  try:
126
  x, y = evt.index
127
+ marked_image = self.draw_circle(self.image_display1, x, y)
128
+ self.image_display1 = marked_image
129
 
130
+ results = self.analyze_point(self.current_image1, self.dicom_data1, x, y)
131
  if results:
132
  results['Point'] = f"({x}, {y})"
133
  self.results.append(results)
134
 
135
+ return self.image_display1, self.format_results()
136
  except Exception as e:
137
  print(f"Error in handle_click: {str(e)}")
138
+ return self.image_display1, f"Error: {str(e)}"
139
 
140
  def format_results(self):
141
  if not self.results:
 
145
 
146
  def clear_results(self):
147
  self.results = []
148
+ self.marks1 = []
149
+ if self.current_image1 is not None:
150
+ self.image_display1 = cv2.cvtColor(
151
+ cv2.normalize(self.current_image1, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8),
152
  cv2.COLOR_GRAY2BGR
153
  )
154
+ return "Results cleared", self.image_display1
155
 
156
  def update_circle_diameter(self, value):
157
  self.circle_diameter = value
 
183
  gr.Markdown("# CT DICOM Image Analyzer")
184
 
185
  with gr.Row():
186
+ with gr.Column():
187
+ file1 = gr.File(label="Upload DICOM file")
188
+ image1 = gr.Image(label="DICOM Image", interactive=True, type="numpy")
189
+ file1.change(fn=analyzer.process_image, inputs=file1, outputs=image1)
190
 
191
  with gr.Row():
192
  circle_diameter = gr.Slider(
193
+ minimum=1,
194
+ maximum=20,
195
+ value=9,
196
+ step=1,
197
  label="Circle Diameter"
198
  )
199
 
 
207
 
208
  # Connect events
209
  circle_diameter.change(
210
+ fn=analyzer.update_circle_diameter,
211
+ inputs=circle_diameter,
212
  outputs=status
213
  )
214
 
215
+ image1.select(
216
+ fn=analyzer.handle_click,
217
+ outputs=[image1, results]
218
  )
219
 
220
  clear_btn.click(
221
+ fn=analyzer.clear_results,
222
+ outputs=[status, image1]
223
  )
224
 
225
  save_btn.click(
226
+ fn=analyzer.save_results,
227
  outputs=[file_output, status]
228
  )
229