Skip to content

Commit 96f01e1

Browse files
committed
Cover utils
1 parent 4a52a1c commit 96f01e1

File tree

4 files changed

+67
-58
lines changed

4 files changed

+67
-58
lines changed

model_api/python/model_api/adapters/openvino_adapter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ def embed_preprocessing(
380380
ppp.input(input_idx).tensor().set_shape(input_shape)
381381
ppp.input(input_idx).preprocess().custom(
382382
RESIZE_MODE_MAP[resize_mode](
383-
target_shape,
383+
(target_shape[0], target_shape[1]),
384384
INTERPOLATION_MODE_MAP[interpolation_mode],
385385
pad_value,
386386
),

model_api/python/model_api/adapters/utils.py

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77

88
import math
99
from functools import partial
10-
from typing import TYPE_CHECKING
10+
from typing import TYPE_CHECKING, Any
1111

1212
import cv2
1313
import numpy as np
1414
from openvino import Model, OVAny, Type, layout_helpers
15-
from openvino.runtime import Output
15+
from openvino.runtime import Input, Node, Output
1616
from openvino.runtime import opset10 as opset
1717
from openvino.runtime.utils.decorators import custom_preprocess_function
1818

@@ -21,11 +21,11 @@
2121

2222

2323
class Layout:
24-
def __init__(self, layout="") -> None:
24+
def __init__(self, layout: str = "") -> None:
2525
self.layout = layout
2626

2727
@staticmethod
28-
def from_shape(shape):
28+
def from_shape(shape: list[int] | tuple[int, ...]) -> str:
2929
"""Create Layout from given shape"""
3030
if len(shape) == 2:
3131
return "NC"
@@ -40,7 +40,7 @@ def from_shape(shape):
4040
raise RuntimeError(msg)
4141

4242
@staticmethod
43-
def from_openvino(input):
43+
def from_openvino(input: Input):
4444
"""Create Layout from openvino input"""
4545
return layout_helpers.get_layout(input).to_string().strip("[]").replace(",", "")
4646

@@ -75,7 +75,7 @@ def parse_layouts(layout_string: str) -> dict | None:
7575
return user_layouts
7676

7777

78-
def resize_image_letterbox_graph(input: Output, size, interpolation, pad_value):
78+
def resize_image_letterbox_graph(input: Output, size: tuple[int, int], interpolation: str, pad_value: int) -> Node:
7979
if not isinstance(pad_value, int):
8080
msg = "pad_value must be int"
8181
raise RuntimeError(msg)
@@ -157,7 +157,7 @@ def resize_image_letterbox_graph(input: Output, size, interpolation, pad_value):
157157
)
158158

159159

160-
def crop_resize_graph(input: Output, size):
160+
def crop_resize_graph(input: Output, size: tuple[int, int]) -> Node:
161161
h_axis = 1
162162
w_axis = 2
163163
desired_aspect_ratio = size[1] / size[0] # width / height
@@ -288,11 +288,11 @@ def crop_resize_graph(input: Output, size):
288288

289289
def resize_image_graph(
290290
input: Output,
291-
size,
292-
keep_aspect_ratio,
293-
interpolation,
294-
pad_value,
295-
):
291+
size: tuple[int, int],
292+
keep_aspect_ratio: bool,
293+
interpolation: str,
294+
pad_value: int,
295+
) -> Node:
296296
if not isinstance(pad_value, int):
297297
msg = "pad_value must be int"
298298
raise RuntimeError(msg)
@@ -365,7 +365,7 @@ def resize_image_graph(
365365
)
366366

367367

368-
def resize_image(size, interpolation, pad_value):
368+
def resize_image(size: tuple[int, int], interpolation: str, pad_value: int) -> Callable:
369369
return custom_preprocess_function(
370370
partial(
371371
resize_image_graph,
@@ -377,7 +377,7 @@ def resize_image(size, interpolation, pad_value):
377377
)
378378

379379

380-
def resize_image_with_aspect(size, interpolation, pad_value):
380+
def resize_image_with_aspect(size: tuple[int, int], interpolation: str, pad_value: int) -> Callable:
381381
return custom_preprocess_function(
382382
partial(
383383
resize_image_graph,
@@ -389,11 +389,11 @@ def resize_image_with_aspect(size, interpolation, pad_value):
389389
)
390390

391391

392-
def crop_resize(size, interpolation, pad_value):
392+
def crop_resize(size: tuple[int, int], interpolation: str, pad_value: int) -> Callable:
393393
return custom_preprocess_function(partial(crop_resize_graph, size=size))
394394

395395

396-
def resize_image_letterbox(size, interpolation, pad_value):
396+
def resize_image_letterbox(size: tuple[int, int], interpolation: str, pad_value: int) -> Callable:
397397
return custom_preprocess_function(
398398
partial(
399399
resize_image_letterbox_graph,
@@ -404,8 +404,8 @@ def resize_image_letterbox(size, interpolation, pad_value):
404404
)
405405

406406

407-
def load_parameters_from_onnx(onnx_model):
408-
parameters = {}
407+
def load_parameters_from_onnx(onnx_model: Any) -> dict[str, Any]:
408+
parameters: dict[str, Any] = {}
409409

410410
def insert_hierarchical(keys, val, root_dict):
411411
if len(keys) == 1:
@@ -423,7 +423,7 @@ def insert_hierarchical(keys, val, root_dict):
423423
return parameters
424424

425425

426-
def get_rt_info_from_dict(rt_info_dict, path):
426+
def get_rt_info_from_dict(rt_info_dict: dict[str, Any], path: list[str]) -> OVAny:
427427
value = rt_info_dict
428428
try:
429429
value = rt_info_dict
@@ -436,13 +436,13 @@ def get_rt_info_from_dict(rt_info_dict, path):
436436

437437

438438
def resize_image_ocv(
439-
image,
440-
size,
441-
keep_aspect_ratio=False,
442-
is_pad=False,
443-
pad_value=0,
444-
interpolation=cv2.INTER_LINEAR,
445-
):
439+
image: np.ndarray,
440+
size: tuple[int, int],
441+
keep_aspect_ratio: bool = False,
442+
is_pad: bool = False,
443+
pad_value: int = 0,
444+
interpolation: int = cv2.INTER_LINEAR,
445+
) -> np.ndarray:
446446
if keep_aspect_ratio:
447447
h, w = image.shape[:2]
448448
scale = min(size[1] / h, size[0] / w)
@@ -460,7 +460,11 @@ def resize_image_ocv(
460460
return cv2.resize(image, size, interpolation=interpolation)
461461

462462

463-
def resize_image_with_aspect_ocv(image, size, interpolation=cv2.INTER_LINEAR):
463+
def resize_image_with_aspect_ocv(
464+
image: np.ndarray,
465+
size: tuple[int, int],
466+
interpolation: int = cv2.INTER_LINEAR,
467+
) -> np.ndarray:
464468
return resize_image_ocv(
465469
image,
466470
size,
@@ -472,11 +476,11 @@ def resize_image_with_aspect_ocv(image, size, interpolation=cv2.INTER_LINEAR):
472476

473477

474478
def resize_image_letterbox_ocv(
475-
image,
476-
size,
477-
interpolation=cv2.INTER_LINEAR,
478-
pad_value=0,
479-
):
479+
image: np.ndarray,
480+
size: tuple[int, int],
481+
interpolation: int = cv2.INTER_LINEAR,
482+
pad_value: int = 0,
483+
) -> np.ndarray:
480484
ih, iw = image.shape[0:2]
481485
w, h = size
482486
scale = min(w / iw, h / ih)
@@ -493,7 +497,7 @@ def resize_image_letterbox_ocv(
493497
)
494498

495499

496-
def crop_resize_ocv(image, size):
500+
def crop_resize_ocv(image: np.ndarray, size: tuple[int, int]) -> np.ndarray:
497501
desired_aspect_ratio = size[1] / size[0] # width / height
498502
if desired_aspect_ratio == 1:
499503
if image.shape[0] > image.shape[1]:
@@ -522,7 +526,7 @@ def crop_resize_ocv(image, size):
522526
}
523527

524528

525-
INTERPOLATION_TYPES = {
529+
INTERPOLATION_TYPES: dict[str, int] = {
526530
"LINEAR": cv2.INTER_LINEAR,
527531
"CUBIC": cv2.INTER_CUBIC,
528532
"NEAREST": cv2.INTER_NEAREST,
@@ -533,9 +537,9 @@ def crop_resize_ocv(image, size):
533537
class InputTransform:
534538
def __init__(
535539
self,
536-
reverse_input_channels=False,
537-
mean_values=None,
538-
scale_values=None,
540+
reverse_input_channels: bool = False,
541+
mean_values: list[float] | None = None,
542+
scale_values: list[float] | None = None,
539543
):
540544
self.reverse_input_channels = reverse_input_channels
541545
self.is_trivial = not (reverse_input_channels or mean_values or scale_values)

model_api/python/model_api/models/classification.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from model_api.models.image_model import ImageModel
2020
from model_api.models.result_types import ClassificationResult
2121
from model_api.models.types import BooleanValue, ListValue, NumericalValue, StringValue
22+
from model_api.models.utils import softmax
2223

2324
if TYPE_CHECKING:
2425
from model_api.adapters.inference_adapter import InferenceAdapter
@@ -232,7 +233,7 @@ def get_all_probs(self, logits: np.ndarray) -> np.ndarray:
232233
cls_heads_info = self.hierarchical_info["cls_heads_info"]
233234
for i in range(cls_heads_info["num_multiclass_heads"]):
234235
logits_begin, logits_end = cls_heads_info["head_idx_to_logits_range"][str(i)]
235-
probs[logits_begin:logits_end] = softmax_numpy(
236+
probs[logits_begin:logits_end] = softmax(
236237
logits[logits_begin:logits_end],
237238
)
238239

@@ -242,7 +243,7 @@ def get_all_probs(self, logits: np.ndarray) -> np.ndarray:
242243
elif self.embedded_topk:
243244
probs = logits.reshape(-1)
244245
else:
245-
probs = softmax_numpy(logits.reshape(-1))
246+
probs = softmax(logits.reshape(-1))
246247
return probs
247248

248249
def get_hierarchical_predictions(self, logits: np.ndarray):
@@ -252,7 +253,7 @@ def get_hierarchical_predictions(self, logits: np.ndarray):
252253
for i in range(cls_heads_info["num_multiclass_heads"]):
253254
logits_begin, logits_end = cls_heads_info["head_idx_to_logits_range"][str(i)]
254255
head_logits = logits[logits_begin:logits_end]
255-
head_logits = softmax_numpy(head_logits)
256+
head_logits = softmax(head_logits)
256257
j = np.argmax(head_logits)
257258
label_str = cls_heads_info["all_groups"][i][j]
258259
predicted_labels.append(label_str)
@@ -290,7 +291,7 @@ def get_multiclass_predictions(self, outputs: dict) -> list[tuple[int, str, floa
290291
scoresTensor = outputs[self.out_layer_names[1]][0]
291292
labels = [self.labels[i] if self.labels else "" for i in indicesTensor]
292293
else:
293-
scoresTensor = softmax_numpy(outputs[self.out_layer_names[0]][0])
294+
scoresTensor = softmax(outputs[self.out_layer_names[0]][0])
294295
indicesTensor = [np.argmax(scoresTensor)]
295296
labels = [self.labels[i] if self.labels else "" for i in indicesTensor]
296297
return list(zip(indicesTensor, labels, scoresTensor))
@@ -352,11 +353,6 @@ def sigmoid_numpy(x: np.ndarray) -> np.ndarray:
352353
return 1.0 / (1.0 + np.exp(-x))
353354

354355

355-
def softmax_numpy(x: np.ndarray, eps: float = 1e-9) -> np.ndarray:
356-
x = np.exp(x - np.max(x))
357-
return x / (np.sum(x) + eps)
358-
359-
360356
class GreedyLabelsResolver:
361357
def __init__(self, hierarchical_config: dict) -> None:
362358
self.label_to_idx = hierarchical_config["cls_heads_info"]["label_to_idx"]

model_api/python/model_api/models/utils.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
import cv2
1111
import numpy as np
1212

13-
from model_api.models.result_types import Contour, SegmentedObject, SegmentedObjectWithRects
13+
from model_api.models.result_types import Contour, Detection, SegmentedObject, SegmentedObjectWithRects
1414

1515

16-
def add_rotated_rects(segmented_objects):
16+
def add_rotated_rects(segmented_objects: list[SegmentedObject]) -> list[SegmentedObjectWithRects]:
1717
objects_with_rects = []
1818
for segmented_object in segmented_objects:
1919
mask = segmented_object.mask.astype(np.uint8)
@@ -32,7 +32,7 @@ def add_rotated_rects(segmented_objects):
3232

3333
def get_contours(
3434
segmentedObjects: list[SegmentedObject | SegmentedObjectWithRects],
35-
):
35+
) -> list[Contour]:
3636
combined_contours = []
3737
for obj in segmentedObjects:
3838
contours, _ = cv2.findContours(
@@ -49,7 +49,7 @@ def get_contours(
4949
return combined_contours
5050

5151

52-
def clip_detections(detections, size):
52+
def clip_detections(detections: list[Detection], size: tuple[int, int]) -> list[Detection]:
5353
for detection in detections:
5454
detection.xmin = min(max(round(detection.xmin), 0), size[1])
5555
detection.ymin = min(max(round(detection.ymin), 0), size[0])
@@ -94,7 +94,16 @@ def load_labels(label_file):
9494
return [x.strip() for x in f]
9595

9696

97-
def nms(x1, y1, x2, y2, scores, thresh, include_boundaries=False, keep_top_k=0):
97+
def nms(
98+
x1: np.ndarray,
99+
y1: np.ndarray,
100+
x2: np.ndarray,
101+
y2: np.ndarray,
102+
scores: np.ndarray,
103+
thresh: float,
104+
include_boundaries: bool = False,
105+
keep_top_k: int = 0,
106+
) -> list[int]:
98107
b = 1 if include_boundaries else 0
99108
areas = (x2 - x1 + b) * (y2 - y1 + b)
100109
order = scores.argsort()[::-1]
@@ -130,9 +139,9 @@ def nms(x1, y1, x2, y2, scores, thresh, include_boundaries=False, keep_top_k=0):
130139

131140

132141
def multiclass_nms(
133-
detections,
134-
iou_threshold=0.45,
135-
max_num=200,
142+
detections: np.ndarray,
143+
iou_threshold: float = 0.45,
144+
max_num: int = 200,
136145
):
137146
"""Multi-class NMS.
138147
@@ -158,14 +167,14 @@ def multiclass_nms(
158167
offsets = labels.astype(boxes.dtype) * (max_coordinate + 1)
159168
boxes_for_nms = boxes + offsets[:, None]
160169

161-
keep = nms(*boxes_for_nms.T, scores, iou_threshold)
170+
keep = nms(*boxes_for_nms.T, scores=scores, thresh=iou_threshold)
162171
if max_num > 0:
163172
keep = keep[:max_num]
164173
keep = np.array(keep)
165174
det = detections[keep]
166175
return det, keep
167176

168177

169-
def softmax(logits, axis=None, keepdims=False):
178+
def softmax(logits: np.ndarray, eps: float = 1e-9, axis=None, keepdims: bool = False) -> np.ndarray:
170179
exp = np.exp(logits - np.max(logits))
171-
return exp / np.sum(exp, axis=axis, keepdims=keepdims)
180+
return exp / (np.sum(exp, axis=axis, keepdims=keepdims) + eps)

0 commit comments

Comments
 (0)