Skip to content
Draft
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
2 changes: 1 addition & 1 deletion model_api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ classifiers = [
]
dependencies = [
"numpy>=1.16.6",
"opencv-python-headless~=4.0",
"opencv-python-headless",
"openvino>=2025.3",
"pillow",
]
Expand Down
4 changes: 2 additions & 2 deletions model_api/src/model_api/models/result/segmentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ def hist(self) -> dict[str, float]:
ranges=[0, 255],
)
hist = {}
for i, count in enumerate(outHist):
for i, count in enumerate(outHist.flatten()):
if count > 0:
hist[str(i)] = count[0].item() / self.resultImage.size
hist[str(i)] = count.item() / self.resultImage.size

return hist

Expand Down
72 changes: 72 additions & 0 deletions model_api/tests/unit/results/test_sseg_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,80 @@
# SPDX-License-Identifier: Apache-2.0
#

from unittest.mock import patch

import numpy as np
import pytest
from model_api.models.result import Contour
from model_api.models.result.segmentation import ImageResultWithSoftPrediction


class TestImageResultWithSoftPredictionHist:
"""Tests for hist() method supporting OpenCV 4 and 5 return types."""

@pytest.fixture
def result_image(self):
"""Create a simple test image with known pixel distribution."""
# 10x10 image: 50 pixels of value 0, 30 pixels of value 128, 20 pixels of value 255
img = np.zeros((10, 10), dtype=np.uint8)
img[0:5, :] = 0 # 50 pixels
img[5:8, :] = 128 # 30 pixels
img[8:10, :] = 255 # 20 pixels
return img

@pytest.fixture
def image_result(self, result_image):
"""Create ImageResultWithSoftPrediction instance."""
return ImageResultWithSoftPrediction(
resultImage=result_image,
soft_prediction=np.zeros((10, 10, 3)),
saliency_map=np.zeros((10, 10)),
feature_vector=np.zeros((256,)),
)

def test_hist_with_opencv4_column_vector(self, image_result):
"""OpenCV 4 returns column vector [N, 1] from calcHist."""
# Simulate OpenCV 4 output: column vector shape [256, 1]
opencv4_hist = np.zeros((256, 1), dtype=np.float32)
opencv4_hist[0, 0] = 50.0 # 50 pixels of value 0
opencv4_hist[128, 0] = 30.0 # 30 pixels of value 128
opencv4_hist[255, 0] = 20.0 # 20 pixels of value 255

with patch("cv2.calcHist", return_value=opencv4_hist):
hist = image_result.hist()

assert hist == {"0": 0.5, "128": 0.3, "255": 0.2}

def test_hist_with_opencv5_1d_array(self, image_result):
"""OpenCV 5+ returns 1D array [N] from calcHist."""
# Simulate OpenCV 5 output: 1D array shape [256]
opencv5_hist = np.zeros((256,), dtype=np.float32)
opencv5_hist[0] = 50.0 # 50 pixels of value 0
opencv5_hist[128] = 30.0 # 30 pixels of value 128
opencv5_hist[255] = 20.0 # 20 pixels of value 255

with patch("cv2.calcHist", return_value=opencv5_hist):
hist = image_result.hist()

assert hist == {"0": 0.5, "128": 0.3, "255": 0.2}

def test_hist_both_formats_produce_same_result(self, image_result):
"""Both OpenCV formats produce identical histogram output."""
opencv4_hist = np.zeros((256, 1), dtype=np.float32)
opencv4_hist[10, 0] = 25.0
opencv4_hist[20, 0] = 75.0

opencv5_hist = np.zeros((256,), dtype=np.float32)
opencv5_hist[10] = 25.0
opencv5_hist[20] = 75.0

with patch("cv2.calcHist", return_value=opencv4_hist):
hist_v4 = image_result.hist()

with patch("cv2.calcHist", return_value=opencv5_hist):
hist_v5 = image_result.hist()

assert hist_v4 == hist_v5


def test_contour_type():
Expand Down
2 changes: 1 addition & 1 deletion model_api/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion model_converter/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading