Implementation:Tencent Ncnn DFL Anchor Free Decode
| Knowledge Sources | |
|---|---|
| Domains | Computer_Vision, Object_Detection |
| Last Updated | 2026-02-09 00:00 GMT |
Overview
Pattern implementation for decoding DFL-based anchor-free detection outputs into bounding boxes, as demonstrated in ncnn YOLOv8 examples.
Description
This is a Pattern Doc documenting the DFL bounding box decoding pattern from the ncnn yolov8.cpp example. The implementation uses ncnn::create_layer("Softmax") internally to compute DFL softmax over the 16-bin distribution for each box edge. The pattern processes the raw detection output tensor (shape: w=num_classes+64, h=num_anchors) and produces a vector of decoded Object structs.
The implementation handles three detection strides (8, 16, 32) and uses a confidence threshold to filter low-probability detections before decoding, saving computation.
Usage
Implement this pattern for YOLOv8 and YOLO11 anchor-free detection post-processing. Adapt reg_max and stride values for different model architectures.
Code Reference
Source Location
- Repository: ncnn
- File: examples/yolov8.cpp
- Lines: L160-254 (generate_proposals with DFL decode), L256-273 (multi-stride dispatch)
Signature
// Pattern: DFL bounding box decode
// User-implemented function based on ncnn example pattern
struct Object
{
cv::Rect_<float> rect; // bounding box (x, y, width, height)
int label; // class index
float prob; // confidence score
};
static void generate_proposals(
const ncnn::Mat& pred, // raw detection output
int stride, // detection stride (8, 16, or 32)
const ncnn::Mat& in_pad, // letterboxed input (for shape)
float prob_threshold, // confidence threshold (e.g., 0.25)
std::vector<Object>& objects // output: decoded detections
);
Import
#include "layer.h" // for ncnn::create_layer("Softmax")
#include "net.h"
#include <vector>
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| pred | ncnn::Mat | Yes | Raw detection output (w=num_class+reg_max*4, h=num_anchors) |
| stride | int | Yes | Detection stride (8, 16, or 32) |
| prob_threshold | float | Yes | Minimum confidence threshold (e.g., 0.25) |
Outputs
| Name | Type | Description |
|---|---|---|
| objects | std::vector<Object> | Decoded detections with rect, label, and prob fields |
Usage Examples
YOLOv8 Multi-Stride Decode
// After inference: extract single output blob
ncnn::Mat out;
ex.extract("out0", out);
// Decode at three strides
std::vector<Object> proposals;
std::vector<Object> objects8, objects16, objects32;
// Stride 8 proposals
{
ncnn::Mat pred(out.w, out.h / 3, (float*)out.data);
generate_proposals(pred, 8, in_pad, 0.25f, objects8);
proposals.insert(proposals.end(), objects8.begin(), objects8.end());
}
// Stride 16 and 32 similarly...
// Apply NMS to merged proposals