Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/model_api/models/instance_segmentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,14 @@ def postprocess(self, outputs: dict, meta: dict) -> InstanceSegmentationResult:
saliency_maps = []

# Apply confidence threshold, bounding box area filter and label index filter.
keep = (scores > self.confidence_threshold) & ((boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) > 1)
# Calculate box areas safely to avoid overflow
box_widths = np.clip(boxes[:, 2] - boxes[:, 0], 0, None)
box_heights = np.clip(boxes[:, 3] - boxes[:, 1], 0, None)

# Use float64 for area calculation to prevent overflow, then check if area > 1
box_areas = box_widths.astype(np.float64) * box_heights.astype(np.float64)

keep = (scores > self.confidence_threshold) & (box_areas > 1)

if self.labels:
keep &= labels < len(self.labels)
Expand Down
3 changes: 3 additions & 0 deletions src/model_api/models/segmentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ def get_contours(
cv2.drawContours(mask, contours, contourIdx=next_child_idx, color=0, thickness=-1)
next_child_idx = hierarchy[next_child_idx][0]

if current_label_soft_prediction.dtype != np.float32:
current_label_soft_prediction = current_label_soft_prediction.astype(np.float32)

probability = cv2.mean(current_label_soft_prediction, mask)[0]
combined_contours.append(Contour(label, probability, contour, children))

Expand Down
8 changes: 6 additions & 2 deletions src/model_api/models/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ def add_rotated_rects(inst_seg_result: InstanceSegmentationResult) -> RotatedSeg
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE,
)
contour = np.vstack(contours)
objects_with_rects.append(cv2.minAreaRect(contour))
# Check if contours were found before processing
if contours:
contour = np.vstack(contours)
objects_with_rects.append(cv2.minAreaRect(contour))
else:
objects_with_rects.append(((0, 0), (0, 0), 0))
return RotatedSegmentationResult(
bboxes=inst_seg_result.bboxes,
masks=inst_seg_result.masks,
Expand Down
6 changes: 6 additions & 0 deletions tests/accuracy/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@

def pytest_addoption(parser):
parser.addoption("--data", action="store", help="data folder with dataset")
parser.addoption(
"--model_data",
action="store",
default="public_scope.json",
help="path to model data JSON file for test parameterization",
)
parser.addoption(
"--device",
action="store",
Expand Down
75 changes: 75 additions & 0 deletions tests/accuracy/download_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
import argparse
import asyncio
import json
import time
from pathlib import Path

import httpx


async def stream_file(client, url, filename, semaphore):
async with semaphore:
start_time = time.time()
total_bytes = 0
async with client.stream("GET", url) as stream:
with Path(filename).open("wb") as file:
async for data in stream.aiter_bytes():
file.write(data)
total_bytes += len(data)
end_time = time.time()
download_time = end_time - start_time
total_bytes /= 1024 * 1024

speed_mbps = total_bytes / download_time if download_time > 0 else 0
print(f"Downloaded {url} - {total_bytes:.2f} MB in {download_time:.2f}s ({speed_mbps:.2f} MB/s)")


async def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"-d",
"--data_dir",
type=Path,
required=True,
help="Directory to store downloaded models and datasets",
)
parser.add_argument(
"-j",
"--json_path",
type=Path,
required=True,
help="Path to the JSON file with model information",
)
args = parser.parse_args()

with args.json_path.open("r") as f:
models_data = json.load(f)

base_path = "https://storage.geti.intel.com/geti_predict/test/"
semaphore = asyncio.Semaphore(10)
args.data_dir.mkdir(parents=True, exist_ok=True)
async with httpx.AsyncClient(timeout=60.0) as client:
tasks = []
for model_entry in models_data:
model_name = model_entry["name"]
download_url = base_path + model_name
save_path = args.data_dir / model_name
save_path.parent.mkdir(parents=True, exist_ok=True)
tasks.append(stream_file(client, download_url, save_path, semaphore))

if model_name.endswith(".xml"):
tasks.append(
stream_file(client, download_url.replace(".xml", ".bin"), save_path.with_suffix(".bin"), semaphore),
)

print(f"Starting download of {len(tasks)} files with max 10 concurrent downloads...")
await asyncio.gather(*tasks)
print(f"All {len(tasks)} files downloaded successfully!")


if __name__ == "__main__":
asyncio.run(main())
Loading