From dae7da9a6aaa2c9b6c68f49da25e8010e2d60b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20P=C4=99czek?= Date: Thu, 14 Nov 2024 18:36:37 +0100 Subject: [PATCH 1/3] Fix issue with label visualization --- .../core_steps/visualizations/label/v1.py | 13 +++- .../test_workflow_with_label_visualization.py | 73 +++++++++++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 tests/workflows/integration_tests/execution/test_workflow_with_label_visualization.py diff --git a/inference/core/workflows/core_steps/visualizations/label/v1.py b/inference/core/workflows/core_steps/visualizations/label/v1.py index 9a8da25c1..0b623380a 100644 --- a/inference/core/workflows/core_steps/visualizations/label/v1.py +++ b/inference/core/workflows/core_steps/visualizations/label/v1.py @@ -1,4 +1,4 @@ -from typing import List, Literal, Optional, Type, Union +from typing import List, Literal, Optional, Type, TypeVar, Union import supervision as sv from pydantic import ConfigDict, Field @@ -20,6 +20,9 @@ ) from inference.core.workflows.prototypes.block import BlockResult, WorkflowBlockManifest +T = TypeVar("T") + + TYPE: str = "roboflow_core/label_visualization@v1" SHORT_DESCRIPTION = ( "Draws labels on an image at specific coordinates based on provided detections." @@ -206,7 +209,12 @@ def run( if text == "Class": labels = predictions["class_name"] elif text == "Tracker Id": - labels = [str(t) if t else "" for t in predictions.tracker_id] + if predictions.tracker_id is not None: + labels = [ + str(t) if t else "No Tracker ID" for t in predictions.tracker_id + ] + else: + labels = ["No Tracker ID"] * len(predictions) elif text == "Time In Zone": if "time_in_zone" in predictions.data: labels = [ @@ -241,7 +249,6 @@ def run( labels = [str(d) if d else "" for d in predictions[text]] except Exception: raise ValueError(f"Invalid text type: {text}") - annotated_image = annotator.annotate( scene=image.numpy_image.copy() if copy_image else image.numpy_image, detections=predictions, diff --git a/tests/workflows/integration_tests/execution/test_workflow_with_label_visualization.py b/tests/workflows/integration_tests/execution/test_workflow_with_label_visualization.py new file mode 100644 index 000000000..5584e962a --- /dev/null +++ b/tests/workflows/integration_tests/execution/test_workflow_with_label_visualization.py @@ -0,0 +1,73 @@ +import numpy as np + +from inference.core.env import WORKFLOWS_MAX_CONCURRENT_STEPS +from inference.core.managers.base import ModelManager +from inference.core.workflows.core_steps.common.entities import StepExecutionMode +from inference.core.workflows.execution_engine.core import ExecutionEngine + +VISUALIZATION_WORKFLOW = { + "version": "1.0", + "inputs": [ + {"type": "WorkflowImage", "name": "image"}, + { + "type": "WorkflowParameter", + "name": "model_id", + "default_value": "yolov8n-640", + }, + {"type": "WorkflowParameter", "name": "confidence", "default_value": 0.3}, + ], + "steps": [ + { + "type": "RoboflowObjectDetectionModel", + "name": "detection", + "image": "$inputs.image", + "model_id": "$inputs.model_id", + "confidence": "$inputs.confidence", + }, + { + "type": "roboflow_core/label_visualization@v1", + "name": "label_visualization", + "predictions": "$steps.detection.predictions", + "image": "$inputs.image", + "text": "Tracker Id", + }, + ], + "outputs": [ + {"type": "JsonField", "name": "result", "selector": "$steps.detection.*"}, + { + "type": "JsonField", + "name": "visualized", + "selector": "$steps.label_visualization.image", + }, + ], +} + + +def test_workflow_when_detections_are_not_present( + model_manager: ModelManager, + crowd_image: np.ndarray, +) -> None: + """This test covers bug in label annotator block.""" + # given + workflow_init_parameters = { + "workflows_core.model_manager": model_manager, + "workflows_core.api_key": None, + "workflows_core.step_execution_mode": StepExecutionMode.LOCAL, + } + execution_engine = ExecutionEngine.init( + workflow_definition=VISUALIZATION_WORKFLOW, + init_parameters=workflow_init_parameters, + max_concurrent_steps=WORKFLOWS_MAX_CONCURRENT_STEPS, + ) + + # when + result = execution_engine.run( + runtime_parameters={"image": crowd_image, "confidence": 0.99999} + ) + + # then + assert isinstance(result, list), "Expected result to be list" + assert len(result) == 1, "Single image provided - single output expected" + assert ( + len(result[0]["result"]["predictions"]) == 0 + ), "Expected no predictions to be delivered" From 137b5d512062fb5c400abbc43f753d77da50ca35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20P=C4=99czek?= Date: Thu, 14 Nov 2024 18:38:09 +0100 Subject: [PATCH 2/3] Remove unintended changes --- .../core/workflows/core_steps/visualizations/label/v1.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/inference/core/workflows/core_steps/visualizations/label/v1.py b/inference/core/workflows/core_steps/visualizations/label/v1.py index 0b623380a..b21d9a3ee 100644 --- a/inference/core/workflows/core_steps/visualizations/label/v1.py +++ b/inference/core/workflows/core_steps/visualizations/label/v1.py @@ -1,4 +1,4 @@ -from typing import List, Literal, Optional, Type, TypeVar, Union +from typing import List, Literal, Optional, Type, Union import supervision as sv from pydantic import ConfigDict, Field @@ -20,8 +20,6 @@ ) from inference.core.workflows.prototypes.block import BlockResult, WorkflowBlockManifest -T = TypeVar("T") - TYPE: str = "roboflow_core/label_visualization@v1" SHORT_DESCRIPTION = ( From 0de33d86eb1bb23a5cfd7de9c50bd387608a2cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20P=C4=99czek?= Date: Thu, 14 Nov 2024 18:43:41 +0100 Subject: [PATCH 3/3] Make linters happy --- inference/core/workflows/core_steps/visualizations/label/v1.py | 1 - 1 file changed, 1 deletion(-) diff --git a/inference/core/workflows/core_steps/visualizations/label/v1.py b/inference/core/workflows/core_steps/visualizations/label/v1.py index b21d9a3ee..dbff22d2f 100644 --- a/inference/core/workflows/core_steps/visualizations/label/v1.py +++ b/inference/core/workflows/core_steps/visualizations/label/v1.py @@ -20,7 +20,6 @@ ) from inference.core.workflows.prototypes.block import BlockResult, WorkflowBlockManifest - TYPE: str = "roboflow_core/label_visualization@v1" SHORT_DESCRIPTION = ( "Draws labels on an image at specific coordinates based on provided detections."