Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Tencent Ncnn NMS Sorted Bboxes

From Leeroopedia


Knowledge Sources
Domains Computer_Vision, Object_Detection
Last Updated 2026-02-09 00:00 GMT

Overview

Pattern implementation for non-maximum suppression of object detections using quicksort and IoU filtering, as demonstrated in ncnn detection examples.

Description

This is a Pattern Doc documenting the NMS pattern from ncnn detection examples. The implementation consists of two functions: qsort_descent_inplace (custom quicksort by confidence) and nms_sorted_bboxes (greedy IoU-based suppression on pre-sorted detections).

The pattern supports both class-agnostic NMS (all classes suppressed together) and class-aware NMS (separate suppression per class, using coordinate offsets to prevent cross-class suppression).

Usage

Implement this pattern after bounding box decoding. Apply to the merged proposals from all detection strides.

Code Reference

Source Location

  • Repository: ncnn
  • File: examples/yolov8.cpp
  • Lines: L73-116 (qsort_descent_inplace), L118-157 (nms_sorted_bboxes)

Signature

// Pattern: NMS for object detection
// User-implemented functions from ncnn examples

// Sort detections by confidence (descending) in-place
static void qsort_descent_inplace(std::vector<Object>& objects);

// Apply NMS to pre-sorted detections
// Returns indices of surviving detections in 'picked'
static void nms_sorted_bboxes(
    const std::vector<Object>& objects,  // sorted by confidence
    std::vector<int>& picked,            // output: surviving indices
    float nms_threshold,                 // IoU threshold (e.g., 0.45)
    bool agnostic = false                // true = class-agnostic NMS
);

Import

#include <vector>
#include <algorithm>  // std::swap

I/O Contract

Inputs

Name Type Required Description
objects std::vector<Object> Yes Candidate detections from decode step
nms_threshold float Yes IoU threshold for suppression (e.g., 0.45)
agnostic bool No If true, suppress across all classes (default: false)

Outputs

Name Type Description
picked std::vector<int> Indices of surviving detections after NMS

Usage Examples

Complete NMS Pipeline

// After decoding proposals from all strides
std::vector<Object> proposals;
// ... fill proposals from generate_proposals()

// Sort by confidence
qsort_descent_inplace(proposals);

// Apply NMS with IoU threshold 0.45
std::vector<int> picked;
nms_sorted_bboxes(proposals, picked, 0.45f);

// Extract final detections
int count = picked.size();
std::vector<Object> objects(count);
for (int i = 0; i < count; i++)
{
    objects[i] = proposals[picked[i]];

    // Adjust coordinates for letterbox padding
    float x0 = (objects[i].rect.x - (wpad / 2)) / scale;
    float y0 = (objects[i].rect.y - (hpad / 2)) / scale;
    float x1 = (objects[i].rect.x + objects[i].rect.width - (wpad / 2)) / scale;
    float y1 = (objects[i].rect.y + objects[i].rect.height - (hpad / 2)) / scale;

    // Clip to image bounds
    objects[i].rect.x = std::max(x0, 0.f);
    objects[i].rect.y = std::max(y0, 0.f);
    objects[i].rect.width = std::min(x1, (float)img_w) - objects[i].rect.x;
    objects[i].rect.height = std::min(y1, (float)img_h) - objects[i].rect.y;
}

Related Pages

Implements Principle

Uses Heuristic

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment