Unable to optimize customized/modified yolov11 with additional output layer

what I wan to implement is to allow yolov11 to predict object with oriented bounding box (x1, y1, x2, y2, angle), not just (x1, y1, x2, y2). The angle is additional.
So I change the yolo11n’s head structure (regression head), which conv’s output channel is +1.

But this model will fail during hailo optimize process.

the error log:

File "/home/jbl/PythonEnv/py310/lib/python3.10/site-packages/hailo_model_optimization/acceleras/hailo_layers/hailo_postprocess.py", line 121, in call_core
    return self.bbox_decoding_and_nms_call(
  File "/home/jbl/PythonEnv/py310/lib/python3.10/site-packages/hailo_model_optimization/acceleras/hailo_layers/hailo_postprocess.py", line 158, in bbox_decoding_and_nms_call
    decoded_bboxes, detection_score = self.yolov8_decoding_call(inputs, offsets=[0.5, 0.5])
  File "/home/jbl/PythonEnv/py310/lib/python3.10/site-packages/hailo_model_optimization/acceleras/hailo_layers/hailo_postprocess.py", line 376, in yolov8_decoding_call
    decoded_bboxes = tf.expand_dims(decoded_bboxes, axis=2)
ValueError: Exception encountered when calling HailoPostprocess.call().

Tried to convert 'input' to a tensor and failed. Error: None values not supported.

Arguments received by HailoPostprocess.call():
  • inputs=['tf.Tensor(shape=(1, 80, 80, 65), dtype=float32)', 'tf.Tensor(shape=(1, 80, 80, 11), dtype=float32)', 'tf.Tensor(shape=(1, 40, 40, 65), dtype=float32)', 'tf.Tensor(shape=(1, 40, 40, 11), dtype=float32)', 'tf.Tensor(shape=(1, 20, 20, 65), dtype=float32)', 'tf.Tensor(shape=(1, 20, 20, 11), dtype=float32)']
  • training=False
  • kwargs={'encoding_tensors': 'None', 'cache_config': 'None'}
Calibration:   0%|          | 0/20 [00:14<?, ?entries/s]         

This is my yolov11.onnx and calib_dataset.npy in google_drive: yolo11n_opt_xywhr

# parser
# based on DFC-3.32.0
runner = ClientRunner(hw_arch="hailo8l")
end_notes = ['/head/cv2.0/cv2.0.2/Conv', '/head/cv3.0/cv3.0.4/Conv',
            '/head/cv2.1/cv2.1.2/Conv', '/head/cv3.1/cv3.1.4/Conv',
            '/head/cv2.2/cv2.2.2/Conv', '/head/cv3.2/cv3.2.4/Conv']

onnx_path = "./my_yolo11n_opt_regression_add_1.onnx"
har_path = "./parsered.fp32.har"
hn, npz = runner.translate_onnx_model(
    onnx_path, "yolo11_xywhr",
    start_node_names=['input'],
    end_node_names=end_notes,
    # net_input_shapes={'input': [1, 3, 640, 640]}
)
runner.save_har(har_path)

# optimize
alls = [
    "quantization_param([conv54, conv65, conv80], force_range_out=[0.0, 1.0])\n",
    "normalization1 = normalization([0.0, 0.0, 0.0], [255.0, 255.0, 255.0])\n",
    "change_output_activation(conv54, sigmoid)\n",
    "change_output_activation(conv65, sigmoid)\n",
    "change_output_activation(conv80, sigmoid)\n",
    "nms_postprocess('./my_yolo11n_nms_config.json', meta_arch=yolov8, engine=cpu)\n",
    "allocator_param(width_splitter_defuse=disabled)\n"
]

calib_npy = "./calib_ds.int8.npy"
runner = ClientRunner(har=har_path)
runner.load_model_script("".join(alls))
runner.optimize(calib_npy)
runner.save_har(out_opt_file)
  • the parsered network (one of the head of custom yolo11n):

Could you hailo R&D team guide me how to fix this error?

This issue may be the same with Unable to optimize custom yolov7 with additional output layer - General - Hailo Community

If yolov8_nms_postprocess in hailo_model_optimization library can not be used in this scenerio, is it possible to customize a new custom_nms_postprocess? And allow the final exported hef model to run in the libhailort?

Hi @Kevin_Chen

Welcome to the Hailo community. At DeGirum (a SW partner of Hailo), we developed a cloud compiler to help users with compiling pytorch checkpoints to hef files. Our PySDK supports postprocessing for OBB models as well. You can see details at: Early Access to DeGirum Cloud Compiler

Hi @Kevin_Chen,

To further clarify, the DeGirum cloud compiler supports the official implementation of OBB by ultralytics. Is there a reason you are not using the ultralytics implementation of OBB?

But yes, the error seems to be because the postprocessing cannot handle the angle regression. If you remove the nms_postprocessing alls line, it should compile fine, and you would have to manually perform postprocessing.

Hi @lawrence . Thank you for your support.
Yes, I remove the nms_postprocss while compiling to hef file (yolo11_opt_no_nms.hef). Then use the yolo11_opt_no_nms.hef to do inference with hailort, and found the output of all convs in six branchs are UINT8 format.
How can I leverage these UINT8 output data to implement my custom nms_postprocess? Is it need to convert thest UINT8 to float32 firstly?

$ hailortcli parse-hef model.hef
Architecture HEF was compiled for: HAILO8L
Network group name: net_640_cspn, Multi Context - Number of contexts: 5
    Network name: net_640_cspn/net_640_cspn
        VStream infos:
            Input  net_640_cspn/input_layer1 UINT8, NHWC(640x640x3)
            Output net_640_cspn/conv51 UINT8, FCR(80x80x65)
            Output net_640_cspn/conv54 UINT8, FCR(80x80x11)
            Output net_640_cspn/conv62 UINT8, FCR(40x40x65)
            Output net_640_cspn/conv65 UINT8, FCR(40x40x11)
            Output net_640_cspn/conv77 UINT8, FCR(20x20x65)
            Output net_640_cspn/conv80 UINT8, FCR(20x20x11)

If you have any guidance doc, that wiil be great.

Hi @lawrence
btw, I’m curious that the fuction of nms_postprocess when hailo optimize.
The yolov8_nms_postprocess when predicting with libhailort is to achieve hailo8/8l hardware accelerated. Right?

You must dequantize the tensors first.

nms_postprocess only works on detection models, not pose models. Even so, for detection models they are not run on the accelerator for yolov8 flavor models (i.e. yolo11).

@lawrence
thanks a lot. Let me try it.

@lawrence a question here the qp_scale and qp_zp it is embedded in the hailo .hef file right?