Failure to deploy first custom model: DeGirum exceptions in postprocessing, tensor shape condition not met

Hi @DAlexSanc
Thanks for reaching out. We are happy to assist you in this process.
It looks like the issue may be related to the compilation of the Hailo HEF file. Specifically, if NMS is included in the HEF compilation and handled by the Hailo8/8L chip, then DetectionYoloV8 should not be used. Instead, a Python postprocessor should be implemented.
Here is the code for HailoDetectionYolo.py


import json


# Post-processor class, must have fixed name 'PostProcessor'
class PostProcessor:
    def __init__(self, json_config):
        """
        Initialize the post-processor with configuration settings.

        Parameters:
            json_config (str): JSON string containing post-processing configuration.
        """
        # Parse the JSON configuration
        self._json_config = json.loads(json_config)

        # Extract configuration parameters
        self._num_classes = int(
            self._json_config["POST_PROCESS"][0]["OutputNumClasses"]
        )
        self._label_json_path = self._json_config["POST_PROCESS"][0]["LabelsPath"]
        self._input_height = int(self._json_config["PRE_PROCESS"][0]["InputH"])
        self._input_width = int(self._json_config["PRE_PROCESS"][0]["InputW"])

        # Load label dictionary from JSON file
        with open(self._label_json_path, "r") as json_file:
            self._label_dictionary = json.load(json_file)

        # Extract confidence threshold
        self._output_conf_threshold = float(
            self._json_config["POST_PROCESS"][0].get("OutputConfThreshold", 0.0)
        )

    def forward(self, tensor_list, details_list):
        """
        Process the raw output tensor to produce formatted JSON results.

        Parameters:
            tensor_list (list): List of tensors from the model.
            details_list (list): Additional details (unused in this example).

        Returns:
            str: JSON-formatted string containing detection results.
        """
        # Initialize results list
        new_inference_results = []

        # Extract and reshape the raw output tensor
        output_array = tensor_list[0].reshape(-1)

        # Index to parse the array
        index = 0

        # Iterate over classes and parse results
        for class_id in range(self._num_classes):
            # Number of detections for this class
            num_detections = int(output_array[index])
            index += 1  # Move to the next entry

            # Skip if no detections for this class
            if num_detections == 0:
                continue

            # Process each detection for this class
            for _ in range(num_detections):
                if index + 5 > len(output_array):
                    # Safeguard against unexpected array end
                    break

                # Extract score and bounding box in x_center, y_center, width, height format
                score = float(output_array[index + 4])
                y_min, x_min, y_max, x_max = map(float, output_array[index : index + 4])
                index += 5  # Move to the next detection

                # Skip detections below the confidence threshold
                if score < self._output_conf_threshold:
                    continue

                # Convert to x_min, y_min, x_max, y_max format
                x_min = x_min * self._input_width
                y_min = y_min * self._input_height
                x_max = x_max * self._input_width
                y_max = y_max * self._input_height

                # Format the detection result
                result = {
                    "bbox": [x_min, y_min, x_max, y_max], 
                    "score": score,
                    "category_id": class_id,
                    "label": self._label_dictionary.get(
                        str(class_id), f"class_{class_id}"
                    ),
                }
                new_inference_results.append(result)

            # Stop processing if padded zeros are reached
            if index >= len(output_array) or all(v == 0 for v in output_array[index:]):
                break

        # Return results as JSON string
        return json.dumps(new_inference_results)

You need to create a python file “HailoDetectionYolo.py” and put this file in the the same folder as hef and JSON.
The new JSON will look like this

{
  "ConfigVersion": 10,
  "DEVICE": [
    {
      "DeviceType": "HAILO8L",
      "RuntimeAgent": "HAILORT",
      "SupportedDeviceTypes": "HAILORT/HAILO8L"
    }
  ],
  "PRE_PROCESS": [
    {
      "InputType": "Image",
      "ImageBackend": "opencv",
      "InputPadMethod": "letterbox",
      "InputResizeMethod": "bilinear",
      "InputN": 1,
      "InputH": 640,
      "InputW": 640,
      "InputC": 3,
      "InputQuantEn": true
    }
  ],
  "MODEL_PARAMETERS": [
    {
      "ModelPath": "custom.hef"
    }
  ],
  "POST_PROCESS": [
    {
      "OutputPostprocessType": "DetectionYoloV8",
      "PythonFile": "HailoDetectionYolo.py",
      "OutputNumClasses": 1,
      "LabelsPath": "labels.json"
    }
  ]
}

Additionally, we are in the process of releasing a web-based cloud compiler tool. This tool will support the compilation of various runtimes, including Hailo, directly into the DeGirum model zoo.

Let me know if this helped.