tau-fibrils-yolo 0.0.6__tar.gz → 0.1.0__tar.gz

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 (39) hide show
  1. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/.github/workflows/release_multiplatform.yml +6 -6
  2. tau_fibrils_yolo-0.1.0/.gitignore +33 -0
  3. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/PKG-INFO +15 -54
  4. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/README.md +7 -52
  5. tau_fibrils_yolo-0.1.0/assets/screenshot.png +0 -0
  6. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/pyproject.toml +6 -1
  7. tau_fibrils_yolo-0.1.0/src/tau_fibrils_yolo/__init__.py +28 -0
  8. tau_fibrils_yolo-0.1.0/src/tau_fibrils_yolo/_version.py +34 -0
  9. tau_fibrils_yolo-0.1.0/src/tau_fibrils_yolo/boxes_utils.py +111 -0
  10. tau_fibrils_yolo-0.1.0/src/tau_fibrils_yolo/cli.py +60 -0
  11. tau_fibrils_yolo-0.1.0/src/tau_fibrils_yolo/sample/sample.tif +0 -0
  12. tau_fibrils_yolo-0.1.0/src/tau_fibrils_yolo/widget.py +248 -0
  13. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/src/tau_fibrils_yolo.egg-info/PKG-INFO +15 -54
  14. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/src/tau_fibrils_yolo.egg-info/SOURCES.txt +4 -6
  15. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/src/tau_fibrils_yolo.egg-info/requires.txt +2 -0
  16. tau_fibrils_yolo-0.0.6/.github/workflows/release.yml +0 -126
  17. tau_fibrils_yolo-0.0.6/.gitignore +0 -171
  18. tau_fibrils_yolo-0.0.6/assets/screenshot.png +0 -0
  19. tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/__init__.py +0 -8
  20. tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/_version.py +0 -16
  21. tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/_widget.py +0 -294
  22. tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/cli.py +0 -102
  23. tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/measure.py +0 -91
  24. tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/postprocess.py +0 -78
  25. tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/predict.py +0 -168
  26. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/LICENSE +0 -0
  27. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/MANIFEST.in +0 -0
  28. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/assets/icon.png +0 -0
  29. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/scripts/00_annotate.py +0 -0
  30. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/scripts/01_shapes_to_labels.py +0 -0
  31. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/scripts/02_split_train_valid.py +0 -0
  32. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/scripts/03_train_yolo.py +0 -0
  33. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/scripts/instructions.md +0 -0
  34. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/setup.cfg +0 -0
  35. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/src/tau_fibrils_yolo/__main__.py +0 -0
  36. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/src/tau_fibrils_yolo/napari.yaml +0 -0
  37. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/src/tau_fibrils_yolo.egg-info/dependency_links.txt +0 -0
  38. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/src/tau_fibrils_yolo.egg-info/entry_points.txt +0 -0
  39. {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.0}/src/tau_fibrils_yolo.egg-info/top_level.txt +0 -0
@@ -23,7 +23,7 @@ jobs:
23
23
  - name: Set up Python
24
24
  uses: actions/setup-python@v4
25
25
  with:
26
- python-version: "3.9"
26
+ python-version: "3.10"
27
27
  - name: Install dependencies
28
28
  run: |
29
29
  python -m pip install --upgrade pip
@@ -74,7 +74,7 @@ jobs:
74
74
  - name: Build executable
75
75
  env:
76
76
  PYAPP_PROJECT_VERSION: ${{ env.VERSION }}
77
- PYAPP_PYTHON_VERSION: '3.9'
77
+ PYAPP_PYTHON_VERSION: '3.10'
78
78
  run: cargo build --release --manifest-path pyapp-latest/Cargo.toml
79
79
 
80
80
  - name: Archive executable
@@ -96,7 +96,7 @@ jobs:
96
96
  fi
97
97
 
98
98
  - name: Upload artifact
99
- uses: actions/upload-artifact@v2
99
+ uses: actions/upload-artifact@v4
100
100
  with:
101
101
  name: executable-${{ runner.os }}
102
102
  path: executable-*.tar.gz
@@ -109,19 +109,19 @@ jobs:
109
109
  uses: actions/checkout@v2
110
110
 
111
111
  - name: Download Windows artifact
112
- uses: actions/download-artifact@v2
112
+ uses: actions/download-artifact@v4
113
113
  with:
114
114
  name: executable-Windows
115
115
  path: .
116
116
 
117
117
  - name: Download Linux artifact
118
- uses: actions/download-artifact@v2
118
+ uses: actions/download-artifact@v4
119
119
  with:
120
120
  name: executable-Linux
121
121
  path: .
122
122
 
123
123
  - name: Download MacOS artifact
124
- uses: actions/download-artifact@v2
124
+ uses: actions/download-artifact@v4
125
125
  with:
126
126
  name: executable-macOS
127
127
  path: .
@@ -0,0 +1,33 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ old/
5
+ data/
6
+ env/
7
+ build/
8
+ dist/
9
+ downloads/
10
+ eggs/
11
+ .eggs/
12
+ *.egg-info/
13
+ .installed.cfg
14
+ *.egg
15
+ .tox/
16
+ .coverage
17
+ .coverage.*
18
+ .cache
19
+ docs/_build/
20
+ .idea/
21
+ venv/
22
+ .vscode/
23
+ .ipynb_checkpoints
24
+ .python-version
25
+ .DS_Store
26
+ **/_version.py
27
+
28
+ push.sh
29
+ todo.txt
30
+ *.pt
31
+ qupath/
32
+ output/
33
+ notebooks/
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: tau-fibrils-yolo
3
- Version: 0.0.6
3
+ Version: 0.1.0
4
4
  Summary: YoloV8 model for the detection of Tau fibrils in EM images.
5
5
  Author-email: Mallory Wittwer <mallory.wittwer@epfl.ch>
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -672,6 +672,9 @@ Classifier: License :: OSI Approved :: BSD License
672
672
  Classifier: Programming Language :: Python :: 3
673
673
  Classifier: Programming Language :: Python :: 3.9
674
674
  Classifier: Programming Language :: Python :: 3.10
675
+ Classifier: Programming Language :: Python :: 3.11
676
+ Classifier: Programming Language :: Python :: 3.12
677
+ Classifier: Programming Language :: Python :: 3.13
675
678
  Classifier: Topic :: Scientific/Engineering :: Image Processing
676
679
  Requires-Python: >=3.9
677
680
  Description-Content-Type: text/markdown
@@ -688,13 +691,16 @@ Requires-Dist: scikit-image
688
691
  Requires-Dist: scikit-learn
689
692
  Requires-Dist: ultralytics
690
693
  Requires-Dist: opencv-contrib-python-headless
694
+ Requires-Dist: imaging-server-kit>=0.1.3
695
+ Requires-Dist: napari-serverkit>=0.0.9
696
+ Dynamic: license-file
691
697
 
692
698
  ![EPFL Center for Imaging logo](https://imaging.epfl.ch/resources/logo-for-gitlab.svg)
693
699
  # 🧬 Tau Fibrils Yolo - Object detection in EM images
694
700
 
695
701
  ![screenshot](assets/screenshot.png)
696
702
 
697
- We provide a [YoloV8](https://docs.ultralytics.com/) model for the detection of oriented bounding boxes (OBBs) of Tau fibrils in EM images.
703
+ We provide a [YoloV8](https://docs.ultralytics.com/) model for the detection of oriented bounding boxes (OBBs) of Tau fibrils in EM images. The model is integrated as a [Napari](https://napari.org/stable/) plugin.
698
704
 
699
705
  [[`Installation`](#installation)] [[`Model`](#model)] [[`Usage`](#usage)] [[`Training`](#training)]
700
706
 
@@ -702,13 +708,7 @@ This project is part of a collaboration between the [EPFL Center for Imaging](ht
702
708
 
703
709
  ## Installation
704
710
 
705
- ### As a standalone app
706
-
707
- Download and run the latest installer from the [Releases](https://github.com/EPFL-Center-for-Imaging/tau-fibrils-yolo/releases) page.
708
-
709
- ### As a Python package
710
-
711
- We recommend performing the installation in a clean Python environment. Install our package from PyPi:
711
+ We recommend performing the installation in a clean Python environment. Install the package from PyPi:
712
712
 
713
713
  ```sh
714
714
  pip install tau-fibrils-yolo
@@ -728,71 +728,32 @@ cd tau-fibrils-yolo
728
728
  pip install -e .
729
729
  ```
730
730
 
731
- ## Model
732
-
733
- The model weights (6.5 Mb) are automatically downloaded from [this repository on Zenodo](https://sandbox.zenodo.org/records/99113) the first time you run inference. The model files are saved in the user home folder in the `.yolo` directory.
734
-
735
731
  ## Usage
736
732
 
737
733
  **In Napari**
738
734
 
739
- To use our model in Napari, start the viewer with
735
+ To use the model in Napari, start the viewer with
740
736
 
741
737
  ```sh
742
738
  napari -w tau-fibrils-yolo
743
739
  ```
744
740
 
745
- or open the Napari menu bar and select `Plugins > Tau fibrils detection`.
746
-
747
- Open an image using `File > Open files` or drag-and-drop an image into the viewer window.
748
-
749
- **Sample data**: To test the model, you can run it on our provided sample image. In Napari, open the image from `File > Open Sample > [TODO - add a sample image]`.
750
-
751
-
752
- **As a library**
753
-
754
- You can run the model to detect fibrils in an image (represented as a numpy array).
755
-
756
- ```py
757
- from tau_fibrils_yolo import FibrilsDetector
758
-
759
- detector = FibrilsDetector()
760
-
761
- boxes, probabilities = detector.predict(your_image)
762
- ```
741
+ or open the plugin from `Plugins > Tau fibrils detection`.
763
742
 
764
- **As a CLI**
743
+ **From the command-line**
765
744
 
766
- Run inference on an image from the command-line. For example:
745
+ Run inference on an image from the command-line:
767
746
 
768
747
  ```sh
769
748
  tau_fibrils_predict_image -i /path/to/folder/image_001.tif
770
749
  ```
771
750
 
772
- The command will save the segmentation next to the image:
773
-
774
- ```
775
- folder/
776
- ├── image_001.tif
777
- ├── image_001_results.csv
778
- ```
779
-
780
- Optionally, you can use the `-r` flag to also rescale the image by a given factor.
781
-
782
- To run inference in batch on all images in a folder, use:
783
-
784
- ```sh
785
- tau_fibrils_predict_folder -i /path/to/folder/
786
- ```
787
-
788
- This will produce:
751
+ This command will run the YOLO model and save a CSV file containing measurements next to the image:
789
752
 
790
753
  ```
791
754
  folder/
792
755
  ├── image_001.tif
793
756
  ├── image_001_results.csv
794
- ├── image_002.tif
795
- ├── image_002_results.csv
796
757
  ```
797
758
 
798
759
  ## Training
@@ -3,7 +3,7 @@
3
3
 
4
4
  ![screenshot](assets/screenshot.png)
5
5
 
6
- We provide a [YoloV8](https://docs.ultralytics.com/) model for the detection of oriented bounding boxes (OBBs) of Tau fibrils in EM images.
6
+ We provide a [YoloV8](https://docs.ultralytics.com/) model for the detection of oriented bounding boxes (OBBs) of Tau fibrils in EM images. The model is integrated as a [Napari](https://napari.org/stable/) plugin.
7
7
 
8
8
  [[`Installation`](#installation)] [[`Model`](#model)] [[`Usage`](#usage)] [[`Training`](#training)]
9
9
 
@@ -11,13 +11,7 @@ This project is part of a collaboration between the [EPFL Center for Imaging](ht
11
11
 
12
12
  ## Installation
13
13
 
14
- ### As a standalone app
15
-
16
- Download and run the latest installer from the [Releases](https://github.com/EPFL-Center-for-Imaging/tau-fibrils-yolo/releases) page.
17
-
18
- ### As a Python package
19
-
20
- We recommend performing the installation in a clean Python environment. Install our package from PyPi:
14
+ We recommend performing the installation in a clean Python environment. Install the package from PyPi:
21
15
 
22
16
  ```sh
23
17
  pip install tau-fibrils-yolo
@@ -37,71 +31,32 @@ cd tau-fibrils-yolo
37
31
  pip install -e .
38
32
  ```
39
33
 
40
- ## Model
41
-
42
- The model weights (6.5 Mb) are automatically downloaded from [this repository on Zenodo](https://sandbox.zenodo.org/records/99113) the first time you run inference. The model files are saved in the user home folder in the `.yolo` directory.
43
-
44
34
  ## Usage
45
35
 
46
36
  **In Napari**
47
37
 
48
- To use our model in Napari, start the viewer with
38
+ To use the model in Napari, start the viewer with
49
39
 
50
40
  ```sh
51
41
  napari -w tau-fibrils-yolo
52
42
  ```
53
43
 
54
- or open the Napari menu bar and select `Plugins > Tau fibrils detection`.
55
-
56
- Open an image using `File > Open files` or drag-and-drop an image into the viewer window.
57
-
58
- **Sample data**: To test the model, you can run it on our provided sample image. In Napari, open the image from `File > Open Sample > [TODO - add a sample image]`.
59
-
60
-
61
- **As a library**
62
-
63
- You can run the model to detect fibrils in an image (represented as a numpy array).
64
-
65
- ```py
66
- from tau_fibrils_yolo import FibrilsDetector
67
-
68
- detector = FibrilsDetector()
69
-
70
- boxes, probabilities = detector.predict(your_image)
71
- ```
44
+ or open the plugin from `Plugins > Tau fibrils detection`.
72
45
 
73
- **As a CLI**
46
+ **From the command-line**
74
47
 
75
- Run inference on an image from the command-line. For example:
48
+ Run inference on an image from the command-line:
76
49
 
77
50
  ```sh
78
51
  tau_fibrils_predict_image -i /path/to/folder/image_001.tif
79
52
  ```
80
53
 
81
- The command will save the segmentation next to the image:
82
-
83
- ```
84
- folder/
85
- ├── image_001.tif
86
- ├── image_001_results.csv
87
- ```
88
-
89
- Optionally, you can use the `-r` flag to also rescale the image by a given factor.
90
-
91
- To run inference in batch on all images in a folder, use:
92
-
93
- ```sh
94
- tau_fibrils_predict_folder -i /path/to/folder/
95
- ```
96
-
97
- This will produce:
54
+ This command will run the YOLO model and save a CSV file containing measurements next to the image:
98
55
 
99
56
  ```
100
57
  folder/
101
58
  ├── image_001.tif
102
59
  ├── image_001_results.csv
103
- ├── image_002.tif
104
- ├── image_002_results.csv
105
60
  ```
106
61
 
107
62
  ## Training
@@ -13,6 +13,9 @@ classifiers = [
13
13
  "Programming Language :: Python :: 3",
14
14
  "Programming Language :: Python :: 3.9",
15
15
  "Programming Language :: Python :: 3.10",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
16
19
  "Topic :: Scientific/Engineering :: Image Processing",
17
20
  ]
18
21
 
@@ -28,7 +31,9 @@ dependencies = [
28
31
  "scikit-image",
29
32
  "scikit-learn",
30
33
  "ultralytics",
31
- "opencv-contrib-python-headless"
34
+ "opencv-contrib-python-headless",
35
+ "imaging-server-kit>=0.1.3",
36
+ "napari-serverkit>=0.0.9",
32
37
  ]
33
38
 
34
39
  [project.entry-points."napari.manifest"]
@@ -0,0 +1,28 @@
1
+ from tau_fibrils_yolo.widget import (
2
+ detect_fibrils,
3
+ max_iou_boxes,
4
+ min_distance_boxes,
5
+ boxes_kernel_density,
6
+ )
7
+
8
+ from qtpy.QtWidgets import QWidget
9
+ import imaging_server_kit as sk
10
+
11
+
12
+ class YoloDetectorWidget(QWidget):
13
+ def __init__(self, viewer):
14
+ super().__init__()
15
+ multi = sk.combine(
16
+ [detect_fibrils, max_iou_boxes, min_distance_boxes, boxes_kernel_density],
17
+ name="Tau fibrils analysis",
18
+ )
19
+ widget = sk.to_qwidget(multi, viewer)
20
+ self.setLayout(widget.layout())
21
+
22
+
23
+ from ._version import version as __version__
24
+
25
+ try:
26
+ from ._version import version as __version__
27
+ except ImportError:
28
+ __version__ = "unknown"
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.1.0'
32
+ __version_tuple__ = version_tuple = (0, 1, 0)
33
+
34
+ __commit_id__ = commit_id = 'g53b41a1b4'
@@ -0,0 +1,111 @@
1
+ from typing import Any, Optional
2
+
3
+ import cv2
4
+ import numpy as np
5
+ from numpy.linalg import norm
6
+ from scipy.ndimage import zoom
7
+ from scipy.spatial import distance_matrix
8
+ from sklearn.neighbors import KernelDensity
9
+
10
+
11
+ def boxes_min_distance_filter(
12
+ boxes, min_dist_px=5, probas: Optional[np.ndarray] = None
13
+ ) -> Any:
14
+ """Returns a filter matching objects isolated by less than min_dist_px pixels."""
15
+ centers = boxes_centers(boxes)
16
+ dist_matrix = distance_matrix(centers, centers)
17
+ np.fill_diagonal(dist_matrix, np.inf)
18
+ filt = np.min(dist_matrix, axis=1) > min_dist_px
19
+ if probas is not None:
20
+ return boxes[filt], probas[filt]
21
+ else:
22
+ return boxes[filt]
23
+
24
+
25
+ def boxes_iou_filter(
26
+ boxes: np.ndarray, max_iou: float = 0.0, probas: Optional[np.ndarray] = None
27
+ ) -> Any:
28
+ """Removes boxes based on an intersection over union threshold."""
29
+ keep = []
30
+ for i, box_i in enumerate(boxes):
31
+ should_keep_i = True
32
+ box_i = boxes[i]
33
+ for j in keep:
34
+ box_j = boxes[j]
35
+ intersection, _ = cv2.intersectConvexConvex(box_i, box_j)
36
+ area_i = cv2.contourArea(box_i)
37
+ area_j = cv2.contourArea(box_j)
38
+ union = area_i + area_j - intersection
39
+ iou = intersection / union
40
+ if iou >= max_iou:
41
+ should_keep_i = False
42
+ break
43
+ if should_keep_i:
44
+ keep.append(i)
45
+
46
+ if probas is not None:
47
+ return boxes[keep], probas[keep]
48
+ else:
49
+ return boxes[keep]
50
+
51
+
52
+ def clear_border_boxes(boxes: np.ndarray, probas: Optional[np.ndarray] = None) -> Any:
53
+ """Removes boxes touching the image border."""
54
+ filt = ~(boxes < 0).any(axis=2).any(axis=1)
55
+ if probas is not None:
56
+ return boxes[filt], probas[filt]
57
+ else:
58
+ return boxes[filt]
59
+
60
+
61
+ def boxes_centers(boxes: np.ndarray) -> np.ndarray:
62
+ """Returns the center coordinates of the boxes."""
63
+ box_cy = (np.max(boxes[..., 1], axis=1) + np.min(boxes[..., 1], axis=1)) / 2
64
+ box_cx = (np.max(boxes[..., 0], axis=1) + np.min(boxes[..., 0], axis=1)) / 2
65
+ box_centers = np.vstack((box_cx, box_cy)).T
66
+ return box_centers
67
+
68
+
69
+ def boxes_kernel_density_map(boxes, image, gaussian_sigma_px=50, downscale_factor=8):
70
+ """Returns a kernel density image from box coordinates."""
71
+ grid_size_x = image.shape[0] // downscale_factor
72
+ grid_size_y = image.shape[1] // downscale_factor
73
+
74
+ x_grid, y_grid = np.meshgrid(
75
+ np.linspace(0, grid_size_y - 1, grid_size_y),
76
+ np.linspace(0, grid_size_x - 1, grid_size_x),
77
+ )
78
+
79
+ grid_points = np.vstack([y_grid.ravel(), x_grid.ravel()]).T
80
+
81
+ kde = KernelDensity(
82
+ bandwidth=gaussian_sigma_px, kernel="gaussian", algorithm="ball_tree"
83
+ )
84
+
85
+ kde.fit(boxes_centers(boxes) / downscale_factor)
86
+
87
+ density_map = np.exp(kde.score_samples(grid_points)).reshape(
88
+ (grid_size_x, grid_size_y)
89
+ )
90
+ density_map = zoom(density_map, zoom=downscale_factor, order=1)
91
+
92
+ return density_map
93
+
94
+
95
+ def box_measurements(box):
96
+ """Returns the center, length, and width of an oriented bounding box."""
97
+ p0, p1, p2, p3 = box
98
+
99
+ if norm(p2 - p0) < norm(p1 - p0):
100
+ p0, p3, p2, p1 = box
101
+
102
+ p5 = p0 + (p1 - p0) / 2
103
+ p6 = p3 + (p2 - p3) / 2
104
+
105
+ width = norm(p1 - p0)
106
+ length = norm(p2 - p0)
107
+
108
+ diagonal = p6 - p5
109
+ center = p5 + diagonal / 2
110
+
111
+ return center, length, width
@@ -0,0 +1,60 @@
1
+ import tifffile
2
+ from pathlib import Path
3
+ import argparse
4
+ import pandas as pd
5
+
6
+
7
+ from tau_fibrils_yolo.widget import detect_fibrils
8
+ from tau_fibrils_yolo.boxes_utils import box_measurements
9
+
10
+
11
+ def process_input_file_predict(input_image_file):
12
+ image = tifffile.imread(input_image_file)
13
+
14
+ results = detect_fibrils.run(image)
15
+ box_results = results.read("Tau fibrils")
16
+
17
+ boxes = box_results.data
18
+ probas = box_results.meta["features"]["probabilities"]
19
+
20
+ centers_x = []
21
+ centers_y = []
22
+ lengths = []
23
+ widths = []
24
+ for box in boxes:
25
+ center, length, width = box_measurements(box)
26
+ centers_x.append(center[0])
27
+ centers_y.append(center[1])
28
+ lengths.append(length)
29
+ widths.append(width)
30
+
31
+ df = pd.DataFrame(
32
+ {
33
+ "probability": probas,
34
+ "length": lengths,
35
+ "width": widths,
36
+ "center_x": centers_x,
37
+ "center_y": centers_y,
38
+ }
39
+ )
40
+
41
+ input_image_path = Path(input_image_file)
42
+ out_file_name = input_image_path.parent / f"{input_image_path.stem}_results.csv"
43
+
44
+ df.to_csv(out_file_name)
45
+
46
+ print("Saved results to ", out_file_name)
47
+
48
+
49
+ def cli_predict_image():
50
+ """Command-line entry point for model inference."""
51
+ parser = argparse.ArgumentParser(description="Use this command to run inference.")
52
+ parser.add_argument(
53
+ "-i",
54
+ type=str,
55
+ required=True,
56
+ help="Input image. Must be a TIF image file.",
57
+ )
58
+ args = parser.parse_args()
59
+
60
+ process_input_file_predict(args.i)