ibrahim313 commited on
Commit
cfb7ff1
·
verified ·
1 Parent(s): cd32abe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -77
app.py CHANGED
@@ -2,11 +2,12 @@ import cv2
2
  import numpy as np
3
  import pandas as pd
4
  import gradio as gr
 
5
  import matplotlib.pyplot as plt
6
  from datetime import datetime
7
 
8
  def detect_blood_cells(image):
9
- """Optimized function for blood cell detection"""
10
  # Convert to RGB if grayscale
11
  if len(image.shape) == 2:
12
  image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
@@ -14,48 +15,45 @@ def detect_blood_cells(image):
14
  # Convert to HSV color space
15
  hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
16
 
17
- # Optimized red color ranges for blood cells
18
- lower_red1 = np.array([0, 100, 100]) # Increased saturation threshold
 
19
  upper_red1 = np.array([10, 255, 255])
20
- lower_red2 = np.array([160, 100, 100]) # Increased saturation threshold
21
  upper_red2 = np.array([180, 255, 255])
22
 
23
- # Create masks for red color
24
  mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
25
  mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
26
  mask = mask1 + mask2
27
-
28
- # Enhanced noise removal
29
- kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
30
- mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)
31
- mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=2)
32
-
33
- # Apply distance transform to separate touching cells
34
- dist_transform = cv2.distanceTransform(mask, cv2.DIST_L2, 5)
35
- _, sure_fg = cv2.threshold(dist_transform, 0.5 * dist_transform.max(), 255, 0)
36
- sure_fg = np.uint8(sure_fg)
37
 
38
- # Find connected components
39
- _, markers = cv2.connectedComponents(sure_fg)
 
 
40
 
41
- # Find contours with hierarchy to handle nested contours
42
- contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
43
 
44
- # Filter contours based on area and circularity
45
- filtered_contours = []
46
- for contour in contours:
47
- area = cv2.contourArea(contour)
48
- perimeter = cv2.arcLength(contour, True)
49
- if perimeter == 0:
50
- continue
51
-
52
- circularity = 4 * np.pi * area / (perimeter * perimeter)
53
-
54
- # Optimized thresholds for your specific images
55
- if 500 < area < 2500 and circularity > 0.8: # Adjusted thresholds
56
- filtered_contours.append(contour)
57
 
58
- return filtered_contours, markers
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  def process_image(image, transform_type):
61
  """Process uploaded image and extract blood cell features"""
@@ -63,68 +61,64 @@ def process_image(image, transform_type):
63
  return None, None, None, None
64
 
65
  try:
66
- # Store original image
67
  original_image = image.copy()
68
 
69
  # Detect blood cells
70
- contours, markers = detect_blood_cells(image)
71
 
72
  # Extract features
73
  features = []
74
  for i, contour in enumerate(contours, 1):
75
  area = cv2.contourArea(contour)
76
- perimeter = cv2.arcLength(contour, True)
77
- circularity = 4 * np.pi * area / (perimeter * perimeter)
78
-
79
- # Calculate centroid
80
- M = cv2.moments(contour)
81
- if M["m00"] != 0:
82
- cx = int(M["m10"] / M["m00"])
83
- cy = int(M["m01"] / M["m00"])
84
-
85
- # Extract mean color intensity
86
- mask = np.zeros(image.shape[:2], dtype=np.uint8)
87
- cv2.drawContours(mask, [contour], -1, 255, -1)
88
- mean_intensity = cv2.mean(cv2.cvtColor(image, cv2.COLOR_RGB2GRAY), mask=mask)[0]
89
 
90
- features.append({
91
- 'label': i,
92
- 'area': area,
93
- 'perimeter': perimeter,
94
- 'circularity': circularity,
95
- 'mean_intensity': mean_intensity,
96
- 'centroid_x': cx,
97
- 'centroid_y': cy
98
- })
 
 
 
 
 
 
99
 
100
  # Create visualization
101
  vis_img = image.copy()
102
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
103
 
104
- # Draw contours and labels with enhanced visibility
105
  for feature in features:
106
- i = feature['label'] - 1
107
- cv2.drawContours(vis_img, contours, i, (0, 255, 0), 2)
108
 
109
  # Add cell labels
110
  x = feature['centroid_x']
111
  y = feature['centroid_y']
112
  # White outline
113
  cv2.putText(vis_img, str(feature['label']),
114
- (x-10, y), cv2.FONT_HERSHEY_SIMPLEX,
115
- 0.4, (255, 255, 255), 2)
116
  # Red text
117
  cv2.putText(vis_img, str(feature['label']),
118
- (x-10, y), cv2.FONT_HERSHEY_SIMPLEX,
119
- 0.4, (0, 0, 255), 1)
120
 
121
- # Add timestamp and cell count with better positioning
122
- info_text = f"Analyzed: {timestamp} | Cells Detected: {len(features)}"
123
- cv2.putText(vis_img, info_text,
124
- (10, 25), cv2.FONT_HERSHEY_SIMPLEX,
125
- 0.6, (255, 255, 255), 2)
126
 
127
- # Create analysis plots
128
  plt.style.use('default')
129
  fig, axes = plt.subplots(2, 2, figsize=(15, 12))
130
  fig.suptitle('Blood Cell Analysis Results', fontsize=16, y=0.95)
@@ -145,14 +139,11 @@ def process_image(image, transform_type):
145
  axes[0,1].grid(True, alpha=0.3)
146
 
147
  # Scatter plot
148
- scatter = axes[1,0].scatter(df['area'], df['mean_intensity'],
149
- c=df['circularity'], cmap='viridis',
150
- alpha=0.6)
151
- axes[1,0].set_title('Area vs Intensity')
152
  axes[1,0].set_xlabel('Area')
153
- axes[1,0].set_ylabel('Mean Intensity')
154
  axes[1,0].grid(True, alpha=0.3)
155
- plt.colorbar(scatter, ax=axes[1,0], label='Circularity')
156
 
157
  # Box plot
158
  df.boxplot(column=['area', 'circularity'], ax=axes[1,1])
@@ -177,7 +168,7 @@ def process_image(image, transform_type):
177
  except Exception as e:
178
  print(f"Error processing image: {str(e)}")
179
  import traceback
180
- traceback.print_exc()
181
  return None, None, None, None
182
 
183
 
 
2
  import numpy as np
3
  import pandas as pd
4
  import gradio as gr
5
+ from skimage import measure, morphology
6
  import matplotlib.pyplot as plt
7
  from datetime import datetime
8
 
9
  def detect_blood_cells(image):
10
+ """Specialized function for blood cell detection"""
11
  # Convert to RGB if grayscale
12
  if len(image.shape) == 2:
13
  image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
 
15
  # Convert to HSV color space
16
  hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
17
 
18
+ # Create mask for red blood cells
19
+ # Red color has two ranges in HSV
20
+ lower_red1 = np.array([0, 70, 50])
21
  upper_red1 = np.array([10, 255, 255])
22
+ lower_red2 = np.array([170, 70, 50])
23
  upper_red2 = np.array([180, 255, 255])
24
 
 
25
  mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
26
  mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
27
  mask = mask1 + mask2
 
 
 
 
 
 
 
 
 
 
28
 
29
+ # Noise removal and smoothing
30
+ kernel = np.ones((3,3), np.uint8)
31
+ mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=2)
32
+ mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=2)
33
 
34
+ # Find contours
35
+ contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
36
 
37
+ return contours, mask
38
+
39
+ def apply_color_transformation(image, transform_type):
40
+ """Apply different color transformations to the image"""
41
+ if len(image.shape) == 2:
42
+ image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
 
 
 
 
 
 
 
43
 
44
+ if transform_type == "Original":
45
+ return image
46
+ elif transform_type == "Grayscale":
47
+ return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
48
+ elif transform_type == "Binary":
49
+ gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
50
+ _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
51
+ return binary
52
+ elif transform_type == "CLAHE":
53
+ gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
54
+ clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
55
+ return clahe.apply(gray)
56
+ return image
57
 
58
  def process_image(image, transform_type):
59
  """Process uploaded image and extract blood cell features"""
 
61
  return None, None, None, None
62
 
63
  try:
64
+ # Store original image for transformations
65
  original_image = image.copy()
66
 
67
  # Detect blood cells
68
+ contours, mask = detect_blood_cells(image)
69
 
70
  # Extract features
71
  features = []
72
  for i, contour in enumerate(contours, 1):
73
  area = cv2.contourArea(contour)
74
+ # Filter out very small or very large regions
75
+ if 100 < area < 5000: # Adjust these thresholds based on your images
76
+ perimeter = cv2.arcLength(contour, True)
77
+ circularity = 4 * np.pi * area / (perimeter * perimeter) if perimeter > 0 else 0
 
 
 
 
 
 
 
 
 
78
 
79
+ # Only include if it's reasonably circular
80
+ if circularity > 0.7: # Adjust threshold as needed
81
+ M = cv2.moments(contour)
82
+ if M["m00"] != 0:
83
+ cx = int(M["m10"] / M["m00"])
84
+ cy = int(M["m01"] / M["m00"])
85
+
86
+ features.append({
87
+ 'label': i,
88
+ 'area': area,
89
+ 'perimeter': perimeter,
90
+ 'circularity': circularity,
91
+ 'centroid_x': cx,
92
+ 'centroid_y': cy
93
+ })
94
 
95
  # Create visualization
96
  vis_img = image.copy()
97
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
98
 
99
+ # Draw contours and labels
100
  for feature in features:
101
+ contour = contours[feature['label']-1]
102
+ cv2.drawContours(vis_img, [contour], -1, (0, 255, 0), 2)
103
 
104
  # Add cell labels
105
  x = feature['centroid_x']
106
  y = feature['centroid_y']
107
  # White outline
108
  cv2.putText(vis_img, str(feature['label']),
109
+ (x, y), cv2.FONT_HERSHEY_SIMPLEX,
110
+ 0.5, (255, 255, 255), 2)
111
  # Red text
112
  cv2.putText(vis_img, str(feature['label']),
113
+ (x, y), cv2.FONT_HERSHEY_SIMPLEX,
114
+ 0.5, (0, 0, 255), 1)
115
 
116
+ # Add timestamp and cell count
117
+ cv2.putText(vis_img, f"Analyzed: {timestamp} | Cells: {len(features)}",
118
+ (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
119
+ 0.7, (255, 255, 255), 2)
 
120
 
121
+ # Create analysis plots with default style
122
  plt.style.use('default')
123
  fig, axes = plt.subplots(2, 2, figsize=(15, 12))
124
  fig.suptitle('Blood Cell Analysis Results', fontsize=16, y=0.95)
 
139
  axes[0,1].grid(True, alpha=0.3)
140
 
141
  # Scatter plot
142
+ axes[1,0].scatter(df['area'], df['circularity'], alpha=0.6, c='purple')
143
+ axes[1,0].set_title('Area vs Circularity')
 
 
144
  axes[1,0].set_xlabel('Area')
145
+ axes[1,0].set_ylabel('Circularity')
146
  axes[1,0].grid(True, alpha=0.3)
 
147
 
148
  # Box plot
149
  df.boxplot(column=['area', 'circularity'], ax=axes[1,1])
 
168
  except Exception as e:
169
  print(f"Error processing image: {str(e)}")
170
  import traceback
171
+ traceback.print_exc() # This will print the full error trace
172
  return None, None, None, None
173
 
174