napari-microplate 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. napari_microplate/__init__.py +3 -0
  2. napari_microplate/_dock.py +113 -0
  3. napari_microplate/_models.py +39 -0
  4. napari_microplate/_pipeline.py +194 -0
  5. napari_microplate/_vendor/ultralytics/__init__.py +30 -0
  6. napari_microplate/_vendor/ultralytics/cfg/__init__.py +873 -0
  7. napari_microplate/_vendor/ultralytics/cfg/datasets/Argoverse.yaml +74 -0
  8. napari_microplate/_vendor/ultralytics/cfg/datasets/DOTAv1.5.yaml +36 -0
  9. napari_microplate/_vendor/ultralytics/cfg/datasets/DOTAv1.yaml +35 -0
  10. napari_microplate/_vendor/ultralytics/cfg/datasets/GlobalWheat2020.yaml +53 -0
  11. napari_microplate/_vendor/ultralytics/cfg/datasets/ImageNet.yaml +2024 -0
  12. napari_microplate/_vendor/ultralytics/cfg/datasets/Objects365.yaml +442 -0
  13. napari_microplate/_vendor/ultralytics/cfg/datasets/SKU-110K.yaml +57 -0
  14. napari_microplate/_vendor/ultralytics/cfg/datasets/VOC.yaml +99 -0
  15. napari_microplate/_vendor/ultralytics/cfg/datasets/VisDrone.yaml +72 -0
  16. napari_microplate/_vendor/ultralytics/cfg/datasets/african-wildlife.yaml +24 -0
  17. napari_microplate/_vendor/ultralytics/cfg/datasets/brain-tumor.yaml +22 -0
  18. napari_microplate/_vendor/ultralytics/cfg/datasets/carparts-seg.yaml +43 -0
  19. napari_microplate/_vendor/ultralytics/cfg/datasets/coco-pose.yaml +38 -0
  20. napari_microplate/_vendor/ultralytics/cfg/datasets/coco.yaml +114 -0
  21. napari_microplate/_vendor/ultralytics/cfg/datasets/coco128-seg.yaml +100 -0
  22. napari_microplate/_vendor/ultralytics/cfg/datasets/coco128.yaml +100 -0
  23. napari_microplate/_vendor/ultralytics/cfg/datasets/coco8-pose.yaml +25 -0
  24. napari_microplate/_vendor/ultralytics/cfg/datasets/coco8-seg.yaml +100 -0
  25. napari_microplate/_vendor/ultralytics/cfg/datasets/coco8.yaml +100 -0
  26. napari_microplate/_vendor/ultralytics/cfg/datasets/crack-seg.yaml +21 -0
  27. napari_microplate/_vendor/ultralytics/cfg/datasets/dota8.yaml +34 -0
  28. napari_microplate/_vendor/ultralytics/cfg/datasets/hand-keypoints.yaml +25 -0
  29. napari_microplate/_vendor/ultralytics/cfg/datasets/lvis.yaml +1235 -0
  30. napari_microplate/_vendor/ultralytics/cfg/datasets/open-images-v7.yaml +660 -0
  31. napari_microplate/_vendor/ultralytics/cfg/datasets/package-seg.yaml +21 -0
  32. napari_microplate/_vendor/ultralytics/cfg/datasets/signature.yaml +20 -0
  33. napari_microplate/_vendor/ultralytics/cfg/datasets/tiger-pose.yaml +24 -0
  34. napari_microplate/_vendor/ultralytics/cfg/datasets/xView.yaml +152 -0
  35. napari_microplate/_vendor/ultralytics/cfg/default.yaml +128 -0
  36. napari_microplate/_vendor/ultralytics/cfg/models/11/yolo11-cls.yaml +30 -0
  37. napari_microplate/_vendor/ultralytics/cfg/models/11/yolo11-obb.yaml +47 -0
  38. napari_microplate/_vendor/ultralytics/cfg/models/11/yolo11-pose.yaml +48 -0
  39. napari_microplate/_vendor/ultralytics/cfg/models/11/yolo11-seg.yaml +47 -0
  40. napari_microplate/_vendor/ultralytics/cfg/models/11/yolo11.yaml +47 -0
  41. napari_microplate/_vendor/ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +50 -0
  42. napari_microplate/_vendor/ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +42 -0
  43. napari_microplate/_vendor/ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +42 -0
  44. napari_microplate/_vendor/ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +54 -0
  45. napari_microplate/_vendor/ultralytics/cfg/models/v10/yolov10b.yaml +42 -0
  46. napari_microplate/_vendor/ultralytics/cfg/models/v10/yolov10l.yaml +42 -0
  47. napari_microplate/_vendor/ultralytics/cfg/models/v10/yolov10m.yaml +42 -0
  48. napari_microplate/_vendor/ultralytics/cfg/models/v10/yolov10n.yaml +42 -0
  49. napari_microplate/_vendor/ultralytics/cfg/models/v10/yolov10s.yaml +42 -0
  50. napari_microplate/_vendor/ultralytics/cfg/models/v10/yolov10x.yaml +42 -0
  51. napari_microplate/_vendor/ultralytics/cfg/models/v3/yolov3-spp.yaml +46 -0
  52. napari_microplate/_vendor/ultralytics/cfg/models/v3/yolov3-tiny.yaml +37 -0
  53. napari_microplate/_vendor/ultralytics/cfg/models/v3/yolov3.yaml +46 -0
  54. napari_microplate/_vendor/ultralytics/cfg/models/v5/yolov5-p6.yaml +59 -0
  55. napari_microplate/_vendor/ultralytics/cfg/models/v5/yolov5.yaml +48 -0
  56. napari_microplate/_vendor/ultralytics/cfg/models/v6/yolov6.yaml +53 -0
  57. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +25 -0
  58. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +25 -0
  59. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-cls.yaml +29 -0
  60. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +54 -0
  61. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +56 -0
  62. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-ghost.yaml +47 -0
  63. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-obb.yaml +46 -0
  64. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-p2.yaml +54 -0
  65. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-p6.yaml +56 -0
  66. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +57 -0
  67. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-pose.yaml +47 -0
  68. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +46 -0
  69. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +56 -0
  70. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-seg.yaml +46 -0
  71. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-world.yaml +48 -0
  72. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8-worldv2.yaml +46 -0
  73. napari_microplate/_vendor/ultralytics/cfg/models/v8/yolov8.yaml +46 -0
  74. napari_microplate/_vendor/ultralytics/cfg/models/v9/yolov9c-seg.yaml +38 -0
  75. napari_microplate/_vendor/ultralytics/cfg/models/v9/yolov9c.yaml +38 -0
  76. napari_microplate/_vendor/ultralytics/cfg/models/v9/yolov9e-seg.yaml +61 -0
  77. napari_microplate/_vendor/ultralytics/cfg/models/v9/yolov9e.yaml +61 -0
  78. napari_microplate/_vendor/ultralytics/cfg/models/v9/yolov9m.yaml +38 -0
  79. napari_microplate/_vendor/ultralytics/cfg/models/v9/yolov9s.yaml +38 -0
  80. napari_microplate/_vendor/ultralytics/cfg/models/v9/yolov9t.yaml +38 -0
  81. napari_microplate/_vendor/ultralytics/cfg/trackers/botsort.yaml +18 -0
  82. napari_microplate/_vendor/ultralytics/cfg/trackers/bytetrack.yaml +11 -0
  83. napari_microplate/_vendor/ultralytics/data/__init__.py +26 -0
  84. napari_microplate/_vendor/ultralytics/data/annotator.py +54 -0
  85. napari_microplate/_vendor/ultralytics/data/augment.py +2740 -0
  86. napari_microplate/_vendor/ultralytics/data/base.py +314 -0
  87. napari_microplate/_vendor/ultralytics/data/build.py +207 -0
  88. napari_microplate/_vendor/ultralytics/data/converter.py +637 -0
  89. napari_microplate/_vendor/ultralytics/data/dataset.py +532 -0
  90. napari_microplate/_vendor/ultralytics/data/explorer/__init__.py +5 -0
  91. napari_microplate/_vendor/ultralytics/data/explorer/explorer.py +460 -0
  92. napari_microplate/_vendor/ultralytics/data/explorer/gui/__init__.py +1 -0
  93. napari_microplate/_vendor/ultralytics/data/explorer/gui/dash.py +282 -0
  94. napari_microplate/_vendor/ultralytics/data/explorer/utils.py +167 -0
  95. napari_microplate/_vendor/ultralytics/data/loaders.py +577 -0
  96. napari_microplate/_vendor/ultralytics/data/split_dota.py +298 -0
  97. napari_microplate/_vendor/ultralytics/data/utils.py +673 -0
  98. napari_microplate/_vendor/ultralytics/engine/__init__.py +1 -0
  99. napari_microplate/_vendor/ultralytics/engine/exporter.py +1196 -0
  100. napari_microplate/_vendor/ultralytics/engine/model.py +1130 -0
  101. napari_microplate/_vendor/ultralytics/engine/predictor.py +434 -0
  102. napari_microplate/_vendor/ultralytics/engine/results.py +1741 -0
  103. napari_microplate/_vendor/ultralytics/engine/trainer.py +822 -0
  104. napari_microplate/_vendor/ultralytics/engine/tuner.py +241 -0
  105. napari_microplate/_vendor/ultralytics/engine/validator.py +346 -0
  106. napari_microplate/_vendor/ultralytics/hub/__init__.py +146 -0
  107. napari_microplate/_vendor/ultralytics/hub/auth.py +140 -0
  108. napari_microplate/_vendor/ultralytics/hub/google/__init__.py +159 -0
  109. napari_microplate/_vendor/ultralytics/hub/session.py +390 -0
  110. napari_microplate/_vendor/ultralytics/hub/utils.py +246 -0
  111. napari_microplate/_vendor/ultralytics/models/__init__.py +9 -0
  112. napari_microplate/_vendor/ultralytics/models/fastsam/__init__.py +7 -0
  113. napari_microplate/_vendor/ultralytics/models/fastsam/model.py +55 -0
  114. napari_microplate/_vendor/ultralytics/models/fastsam/predict.py +146 -0
  115. napari_microplate/_vendor/ultralytics/models/fastsam/utils.py +24 -0
  116. napari_microplate/_vendor/ultralytics/models/fastsam/val.py +40 -0
  117. napari_microplate/_vendor/ultralytics/models/nas/__init__.py +7 -0
  118. napari_microplate/_vendor/ultralytics/models/nas/model.py +94 -0
  119. napari_microplate/_vendor/ultralytics/models/nas/predict.py +57 -0
  120. napari_microplate/_vendor/ultralytics/models/nas/val.py +50 -0
  121. napari_microplate/_vendor/ultralytics/models/rtdetr/__init__.py +7 -0
  122. napari_microplate/_vendor/ultralytics/models/rtdetr/model.py +54 -0
  123. napari_microplate/_vendor/ultralytics/models/rtdetr/predict.py +84 -0
  124. napari_microplate/_vendor/ultralytics/models/rtdetr/train.py +102 -0
  125. napari_microplate/_vendor/ultralytics/models/rtdetr/val.py +135 -0
  126. napari_microplate/_vendor/ultralytics/models/sam/__init__.py +6 -0
  127. napari_microplate/_vendor/ultralytics/models/sam/amg.py +193 -0
  128. napari_microplate/_vendor/ultralytics/models/sam/build.py +350 -0
  129. napari_microplate/_vendor/ultralytics/models/sam/model.py +175 -0
  130. napari_microplate/_vendor/ultralytics/models/sam/modules/__init__.py +1 -0
  131. napari_microplate/_vendor/ultralytics/models/sam/modules/blocks.py +1129 -0
  132. napari_microplate/_vendor/ultralytics/models/sam/modules/decoders.py +518 -0
  133. napari_microplate/_vendor/ultralytics/models/sam/modules/encoders.py +794 -0
  134. napari_microplate/_vendor/ultralytics/models/sam/modules/memory_attention.py +237 -0
  135. napari_microplate/_vendor/ultralytics/models/sam/modules/sam.py +956 -0
  136. napari_microplate/_vendor/ultralytics/models/sam/modules/tiny_encoder.py +1012 -0
  137. napari_microplate/_vendor/ultralytics/models/sam/modules/transformer.py +373 -0
  138. napari_microplate/_vendor/ultralytics/models/sam/modules/utils.py +293 -0
  139. napari_microplate/_vendor/ultralytics/models/sam/predict.py +787 -0
  140. napari_microplate/_vendor/ultralytics/models/utils/__init__.py +1 -0
  141. napari_microplate/_vendor/ultralytics/models/utils/loss.py +358 -0
  142. napari_microplate/_vendor/ultralytics/models/utils/ops.py +259 -0
  143. napari_microplate/_vendor/ultralytics/models/yolo/__init__.py +7 -0
  144. napari_microplate/_vendor/ultralytics/models/yolo/classify/__init__.py +7 -0
  145. napari_microplate/_vendor/ultralytics/models/yolo/classify/predict.py +64 -0
  146. napari_microplate/_vendor/ultralytics/models/yolo/classify/train.py +154 -0
  147. napari_microplate/_vendor/ultralytics/models/yolo/classify/val.py +113 -0
  148. napari_microplate/_vendor/ultralytics/models/yolo/detect/__init__.py +7 -0
  149. napari_microplate/_vendor/ultralytics/models/yolo/detect/predict.py +41 -0
  150. napari_microplate/_vendor/ultralytics/models/yolo/detect/train.py +143 -0
  151. napari_microplate/_vendor/ultralytics/models/yolo/detect/val.py +338 -0
  152. napari_microplate/_vendor/ultralytics/models/yolo/model.py +111 -0
  153. napari_microplate/_vendor/ultralytics/models/yolo/obb/__init__.py +7 -0
  154. napari_microplate/_vendor/ultralytics/models/yolo/obb/predict.py +53 -0
  155. napari_microplate/_vendor/ultralytics/models/yolo/obb/train.py +42 -0
  156. napari_microplate/_vendor/ultralytics/models/yolo/obb/val.py +203 -0
  157. napari_microplate/_vendor/ultralytics/models/yolo/pose/__init__.py +7 -0
  158. napari_microplate/_vendor/ultralytics/models/yolo/pose/predict.py +56 -0
  159. napari_microplate/_vendor/ultralytics/models/yolo/pose/train.py +79 -0
  160. napari_microplate/_vendor/ultralytics/models/yolo/pose/val.py +282 -0
  161. napari_microplate/_vendor/ultralytics/models/yolo/segment/__init__.py +7 -0
  162. napari_microplate/_vendor/ultralytics/models/yolo/segment/predict.py +55 -0
  163. napari_microplate/_vendor/ultralytics/models/yolo/segment/train.py +62 -0
  164. napari_microplate/_vendor/ultralytics/models/yolo/segment/val.py +318 -0
  165. napari_microplate/_vendor/ultralytics/models/yolo/world/__init__.py +5 -0
  166. napari_microplate/_vendor/ultralytics/models/yolo/world/train.py +92 -0
  167. napari_microplate/_vendor/ultralytics/models/yolo/world/train_world.py +109 -0
  168. napari_microplate/_vendor/ultralytics/nn/__init__.py +29 -0
  169. napari_microplate/_vendor/ultralytics/nn/autobackend.py +671 -0
  170. napari_microplate/_vendor/ultralytics/nn/modules/__init__.py +159 -0
  171. napari_microplate/_vendor/ultralytics/nn/modules/activation.py +21 -0
  172. napari_microplate/_vendor/ultralytics/nn/modules/block.py +1108 -0
  173. napari_microplate/_vendor/ultralytics/nn/modules/conv.py +332 -0
  174. napari_microplate/_vendor/ultralytics/nn/modules/head.py +597 -0
  175. napari_microplate/_vendor/ultralytics/nn/modules/transformer.py +427 -0
  176. napari_microplate/_vendor/ultralytics/nn/modules/utils.py +84 -0
  177. napari_microplate/_vendor/ultralytics/nn/tasks.py +1183 -0
  178. napari_microplate/_vendor/ultralytics/solutions/__init__.py +24 -0
  179. napari_microplate/_vendor/ultralytics/solutions/ai_gym.py +127 -0
  180. napari_microplate/_vendor/ultralytics/solutions/analytics.py +307 -0
  181. napari_microplate/_vendor/ultralytics/solutions/distance_calculation.py +139 -0
  182. napari_microplate/_vendor/ultralytics/solutions/heatmap.py +259 -0
  183. napari_microplate/_vendor/ultralytics/solutions/object_counter.py +243 -0
  184. napari_microplate/_vendor/ultralytics/solutions/parking_management.py +241 -0
  185. napari_microplate/_vendor/ultralytics/solutions/queue_management.py +127 -0
  186. napari_microplate/_vendor/ultralytics/solutions/speed_estimation.py +116 -0
  187. napari_microplate/_vendor/ultralytics/solutions/streamlit_inference.py +149 -0
  188. napari_microplate/_vendor/ultralytics/trackers/__init__.py +7 -0
  189. napari_microplate/_vendor/ultralytics/trackers/basetrack.py +124 -0
  190. napari_microplate/_vendor/ultralytics/trackers/bot_sort.py +233 -0
  191. napari_microplate/_vendor/ultralytics/trackers/byte_tracker.py +476 -0
  192. napari_microplate/_vendor/ultralytics/trackers/track.py +104 -0
  193. napari_microplate/_vendor/ultralytics/trackers/utils/__init__.py +1 -0
  194. napari_microplate/_vendor/ultralytics/trackers/utils/gmc.py +377 -0
  195. napari_microplate/_vendor/ultralytics/trackers/utils/kalman_filter.py +491 -0
  196. napari_microplate/_vendor/ultralytics/trackers/utils/matching.py +158 -0
  197. napari_microplate/_vendor/ultralytics/utils/__init__.py +1298 -0
  198. napari_microplate/_vendor/ultralytics/utils/autobatch.py +91 -0
  199. napari_microplate/_vendor/ultralytics/utils/benchmarks.py +574 -0
  200. napari_microplate/_vendor/ultralytics/utils/callbacks/__init__.py +5 -0
  201. napari_microplate/_vendor/ultralytics/utils/callbacks/base.py +217 -0
  202. napari_microplate/_vendor/ultralytics/utils/callbacks/clearml.py +153 -0
  203. napari_microplate/_vendor/ultralytics/utils/callbacks/comet.py +374 -0
  204. napari_microplate/_vendor/ultralytics/utils/callbacks/dvc.py +145 -0
  205. napari_microplate/_vendor/ultralytics/utils/callbacks/hub.py +112 -0
  206. napari_microplate/_vendor/ultralytics/utils/callbacks/mlflow.py +137 -0
  207. napari_microplate/_vendor/ultralytics/utils/callbacks/neptune.py +112 -0
  208. napari_microplate/_vendor/ultralytics/utils/callbacks/raytune.py +29 -0
  209. napari_microplate/_vendor/ultralytics/utils/callbacks/tensorboard.py +107 -0
  210. napari_microplate/_vendor/ultralytics/utils/callbacks/wb.py +163 -0
  211. napari_microplate/_vendor/ultralytics/utils/checks.py +754 -0
  212. napari_microplate/_vendor/ultralytics/utils/dist.py +72 -0
  213. napari_microplate/_vendor/ultralytics/utils/downloads.py +507 -0
  214. napari_microplate/_vendor/ultralytics/utils/errors.py +22 -0
  215. napari_microplate/_vendor/ultralytics/utils/files.py +222 -0
  216. napari_microplate/_vendor/ultralytics/utils/instance.py +416 -0
  217. napari_microplate/_vendor/ultralytics/utils/loss.py +745 -0
  218. napari_microplate/_vendor/ultralytics/utils/metrics.py +1291 -0
  219. napari_microplate/_vendor/ultralytics/utils/ops.py +834 -0
  220. napari_microplate/_vendor/ultralytics/utils/patches.py +104 -0
  221. napari_microplate/_vendor/ultralytics/utils/plotting.py +1357 -0
  222. napari_microplate/_vendor/ultralytics/utils/tal.py +355 -0
  223. napari_microplate/_vendor/ultralytics/utils/torch_utils.py +721 -0
  224. napari_microplate/_vendor/ultralytics/utils/triton.py +92 -0
  225. napari_microplate/_vendor/ultralytics/utils/tuner.py +152 -0
  226. napari_microplate/_viz.py +58 -0
  227. napari_microplate/_weights.py +81 -0
  228. napari_microplate/napari.yaml +10 -0
  229. napari_microplate-0.1.0.dist-info/METADATA +157 -0
  230. napari_microplate-0.1.0.dist-info/RECORD +234 -0
  231. napari_microplate-0.1.0.dist-info/WHEEL +5 -0
  232. napari_microplate-0.1.0.dist-info/entry_points.txt +2 -0
  233. napari_microplate-0.1.0.dist-info/licenses/LICENSE +651 -0
  234. napari_microplate-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,3 @@
1
+ """napari-microplate — plugin chạy full microplate pipeline (align → detect → classify)."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,113 @@
1
+ """napari dock widget cho full microplate pipeline.
2
+
3
+ npe2 manifest trỏ tới `MicroplateWidget` (callable trả widget). Khi click "Run
4
+ Pipeline": lấy ảnh từ layer đang chọn → chạy 3 stage → thêm 2 layer (plate
5
+ aligned image + wells shapes màu theo class) + thông báo counts + tuỳ chọn save PNG.
6
+ """
7
+
8
+ from pathlib import Path
9
+
10
+ import numpy as np
11
+ from magicgui import magic_factory
12
+
13
+ from ._pipeline import CLASS_COLORS, CLASS_NAMES, get_pipeline
14
+ from ._viz import draw_result, save_png
15
+
16
+
17
+ def _to_gray_uint8(data):
18
+ """Ép dữ liệu layer napari về uint8 grayscale 2D."""
19
+ arr = np.asarray(data)
20
+ if arr.ndim == 3: # (H,W,3) hoặc (H,W,4)
21
+ if arr.shape[-1] >= 3:
22
+ # napari dùng RGB; OpenCV muốn BGR → đảo kênh cho đúng trước gray
23
+ arr = arr[..., :3][..., ::-1]
24
+ arr = arr.mean(axis=-1) if arr.ndim == 3 else arr
25
+ if arr.dtype != np.uint8:
26
+ arr = arr.astype(np.float32)
27
+ if arr.max() <= 1.0:
28
+ arr = arr * 255.0
29
+ arr = np.clip(arr, 0, 255).astype(np.uint8)
30
+ return arr
31
+
32
+
33
+ def _bgr_to_rgb01(bgr):
34
+ """BGR uint8 (0..255) → RGB float (0..1) cho face_color của napari Shapes."""
35
+ r, g, b = int(bgr[2]), int(bgr[1]), int(bgr[0])
36
+ return (r / 255.0, g / 255.0, b / 255.0, 1.0)
37
+
38
+
39
+ @magic_factory(
40
+ call_button="Run Pipeline",
41
+ layout="vertical",
42
+ input_layer={"label": "Image layer"},
43
+ save_png={"label": "Save PNG"},
44
+ save_dir={"label": "Save dir", "mode": "d"},
45
+ )
46
+ def _pipeline_widget(
47
+ viewer: "napari.Viewer",
48
+ input_layer: "napari.layers.Image",
49
+ save_png: bool = False,
50
+ save_dir: Path = Path.home(),
51
+ ):
52
+ if input_layer is None:
53
+ from napari.utils.notifications import warning
54
+ warning("Chọn 1 image layer chứa ảnh microplate raw trước.")
55
+ return
56
+
57
+ from napari.utils.notifications import info
58
+
59
+ img_gray = _to_gray_uint8(input_layer.data)
60
+
61
+ pipe = get_pipeline()
62
+ out = pipe.run_array(img_gray)
63
+
64
+ # ── Layer 1: plate aligned (grayscale image) ──
65
+ # Gỡ layer cũ cùng tên để chạy lại không chồng
66
+ for nm in ("aligned_plate", "wells"):
67
+ if nm in viewer.layers:
68
+ del viewer.layers[nm]
69
+ viewer.add_image(out['plate'], name="aligned_plate", colormap="gray")
70
+
71
+ # ── Layer 2: well bbox (shapes), màu theo class ──
72
+ rects = []
73
+ face_colors = []
74
+ for (x1, y1, x2, y2, _), cls in zip(out['boxes'], out['classes']):
75
+ # napari toạ độ theo (row, col) = (y, x)
76
+ rects.append(np.array([[y1, x1], [y1, x2], [y2, x2], [y2, x1]]))
77
+ name = CLASS_NAMES.get(int(cls), 'NoGrowth')
78
+ face_colors.append(_bgr_to_rgb01(CLASS_COLORS[name]))
79
+
80
+ counts = {'Growth': 0, 'NoGrowth': 0, 'NoAgar': 0}
81
+ for cls in out['classes']:
82
+ counts[CLASS_NAMES.get(int(cls), 'NoGrowth')] += 1
83
+
84
+ if rects:
85
+ viewer.add_shapes(
86
+ rects,
87
+ shape_type="rectangle",
88
+ face_color=face_colors,
89
+ edge_color="white",
90
+ edge_width=1,
91
+ opacity=0.35,
92
+ name="wells",
93
+ )
94
+
95
+ msg = (f"Total wells: {len(out['boxes'])} — "
96
+ f"Growth={counts['Growth']} "
97
+ f"NoGrowth={counts['NoGrowth']} "
98
+ f"NoAgar={counts['NoAgar']}")
99
+ info(msg)
100
+ print(msg)
101
+
102
+ if save_png:
103
+ canvas, _ = draw_result(out, show_labels=True)
104
+ save_dir = Path(save_dir)
105
+ save_dir.mkdir(parents=True, exist_ok=True)
106
+ stem = Path(str(input_layer.name)).stem or "result"
107
+ out_path = save_dir / f"pipeline_{stem}.png"
108
+ save_png(canvas, out_path)
109
+ info(f"Đã lưu: {out_path}")
110
+
111
+
112
+ # npe2 trỏ tới callable này — magic_factory trả widget mới mỗi lần gọi.
113
+ MicroplateWidget = _pipeline_widget
@@ -0,0 +1,39 @@
1
+ """Định nghĩa model Stage 1 (EfficientNet corner regression) — port từ full_pipeline.ipynb."""
2
+
3
+ import timm
4
+ import torch
5
+ import torch.nn as nn
6
+
7
+
8
+ class EfficientNetCorner(nn.Module):
9
+ """EfficientNet-B3 backbone + regression head xuất 4 corner (8 giá trị, sigmoid).
10
+
11
+ Input: ảnh grayscale 1 kênh. gray_to_rgb (conv 1x1) nhân bản thành 3 kênh
12
+ trước khi đưa vào backbone timm.
13
+ """
14
+
15
+ def __init__(self, variant='b3', dropout=0.0):
16
+ super().__init__()
17
+ self.gray_to_rgb = nn.Conv2d(1, 3, kernel_size=1, bias=False)
18
+ nn.init.constant_(self.gray_to_rgb.weight, 1.0 / 3.0)
19
+ self.backbone = timm.create_model(
20
+ f'efficientnet_{variant}', pretrained=False,
21
+ num_classes=0, global_pool='avg',
22
+ )
23
+ feat_dim = self.backbone.num_features
24
+ self.head = nn.Sequential(
25
+ nn.Linear(feat_dim, 512), nn.SiLU(inplace=True), nn.Dropout(p=dropout),
26
+ nn.Linear(512, 256), nn.SiLU(inplace=True), nn.Dropout(p=dropout * 0.5),
27
+ nn.Linear(256, 8), nn.Sigmoid(),
28
+ )
29
+
30
+ def forward(self, x):
31
+ return self.head(self.backbone(self.gray_to_rgb(x)))
32
+
33
+
34
+ def order_corners_tl_tr_br_bl(pts):
35
+ """Sort 4 (x,y) points → TL, TR, BR, BL (consistent warp target)."""
36
+ by_y = sorted(pts, key=lambda p: p[1])
37
+ top = sorted(by_y[:2], key=lambda p: p[0])
38
+ bot = sorted(by_y[2:], key=lambda p: p[0])
39
+ return [top[0], top[1], bot[1], bot[0]]
@@ -0,0 +1,194 @@
1
+ """Full microplate pipeline: Stage 1 align → Stage 2 detect → Stage 3 classify.
2
+
3
+ Port từ full_pipeline.ipynb. Đổi: nhận array grayscale trực tiếp (run_array) để
4
+ dùng trong napari widget mà không cần ghi file tạm. Models lazy-load 1 lần.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ import cv2
12
+ import joblib
13
+ import numpy as np
14
+ import torch
15
+ import torch.nn as nn
16
+
17
+ from ._models import EfficientNetCorner, order_corners_tl_tr_br_bl
18
+ from ._weights import resolve_weight
19
+
20
+ # ── Fork ultralytics ch=1 được VENDOR trong package (napari_microplate/_vendor).
21
+ # Đưa _vendor lên đầu sys.path để `import ultralytics` (và các absolute import
22
+ # nội bộ của nó) resolve về bản vendor này, không bị nhầm với pip package. ──
23
+ _VENDOR_DIR = Path(__file__).resolve().parent / "_vendor"
24
+ if str(_VENDOR_DIR) not in sys.path:
25
+ sys.path.insert(0, str(_VENDOR_DIR))
26
+
27
+ # ─────────────────────────────────────────────
28
+ # CONFIG — khớp 1:1 với notebook (đừng sửa lẻ tẻ)
29
+ # ─────────────────────────────────────────────
30
+ STAGE1_VARIANT = 'b3'
31
+ STAGE1_IMG_SIZE = 896
32
+
33
+ STAGE2_CONF = 0.05
34
+ STAGE2_IOU = 0.15
35
+ STAGE2_MAX = 384
36
+
37
+ STAGE3_SIZE = 64
38
+
39
+ # Phải khớp generate_stage2_data.py (PLATE_MARGIN = 0.08).
40
+ PLATE_MARGIN = 0.08
41
+
42
+ CLASS_NAMES = {0: 'Growth', 1: 'NoGrowth', 2: 'NoAgar'}
43
+ CLASS_COLORS = { # BGR
44
+ 'Growth': (0, 180, 0),
45
+ 'NoGrowth': (0, 0, 220),
46
+ 'NoAgar': (200, 0, 200),
47
+ }
48
+
49
+
50
+ def _get_device():
51
+ return torch.device('cuda' if torch.cuda.is_available() else 'cpu')
52
+
53
+
54
+ class MicroplatePipeline:
55
+ """Singleton-ish wrapper load 3 model lần đầu, cache lại cho các lần gọi sau."""
56
+
57
+ def __init__(self, device=None):
58
+ self.device = device or _get_device()
59
+ self._model1 = None # EfficientNetCorner
60
+ self._model2 = None # YOLO
61
+ self._rf_model = None # RandomForest
62
+ self._w1 = None
63
+ self._w2 = None
64
+ self._w3 = None
65
+
66
+ def _ensure_loaded(self):
67
+ if self._model1 is not None:
68
+ return
69
+ print('[MicroplatePipeline] loading models (lần đầu)...')
70
+ self._w1 = resolve_weight('stage1')
71
+ self._w2 = resolve_weight('stage2')
72
+ self._w3 = resolve_weight('stage3')
73
+
74
+ # Stage 1
75
+ self._model1 = EfficientNetCorner(variant=STAGE1_VARIANT, dropout=0.0).to(self.device)
76
+ ckpt = torch.load(str(self._w1), map_location=self.device)
77
+ state = ckpt['model_state'] if isinstance(ckpt, dict) and 'model_state' in ckpt else ckpt
78
+ self._model1.load_state_dict(state)
79
+ self._model1.eval()
80
+
81
+ # Stage 2 — import sau khi đã thêm fork lên sys.path
82
+ from ultralytics import YOLO
83
+ self._model2 = YOLO(str(self._w2))
84
+
85
+ # Stage 3
86
+ bundle = joblib.load(str(self._w3))
87
+ self._rf_model = bundle['model'] if isinstance(bundle, dict) and 'model' in bundle else bundle
88
+
89
+ dev = 'cuda' if self.device.type == 'cuda' else 'cpu'
90
+ print(f'[MicroplatePipeline] ready on {dev}')
91
+
92
+ # ── Stage 1 ──────────────────────────────
93
+ @torch.no_grad()
94
+ def _stage1_align_array(self, img_gray):
95
+ """img_gray: 2D uint8. Trả (plate_gray, ordered_corners_px)."""
96
+ h_o, w_o = img_gray.shape[:2]
97
+ img_r = cv2.resize(img_gray, (STAGE1_IMG_SIZE, STAGE1_IMG_SIZE)).astype(np.float32) / 255.0
98
+ img_r = (img_r - 0.485) / 0.229
99
+ t = torch.from_numpy(img_r).unsqueeze(0).unsqueeze(0).to(self.device)
100
+ pred = self._model1(t).cpu().numpy().reshape(4, 2)
101
+ corners_px = pred * np.array([w_o, h_o])
102
+ ordered = np.array(order_corners_tl_tr_br_bl(corners_px.tolist()), dtype=np.float32)
103
+
104
+ w_top = np.linalg.norm(ordered[1] - ordered[0])
105
+ w_bottom = np.linalg.norm(ordered[2] - ordered[3])
106
+ h_left = np.linalg.norm(ordered[3] - ordered[0])
107
+ h_right = np.linalg.norm(ordered[2] - ordered[1])
108
+ plate_w = int(round((w_top + w_bottom) / 2))
109
+ plate_h = int(round((h_left + h_right) / 2))
110
+
111
+ out_w = int(round(plate_w * (1 + 2 * PLATE_MARGIN)))
112
+ out_h = int(round(plate_h * (1 + 2 * PLATE_MARGIN)))
113
+ pad_x = int(plate_w * PLATE_MARGIN)
114
+ pad_y = int(plate_h * PLATE_MARGIN)
115
+ dst = np.array([
116
+ [pad_x, pad_y],
117
+ [pad_x + plate_w - 1, pad_y],
118
+ [pad_x + plate_w - 1, pad_y + plate_h - 1],
119
+ [pad_x, pad_y + plate_h - 1],
120
+ ], dtype=np.float32)
121
+ M = cv2.getPerspectiveTransform(ordered, dst)
122
+ plate = cv2.warpPerspective(img_gray, M, (out_w, out_h), borderValue=0)
123
+ return plate, ordered
124
+
125
+ # ── Stage 2 ──────────────────────────────
126
+ def _stage2_detect(self, plate_gray):
127
+ H, W = plate_gray.shape[:2]
128
+ res = self._model2(plate_gray, conf=STAGE2_CONF, iou=STAGE2_IOU,
129
+ max_det=STAGE2_MAX, verbose=False, ch=1)[0]
130
+ boxes = []
131
+ if res.boxes is not None and len(res.boxes):
132
+ for b in res.boxes:
133
+ x1, y1, x2, y2 = b.xyxy[0].cpu().numpy().astype(int)
134
+ conf = float(b.conf[0])
135
+ boxes.append((int(x1), int(y1), int(x2), int(y2), conf))
136
+ return boxes
137
+
138
+ # ── Stage 3 ──────────────────────────────
139
+ def _stage3_classify(self, plate_gray, boxes, margin_ratio=0.05):
140
+ if not boxes:
141
+ return []
142
+ H, W = plate_gray.shape[:2]
143
+ crops = []
144
+ for (x1, y1, x2, y2, _) in boxes:
145
+ cx, cy = (x1 + x2) / 2, (y1 + y2) / 2
146
+ bw, bh = x2 - x1, y2 - y1
147
+ half_w = bw * (1 + 2 * margin_ratio) / 2
148
+ half_h = bh * (1 + 2 * margin_ratio) / 2
149
+ x1c, y1c = int(cx - half_w), int(cy - half_h)
150
+ x2c, y2c = int(cx + half_w), int(cy + half_h)
151
+ x1c, y1c = max(0, x1c), max(0, y1c)
152
+ x2c, y2c = min(W, x2c), min(H, y2c)
153
+ crop = (plate_gray[y1c:y2c, x1c:x2c]
154
+ if x2c > x1c and y2c > y1c
155
+ else np.zeros((STAGE3_SIZE, STAGE3_SIZE), dtype=np.uint8))
156
+ crop = cv2.resize(crop, (STAGE3_SIZE, STAGE3_SIZE), interpolation=cv2.INTER_AREA)
157
+ crops.append(crop)
158
+ X = np.stack(crops).reshape(-1, STAGE3_SIZE * STAGE3_SIZE).astype(np.float32) / 255.0
159
+ return list(self._rf_model.predict(X))
160
+
161
+ # ── Public API ───────────────────────────
162
+ def run_array(self, img_gray):
163
+ """img_gray: 2D uint8 grayscale. Trả dict {plate, corners, boxes, classes}."""
164
+ self._ensure_loaded()
165
+ if img_gray.ndim == 3:
166
+ img_gray = cv2.cvtColor(img_gray, cv2.COLOR_BGR2GRAY)
167
+ plate, corners = self._stage1_align_array(img_gray)
168
+ boxes = self._stage2_detect(plate)
169
+ classes = self._stage3_classify(plate, boxes)
170
+ return {
171
+ 'orig': img_gray,
172
+ 'corners': corners,
173
+ 'plate': plate,
174
+ 'boxes': boxes,
175
+ 'classes': classes,
176
+ }
177
+
178
+ def run(self, img_path):
179
+ """Tiện ích cho CLI/script: đọc file ảnh → run_array."""
180
+ img = cv2.imread(str(img_path), cv2.IMREAD_GRAYSCALE)
181
+ if img is None:
182
+ raise FileNotFoundError(img_path)
183
+ return self.run_array(img)
184
+
185
+
186
+ # Singleton module-level cho widget dùng chung
187
+ _DEFAULT = None
188
+
189
+
190
+ def get_pipeline():
191
+ global _DEFAULT
192
+ if _DEFAULT is None:
193
+ _DEFAULT = MicroplatePipeline()
194
+ return _DEFAULT
@@ -0,0 +1,30 @@
1
+ # Ultralytics YOLO 🚀, AGPL-3.0 license
2
+
3
+ __version__ = "8.3.2"
4
+
5
+ import os
6
+
7
+ # Set ENV Variables (place before imports)
8
+ os.environ["OMP_NUM_THREADS"] = "1" # reduce CPU utilization during training
9
+
10
+ from ultralytics.data.explorer.explorer import Explorer
11
+ from ultralytics.models import NAS, RTDETR, SAM, YOLO, FastSAM, YOLOWorld
12
+ from ultralytics.utils import ASSETS, SETTINGS
13
+ from ultralytics.utils.checks import check_yolo as checks
14
+ from ultralytics.utils.downloads import download
15
+
16
+ settings = SETTINGS
17
+ __all__ = (
18
+ "__version__",
19
+ "ASSETS",
20
+ "YOLO",
21
+ "YOLOWorld",
22
+ "NAS",
23
+ "SAM",
24
+ "FastSAM",
25
+ "RTDETR",
26
+ "checks",
27
+ "download",
28
+ "settings",
29
+ "Explorer",
30
+ )