frontveg 0.2.0__tar.gz → 0.3.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 (30) hide show
  1. {frontveg-0.2.0 → frontveg-0.3.0}/PKG-INFO +9 -3
  2. {frontveg-0.2.0 → frontveg-0.3.0}/README.md +1 -1
  3. {frontveg-0.2.0 → frontveg-0.3.0}/pyproject.toml +7 -1
  4. frontveg-0.3.0/src/frontveg/__init__.py +9 -0
  5. {frontveg-0.2.0 → frontveg-0.3.0}/src/frontveg/_version.py +2 -2
  6. frontveg-0.3.0/src/frontveg/_widget.py +146 -0
  7. frontveg-0.3.0/src/frontveg/napari.yaml +14 -0
  8. frontveg-0.3.0/src/frontveg/utils.py +109 -0
  9. {frontveg-0.2.0 → frontveg-0.3.0}/src/frontveg.egg-info/PKG-INFO +9 -3
  10. {frontveg-0.2.0 → frontveg-0.3.0}/src/frontveg.egg-info/SOURCES.txt +1 -0
  11. frontveg-0.3.0/src/frontveg.egg-info/requires.txt +18 -0
  12. frontveg-0.2.0/src/frontveg/__init__.py +0 -17
  13. frontveg-0.2.0/src/frontveg/_widget.py +0 -129
  14. frontveg-0.2.0/src/frontveg/napari.yaml +0 -30
  15. frontveg-0.2.0/src/frontveg.egg-info/requires.txt +0 -12
  16. {frontveg-0.2.0 → frontveg-0.3.0}/.github/dependabot.yml +0 -0
  17. {frontveg-0.2.0 → frontveg-0.3.0}/.github/workflows/test_and_deploy.yml +0 -0
  18. {frontveg-0.2.0 → frontveg-0.3.0}/.gitignore +0 -0
  19. {frontveg-0.2.0 → frontveg-0.3.0}/.napari-hub/DESCRIPTION.md +0 -0
  20. {frontveg-0.2.0 → frontveg-0.3.0}/.napari-hub/config.yml +0 -0
  21. {frontveg-0.2.0 → frontveg-0.3.0}/.pre-commit-config.yaml +0 -0
  22. {frontveg-0.2.0 → frontveg-0.3.0}/LICENSE +0 -0
  23. {frontveg-0.2.0 → frontveg-0.3.0}/MANIFEST.in +0 -0
  24. {frontveg-0.2.0 → frontveg-0.3.0}/setup.cfg +0 -0
  25. {frontveg-0.2.0 → frontveg-0.3.0}/src/frontveg/_tests/__init__.py +0 -0
  26. {frontveg-0.2.0 → frontveg-0.3.0}/src/frontveg/_tests/test_widget.py +0 -0
  27. {frontveg-0.2.0 → frontveg-0.3.0}/src/frontveg.egg-info/dependency_links.txt +0 -0
  28. {frontveg-0.2.0 → frontveg-0.3.0}/src/frontveg.egg-info/entry_points.txt +0 -0
  29. {frontveg-0.2.0 → frontveg-0.3.0}/src/frontveg.egg-info/top_level.txt +0 -0
  30. {frontveg-0.2.0 → frontveg-0.3.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frontveg
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Segmentation of vegetation located to close to camera
5
5
  Author: Herearii Metuarea
6
6
  Author-email: herearii.metuarea@univ-angers.fr
@@ -50,13 +50,19 @@ Classifier: Programming Language :: Python :: 3.11
50
50
  Classifier: Programming Language :: Python :: 3.12
51
51
  Classifier: Programming Language :: Python :: 3.13
52
52
  Classifier: Topic :: Scientific/Engineering :: Image Processing
53
- Requires-Python: >=3.10
53
+ Requires-Python: ==3.11.12
54
54
  Description-Content-Type: text/markdown
55
55
  License-File: LICENSE
56
56
  Requires-Dist: numpy
57
57
  Requires-Dist: magicgui
58
58
  Requires-Dist: qtpy
59
59
  Requires-Dist: scikit-image
60
+ Requires-Dist: transformers==4.51.3
61
+ Requires-Dist: torch>=2.3.1
62
+ Requires-Dist: torchvision>=0.18.1
63
+ Requires-Dist: hydra-core==1.3.2
64
+ Requires-Dist: iopath>=0.1.10
65
+ Requires-Dist: pillow>=9.4.0
60
66
  Provides-Extra: testing
61
67
  Requires-Dist: tox; extra == "testing"
62
68
  Requires-Dist: pytest; extra == "testing"
@@ -83,8 +89,8 @@ A plugin for foreground vegetation segmentation, tailored for trellised vegetati
83
89
 
84
90
  The method was developped by Herearii Metuarea, PHENET PhD at LARIS (French laboratory located in Angers, France) and Abdoul-Djalil Hamza Ousseini, AgroEcoPhen Engineer at IRHS (French Institute located in INRAe Angers, France) in Imhorphen team (bioimaging research group lead) under the supervision of Eric Duchêne (Research Engineer), Morgane Roth (Research Engineer) and David Rousseau (Full professor). This plugin was written by Herearii Metuarea and was designed in the context of the european project PHENET.
85
91
 
92
+ ![Data Warehouse](https://github.com/user-attachments/assets/4a110408-5854-4e8c-b655-4cb588434b79)
86
93
 
87
- ![Data Warehouse](https://github.com/user-attachments/assets/781dc1ef-3ae0-47ff-9771-6de2879ed602)
88
94
 
89
95
  ----------------------------------
90
96
 
@@ -15,8 +15,8 @@ A plugin for foreground vegetation segmentation, tailored for trellised vegetati
15
15
 
16
16
  The method was developped by Herearii Metuarea, PHENET PhD at LARIS (French laboratory located in Angers, France) and Abdoul-Djalil Hamza Ousseini, AgroEcoPhen Engineer at IRHS (French Institute located in INRAe Angers, France) in Imhorphen team (bioimaging research group lead) under the supervision of Eric Duchêne (Research Engineer), Morgane Roth (Research Engineer) and David Rousseau (Full professor). This plugin was written by Herearii Metuarea and was designed in the context of the european project PHENET.
17
17
 
18
+ ![Data Warehouse](https://github.com/user-attachments/assets/4a110408-5854-4e8c-b655-4cb588434b79)
18
19
 
19
- ![Data Warehouse](https://github.com/user-attachments/assets/781dc1ef-3ae0-47ff-9771-6de2879ed602)
20
20
 
21
21
  ----------------------------------
22
22
 
@@ -23,12 +23,18 @@ classifiers = [
23
23
  "Programming Language :: Python :: 3.13",
24
24
  "Topic :: Scientific/Engineering :: Image Processing",
25
25
  ]
26
- requires-python = ">=3.10"
26
+ requires-python = "==3.11.12"
27
27
  dependencies = [
28
28
  "numpy",
29
29
  "magicgui",
30
30
  "qtpy",
31
31
  "scikit-image",
32
+ "transformers==4.51.3",
33
+ "torch>=2.3.1",
34
+ "torchvision>=0.18.1",
35
+ "hydra-core==1.3.2",
36
+ "iopath>=0.1.10",
37
+ "pillow>=9.4.0",
32
38
  ]
33
39
 
34
40
  [project.optional-dependencies]
@@ -0,0 +1,9 @@
1
+ try:
2
+ from ._version import version as __version__
3
+ except ImportError:
4
+ __version__ = "unknown"
5
+ from ._widget import (
6
+ vegetation,
7
+ )
8
+
9
+ __all__ = ("vegetation",)
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.2.0'
21
- __version_tuple__ = version_tuple = (0, 2, 0)
20
+ __version__ = version = '0.3.0'
21
+ __version_tuple__ = version_tuple = (0, 3, 0)
@@ -0,0 +1,146 @@
1
+ """
2
+ This module contains four napari widgets declared in
3
+ different ways:
4
+
5
+ - a pure Python function flagged with `autogenerate: true`
6
+ in the plugin manifest. Type annotations are used by
7
+ magicgui to generate widgets for each parameter. Best
8
+ suited for simple processing tasks - usually taking
9
+ in and/or returning a layer.
10
+ - a `magic_factory` decorated function. The `magic_factory`
11
+ decorator allows us to customize aspects of the resulting
12
+ GUI, including the widgets associated with each parameter.
13
+ Best used when you have a very simple processing task,
14
+ but want some control over the autogenerated widgets. If you
15
+ find yourself needing to define lots of nested functions to achieve
16
+ your functionality, maybe look at the `Container` widget!
17
+ - a `magicgui.widgets.Container` subclass. This provides lots
18
+ of flexibility and customization options while still supporting
19
+ `magicgui` widgets and convenience methods for creating widgets
20
+ from type annotations. If you want to customize your widgets and
21
+ connect callbacks, this is the best widget option for you.
22
+ - a `QWidget` subclass. This provides maximal flexibility but requires
23
+ full specification of widget layouts, callbacks, events, etc.
24
+
25
+ References:
26
+ - Widget specification: https://napari.org/stable/plugins/building_a_plugin/guides.html#widgets
27
+ - magicgui docs: https://pyapp-kit.github.io/magicgui/
28
+
29
+ Replace code below according to your needs.
30
+ """
31
+
32
+ from typing import TYPE_CHECKING
33
+
34
+ import numpy as np
35
+ import torch
36
+ from magicgui import magic_factory
37
+ from PIL import Image
38
+ from scipy import ndimage
39
+ from transformers import pipeline
40
+
41
+ if TYPE_CHECKING:
42
+ import napari
43
+ from frontveg.utils import frontground_part, ground_dino, sam2
44
+
45
+ pipe = pipeline(
46
+ task="depth-estimation", model="depth-anything/Depth-Anything-V2-Large-hf"
47
+ )
48
+
49
+
50
+ @magic_factory(call_button="Run")
51
+ def vegetation(
52
+ input_data: "napari.types.ImageData",
53
+ ) -> "napari.types.LabelsData":
54
+ device = "cuda"
55
+
56
+ if input_data.ndim == 4:
57
+ output_data = np.zeros(
58
+ (input_data.shape[0], input_data.shape[1], input_data.shape[2]),
59
+ dtype="uint8",
60
+ )
61
+ INPUT = []
62
+ for i in range(len(input_data)):
63
+ rgb_data = input_data[i, :, :, :].compute()
64
+ image = Image.fromarray(rgb_data)
65
+ INPUT.append(image)
66
+ else:
67
+ output_data = np.zeros(
68
+ (1, input_data.shape[0], input_data.shape[1]), dtype="uint8"
69
+ )
70
+ rgb_data = input_data
71
+ image = Image.fromarray(rgb_data)
72
+ INPUT = [image]
73
+ depth = pipe(INPUT)
74
+ n = len(depth)
75
+
76
+ model, processor = ground_dino()
77
+ predictor, text_labels = sam2()
78
+
79
+ for i in range(n):
80
+ depth_pred = depth[i]["depth"]
81
+ msks_depth = np.array(depth_pred)
82
+ msks_front = frontground_part(msks_depth)
83
+ msks_front = msks_front.astype(np.uint8) * 255
84
+
85
+ image = INPUT[i]
86
+ inputs = processor(
87
+ images=image, text=text_labels, return_tensors="pt"
88
+ ).to(device)
89
+ with torch.no_grad():
90
+ outputs = model(**inputs)
91
+
92
+ results = processor.post_process_grounded_object_detection(
93
+ outputs,
94
+ inputs.input_ids,
95
+ box_threshold=0.4,
96
+ text_threshold=0.3,
97
+ target_sizes=[image.size[::-1]],
98
+ )
99
+
100
+ # Retrieve the first image result
101
+ result = results[0]
102
+ for box, score, labels in zip(
103
+ result["boxes"], result["scores"], result["labels"], strict=False
104
+ ):
105
+ box = [round(x, 2) for x in box.tolist()]
106
+ print(
107
+ f"Detected {labels} with confidence {round(score.item(), 3)} at location {box}"
108
+ )
109
+ if len(result["boxes"]) == 0:
110
+ masks = np.zeros(image.size[::-1], dtype="uint8")
111
+ else:
112
+ with (
113
+ torch.inference_mode(),
114
+ torch.autocast("cuda", dtype=torch.bfloat16),
115
+ ):
116
+ predictor.set_image(image)
117
+ masks_sam, _, _ = predictor.predict(
118
+ box=result["boxes"],
119
+ point_labels=result["labels"],
120
+ multimask_output=False,
121
+ )
122
+ if masks_sam.ndim == 4:
123
+ masks = np.sum(masks_sam, axis=0)
124
+ masks = masks[0, :, :]
125
+ else:
126
+ masks = masks_sam[0, :, :]
127
+
128
+ msks_veg = masks.astype(np.uint8) * 255
129
+
130
+ mask1 = msks_front.copy() # Masque 1
131
+ mask2 = msks_veg.copy() # Masque 2
132
+ mask2 = ndimage.binary_fill_holes(mask2) # Fill holes
133
+ mask1 = (mask1 > 0).astype(np.uint8) # Convertir en binaire
134
+ mask2 = (mask2 > 0).astype(np.uint8) # Convertir en binaire
135
+ if len(np.unique(mask2)) == 2:
136
+ intersection = (
137
+ mask1 & mask2
138
+ ) # Intersection : les pixels qui sont 1 dans les deux masques
139
+ intersection = intersection > 0
140
+ else:
141
+ intersection = mask1.copy()
142
+ intersection = (intersection * 255).astype(
143
+ np.uint8
144
+ ) # Si tu veux un masque avec des 0 et 255 (ex. pour OpenCV)
145
+ output_data[i, :, :] = intersection
146
+ return output_data
@@ -0,0 +1,14 @@
1
+ name: frontveg
2
+ display_name: Frontveg
3
+ # use 'hidden' to remove plugin from napari hub search results
4
+ visibility: public
5
+ # see https://napari.org/stable/plugins/technical_references/manifest.html#fields for valid categories
6
+ categories: ["Annotation", "Segmentation", "Acquisition"]
7
+ contributions:
8
+ commands:
9
+ - id: frontveg.vegetation
10
+ python_name: frontveg:vegetation
11
+ title: Vegetation plugin
12
+ widgets:
13
+ - command: frontveg.vegetation
14
+ display_name: Frontground vegetation
@@ -0,0 +1,109 @@
1
+ import os
2
+ from collections import Counter
3
+
4
+ import matplotlib.pyplot as plt
5
+ import numpy as np
6
+ from scipy.signal import find_peaks
7
+ from tqdm import tqdm
8
+ from transformers import AutoModelForZeroShotObjectDetection, AutoProcessor
9
+
10
+ # CONF = config.get_conf_dict()
11
+ homedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
12
+
13
+ # base_dir = CONF['general']['base_directory']
14
+ base_dir = "."
15
+
16
+ model_id = "IDEA-Research/grounding-dino-tiny"
17
+ device = "cuda"
18
+
19
+ processor = AutoProcessor.from_pretrained(model_id)
20
+ model = AutoModelForZeroShotObjectDetection.from_pretrained(model_id).to(
21
+ device
22
+ )
23
+
24
+
25
+ def ground_dino():
26
+ return model, processor
27
+
28
+
29
+ from sam2.sam2_image_predictor import SAM2ImagePredictor
30
+
31
+ predictor = SAM2ImagePredictor.from_pretrained("facebook/sam2-hiera-large")
32
+ text_labels = ["green region. foliage."]
33
+
34
+
35
+ def sam2():
36
+ return predictor, text_labels
37
+
38
+
39
+ def minimum_betw_max(dico_, visua=False):
40
+ Ax = list(dico_.keys())
41
+ Ay = list(dico_.values())
42
+
43
+ # Approximation par une régression polynomiale
44
+ x = Ax[1:]
45
+ y = Ay[1:]
46
+ degree = 14 # Choisissez le degré selon la complexité de la courbe
47
+ coefficients = np.polyfit(x, y, degree)
48
+ polynomial = np.poly1d(coefficients)
49
+
50
+ # Points lissés pour tracer la courbe
51
+ x_fit = np.linspace(min(x), max(x), 500)
52
+ y_fit = polynomial(x_fit)
53
+
54
+ # Détection des maxima
55
+ peaks, _ = find_peaks(y_fit)
56
+
57
+ peak_values = y_fit[peaks]
58
+ sorted_indices = np.argsort(peak_values)[
59
+ ::-1
60
+ ] # Trier en ordre décroissant
61
+ top_two_peaks = peaks[
62
+ sorted_indices[:2]
63
+ ] # Les indices des deux plus grands pics
64
+
65
+ # Trouver le minimum entre les deux maxima
66
+ x_min_range = x_fit[top_two_peaks[0] : top_two_peaks[1] + 1]
67
+ y_min_range = y_fit[top_two_peaks[0] : top_two_peaks[1] + 1]
68
+ minx = min([top_two_peaks[0], top_two_peaks[1]])
69
+ maxx = max([top_two_peaks[0], top_two_peaks[1]])
70
+ x_min_range = x_fit[minx : maxx + 1]
71
+ y_min_range = y_fit[minx : maxx + 1]
72
+ min_index = np.argmin(y_min_range) # Index du minimum dans cette plage
73
+ x_min = x_min_range[min_index]
74
+ y_min = y_min_range[min_index]
75
+
76
+ if visua:
77
+ # Tracé
78
+ plt.scatter(x, y, color="blue")
79
+ plt.plot(x_fit, y_fit, color="red", label="Polynomial regression")
80
+ plt.scatter(
81
+ x_fit[top_two_peaks],
82
+ y_fit[top_two_peaks],
83
+ color="green",
84
+ label="Local maximum",
85
+ )
86
+ plt.scatter(x_min, y_min, color="orange", s=100, label="Local minimum")
87
+ plt.legend()
88
+ plt.xlabel("Depth pixel")
89
+ plt.ylabel("Count")
90
+ # plt.title('Approximation et détection des points maximum')
91
+ plt.show()
92
+ return x_min, y_min
93
+
94
+
95
+ def frontground_part(depths):
96
+ depth_one = depths[:, :]
97
+ n, m = depth_one.shape
98
+ A = []
99
+ for i in tqdm(range(n)):
100
+ for j in range(m):
101
+ A.append([i, j, depth_one[i, j]])
102
+ X = np.array(A)
103
+
104
+ dico_ = Counter(X[:, 2])
105
+ min_coord = minimum_betw_max(dico_, visua=False)
106
+
107
+ th_ = min_coord[0]
108
+ msks_depth = depth_one > th_
109
+ return msks_depth
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frontveg
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Segmentation of vegetation located to close to camera
5
5
  Author: Herearii Metuarea
6
6
  Author-email: herearii.metuarea@univ-angers.fr
@@ -50,13 +50,19 @@ Classifier: Programming Language :: Python :: 3.11
50
50
  Classifier: Programming Language :: Python :: 3.12
51
51
  Classifier: Programming Language :: Python :: 3.13
52
52
  Classifier: Topic :: Scientific/Engineering :: Image Processing
53
- Requires-Python: >=3.10
53
+ Requires-Python: ==3.11.12
54
54
  Description-Content-Type: text/markdown
55
55
  License-File: LICENSE
56
56
  Requires-Dist: numpy
57
57
  Requires-Dist: magicgui
58
58
  Requires-Dist: qtpy
59
59
  Requires-Dist: scikit-image
60
+ Requires-Dist: transformers==4.51.3
61
+ Requires-Dist: torch>=2.3.1
62
+ Requires-Dist: torchvision>=0.18.1
63
+ Requires-Dist: hydra-core==1.3.2
64
+ Requires-Dist: iopath>=0.1.10
65
+ Requires-Dist: pillow>=9.4.0
60
66
  Provides-Extra: testing
61
67
  Requires-Dist: tox; extra == "testing"
62
68
  Requires-Dist: pytest; extra == "testing"
@@ -83,8 +89,8 @@ A plugin for foreground vegetation segmentation, tailored for trellised vegetati
83
89
 
84
90
  The method was developped by Herearii Metuarea, PHENET PhD at LARIS (French laboratory located in Angers, France) and Abdoul-Djalil Hamza Ousseini, AgroEcoPhen Engineer at IRHS (French Institute located in INRAe Angers, France) in Imhorphen team (bioimaging research group lead) under the supervision of Eric Duchêne (Research Engineer), Morgane Roth (Research Engineer) and David Rousseau (Full professor). This plugin was written by Herearii Metuarea and was designed in the context of the european project PHENET.
85
91
 
92
+ ![Data Warehouse](https://github.com/user-attachments/assets/4a110408-5854-4e8c-b655-4cb588434b79)
86
93
 
87
- ![Data Warehouse](https://github.com/user-attachments/assets/781dc1ef-3ae0-47ff-9771-6de2879ed602)
88
94
 
89
95
  ----------------------------------
90
96
 
@@ -13,6 +13,7 @@ src/frontveg/__init__.py
13
13
  src/frontveg/_version.py
14
14
  src/frontveg/_widget.py
15
15
  src/frontveg/napari.yaml
16
+ src/frontveg/utils.py
16
17
  src/frontveg.egg-info/PKG-INFO
17
18
  src/frontveg.egg-info/SOURCES.txt
18
19
  src/frontveg.egg-info/dependency_links.txt
@@ -0,0 +1,18 @@
1
+ numpy
2
+ magicgui
3
+ qtpy
4
+ scikit-image
5
+ transformers==4.51.3
6
+ torch>=2.3.1
7
+ torchvision>=0.18.1
8
+ hydra-core==1.3.2
9
+ iopath>=0.1.10
10
+ pillow>=9.4.0
11
+
12
+ [testing]
13
+ tox
14
+ pytest
15
+ pytest-cov
16
+ pytest-qt
17
+ napari
18
+ pyqt5
@@ -1,17 +0,0 @@
1
- try:
2
- from ._version import version as __version__
3
- except ImportError:
4
- __version__ = "unknown"
5
- from ._widget import (
6
- ExampleQWidget,
7
- ImageThreshold,
8
- threshold_autogenerate_widget,
9
- threshold_magic_widget,
10
- )
11
-
12
- __all__ = (
13
- "ExampleQWidget",
14
- "ImageThreshold",
15
- "threshold_autogenerate_widget",
16
- "threshold_magic_widget",
17
- )
@@ -1,129 +0,0 @@
1
- """
2
- This module contains four napari widgets declared in
3
- different ways:
4
-
5
- - a pure Python function flagged with `autogenerate: true`
6
- in the plugin manifest. Type annotations are used by
7
- magicgui to generate widgets for each parameter. Best
8
- suited for simple processing tasks - usually taking
9
- in and/or returning a layer.
10
- - a `magic_factory` decorated function. The `magic_factory`
11
- decorator allows us to customize aspects of the resulting
12
- GUI, including the widgets associated with each parameter.
13
- Best used when you have a very simple processing task,
14
- but want some control over the autogenerated widgets. If you
15
- find yourself needing to define lots of nested functions to achieve
16
- your functionality, maybe look at the `Container` widget!
17
- - a `magicgui.widgets.Container` subclass. This provides lots
18
- of flexibility and customization options while still supporting
19
- `magicgui` widgets and convenience methods for creating widgets
20
- from type annotations. If you want to customize your widgets and
21
- connect callbacks, this is the best widget option for you.
22
- - a `QWidget` subclass. This provides maximal flexibility but requires
23
- full specification of widget layouts, callbacks, events, etc.
24
-
25
- References:
26
- - Widget specification: https://napari.org/stable/plugins/building_a_plugin/guides.html#widgets
27
- - magicgui docs: https://pyapp-kit.github.io/magicgui/
28
-
29
- Replace code below according to your needs.
30
- """
31
-
32
- from typing import TYPE_CHECKING
33
-
34
- from magicgui import magic_factory
35
- from magicgui.widgets import CheckBox, Container, create_widget
36
- from qtpy.QtWidgets import QHBoxLayout, QPushButton, QWidget
37
- from skimage.util import img_as_float
38
-
39
- if TYPE_CHECKING:
40
- import napari
41
-
42
-
43
- # Uses the `autogenerate: true` flag in the plugin manifest
44
- # to indicate it should be wrapped as a magicgui to autogenerate
45
- # a widget.
46
- def threshold_autogenerate_widget(
47
- img: "napari.types.ImageData",
48
- threshold: "float",
49
- ) -> "napari.types.LabelsData":
50
- return img_as_float(img) > threshold
51
-
52
-
53
- # the magic_factory decorator lets us customize aspects of our widget
54
- # we specify a widget type for the threshold parameter
55
- # and use auto_call=True so the function is called whenever
56
- # the value of a parameter changes
57
- @magic_factory(
58
- threshold={"widget_type": "FloatSlider", "max": 1}, auto_call=True
59
- )
60
- def threshold_magic_widget(
61
- img_layer: "napari.layers.Image", threshold: "float"
62
- ) -> "napari.types.LabelsData":
63
- return img_as_float(img_layer.data) > threshold
64
-
65
-
66
- # if we want even more control over our widget, we can use
67
- # magicgui `Container`
68
- class ImageThreshold(Container):
69
- def __init__(self, viewer: "napari.viewer.Viewer"):
70
- super().__init__()
71
- self._viewer = viewer
72
- # use create_widget to generate widgets from type annotations
73
- self._image_layer_combo = create_widget(
74
- label="Image", annotation="napari.layers.Image"
75
- )
76
- self._threshold_slider = create_widget(
77
- label="Threshold", annotation=float, widget_type="FloatSlider"
78
- )
79
- self._threshold_slider.min = 0
80
- self._threshold_slider.max = 1
81
- # use magicgui widgets directly
82
- self._invert_checkbox = CheckBox(text="Keep pixels below threshold")
83
-
84
- # connect your own callbacks
85
- self._threshold_slider.changed.connect(self._threshold_im)
86
- self._invert_checkbox.changed.connect(self._threshold_im)
87
-
88
- # append into/extend the container with your widgets
89
- self.extend(
90
- [
91
- self._image_layer_combo,
92
- self._threshold_slider,
93
- self._invert_checkbox,
94
- ]
95
- )
96
-
97
- def _threshold_im(self):
98
- image_layer = self._image_layer_combo.value
99
- if image_layer is None:
100
- return
101
-
102
- image = img_as_float(image_layer.data)
103
- name = image_layer.name + "_thresholded"
104
- threshold = self._threshold_slider.value
105
- if self._invert_checkbox.value:
106
- thresholded = image < threshold
107
- else:
108
- thresholded = image > threshold
109
- if name in self._viewer.layers:
110
- self._viewer.layers[name].data = thresholded
111
- else:
112
- self._viewer.add_labels(thresholded, name=name)
113
-
114
-
115
- class ExampleQWidget(QWidget):
116
- # your QWidget.__init__ can optionally request the napari viewer instance
117
- # use a type annotation of 'napari.viewer.Viewer' for any parameter
118
- def __init__(self, viewer: "napari.viewer.Viewer"):
119
- super().__init__()
120
- self.viewer = viewer
121
-
122
- btn = QPushButton("Click me!")
123
- btn.clicked.connect(self._on_click)
124
-
125
- self.setLayout(QHBoxLayout())
126
- self.layout().addWidget(btn)
127
-
128
- def _on_click(self):
129
- print("napari has", len(self.viewer.layers), "layers")
@@ -1,30 +0,0 @@
1
- name: frontveg
2
- display_name: Frontveg
3
- # use 'hidden' to remove plugin from napari hub search results
4
- visibility: public
5
- # see https://napari.org/stable/plugins/technical_references/manifest.html#fields for valid categories
6
- categories: ["Annotation", "Segmentation", "Acquisition"]
7
- contributions:
8
- commands:
9
- - id: frontveg.make_container_widget
10
- python_name: frontveg:ImageThreshold
11
- title: Make threshold Container widget
12
- - id: frontveg.make_magic_widget
13
- python_name: frontveg:threshold_magic_widget
14
- title: Make threshold magic widget
15
- - id: frontveg.make_function_widget
16
- python_name: frontveg:threshold_autogenerate_widget
17
- title: Make threshold function widget
18
- - id: frontveg.make_qwidget
19
- python_name: frontveg:ExampleQWidget
20
- title: Make example QWidget
21
- widgets:
22
- - command: frontveg.make_container_widget
23
- display_name: Container Threshold
24
- - command: frontveg.make_magic_widget
25
- display_name: Magic Threshold
26
- - command: frontveg.make_function_widget
27
- autogenerate: true
28
- display_name: Autogenerate Threshold
29
- - command: frontveg.make_qwidget
30
- display_name: Example QWidget
@@ -1,12 +0,0 @@
1
- numpy
2
- magicgui
3
- qtpy
4
- scikit-image
5
-
6
- [testing]
7
- tox
8
- pytest
9
- pytest-cov
10
- pytest-qt
11
- napari
12
- pyqt5
File without changes
File without changes
File without changes
File without changes
File without changes