ibrahim313 commited on
Commit
8f2167b
·
verified ·
1 Parent(s): a0d6076

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -82
app.py CHANGED
@@ -5,102 +5,118 @@ import gradio as gr
5
  from skimage import measure, morphology
6
  from skimage.segmentation import watershed
7
  import matplotlib.pyplot as plt
8
- import base64
9
  from datetime import datetime
 
10
 
11
  def apply_color_transformation(image, transform_type):
12
  """Apply different color transformations to the image"""
13
- try:
14
- # Convert to BGR if needed
15
- if len(image.shape) == 3 and image.shape[2] == 3:
16
- image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
17
-
18
- if transform_type == "Original":
19
- return cv2.cvtColor(image, cv2.COLOR_BGR2RGB) if len(image.shape) == 3 else image
20
- elif transform_type == "Grayscale":
21
- return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if len(image.shape) == 3 else image
22
- elif transform_type == "Binary":
23
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if len(image.shape) == 3 else image
24
- _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
25
- return binary
26
- elif transform_type == "CLAHE":
27
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if len(image.shape) == 3 else image
28
- clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
29
- return clahe.apply(gray)
30
- return image
31
- except Exception as e:
32
- print(f"Transformation error: {str(e)}")
33
- return None
34
 
35
  def process_image(image, transform_type):
36
  """Process uploaded image and extract cell features"""
 
 
 
37
  try:
38
- if image is None:
39
- return [None]*4
40
-
41
  # Store original image for color transformations
42
  original_image = image.copy()
43
 
44
- # Convert to BGR for OpenCV processing
45
  if len(image.shape) == 3:
46
  image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
47
 
48
- # Preprocessing pipeline
49
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
50
  clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
51
  enhanced = clahe.apply(gray)
52
  blurred = cv2.medianBlur(enhanced, 5)
53
 
54
  # Thresholding
55
- _, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
56
 
57
- # Noise removal
58
  kernel = np.ones((3,3), np.uint8)
59
- opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
60
 
61
  # Sure background area
62
  sure_bg = cv2.dilate(opening, kernel, iterations=3)
63
 
64
  # Finding sure foreground area
65
  dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
66
- _, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
67
- sure_fg = np.uint8(sure_fg)
68
 
69
- # Unknown region
70
  unknown = cv2.subtract(sure_bg, sure_fg)
71
 
72
  # Marker labelling
73
  _, markers = cv2.connectedComponents(sure_fg)
74
- markers += 1
75
  markers[unknown == 255] = 0
76
 
77
- # Watershed algorithm
78
  markers = cv2.watershed(image, markers)
79
 
80
- # Feature extraction
81
  features = []
82
- vis_img = image.copy()
83
-
84
  for region in measure.regionprops(markers):
85
- if region.area >= 50:
86
- y, x = region.centroid
87
- # Store features
88
  features.append({
89
  'label': region.label,
90
  'area': region.area,
 
91
  'circularity': (4 * np.pi * region.area) / (region.perimeter ** 2) if region.perimeter > 0 else 0,
92
- 'mean_intensity': region.mean_intensity
 
 
93
  })
94
- # Draw text with contrast
95
- cv2.putText(vis_img, str(region.label), (int(x), int(y)),
96
- cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2)
97
- cv2.putText(vis_img, str(region.label), (int(x), int(y)),
98
- cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 1)
99
 
100
- # Convert visualization image back to RGB
101
- vis_img = cv2.cvtColor(vis_img, cv2.COLOR_BGR2RGB)
 
102
 
103
- # Create analysis plots
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  plt.style.use('seaborn')
105
  fig, axes = plt.subplots(2, 2, figsize=(15, 12))
106
  fig.suptitle('Cell Analysis Results', fontsize=16, y=0.95)
@@ -110,16 +126,24 @@ def process_image(image, transform_type):
110
  # Distribution plots
111
  df['area'].hist(ax=axes[0,0], bins=20, color='skyblue', edgecolor='black')
112
  axes[0,0].set_title('Cell Size Distribution')
 
 
113
 
114
  df['circularity'].hist(ax=axes[0,1], bins=20, color='lightgreen', edgecolor='black')
115
  axes[0,1].set_title('Circularity Distribution')
 
 
116
 
117
- # Scatter plot
118
- axes[1,0].scatter(df['circularity'], df['mean_intensity'], alpha=0.6, c='purple')
 
119
  axes[1,0].set_title('Circularity vs Intensity')
 
 
120
 
121
  # Box plot
122
  df.boxplot(column=['area', 'circularity'], ax=axes[1,1])
 
123
  else:
124
  for ax in axes.flat:
125
  ax.text(0.5, 0.5, 'No cells detected', ha='center', va='center')
@@ -127,23 +151,20 @@ def process_image(image, transform_type):
127
  plt.tight_layout()
128
 
129
  # Apply color transformation
130
- transformed_img = apply_color_transformation(original_image, transform_type)
131
- if transformed_img is not None and len(transformed_img.shape) == 2:
132
- transformed_img = cv2.cvtColor(transformed_img, cv2.COLOR_GRAY2RGB)
133
 
134
  return (
135
- vis_img,
136
- transformed_img if transformed_img is not None else original_image,
137
  fig,
138
  df
139
  )
140
-
141
  except Exception as e:
142
- print(f"Processing error: {str(e)}")
143
- return [None]*4
144
-
145
 
146
- # Create enhanced Gradio interface
147
  with gr.Blocks(title="Advanced Cell Analysis Tool", theme=gr.themes.Soft()) as demo:
148
  gr.Markdown("""
149
  # 🔬 Advanced Bioengineering Cell Analysis Tool
@@ -157,7 +178,6 @@ with gr.Blocks(title="Advanced Cell Analysis Tool", theme=gr.themes.Soft()) as d
157
  ## Author
158
  - **Muhammad Ibrahim Qasmi**
159
  - [LinkedIn](https://www.linkedin.com/in/muhammad-ibrahim-qasmi-9876a1297/)
160
- - [GitHub](https://github.com/yourusername) <!-- Add your GitHub URL -->
161
  """)
162
 
163
  with gr.Row():
@@ -201,21 +221,6 @@ with gr.Blocks(title="Advanced Cell Analysis Tool", theme=gr.themes.Soft()) as d
201
  output_table = gr.DataFrame(
202
  label="Cell Features"
203
  )
204
- download_btn = gr.Button(
205
- "Download Results",
206
- variant="secondary"
207
- )
208
-
209
- # Add footer
210
- gr.Markdown("""
211
- ---
212
- ### 📝 Notes
213
- - Supported image formats: PNG, JPG, JPEG
214
- - Minimum recommended resolution: 512x512 pixels
215
- - Processing time varies with image size and cell count
216
-
217
- *Last updated: January 2025*
218
- """)
219
 
220
  analyze_btn.click(
221
  fn=process_image,
@@ -225,7 +230,4 @@ with gr.Blocks(title="Advanced Cell Analysis Tool", theme=gr.themes.Soft()) as d
225
 
226
  # Launch the demo
227
  if __name__ == "__main__":
228
- try:
229
- demo.launch()
230
- except Exception as e:
231
- print(f"Error launching Gradio interface: {e}")
 
5
  from skimage import measure, morphology
6
  from skimage.segmentation import watershed
7
  import matplotlib.pyplot as plt
 
8
  from datetime import datetime
9
+ import logging
10
 
11
  def apply_color_transformation(image, transform_type):
12
  """Apply different color transformations to the image"""
13
+ if len(image.shape) == 3:
14
+ image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
15
+
16
+ if transform_type == "Original":
17
+ return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
18
+ elif transform_type == "Grayscale":
19
+ return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
20
+ elif transform_type == "Binary":
21
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
22
+ _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
23
+ return binary
24
+ elif transform_type == "CLAHE":
25
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
26
+ clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
27
+ return clahe.apply(gray)
28
+ return image
 
 
 
 
 
29
 
30
  def process_image(image, transform_type):
31
  """Process uploaded image and extract cell features"""
32
+ if image is None:
33
+ return None, None, None, None
34
+
35
  try:
 
 
 
36
  # Store original image for color transformations
37
  original_image = image.copy()
38
 
39
+ # Convert to BGR if needed
40
  if len(image.shape) == 3:
41
  image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
42
 
43
+ # Basic preprocessing
44
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
45
  clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
46
  enhanced = clahe.apply(gray)
47
  blurred = cv2.medianBlur(enhanced, 5)
48
 
49
  # Thresholding
50
+ _, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
51
 
52
+ # Noise removal and cell separation
53
  kernel = np.ones((3,3), np.uint8)
54
+ opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=2)
55
 
56
  # Sure background area
57
  sure_bg = cv2.dilate(opening, kernel, iterations=3)
58
 
59
  # Finding sure foreground area
60
  dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
61
+ _, sure_fg = cv2.threshold(dist_transform, 0.5 * dist_transform.max(), 255, 0)
62
+ sure_fg = sure_fg.astype(np.uint8)
63
 
64
+ # Finding unknown region
65
  unknown = cv2.subtract(sure_bg, sure_fg)
66
 
67
  # Marker labelling
68
  _, markers = cv2.connectedComponents(sure_fg)
69
+ markers = markers + 1
70
  markers[unknown == 255] = 0
71
 
72
+ # Apply watershed
73
  markers = cv2.watershed(image, markers)
74
 
75
+ # Extract features
76
  features = []
 
 
77
  for region in measure.regionprops(markers):
78
+ if region.area >= 50: # Filter small regions
 
 
79
  features.append({
80
  'label': region.label,
81
  'area': region.area,
82
+ 'perimeter': region.perimeter,
83
  'circularity': (4 * np.pi * region.area) / (region.perimeter ** 2) if region.perimeter > 0 else 0,
84
+ 'mean_intensity': region.mean_intensity,
85
+ 'centroid_x': region.centroid[1],
86
+ 'centroid_y': region.centroid[0]
87
  })
 
 
 
 
 
88
 
89
+ # Create visualization
90
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
91
+ vis_img = image.copy()
92
 
93
+ # Draw contours
94
+ contours = measure.find_contours(markers, 0.5)
95
+ for contour in contours:
96
+ coords = np.array(contour).astype(int)
97
+ coords = coords[:, [1, 0]] # Swap x and y coordinates
98
+ coords = coords.reshape((-1, 1, 2))
99
+ cv2.polylines(vis_img, [coords], True, (0, 255, 0), 2)
100
+
101
+ # Add cell labels and measurements
102
+ for feature in features:
103
+ x = int(feature['centroid_x'])
104
+ y = int(feature['centroid_y'])
105
+ # White outline
106
+ cv2.putText(vis_img, str(feature['label']),
107
+ (x, y), cv2.FONT_HERSHEY_SIMPLEX,
108
+ 0.5, (255,255,255), 2)
109
+ # Red text
110
+ cv2.putText(vis_img, str(feature['label']),
111
+ (x, y), cv2.FONT_HERSHEY_SIMPLEX,
112
+ 0.5, (0,0,255), 1)
113
+
114
+ # Add timestamp
115
+ cv2.putText(vis_img, f"Analyzed: {timestamp}",
116
+ (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
117
+ 0.7, (255,255,255), 2)
118
+
119
+ # Create plots
120
  plt.style.use('seaborn')
121
  fig, axes = plt.subplots(2, 2, figsize=(15, 12))
122
  fig.suptitle('Cell Analysis Results', fontsize=16, y=0.95)
 
126
  # Distribution plots
127
  df['area'].hist(ax=axes[0,0], bins=20, color='skyblue', edgecolor='black')
128
  axes[0,0].set_title('Cell Size Distribution')
129
+ axes[0,0].set_xlabel('Area')
130
+ axes[0,0].set_ylabel('Count')
131
 
132
  df['circularity'].hist(ax=axes[0,1], bins=20, color='lightgreen', edgecolor='black')
133
  axes[0,1].set_title('Circularity Distribution')
134
+ axes[0,1].set_xlabel('Circularity')
135
+ axes[0,1].set_ylabel('Count')
136
 
137
+ # Scatter plots
138
+ axes[1,0].scatter(df['circularity'], df['mean_intensity'],
139
+ alpha=0.6, c='purple')
140
  axes[1,0].set_title('Circularity vs Intensity')
141
+ axes[1,0].set_xlabel('Circularity')
142
+ axes[1,0].set_ylabel('Mean Intensity')
143
 
144
  # Box plot
145
  df.boxplot(column=['area', 'circularity'], ax=axes[1,1])
146
+ axes[1,1].set_title('Feature Distributions')
147
  else:
148
  for ax in axes.flat:
149
  ax.text(0.5, 0.5, 'No cells detected', ha='center', va='center')
 
151
  plt.tight_layout()
152
 
153
  # Apply color transformation
154
+ transformed_image = apply_color_transformation(original_image, transform_type)
 
 
155
 
156
  return (
157
+ cv2.cvtColor(vis_img, cv2.COLOR_BGR2RGB),
158
+ transformed_image,
159
  fig,
160
  df
161
  )
162
+
163
  except Exception as e:
164
+ print(f"Error processing image: {str(e)}")
165
+ return None, None, None, None
 
166
 
167
+ # Create Gradio interface
168
  with gr.Blocks(title="Advanced Cell Analysis Tool", theme=gr.themes.Soft()) as demo:
169
  gr.Markdown("""
170
  # 🔬 Advanced Bioengineering Cell Analysis Tool
 
178
  ## Author
179
  - **Muhammad Ibrahim Qasmi**
180
  - [LinkedIn](https://www.linkedin.com/in/muhammad-ibrahim-qasmi-9876a1297/)
 
181
  """)
182
 
183
  with gr.Row():
 
221
  output_table = gr.DataFrame(
222
  label="Cell Features"
223
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
  analyze_btn.click(
226
  fn=process_image,
 
230
 
231
  # Launch the demo
232
  if __name__ == "__main__":
233
+ demo.launch()