| 40 | } |
| 41 | |
| 42 | void nms_boxes(std::vector<face_box>& input, float threshold, int type, std::vector<face_box>& output) |
| 43 | { |
| 44 | std::sort(input.begin(), input.end(), [](const face_box& a, const face_box& b) { return a.score > b.score; }); |
| 45 | |
| 46 | int box_num = input.size(); |
| 47 | |
| 48 | std::vector<int> merged(box_num, 0); |
| 49 | |
| 50 | for(int i = 0; i < box_num; i++) |
| 51 | { |
| 52 | if(merged[i]) |
| 53 | continue; |
| 54 | |
| 55 | output.push_back(input[i]); |
| 56 | |
| 57 | float h0 = input[i].y1 - input[i].y0 + 1; |
| 58 | float w0 = input[i].x1 - input[i].x0 + 1; |
| 59 | |
| 60 | float area0 = h0 * w0; |
| 61 | |
| 62 | for(int j = i + 1; j < box_num; j++) |
| 63 | { |
| 64 | if(merged[j]) |
| 65 | continue; |
| 66 | |
| 67 | float inner_x0 = std::max(input[i].x0, input[j].x0); |
| 68 | float inner_y0 = std::max(input[i].y0, input[j].y0); |
| 69 | |
| 70 | float inner_x1 = std::min(input[i].x1, input[j].x1); |
| 71 | float inner_y1 = std::min(input[i].y1, input[j].y1); |
| 72 | |
| 73 | float inner_h = inner_y1 - inner_y0 + 1; |
| 74 | float inner_w = inner_x1 - inner_x0 + 1; |
| 75 | |
| 76 | if(inner_h <= 0 || inner_w <= 0) |
| 77 | continue; |
| 78 | |
| 79 | float inner_area = inner_h * inner_w; |
| 80 | |
| 81 | float h1 = input[j].y1 - input[j].y0 + 1; |
| 82 | float w1 = input[j].x1 - input[j].x0 + 1; |
| 83 | |
| 84 | float area1 = h1 * w1; |
| 85 | |
| 86 | float score; |
| 87 | |
| 88 | if(type == NMS_UNION) |
| 89 | { |
| 90 | score = inner_area / (area0 + area1 - inner_area); |
| 91 | } |
| 92 | else |
| 93 | { |
| 94 | score = inner_area / std::min(area0, area1); |
| 95 | } |
| 96 | |
| 97 | if(score > threshold) |
| 98 | merged[j] = 1; |
| 99 | } |