tau-fibrils-yolo 0.0.6__tar.gz → 0.1.1__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.
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/.github/workflows/release_multiplatform.yml +6 -6
- tau_fibrils_yolo-0.1.1/.gitignore +34 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/PKG-INFO +15 -55
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/README.md +7 -52
- tau_fibrils_yolo-0.1.1/assets/screenshot.png +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/pyproject.toml +6 -2
- tau_fibrils_yolo-0.1.1/src/tau_fibrils_yolo/__init__.py +28 -0
- tau_fibrils_yolo-0.1.1/src/tau_fibrils_yolo/_version.py +34 -0
- tau_fibrils_yolo-0.1.1/src/tau_fibrils_yolo/boxes_utils.py +111 -0
- tau_fibrils_yolo-0.1.1/src/tau_fibrils_yolo/cli.py +60 -0
- tau_fibrils_yolo-0.1.1/src/tau_fibrils_yolo/model/100ep.pt +0 -0
- tau_fibrils_yolo-0.1.1/src/tau_fibrils_yolo/sample/sample.tif +0 -0
- tau_fibrils_yolo-0.1.1/src/tau_fibrils_yolo/widget.py +230 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/src/tau_fibrils_yolo.egg-info/PKG-INFO +15 -55
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/src/tau_fibrils_yolo.egg-info/SOURCES.txt +5 -6
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/src/tau_fibrils_yolo.egg-info/requires.txt +2 -1
- tau_fibrils_yolo-0.0.6/.github/workflows/release.yml +0 -126
- tau_fibrils_yolo-0.0.6/.gitignore +0 -171
- tau_fibrils_yolo-0.0.6/assets/screenshot.png +0 -0
- tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/__init__.py +0 -8
- tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/_version.py +0 -16
- tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/_widget.py +0 -294
- tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/cli.py +0 -102
- tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/measure.py +0 -91
- tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/postprocess.py +0 -78
- tau_fibrils_yolo-0.0.6/src/tau_fibrils_yolo/predict.py +0 -168
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/LICENSE +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/MANIFEST.in +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/assets/icon.png +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/scripts/00_annotate.py +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/scripts/01_shapes_to_labels.py +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/scripts/02_split_train_valid.py +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/scripts/03_train_yolo.py +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/scripts/instructions.md +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/setup.cfg +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/src/tau_fibrils_yolo/__main__.py +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/src/tau_fibrils_yolo/napari.yaml +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/src/tau_fibrils_yolo.egg-info/dependency_links.txt +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/src/tau_fibrils_yolo.egg-info/entry_points.txt +0 -0
- {tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/src/tau_fibrils_yolo.egg-info/top_level.txt +0 -0
{tau_fibrils_yolo-0.0.6 → tau_fibrils_yolo-0.1.1}/.github/workflows/release_multiplatform.yml
RENAMED
|
@@ -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.
|
|
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.
|
|
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@
|
|
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@
|
|
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@
|
|
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@
|
|
124
|
+
uses: actions/download-artifact@v4
|
|
125
125
|
with:
|
|
126
126
|
name: executable-macOS
|
|
127
127
|
path: .
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
trained_models/
|
|
31
|
+
pretrained_models/
|
|
32
|
+
qupath/
|
|
33
|
+
output/
|
|
34
|
+
notebooks/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: tau-fibrils-yolo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.1
|
|
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
|
|
@@ -683,18 +686,20 @@ Requires-Dist: numpy
|
|
|
683
686
|
Requires-Dist: pandas
|
|
684
687
|
Requires-Dist: tifffile
|
|
685
688
|
Requires-Dist: matplotlib
|
|
686
|
-
Requires-Dist: pooch==1.8.0
|
|
687
689
|
Requires-Dist: scikit-image
|
|
688
690
|
Requires-Dist: scikit-learn
|
|
689
691
|
Requires-Dist: ultralytics
|
|
690
692
|
Requires-Dist: opencv-contrib-python-headless
|
|
693
|
+
Requires-Dist: imaging-server-kit==0.1.3
|
|
694
|
+
Requires-Dist: napari-serverkit==0.0.9
|
|
695
|
+
Dynamic: license-file
|
|
691
696
|
|
|
692
697
|

|
|
693
698
|
# 🧬 Tau Fibrils Yolo - Object detection in EM images
|
|
694
699
|
|
|
695
700
|

|
|
696
701
|
|
|
697
|
-
We provide a [YoloV8](https://docs.ultralytics.com/) model for the detection of oriented bounding boxes (OBBs) of Tau fibrils in EM images.
|
|
702
|
+
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
703
|
|
|
699
704
|
[[`Installation`](#installation)] [[`Model`](#model)] [[`Usage`](#usage)] [[`Training`](#training)]
|
|
700
705
|
|
|
@@ -702,13 +707,7 @@ This project is part of a collaboration between the [EPFL Center for Imaging](ht
|
|
|
702
707
|
|
|
703
708
|
## Installation
|
|
704
709
|
|
|
705
|
-
|
|
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:
|
|
710
|
+
We recommend performing the installation in a clean Python environment. Install the package from PyPi:
|
|
712
711
|
|
|
713
712
|
```sh
|
|
714
713
|
pip install tau-fibrils-yolo
|
|
@@ -728,71 +727,32 @@ cd tau-fibrils-yolo
|
|
|
728
727
|
pip install -e .
|
|
729
728
|
```
|
|
730
729
|
|
|
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
730
|
## Usage
|
|
736
731
|
|
|
737
732
|
**In Napari**
|
|
738
733
|
|
|
739
|
-
To use
|
|
734
|
+
To use the model in Napari, start the viewer with
|
|
740
735
|
|
|
741
736
|
```sh
|
|
742
737
|
napari -w tau-fibrils-yolo
|
|
743
738
|
```
|
|
744
739
|
|
|
745
|
-
or open the
|
|
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
|
-
```
|
|
740
|
+
or open the plugin from `Plugins > Tau fibrils detection`.
|
|
763
741
|
|
|
764
|
-
**
|
|
742
|
+
**From the command-line**
|
|
765
743
|
|
|
766
|
-
Run inference on an image from the command-line
|
|
744
|
+
Run inference on an image from the command-line:
|
|
767
745
|
|
|
768
746
|
```sh
|
|
769
747
|
tau_fibrils_predict_image -i /path/to/folder/image_001.tif
|
|
770
748
|
```
|
|
771
749
|
|
|
772
|
-
|
|
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:
|
|
750
|
+
This command will run the YOLO model and save a CSV file containing measurements next to the image:
|
|
789
751
|
|
|
790
752
|
```
|
|
791
753
|
folder/
|
|
792
754
|
├── image_001.tif
|
|
793
755
|
├── image_001_results.csv
|
|
794
|
-
├── image_002.tif
|
|
795
|
-
├── image_002_results.csv
|
|
796
756
|
```
|
|
797
757
|
|
|
798
758
|
## Training
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|

|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
**
|
|
46
|
+
**From the command-line**
|
|
74
47
|
|
|
75
|
-
Run inference on an image from the command-line
|
|
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
|
-
|
|
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
|
|
Binary file
|
|
@@ -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
|
|
|
@@ -24,11 +27,12 @@ dependencies = [
|
|
|
24
27
|
"pandas",
|
|
25
28
|
"tifffile",
|
|
26
29
|
"matplotlib",
|
|
27
|
-
"pooch==1.8.0",
|
|
28
30
|
"scikit-image",
|
|
29
31
|
"scikit-learn",
|
|
30
32
|
"ultralytics",
|
|
31
|
-
"opencv-contrib-python-headless"
|
|
33
|
+
"opencv-contrib-python-headless",
|
|
34
|
+
"imaging-server-kit==0.1.3",
|
|
35
|
+
"napari-serverkit==0.0.9",
|
|
32
36
|
]
|
|
33
37
|
|
|
34
38
|
[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, napari_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, napari_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.1'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 1, 1)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = 'g697cbb526'
|
|
@@ -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)
|
|
Binary file
|
|
Binary file
|