champ7 commited on
Commit
bc8bbcf
·
verified ·
1 Parent(s): efd4d7b

Create omnipose.py

Browse files
Files changed (1) hide show
  1. omnipose.py +266 -0
omnipose.py ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import glob
3
+ import random
4
+ import numpy as np
5
+ import pandas as pd
6
+ import tifffile as tiff
7
+ import matplotlib.pyplot as plt
8
+ from scipy.ndimage import median_filter
9
+ from skimage.filters import gaussian
10
+ from skimage import exposure
11
+ from huggingface_hub import snapshot_download
12
+ from cellpose_omni import models, metrics, core
13
+
14
+ # ==========================================
15
+ # 1. Custom Preprocessing (Prep 1)
16
+ # ==========================================
17
+ def preprocess_w3(input_data):
18
+ """ W3: Cells (Brightfield) -> Blur, Median, Contrast """
19
+ if isinstance(input_data, str):
20
+ img_raw = tiff.imread(input_data).astype(np.float32)
21
+ else:
22
+ img_raw = input_data.astype(np.float32)
23
+
24
+ img_min, img_max = np.min(img_raw), np.max(img_raw)
25
+ img_8bit = ((img_raw - img_min) / (img_max - img_min) * 255).astype(np.uint8) if img_max > img_min else np.zeros(img_raw.shape, dtype=np.uint8)
26
+
27
+ img_inverted = 255 - img_8bit
28
+ img_blur = gaussian(img_inverted, sigma=1, preserve_range=True)
29
+ img_filtered = median_filter(img_blur, size=5).astype(np.uint8)
30
+ p_low, p_high = np.percentile(img_filtered, (0.75, 99.25))
31
+
32
+ if p_low >= p_high:
33
+ final_img = img_filtered
34
+ else:
35
+ final_img = exposure.rescale_intensity(img_filtered, in_range=(p_low, p_high), out_range=(0, 255)).astype(np.uint8)
36
+
37
+ # Standardize to 0.0 - 1.0 floats
38
+ return (final_img / 255.0).astype(np.float32)
39
+
40
+ # ==========================================
41
+ # 2. Data Preparation
42
+ # ==========================================
43
+ def prepare_data(repo_id="champ7/CEllDataW3"):
44
+ print(f"Downloading dataset {repo_id} from Hugging Face...")
45
+ dataset_path = snapshot_download(repo_id=repo_id, repo_type="dataset")
46
+ data_dir = os.path.join(dataset_path, "combined_data")
47
+
48
+ image_files = sorted(glob.glob(os.path.join(data_dir, "*.TIF")))
49
+ seg_files = sorted(glob.glob(os.path.join(data_dir, "*_seg.npy")))
50
+
51
+ images, masks = [], []
52
+
53
+ for img_path in image_files:
54
+ base_name = img_path.replace(".TIF", "")
55
+ seg_path = base_name + "_seg.npy"
56
+
57
+ if seg_path in seg_files:
58
+ img = tiff.imread(img_path).astype(np.float32)
59
+ images.append(img)
60
+
61
+ seg_data = np.load(seg_path, allow_pickle=True)
62
+ if seg_data.shape == ():
63
+ seg_dict = seg_data.item()
64
+ mask_raw = seg_dict['masks']
65
+ else:
66
+ mask_raw = seg_data
67
+
68
+ # Convert to standard 32-bit integer labels
69
+ masks.append(mask_raw.astype(np.int32))
70
+
71
+ X_train, y_train = images, masks
72
+
73
+ combined = list(zip(images, masks))
74
+ random.seed(42)
75
+ sample_10 = random.sample(combined, min(10, len(combined)))
76
+ X_test, y_test = zip(*sample_10)
77
+
78
+ return list(X_train), list(X_test), list(y_train), list(y_test)
79
+
80
+ # ==========================================
81
+ # 3. Metrics & Utilities
82
+ # ==========================================
83
+ def compute_metrics(masks_true, masks_pred, threshold=0.0):
84
+ ap, tp, fp, fn = metrics.average_precision(masks_true, masks_pred, threshold=[threshold])
85
+
86
+ tp_sum = np.sum(tp)
87
+ fp_sum = np.sum(fp)
88
+ fn_sum = np.sum(fn)
89
+
90
+ f1_score = 0.0 if (2 * tp_sum + fp_sum + fn_sum) == 0 else (2 * tp_sum) / (2 * tp_sum + fp_sum + fn_sum)
91
+ mean_ap = np.mean(ap)
92
+
93
+ return f1_score, mean_ap
94
+
95
+ def to_numpy(data):
96
+ if hasattr(data, 'cpu'):
97
+ return data.cpu().detach().numpy()
98
+ elif isinstance(data, list):
99
+ return [to_numpy(d) for d in data]
100
+ elif isinstance(data, tuple):
101
+ return tuple(to_numpy(d) for d in data)
102
+ elif isinstance(data, dict):
103
+ return {k: to_numpy(v) for k, v in data.items()}
104
+ elif isinstance(data, np.ndarray) and data.dtype == object:
105
+ return np.array([to_numpy(d) for d in data])
106
+ return data
107
+
108
+ # ==========================================
109
+ # 4. Visualization Helper (4 Panels)
110
+ # ==========================================
111
+ def visualize_results(raw_img, fed_img, y_true, y_pred, config_name, model_type, img_idx):
112
+ fig, axes = plt.subplots(1, 4, figsize=(24, 6))
113
+ fig.suptitle(f"{config_name} | {model_type} | Image {img_idx}", fontsize=16, fontweight='bold')
114
+
115
+ axes[0].imshow(raw_img, cmap='gray')
116
+ axes[0].set_title("Original Image", fontsize=14)
117
+ axes[0].axis('off')
118
+
119
+ axes[1].imshow(raw_img, cmap='gray')
120
+ mask_true_display = np.ma.masked_where(y_true == 0, y_true)
121
+ axes[1].imshow(mask_true_display, cmap='nipy_spectral', alpha=0.5, interpolation='none')
122
+ axes[1].set_title("Original Image + GT Mask", fontsize=14)
123
+ axes[1].axis('off')
124
+
125
+ axes[2].imshow(fed_img, cmap='gray')
126
+ axes[2].set_title("Preprocessed Image (Fed to Model)", fontsize=14)
127
+ axes[2].axis('off')
128
+
129
+ axes[3].imshow(raw_img, cmap='gray')
130
+ mask_pred_display = np.ma.masked_where(y_pred == 0, y_pred)
131
+ axes[3].imshow(mask_pred_display, cmap='nipy_spectral', alpha=0.5, interpolation='none')
132
+ axes[3].set_title("Original Image + Predicted Mask", fontsize=14)
133
+ axes[3].axis('off')
134
+
135
+ plt.tight_layout()
136
+ plt.show()
137
+
138
+ # ==========================================
139
+ # 5. Pipeline Execution
140
+ # ==========================================
141
+ def run_pipeline():
142
+ # Use GPU for fast inference/evaluation
143
+ use_gpu_eval = core.use_gpu()
144
+ channels = [0, 0]
145
+ base_model_name = 'cyto2'
146
+
147
+ X_train_raw, X_test_raw, y_train, y_test = prepare_data()
148
+
149
+ X_train_p1 = [preprocess_w3(img) for img in X_train_raw]
150
+ X_test_p1 = [preprocess_w3(img) for img in X_test_raw]
151
+
152
+ configs = [
153
+ {
154
+ "name": "Prep 1",
155
+ "train_data": X_train_p1, "test_data": X_test_p1,
156
+ "train_kwargs": {"normalize": False, "rescale": None},
157
+ "eval_kwargs": {"normalize": False, "flow_threshold": 0, "mask_threshold": -1, "rescale": None}
158
+ },
159
+ {
160
+ "name": "Prep 2",
161
+ "train_data": X_train_raw, "test_data": X_test_raw,
162
+ "train_kwargs": {"normalize": True, "rescale": None},
163
+ "eval_kwargs": {"normalize": True, "flow_threshold": 0, "mask_threshold": -1, "rescale": None}
164
+ },
165
+ {
166
+ "name": "Prep 1 + Prep 2",
167
+ "train_data": X_train_p1, "test_data": X_test_p1,
168
+ "train_kwargs": {"normalize": True, "rescale": None},
169
+ "eval_kwargs": {"normalize": True, "flow_threshold": 0, "mask_threshold": -1, "rescale": None}
170
+ }
171
+ ]
172
+
173
+ results = []
174
+
175
+ for cfg in configs:
176
+ print(f"\n--- Running Configuration: {cfg['name']} ---")
177
+
178
+ # ------------------------------------------
179
+ # A. Pretrained Model Evaluation (Runs on GPU if available)
180
+ # ------------------------------------------
181
+ pretrained_model = models.CellposeModel(
182
+ gpu=use_gpu_eval,
183
+ model_type=base_model_name,
184
+ omni=True,
185
+ nchan=2,
186
+ nclasses=2
187
+ )
188
+ preds_pre, _, _ = pretrained_model.eval(cfg["test_data"], channels=channels, **cfg["eval_kwargs"])
189
+
190
+ preds_pre = to_numpy(preds_pre)
191
+ f1_pre, iou_pre = compute_metrics(y_test, preds_pre, threshold=0.0)
192
+
193
+ results.append({
194
+ "Configuration": f"{cfg['name']} + Pretrained + Prediction",
195
+ "F1 Score": f"{f1_pre:.4f}",
196
+ "Mean IoU (AP)": f"{iou_pre:.4f}"
197
+ })
198
+
199
+ for viz_idx in range(min(2, len(cfg["test_data"]))):
200
+ visualize_results(
201
+ raw_img=X_test_raw[viz_idx], fed_img=cfg["test_data"][viz_idx],
202
+ y_true=y_test[viz_idx], y_pred=preds_pre[viz_idx],
203
+ config_name=cfg["name"], model_type="Pretrained Model", img_idx=viz_idx + 1
204
+ )
205
+
206
+ # ------------------------------------------
207
+ # B. Fine-tuning Model (gpu=False BYPASSES CUDA LOSS ASSERTIONS COMPLETELY)
208
+ # ------------------------------------------
209
+ print(f"Fine-tuning {base_model_name} on CPU to guarantee zero CUDA assertion crashes...")
210
+ finetune_model = models.CellposeModel(
211
+ #gpu=False, # <--- THIS REMOVES THE ASSERTION PROBLEM ENTIRELY
212
+ model_type=base_model_name,
213
+ omni=True,
214
+ nchan=2,
215
+ nclasses=2
216
+ )
217
+
218
+ model_path = finetune_model.train(
219
+ cfg["train_data"], y_train,
220
+ train_links=[None] * len(y_train),
221
+ channels=channels,
222
+ save_path=f"./omnipose_{cfg['name'].replace(' ', '_')}",
223
+ n_epochs=150,
224
+ learning_rate=0.1,
225
+ batch_size=2,
226
+ **cfg["train_kwargs"]
227
+ )
228
+
229
+ # ------------------------------------------
230
+ # C. Evaluate Fine-Tuned Model (Evaluates back on GPU)
231
+ # ------------------------------------------
232
+ custom_model = models.CellposeModel(
233
+ gpu=use_gpu_eval,
234
+ pretrained_model=model_path,
235
+ model_type=base_model_name,
236
+ omni=True,
237
+ nchan=2,
238
+ nclasses=2
239
+ )
240
+ preds_fine, _, _ = custom_model.eval(cfg["test_data"], channels=channels, **cfg["eval_kwargs"])
241
+
242
+ preds_fine = to_numpy(preds_fine)
243
+ f1_fine, iou_fine = compute_metrics(y_test, preds_fine, threshold=0.0)
244
+
245
+ results.append({
246
+ "Configuration": f"{cfg['name']} + Training + Prediction",
247
+ "F1 Score": f"{f1_fine:.4f}",
248
+ "Mean IoU (AP)": f"{iou_fine:.4f}"
249
+ })
250
+
251
+ for viz_idx in range(min(2, len(cfg["test_data"]))):
252
+ visualize_results(
253
+ raw_img=X_test_raw[viz_idx], fed_img=cfg["test_data"][viz_idx],
254
+ y_true=y_test[viz_idx], y_pred=preds_fine[viz_idx],
255
+ config_name=cfg["name"], model_type="Fine-tuned Model", img_idx=viz_idx + 1
256
+ )
257
+
258
+ # ==========================================
259
+ # 6. Final Output Compilation
260
+ # ==========================================
261
+ print("\n================ FINAL METRICS TABLE ================")
262
+ results_df = pd.DataFrame(results)
263
+ print(results_df.to_markdown(index=False))
264
+
265
+ if __name__ == "__main__":
266
+ run_pipeline()