samgis_core 3.0.4__tar.gz → 3.0.6__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.
- {samgis_core-3.0.4 → samgis_core-3.0.6}/PKG-INFO +1 -1
- {samgis_core-3.0.4 → samgis_core-3.0.6}/pyproject.toml +2 -2
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/prediction_api/sam_onnx2.py +45 -8
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/prediction_api/sam_onnx_inference.py +23 -3
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/utilities/create_folders_if_not_exists.py +20 -0
- samgis_core-3.0.6/samgis_core/utilities/plot_images.py +99 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/utilities/session_logger.py +14 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/utilities/type_hints.py +27 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/utilities/utilities.py +28 -0
- samgis_core-3.0.4/samgis_core/utilities/plot_images.py +0 -11
- {samgis_core-3.0.4 → samgis_core-3.0.6}/LICENSE +0 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/README.md +0 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/__init__.py +0 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/__version__.py +0 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/prediction_api/__init__.py +0 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/utilities/__init__.py +0 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/utilities/constants.py +0 -0
- {samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/utilities/serialize.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "samgis_core"
|
3
|
-
version = "3.0.
|
3
|
+
version = "3.0.6"
|
4
4
|
description = "SamGIS CORE"
|
5
5
|
authors = ["alessandro trinca tornidor <alessandro@trinca.tornidor.com>"]
|
6
6
|
license = "MIT license"
|
@@ -8,7 +8,7 @@ readme = "README.md"
|
|
8
8
|
|
9
9
|
[metadata]
|
10
10
|
name = "samgis_core"
|
11
|
-
version = "3.0.
|
11
|
+
version = "3.0.6"
|
12
12
|
|
13
13
|
[tool.poetry.urls]
|
14
14
|
Source = "https://gitlab.com/aletrn/samgis_core"
|
@@ -37,7 +37,7 @@ from samgis_core.utilities.utilities import convert_ndarray_to_pil, apply_coords
|
|
37
37
|
|
38
38
|
class SegmentAnythingONNX2:
|
39
39
|
"""
|
40
|
-
Segmentation model using
|
40
|
+
Segmentation model using Segment Anything.
|
41
41
|
Compatible with onnxruntime 1.17.x and later
|
42
42
|
"""
|
43
43
|
|
@@ -68,8 +68,17 @@ class SegmentAnythingONNX2:
|
|
68
68
|
)
|
69
69
|
|
70
70
|
@staticmethod
|
71
|
-
def get_input_points(prompt: ListDict):
|
72
|
-
"""
|
71
|
+
def get_input_points(prompt: ListDict) -> tuple[ndarray]:
|
72
|
+
"""
|
73
|
+
Get input points from a prompt dict list.
|
74
|
+
|
75
|
+
Args:
|
76
|
+
prompt: dict list
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
tuple of points, labels ndarray ready for Segment Anything inference
|
80
|
+
|
81
|
+
"""
|
73
82
|
points = []
|
74
83
|
labels = []
|
75
84
|
for mark in prompt:
|
@@ -95,11 +104,12 @@ class SegmentAnythingONNX2:
|
|
95
104
|
|
96
105
|
Returns:
|
97
106
|
embedding image dict useful to store and cache image embeddings
|
107
|
+
|
98
108
|
"""
|
99
109
|
resized_image = self.preprocess_image(img)
|
100
110
|
padded_input_tensor = self.padding_tensor(resized_image)
|
101
111
|
|
102
|
-
# 2. GET IMAGE EMBEDDINGS USING IMAGE ENCODER
|
112
|
+
# 2. GET IMAGE EMBEDDINGS USING IMAGE ENCODER (`size` argument here is like ndarray `shape`)
|
103
113
|
outputs = self.encoder_session.run(None, {"images": padded_input_tensor})
|
104
114
|
image_embedding = outputs[0]
|
105
115
|
img = convert_ndarray_to_pil(img)
|
@@ -109,9 +119,17 @@ class SegmentAnythingONNX2:
|
|
109
119
|
"resized_size": resized_image.size
|
110
120
|
}
|
111
121
|
|
112
|
-
def predict_masks(self, embedding: EmbeddingPILImage, prompt: ListDict):
|
122
|
+
def predict_masks(self, embedding: EmbeddingPILImage, prompt: ListDict) -> ndarray:
|
113
123
|
"""
|
114
124
|
Predict masks for a single image.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
embedding: input image embedding dict
|
128
|
+
prompt: Segment Anything input prompt
|
129
|
+
|
130
|
+
Returns:
|
131
|
+
prediction masks ndarray; this should have (1, 1, **image.shape) shape
|
132
|
+
|
115
133
|
"""
|
116
134
|
input_points, input_labels = self.get_input_points(prompt)
|
117
135
|
|
@@ -136,8 +154,17 @@ class SegmentAnythingONNX2:
|
|
136
154
|
})
|
137
155
|
return output_masks
|
138
156
|
|
139
|
-
def preprocess_image(self, img: PIL_Image | ndarray):
|
140
|
-
"""
|
157
|
+
def preprocess_image(self, img: PIL_Image | ndarray) -> ndarray:
|
158
|
+
"""
|
159
|
+
Resize image preserving aspect ratio using `output_size_target` as a long side.
|
160
|
+
|
161
|
+
Args:
|
162
|
+
img: input ndarray/PIL image
|
163
|
+
|
164
|
+
Returns:
|
165
|
+
image ndarray
|
166
|
+
|
167
|
+
"""
|
141
168
|
from PIL import Image
|
142
169
|
|
143
170
|
app_logger.info(f"image type:{type(img)}, shape/size:{img.size}.")
|
@@ -157,7 +184,17 @@ class SegmentAnythingONNX2:
|
|
157
184
|
img = img.resize((resized_width, resized_height), Image.Resampling.BILINEAR)
|
158
185
|
return img
|
159
186
|
|
160
|
-
def padding_tensor(self, img: PIL_Image | ndarray):
|
187
|
+
def padding_tensor(self, img: PIL_Image | ndarray) -> ndarray:
|
188
|
+
"""
|
189
|
+
Pad an image ndarray/tensor to given instance self.target_size
|
190
|
+
|
191
|
+
Args:
|
192
|
+
img: input ndarray/PIL image
|
193
|
+
|
194
|
+
Returns:
|
195
|
+
image ndarray
|
196
|
+
|
197
|
+
"""
|
161
198
|
# Prepare input tensor from image
|
162
199
|
tensor_input = np_array(img)
|
163
200
|
resized_width, resized_height = img.size
|
@@ -20,6 +20,7 @@ def get_raster_inference(
|
|
20
20
|
|
21
21
|
Returns:
|
22
22
|
raster prediction mask, prediction number
|
23
|
+
|
23
24
|
"""
|
24
25
|
np_img = np_array(img)
|
25
26
|
app_logger.info(f"img type {type(np_img)}, prompt:{prompt}.")
|
@@ -49,6 +50,7 @@ def get_inference_embedding(
|
|
49
50
|
|
50
51
|
Returns:
|
51
52
|
raster dict
|
53
|
+
|
52
54
|
"""
|
53
55
|
if embedding_key in embedding_dict:
|
54
56
|
app_logger.info("found embedding in dict...")
|
@@ -68,7 +70,8 @@ def get_inference_embedding(
|
|
68
70
|
|
69
71
|
|
70
72
|
def get_raster_inference_using_existing_embedding(
|
71
|
-
embedding: dict, prompt: ListDict, models_instance: SegmentAnythingONNX2
|
73
|
+
embedding: dict, prompt: ListDict, models_instance: SegmentAnythingONNX2, folder_write_tmp_on_disk: str = None,
|
74
|
+
key: str = None) -> TupleNdarrayInt:
|
72
75
|
"""
|
73
76
|
Get inference output for a given image using a SegmentAnythingONNX model, using an existing embedding instead of a
|
74
77
|
new ndarray or PIL image
|
@@ -77,9 +80,12 @@ def get_raster_inference_using_existing_embedding(
|
|
77
80
|
embedding: dict
|
78
81
|
prompt: list of prompt dict
|
79
82
|
models_instance: SegmentAnythingONNX instance model
|
83
|
+
folder_write_tmp_on_disk: output folder where to write debug images
|
84
|
+
key: embedding key
|
80
85
|
|
81
86
|
Returns:
|
82
87
|
raster prediction mask, prediction number
|
88
|
+
|
83
89
|
"""
|
84
90
|
app_logger.info(f"using existing embedding of type {type(embedding)}.")
|
85
91
|
inference_out = models_instance.predict_masks(embedding, prompt)
|
@@ -87,16 +93,27 @@ def get_raster_inference_using_existing_embedding(
|
|
87
93
|
app_logger.info(f"Created {len_inference_out} prediction_masks,"
|
88
94
|
f"shape:{inference_out.shape}, dtype:{inference_out.dtype}.")
|
89
95
|
mask = zeros((inference_out.shape[2], inference_out.shape[3]), dtype=uint8)
|
96
|
+
write_tmp_img = bool(folder_write_tmp_on_disk)
|
90
97
|
for n, m in enumerate(inference_out[0, :, :, :]):
|
91
98
|
app_logger.debug(f"{n}th of prediction_masks shape {inference_out.shape}"
|
92
99
|
f" => mask shape:{mask.shape}, {mask.dtype}.")
|
93
100
|
mask[m > 0.0] = 255
|
101
|
+
if write_tmp_img:
|
102
|
+
from pathlib import Path
|
103
|
+
from datetime import datetime
|
104
|
+
from samgis_core.utilities.utilities import convert_ndarray_to_pil, normalize_array
|
105
|
+
m_normalized = normalize_array(m, type_normalization="float")
|
106
|
+
m_out = convert_ndarray_to_pil(m_normalized)
|
107
|
+
now = datetime.now().isoformat()
|
108
|
+
if len(m.shape) == 2:
|
109
|
+
m_out = m_out.convert("L")
|
110
|
+
m_out.save(Path(folder_write_tmp_on_disk) / f"mask_{key}_{now}_n{n}.png")
|
94
111
|
return mask, len_inference_out
|
95
112
|
|
96
113
|
|
97
114
|
def get_raster_inference_with_embedding_from_dict(
|
98
115
|
img: PIL_Image | ndarray, prompt: ListDict, models_instance: SegmentAnythingONNX2, model_name: str,
|
99
|
-
embedding_key: str, embedding_dict: dict) -> TupleNdarrayInt:
|
116
|
+
embedding_key: str, embedding_dict: dict, folder_write_tmp_on_disk: str = None) -> TupleNdarrayInt:
|
100
117
|
"""
|
101
118
|
Get inference output using a SegmentAnythingONNX model, but get the image embedding from the given embedding dict
|
102
119
|
instead of creating a new embedding. This function needs the img argument to update the embedding dict if necessary
|
@@ -108,9 +125,11 @@ def get_raster_inference_with_embedding_from_dict(
|
|
108
125
|
model_name: model name string
|
109
126
|
embedding_key: embedding id
|
110
127
|
embedding_dict: embedding images dict
|
128
|
+
folder_write_tmp_on_disk: output folder where to write debug images
|
111
129
|
|
112
130
|
Returns:
|
113
131
|
raster prediction mask, prediction number
|
132
|
+
|
114
133
|
"""
|
115
134
|
app_logger.info(f"handling embedding using key {embedding_key}.")
|
116
135
|
embedding_dict = get_inference_embedding(img, models_instance, model_name, embedding_key, embedding_dict)
|
@@ -118,4 +137,5 @@ def get_raster_inference_with_embedding_from_dict(
|
|
118
137
|
embedding = embedding_dict[embedding_key]
|
119
138
|
n_keys = len(embedding_dict)
|
120
139
|
app_logger.info(f"embedding created ({n_keys} keys in embedding dict), running predict_masks with prompt {prompt}.")
|
121
|
-
return get_raster_inference_using_existing_embedding(
|
140
|
+
return get_raster_inference_using_existing_embedding(
|
141
|
+
embedding, prompt, models_instance, folder_write_tmp_on_disk=folder_write_tmp_on_disk, key=embedding_key)
|
{samgis_core-3.0.4 → samgis_core-3.0.6}/samgis_core/utilities/create_folders_if_not_exists.py
RENAMED
@@ -10,6 +10,14 @@ def stats_pathname(pathname: Path | str):
|
|
10
10
|
|
11
11
|
|
12
12
|
def create_folder_if_not_exists(pathname: Path | str):
|
13
|
+
"""Create a folder given its path.
|
14
|
+
|
15
|
+
Args:
|
16
|
+
pathname: folder Path or string
|
17
|
+
|
18
|
+
Returns:
|
19
|
+
|
20
|
+
"""
|
13
21
|
current_pathname = Path(pathname)
|
14
22
|
try:
|
15
23
|
print(f"Pathname exists? {current_pathname.exists()}, That's a folder? {current_pathname.is_dir()}...")
|
@@ -32,6 +40,18 @@ def create_folder_if_not_exists(pathname: Path | str):
|
|
32
40
|
|
33
41
|
|
34
42
|
def folders_creation(folders_map: dict | str = None, ignore_errors: bool = True):
|
43
|
+
"""Create all folders listed within the folders_map argument (this argument can be a dict or a json string).
|
44
|
+
If folders_map is None the function will try to load the 'FOLDERS_MAP' env variable, then will load that json into
|
45
|
+
dict. Once loaded and parsed the folders_map variable, the function will loop over the dict to create the folders
|
46
|
+
using the `create_folder_if_not_exists()` function.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
folders_map: dict or string map of folder string
|
50
|
+
ignore_errors: bool needed to eventually ignore errors on folder creation
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
|
54
|
+
"""
|
35
55
|
enforce_validation_with_getenv = folders_map is None
|
36
56
|
if enforce_validation_with_getenv:
|
37
57
|
folders_map = os.getenv("FOLDERS_MAP")
|
@@ -0,0 +1,99 @@
|
|
1
|
+
import structlog.stdlib
|
2
|
+
from numpy import ndarray
|
3
|
+
from matplotlib import pyplot as plt
|
4
|
+
|
5
|
+
from samgis_core.utilities.type_hints import ListStr, MatplotlibBackend
|
6
|
+
|
7
|
+
FigAxes = tuple[plt.Figure, plt.Axes]
|
8
|
+
|
9
|
+
|
10
|
+
logger = structlog.stdlib.get_logger(__file__)
|
11
|
+
|
12
|
+
|
13
|
+
def helper_imshow_output_expected(
|
14
|
+
img_list: list[ndarray], titles_list: ListStr, cmap: str = "gist_rainbow", plot_size: int = 5,
|
15
|
+
show=False, debug: bool = False, close_after: float = 0.0) -> FigAxes:
|
16
|
+
"""
|
17
|
+
Simple way to display a list of images with their titles, color map.
|
18
|
+
Should work also in an automate environments, like tests (use a `close_after` argument > 0)
|
19
|
+
|
20
|
+
Args:
|
21
|
+
img_list: ndarray images to display
|
22
|
+
titles_list: title images
|
23
|
+
cmap: color map
|
24
|
+
plot_size: figure plot size
|
25
|
+
show: fire plt.show() action if needed
|
26
|
+
debug: workaround useful in an interactive context, like Pycharm debugger
|
27
|
+
close_after: close after give seconds (useful in tests, contrasted to 'debug' option)
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
tuple of matplotlib Figure, Axes
|
31
|
+
|
32
|
+
"""
|
33
|
+
n = len(img_list)
|
34
|
+
assert len(titles_list) == n
|
35
|
+
fig, ax = plt.subplot_mosaic([
|
36
|
+
titles_list
|
37
|
+
], figsize=(n * plot_size, plot_size))
|
38
|
+
|
39
|
+
for title, img in zip(titles_list, img_list):
|
40
|
+
ax[title].imshow(img, cmap=cmap)
|
41
|
+
ax[title].legend()
|
42
|
+
if show:
|
43
|
+
if debug:
|
44
|
+
plt.pause(0.01)
|
45
|
+
plt.show()
|
46
|
+
if close_after > 0:
|
47
|
+
plt.pause(close_after)
|
48
|
+
plt.show(block=False)
|
49
|
+
plt.close("all")
|
50
|
+
return fig, ax
|
51
|
+
|
52
|
+
|
53
|
+
def imshow_raster(
|
54
|
+
raster, title, cmap: str = "gist_rainbow", interpolation: str = None, alpha=None, transform=None, plot_size=5,
|
55
|
+
show=False, debug: bool = False, close_after: float = 0.0, backend: MatplotlibBackend = None) -> FigAxes:
|
56
|
+
"""
|
57
|
+
Displays raster images lists/arrays with titles, legend, alpha transparency, figure sizes
|
58
|
+
and geographic transformations, if not none (leveraging rasterio.plot)
|
59
|
+
|
60
|
+
Args:
|
61
|
+
raster: image to display
|
62
|
+
title: title image
|
63
|
+
cmap: color map
|
64
|
+
interpolation: interpolation type
|
65
|
+
alpha: alpha transparency
|
66
|
+
transform: geographic transform, eventually used for map representation by rasterio
|
67
|
+
plot_size: figure plot size
|
68
|
+
show: fire plt.show() action if needed
|
69
|
+
debug: workaround useful in an interactive context, like Pycharm debugger
|
70
|
+
close_after: close after give seconds (useful in tests, contrasted to 'debug' option)
|
71
|
+
backend: matplotlib backend string
|
72
|
+
|
73
|
+
Returns:
|
74
|
+
tuple of matplotlib Figure, Axes
|
75
|
+
|
76
|
+
"""
|
77
|
+
from rasterio import plot
|
78
|
+
|
79
|
+
if not backend:
|
80
|
+
backend = plt.get_backend()
|
81
|
+
plt.rcParams["backend"] = backend
|
82
|
+
logger.info(f"use {backend} as matplotlib backend...")
|
83
|
+
|
84
|
+
fig, ax = plt.subplots(figsize=(plot_size, plot_size))
|
85
|
+
raster_ax = raster[0] if transform is not None else raster
|
86
|
+
image_hidden = ax.imshow(raster_ax, cmap=cmap, interpolation=interpolation, alpha=alpha)
|
87
|
+
if transform is not None:
|
88
|
+
plot.show(raster, transform=transform, ax=ax, cmap=cmap, interpolation=interpolation, alpha=alpha)
|
89
|
+
fig.colorbar(image_hidden, ax=ax)
|
90
|
+
ax.set_title(title)
|
91
|
+
if show:
|
92
|
+
if debug:
|
93
|
+
plt.pause(0.01)
|
94
|
+
plt.show()
|
95
|
+
if close_after > 0:
|
96
|
+
plt.pause(close_after)
|
97
|
+
plt.show(block=False)
|
98
|
+
plt.close("all")
|
99
|
+
return fig, ax
|
@@ -27,6 +27,20 @@ def drop_color_message_key(_, __, event_dict: EventDict) -> EventDict:
|
|
27
27
|
|
28
28
|
|
29
29
|
def setup_logging(json_logs: bool = False, log_level: str = "INFO"):
|
30
|
+
"""Enhance the configuration of structlog.
|
31
|
+
Needed for correlation id injection with fastapi middleware in samgis-web.
|
32
|
+
After the use of logging_middleware() in samgis_web.web.middlewares, add also the CorrelationIdMiddleware from
|
33
|
+
'asgi_correlation_id' package. (See 'tests/web/test_middlewares.py' in samgis_web).
|
34
|
+
To change an input parameter like the log level, re-run the function changing the parameter
|
35
|
+
(no need to re-instantiate the logger instance: it's a hot change)
|
36
|
+
|
37
|
+
Args:
|
38
|
+
json_logs: set logs in json format
|
39
|
+
log_level: log level string
|
40
|
+
|
41
|
+
Returns:
|
42
|
+
|
43
|
+
"""
|
30
44
|
timestamper = structlog.processors.TimeStamper(fmt="iso")
|
31
45
|
|
32
46
|
shared_processors: list[Processor] = [
|
@@ -67,5 +67,32 @@ class EmbeddingPILImage(TypedDict):
|
|
67
67
|
resized_size: TupleInt2
|
68
68
|
|
69
69
|
|
70
|
+
class MatplotlibBackend(StrEnum):
|
71
|
+
gtk3agg = "gtk3agg"
|
72
|
+
gtk3cairo = "gtk3cairo"
|
73
|
+
gtk4agg = "gtk4agg"
|
74
|
+
gtk4cairo = "gtk4cairo"
|
75
|
+
macosx = "macosx"
|
76
|
+
nbagg = "nbagg"
|
77
|
+
notebook = "notebook"
|
78
|
+
qtagg = "qtagg"
|
79
|
+
qtcairo = "qtcairo"
|
80
|
+
qt5agg = "qt5agg"
|
81
|
+
qt5cairo = "qt5cairo"
|
82
|
+
tkagg = "tkagg"
|
83
|
+
tkcairo = "tkcairo"
|
84
|
+
webagg = "webagg"
|
85
|
+
wx = "wx"
|
86
|
+
wxagg = "wxagg"
|
87
|
+
wxcairo = "wxcairo"
|
88
|
+
agg = "agg"
|
89
|
+
cairo = "cairo"
|
90
|
+
pdf = "pdf"
|
91
|
+
pgf = "pgf"
|
92
|
+
ps = "ps"
|
93
|
+
svg = "svg"
|
94
|
+
template = "template"
|
95
|
+
|
96
|
+
|
70
97
|
EmbeddingDict = dict[str, EmbeddingImage]
|
71
98
|
EmbeddingPILDict = dict[str, EmbeddingPILImage]
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""Various utilities (logger, time benchmark, args dump, numerical and stats info)"""
|
2
2
|
from copy import deepcopy
|
3
3
|
|
4
|
+
import numpy as np
|
4
5
|
from numpy import ndarray, float32
|
5
6
|
|
6
7
|
from samgis_core import app_logger
|
@@ -98,6 +99,16 @@ def hash_calculate(arr) -> str | bytes:
|
|
98
99
|
|
99
100
|
|
100
101
|
def convert_ndarray_to_pil(pil_image: PIL_Image | ndarray):
|
102
|
+
"""
|
103
|
+
Check if an image is a ndarray and then convert to a PIL Image instance.
|
104
|
+
|
105
|
+
Args:
|
106
|
+
pil_image: PIL image or ndarray
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
PIL Image
|
110
|
+
|
111
|
+
"""
|
101
112
|
from PIL import Image
|
102
113
|
|
103
114
|
if isinstance(pil_image, ndarray):
|
@@ -109,6 +120,14 @@ def apply_coords(coords: ndarray, embedding: EmbeddingPILImage):
|
|
109
120
|
"""
|
110
121
|
Expects a numpy np_array of length 2 in the final dimension. Requires the
|
111
122
|
original image size in (H, W) format.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
coords: coordinates ndarray
|
126
|
+
embedding: PIL image embedding dict
|
127
|
+
|
128
|
+
Returns:
|
129
|
+
coordinates ndarray
|
130
|
+
|
112
131
|
"""
|
113
132
|
orig_width, orig_height = embedding["original_size"]
|
114
133
|
resized_width, resized_height = embedding["resized_size"]
|
@@ -118,3 +137,12 @@ def apply_coords(coords: ndarray, embedding: EmbeddingPILImage):
|
|
118
137
|
coords[..., 1] = coords[..., 1] * (resized_height / orig_height)
|
119
138
|
|
120
139
|
return coords.astype(float32)
|
140
|
+
|
141
|
+
|
142
|
+
def normalize_array(arr: ndarray, new_h: int | float = 255., type_normalization: str = "int") -> ndarray:
|
143
|
+
arr = arr.astype(float)
|
144
|
+
arr_max = np.nanmax(arr)
|
145
|
+
arr_min = np.nanmin(arr)
|
146
|
+
scaled_arr = (arr - arr_min) / (arr_max - arr_min)
|
147
|
+
multiplied_arr = scaled_arr * new_h
|
148
|
+
return multiplied_arr.astype(int) if type_normalization == "int" else multiplied_arr
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|