| 103 | } |
| 104 | |
| 105 | void nms_boxes(std::vector<face_box>& input, float threshold, int type, std::vector<face_box>& output) |
| 106 | { |
| 107 | output.clear(); |
| 108 | std::sort(input.begin(), input.end(), [](const face_box& a, const face_box& b) { return a.score > b.score; }); |
| 109 | |
| 110 | int box_num = input.size(); |
| 111 | |
| 112 | std::vector<int> merged(box_num, 0); |
| 113 | |
| 114 | for(int i = 0; i < box_num; i++) |
| 115 | { |
| 116 | if(merged[i]) |
| 117 | continue; |
| 118 | |
| 119 | output.push_back(input[i]); |
| 120 | |
| 121 | float h0 = input[i].y1 - input[i].y0 + 1; |
| 122 | float w0 = input[i].x1 - input[i].x0 + 1; |
| 123 | |
| 124 | float area0 = h0 * w0; |
| 125 | |
| 126 | for(int j = i + 1; j < box_num; j++) |
| 127 | { |
| 128 | if(merged[j]) |
| 129 | continue; |
| 130 | |
| 131 | float inner_x0 = std::max(input[i].x0, input[j].x0); |
| 132 | float inner_y0 = std::max(input[i].y0, input[j].y0); |
| 133 | |
| 134 | float inner_x1 = std::min(input[i].x1, input[j].x1); |
| 135 | float inner_y1 = std::min(input[i].y1, input[j].y1); |
| 136 | |
| 137 | float inner_h = inner_y1 - inner_y0 + 1; |
| 138 | float inner_w = inner_x1 - inner_x0 + 1; |
| 139 | |
| 140 | if(inner_h <= 0 || inner_w <= 0) |
| 141 | continue; |
| 142 | |
| 143 | float inner_area = inner_h * inner_w; |
| 144 | |
| 145 | float h1 = input[j].y1 - input[j].y0 + 1; |
| 146 | float w1 = input[j].x1 - input[j].x0 + 1; |
| 147 | |
| 148 | float area1 = h1 * w1; |
| 149 | |
| 150 | float score; |
| 151 | |
| 152 | if(type == NMS_UNION) |
| 153 | { |
| 154 | score = inner_area / (area0 + area1 - inner_area); |
| 155 | } |
| 156 | else |
| 157 | { |
| 158 | score = inner_area / std::min(area0, area1); |
| 159 | } |
| 160 | |
| 161 | if(score > threshold) |
| 162 | merged[j] = 1; |