NMS出现重框问题

问题:

最近做目标检测的时候,发现通过极大值,还是有可能出现两个重叠的方框

具体如下:

核心代码如下:

static void nms_sorted_bboxes(const std::vector<ObjectDef>& faceObjectDefs, std::vector<int>& picked,
    float nms_threshold) {
    picked.clear();

    const int n = faceObjectDefs.size();

    std::vector<float> areas(n);
    for (int i = 0; i < n; i++) {
        areas[i] = faceObjectDefs[i].bbox.rect.area();
    }

    for (int i = 0; i < n; i++) {
        const ObjectDef& a = faceObjectDefs[i];

        int keep = 1;
        for (int j = 0; j < (int)picked.size(); j++) {
            const ObjectDef& b = faceObjectDefs[picked[j]];

            // intersection over union
            float inter_area = intersection_area(a, b);
            float union_area = areas[i] + areas[picked[j]] - inter_area;
            // float IoU = inter_area / union_area
            if (inter_area / union_area > nms_threshold)
                keep = 0;
        }

        if (keep)
            picked.push_back(i);
    }
}

问题排查:

通过定位排查,发现里面有个缺陷,就是在重叠框和目标框过小的时候,容易导致出现出问题

NMS计算是IOU,就是计算重叠面积,占据两个框总面积减去重叠框的比例

如果其中一个面积比较大,一个面积比较小,这个时候哪怕完全重叠,他们的IOU的NMS也比较低,通过阈值过滤会失败,导致出现两个重叠的方框。

比如:我设置的阈值是0.4

有两个方框A和B

方框A的面积是1000,而B的面积是10,他们完全重叠,但是计算出来的NMS会很低。

10/(1000+10 -10) = 0.01 ,这个时候会算作两个方框,那怎么处理了。

解决方案

我添加一个阈值my_iou_threshold,就是IOU和自身面积的比值,如果超于0.5或者0.8 这个看项目设置,那么也进行合并,修改代码如下:


static void nms_sorted_bboxes(const std::vector<ObjectDef>& faceObjectDefs, std::vector<int>& picked,
    float nms_threshold=0.4, float my_iou_threshold=0.5) {
    picked.clear();

    const int n = faceObjectDefs.size();

    std::vector<float> areas(n);
    for (int i = 0; i < n; i++) {
        areas[i] = faceObjectDefs[i].bbox.rect.area();
    }

    for (int i = 0; i < n; i++) {
        const ObjectDef& a = faceObjectDefs[i];

        int keep = 1;
        for (int j = 0; j < (int)picked.size(); j++) {
            const ObjectDef& b = faceObjectDefs[picked[j]];

            // intersection over union
            float inter_area = intersection_area(a, b);
            float union_area = areas[i] + areas[picked[j]] - inter_area;
            if ((inter_area / areas[i] > my_iou_threshold) || (inter_area / areas[picked[j]] > my_iou_threshold)
                || (inter_area / union_area > nms_threshold))
                keep = 0;
             float IoU = inter_area / union_area
            //if (inter_area / union_area > nms_threshold)
            //    keep = 0;
        }

        if (keep)
            picked.push_back(i);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值