I used only 64 calibration images for this first test, using EO/drone images just to verify the HEF generation flow.
The model was parsed by cutting the YOLO head before the ONNX DFL/postprocess section.
The final parser end nodes used were:
/model.23/cv2.0/cv2.0.2/Conv
/model.23/cv3.0/cv3.0.2/Conv
/model.23/cv2.1/cv2.1.2/Conv
/model.23/cv3.1/cv3.1.2/Conv
/model.23/cv2.2/cv2.2.2/Conv
/model.23/cv3.2/cv3.2.2/Conv
The HEF was successfully generated.
parse-hef result
Architecture HEF was compiled for: HAILO8
Network group name: fire_smoke_yolo11n, Multi Context - Number of contexts: 3
Network name: fire_smoke_yolo11n/fire_smoke_yolo11n
VStream infos:
Input fire_smoke_yolo11n/input_layer1 UINT8, NHWC(640x640x3)
Output fire_smoke_yolo11n/conv51 UINT8, FCR(80x80x64)
Output fire_smoke_yolo11n/conv54 UINT8, NHWC(80x80x2)
Output fire_smoke_yolo11n/conv62 UINT8, FCR(40x40x64)
Output fire_smoke_yolo11n/conv65 UINT8, NHWC(40x40x2)
Output fire_smoke_yolo11n/conv77 UINT8, FCR(20x20x64)
Output fire_smoke_yolo11n/conv80 UINT8, FCR(20x20x2)
So I interpret this as 3 YOLO heads:
80x80: bbox conv51, cls conv54
40x40: bbox conv62, cls conv65
20x20: bbox conv77, cls conv80
The model appears to have 2 classes.
Runtime behavior
At runtime, the model initializes correctly:
[Hailo] initialized input=fire_smoke_yolo11n/input_layer1 size=640x640 frame_size=1228800 outputs=6 classes=2
Inference speed is good, around 20~32 FPS.
However, the detections are clearly wrong. I get many boxes all over the frame, many with confidence displayed as 100%.
Example postprocess log:
[Hailo][RawYOLO] heads=3/3 selected={
80x80 box=fire_smoke_yolo11n/conv51 cls=fire_smoke_yolo11n/conv54;
40x40 box=fire_smoke_yolo11n/conv62 cls=fire_smoke_yolo11n/conv65;
20x20 box=fire_smoke_yolo11n/conv77 cls=fire_smoke_yolo11n/conv80
}
threshold=0.1
iou=0.45
scanned_cells=8400
above_threshold=1618
score_min=0
score_mean=0.171588
score_max=1
pre_nms=1617
post_nms=435
returned=100
Another frame:
above_threshold=1657
pre_nms=1652
post_nms=453
returned=100
This seems abnormal. For a YOLO model, I would not expect 1600+ cells out of 8400 to pass the confidence threshold, nor hundreds of boxes after NMS.
Tensor dump examples
For the 80x80 cls output:
cls name=fire_smoke_yolo11n/conv54
shape=80x80x2
order=NHWC
bytes=51200
floats=12800
min=-236.969
mean=-14.2728
max=43.9412
cls cell=(40,40) first_channels_NHWC=4.70799,15.6933
For 40x40 cls:
cls name=fire_smoke_yolo11n/conv65
shape=40x40x2
order=NHWC
bytes=12800
floats=3200
min=-260.11
mean=-28.5579
max=35.5706
For 20x20 cls:
cls name=fire_smoke_yolo11n/conv80
shape=20x20x2
order=FCR
bytes=3200
floats=800
min=-161.55
mean=-33.9575
max=-3.01962
The high positive class logits become almost exactly 1.0 after sigmoid, so the UI displays them as 100%.
Current raw YOLO postprocess assumption
I currently decode the raw outputs manually:
-
Pair bbox/cls heads by same grid size.
-
bbox output has 64 channels, so I assume DFL bins = 16.
-
cls output has 1 or 2 channels depending on model.
-
For each grid cell:
-
apply sigmoid/logistic to cls logits
-
choose best class
-
decode DFL left/top/right/bottom
-
generate bbox
-
-
Apply OpenCV NMS.
This worked enough to run, but the output quality is wrong.
Important question
Is this the correct way to interpret these Hailo raw YOLO outputs?
In particular:
-
Are the FCR bbox tensors supposed to be decoded using the same DFL layout as Ultralytics YOLO?
-
Are the class tensors already sigmoid-activated by DFC, or should I apply sigmoid manually?
-
Since parse-hef says outputs are
UINT8, but my vstream buffer size equals float size, I believe HailoRT is converting output vstreams to FLOAT32. Is this correct? -
Could calibration with non-fire/non-smoke images cause this type of massive over-detection, or is this more likely a postprocess decode issue?
-
Is there a recommended way to generate a YOLOv8/YOLO11 HEF with Hailo NMS output instead of raw 6-output tensors?
Related NMS attempt
I also tried adding Hailo NMS using a model script and JSON similar to Model Zoo YOLOv8 configs.
For custom 1-class YOLOv8-style model, the optimized HAR showed NMS metadata correctly:
NMS Meta Architecture: Yolov8
NMS Target Device: Cpu
and the HAR contained:
best_uav/yolov8_nms_postprocess
But the compiler failed at HEF build with:
BackendAllocatorException: Compilation failed: map::at
So for now I am using raw 6-output HEF and doing the YOLO postprocess myself.
What I need help with
I would like to know whether the over-detection / 100% confidence issue is caused by:
-
wrong raw output decoding,
-
wrong sigmoid / class-score handling,
-
wrong tensor order interpretation,
-
quantization / calibration issue,
-
or a DFC/NMS configuration issue.
Any guidance on the correct raw YOLO output layout for Hailo-compiled YOLOv8/YOLO11 models would be appreciated.
Thank you.