ibrahim313 commited on
Commit
6e20c51
·
verified ·
1 Parent(s): 7702060

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -73
app.py CHANGED
@@ -1,109 +1,91 @@
 
 
1
  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 preprocess_image(image):
9
- """Enhance image contrast, apply thresholding, and clean noise."""
10
  if len(image.shape) == 2:
11
  image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
12
-
13
- gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
14
-
15
- # Apply Gaussian blur to remove noise
16
- blurred = cv2.GaussianBlur(gray, (5, 5), 0)
17
-
18
- # Otsu's Thresholding (more robust than adaptive for blood cells)
19
- _, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
20
-
21
- # Morphological operations to improve segmentation
22
- kernel = np.ones((3, 3), np.uint8)
23
- clean_mask = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=2)
24
- clean_mask = cv2.morphologyEx(clean_mask, cv2.MORPH_OPEN, kernel, iterations=1)
25
-
26
- return clean_mask
27
 
28
  def detect_blood_cells(image):
29
- """Detect blood cells and extract features."""
30
- mask = preprocess_image(image)
31
- contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
32
-
 
 
 
 
 
 
 
 
33
  features = []
34
- total_area = 0
35
-
36
- for i, contour in enumerate(contours, 1):
37
- area = cv2.contourArea(contour)
38
- perimeter = cv2.arcLength(contour, True)
39
- circularity = (4 * np.pi * area / (perimeter * perimeter)) if perimeter > 0 else 0
40
-
41
- # Filtering: Only count reasonable-sized circular objects
42
- if 100 < area < 5000 and circularity > 0.7:
43
- M = cv2.moments(contour)
44
- if M["m00"] != 0:
45
- cx = int(M["m10"] / M["m00"])
46
- cy = int(M["m01"] / M["m00"])
47
- features.append({
48
- 'ID': i, 'Area': area, 'Perimeter': perimeter,
49
- 'Circularity': circularity, 'Centroid_X': cx, 'Centroid_Y': cy
50
- })
51
- total_area += area
52
-
53
- # Summary Statistics
54
- avg_cell_size = total_area / len(features) if features else 0
55
- cell_density = len(features) / (image.shape[0] * image.shape[1]) # Density per pixel
56
-
57
- summary = {
58
- 'Total Cells': len(features),
59
- 'Avg Cell Size': avg_cell_size,
60
- 'Cell Density': cell_density
61
- }
62
-
63
- return contours, features, mask, summary
64
 
65
  def process_image(image):
66
  if image is None:
67
- return None, None, None, None, None
68
 
69
- contours, features, mask, summary = detect_blood_cells(image)
70
  vis_img = image.copy()
71
 
72
  for feature in features:
73
- contour = contours[feature['ID'] - 1]
74
  cv2.drawContours(vis_img, [contour], -1, (0, 255, 0), 2)
75
- cv2.putText(vis_img, str(feature['ID']), (feature['Centroid_X'], feature['Centroid_Y']),
76
  cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
77
 
78
  df = pd.DataFrame(features)
79
- return vis_img, mask, df, summary
80
 
81
  def analyze(image):
82
- vis_img, mask, df, summary = process_image(image)
83
 
84
  plt.style.use('dark_background')
85
  fig, axes = plt.subplots(1, 2, figsize=(12, 5))
86
 
87
  if not df.empty:
88
- axes[0].hist(df['Area'], bins=20, color='cyan', edgecolor='black')
89
  axes[0].set_title('Cell Size Distribution')
90
 
91
- axes[1].scatter(df['Area'], df['Circularity'], alpha=0.6, c='magenta')
92
  axes[1].set_title('Area vs Circularity')
93
 
94
- return vis_img, mask, fig, df, summary
95
 
96
  # Gradio Interface
97
- demo = gr.Interface(
98
- fn=analyze,
99
- inputs=gr.Image(type="numpy"),
100
- outputs=[
101
- gr.Image(label="Processed Image"),
102
- gr.Image(label="Binary Mask"),
103
- gr.Plot(label="Analysis Plots"),
104
- gr.Dataframe(label="Detected Cells Data"),
105
- gr.JSON(label="Summary Statistics")
106
- ]
107
- )
108
-
109
  demo.launch()
 
1
+ from segment_anything import sam_model_registry, SamPredictor
2
+ import torch
3
  import cv2
4
  import numpy as np
 
5
  import gradio as gr
6
+ import pandas as pd
7
  import matplotlib.pyplot as plt
8
+
9
+ # Load SAM model
10
+ sam_checkpoint = "sam_vit_h.pth" # Checkpoint file (download it from Meta AI)
11
+ device = "cuda" if torch.cuda.is_available() else "cpu"
12
+ model_type = "vit_h"
13
+ sam = sam_model_registry[model_type](checkpoint=sam_checkpoint).to(device)
14
+ predictor = SamPredictor(sam)
15
 
16
  def preprocess_image(image):
17
+ """Convert image to RGB format for SAM."""
18
  if len(image.shape) == 2:
19
  image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
20
+ return image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  def detect_blood_cells(image):
23
+ """Detect blood cells using SAM."""
24
+ image = preprocess_image(image)
25
+ predictor.set_image(image)
26
+
27
+ # Generate automatic masks (SAM can also take prompts for guided segmentation)
28
+ masks, _, _ = predictor.predict(
29
+ point_coords=None,
30
+ point_labels=None,
31
+ multimask_output=True
32
+ )
33
+
34
+ contours_list = []
35
  features = []
36
+ for i, mask in enumerate(masks):
37
+ mask = mask.astype(np.uint8) * 255 # Convert boolean mask to uint8
38
+ contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
39
+
40
+ for j, contour in enumerate(contours, 1):
41
+ area = cv2.contourArea(contour)
42
+ perimeter = cv2.arcLength(contour, True)
43
+ circularity = 4 * np.pi * area / (perimeter * perimeter) if perimeter > 0 else 0
44
+
45
+ if 100 < area < 5000 and circularity > 0.7:
46
+ M = cv2.moments(contour)
47
+ if M["m00"] != 0:
48
+ cx = int(M["m10"] / M["m00"])
49
+ cy = int(M["m01"] / M["m00"])
50
+ features.append({
51
+ 'label': f"{i}-{j}", 'area': area, 'perimeter': perimeter,
52
+ 'circularity': circularity, 'centroid_x': cx, 'centroid_y': cy
53
+ })
54
+ contours_list.append(contour)
55
+
56
+ return contours_list, features, masks
 
 
 
 
 
 
 
 
 
57
 
58
  def process_image(image):
59
  if image is None:
60
+ return None, None, None, None
61
 
62
+ contours, features, masks = detect_blood_cells(image)
63
  vis_img = image.copy()
64
 
65
  for feature in features:
66
+ contour = contours[int(feature['label'].split('-')[1]) - 1]
67
  cv2.drawContours(vis_img, [contour], -1, (0, 255, 0), 2)
68
+ cv2.putText(vis_img, str(feature['label']), (feature['centroid_x'], feature['centroid_y']),
69
  cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
70
 
71
  df = pd.DataFrame(features)
72
+ return vis_img, masks[0], df
73
 
74
  def analyze(image):
75
+ vis_img, mask, df = process_image(image)
76
 
77
  plt.style.use('dark_background')
78
  fig, axes = plt.subplots(1, 2, figsize=(12, 5))
79
 
80
  if not df.empty:
81
+ axes[0].hist(df['area'], bins=20, color='cyan', edgecolor='black')
82
  axes[0].set_title('Cell Size Distribution')
83
 
84
+ axes[1].scatter(df['area'], df['circularity'], alpha=0.6, c='magenta')
85
  axes[1].set_title('Area vs Circularity')
86
 
87
+ return vis_img, mask, fig, df
88
 
89
  # Gradio Interface
90
+ demo = gr.Interface(fn=analyze, inputs=gr.Image(type="numpy"), outputs=[gr.Image(), gr.Image(), gr.Plot(), gr.Dataframe()])
 
 
 
 
 
 
 
 
 
 
 
91
  demo.launch()