| | |
| | | #include "box.h" |
| | | #include <stdio.h> |
| | | #include <math.h> |
| | | #include <stdlib.h> |
| | | |
| | | box float_to_box(float *f) |
| | | { |
| | | box b; |
| | | b.x = f[0]; |
| | | b.y = f[1]; |
| | | b.w = f[2]; |
| | | b.h = f[3]; |
| | | return b; |
| | | } |
| | | |
| | | dbox derivative(box a, box b) |
| | | { |
| | |
| | | return box_intersection(a, b)/box_union(a, b); |
| | | } |
| | | |
| | | float box_rmse(box a, box b) |
| | | { |
| | | return sqrt(pow(a.x-b.x, 2) + |
| | | pow(a.y-b.y, 2) + |
| | | pow(a.w-b.w, 2) + |
| | | pow(a.h-b.h, 2)); |
| | | } |
| | | |
| | | dbox dintersect(box a, box b) |
| | | { |
| | | float w = overlap(a.x, a.w, b.x, b.w); |
| | |
| | | return dd; |
| | | } |
| | | |
| | | void do_nms(box *boxes, float **probs, int num_boxes, int classes, float thresh) |
| | | typedef struct{ |
| | | int index; |
| | | int class_id; |
| | | float **probs; |
| | | } sortable_bbox; |
| | | |
| | | int nms_comparator(const void *pa, const void *pb) |
| | | { |
| | | sortable_bbox a = *(sortable_bbox *)pa; |
| | | sortable_bbox b = *(sortable_bbox *)pb; |
| | | float diff = a.probs[a.index][b.class_id] - b.probs[b.index][b.class_id]; |
| | | if(diff < 0) return 1; |
| | | else if(diff > 0) return -1; |
| | | return 0; |
| | | } |
| | | |
| | | void do_nms_sort_v2(box *boxes, float **probs, int total, int classes, float thresh) |
| | | { |
| | | int i, j, k; |
| | | for(i = 0; i < num_boxes*num_boxes; ++i){ |
| | | sortable_bbox *s = calloc(total, sizeof(sortable_bbox)); |
| | | |
| | | for(i = 0; i < total; ++i){ |
| | | s[i].index = i; |
| | | s[i].class_id = 0; |
| | | s[i].probs = probs; |
| | | } |
| | | |
| | | for(k = 0; k < classes; ++k){ |
| | | for(i = 0; i < total; ++i){ |
| | | s[i].class_id = k; |
| | | } |
| | | qsort(s, total, sizeof(sortable_bbox), nms_comparator); |
| | | for(i = 0; i < total; ++i){ |
| | | if(probs[s[i].index][k] == 0) continue; |
| | | box a = boxes[s[i].index]; |
| | | for(j = i+1; j < total; ++j){ |
| | | box b = boxes[s[j].index]; |
| | | if (box_iou(a, b) > thresh){ |
| | | probs[s[j].index][k] = 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | free(s); |
| | | } |
| | | |
| | | int nms_comparator_v3(const void *pa, const void *pb) |
| | | { |
| | | detection a = *(detection *)pa; |
| | | detection b = *(detection *)pb; |
| | | float diff = 0; |
| | | if (b.sort_class >= 0) { |
| | | diff = a.prob[b.sort_class] - b.prob[b.sort_class]; |
| | | } |
| | | else { |
| | | diff = a.objectness - b.objectness; |
| | | } |
| | | if (diff < 0) return 1; |
| | | else if (diff > 0) return -1; |
| | | return 0; |
| | | } |
| | | |
| | | void do_nms_obj(detection *dets, int total, int classes, float thresh) |
| | | { |
| | | printf(" total = %d, classes = %d, thresh = %f \n", total, classes, thresh); |
| | | int i, j, k; |
| | | k = total - 1; |
| | | for (i = 0; i <= k; ++i) { |
| | | if (dets[i].objectness == 0) { |
| | | detection swap = dets[i]; |
| | | dets[i] = dets[k]; |
| | | dets[k] = swap; |
| | | --k; |
| | | --i; |
| | | } |
| | | } |
| | | total = k + 1; |
| | | |
| | | for (i = 0; i < total; ++i) { |
| | | dets[i].sort_class = -1; |
| | | } |
| | | |
| | | qsort(dets, total, sizeof(detection), nms_comparator_v3); |
| | | for (i = 0; i < total; ++i) { |
| | | if (dets[i].objectness == 0) continue; |
| | | box a = dets[i].bbox; |
| | | for (j = i + 1; j < total; ++j) { |
| | | if (dets[j].objectness == 0) continue; |
| | | box b = dets[j].bbox; |
| | | if (box_iou(a, b) > thresh) { |
| | | dets[j].objectness = 0; |
| | | for (k = 0; k < classes; ++k) { |
| | | dets[j].prob[k] = 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | void do_nms_sort(detection *dets, int total, int classes, float thresh) |
| | | { |
| | | int i, j, k; |
| | | k = total - 1; |
| | | for (i = 0; i <= k; ++i) { |
| | | if (dets[i].objectness == 0) { |
| | | detection swap = dets[i]; |
| | | dets[i] = dets[k]; |
| | | dets[k] = swap; |
| | | --k; |
| | | --i; |
| | | } |
| | | } |
| | | total = k + 1; |
| | | |
| | | for (k = 0; k < classes; ++k) { |
| | | for (i = 0; i < total; ++i) { |
| | | dets[i].sort_class = k; |
| | | } |
| | | qsort(dets, total, sizeof(detection), nms_comparator_v3); |
| | | for (i = 0; i < total; ++i) { |
| | | //printf(" k = %d, \t i = %d \n", k, i); |
| | | if (dets[i].prob[k] == 0) continue; |
| | | box a = dets[i].bbox; |
| | | for (j = i + 1; j < total; ++j) { |
| | | box b = dets[j].bbox; |
| | | if (box_iou(a, b) > thresh) { |
| | | dets[j].prob[k] = 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | void do_nms(box *boxes, float **probs, int total, int classes, float thresh) |
| | | { |
| | | int i, j, k; |
| | | for(i = 0; i < total; ++i){ |
| | | int any = 0; |
| | | for(k = 0; k < classes; ++k) any = any || (probs[i][k] > 0); |
| | | if(!any) { |
| | | continue; |
| | | } |
| | | for(j = i+1; j < num_boxes*num_boxes; ++j){ |
| | | for(j = i+1; j < total; ++j){ |
| | | if (box_iou(boxes[i], boxes[j]) > thresh){ |
| | | for(k = 0; k < classes; ++k){ |
| | | if (probs[i][k] < probs[j][k]) probs[i][k] = 0; |
| | |
| | | } |
| | | } |
| | | |
| | | box encode_box(box b, box anchor) |
| | | { |
| | | box encode; |
| | | encode.x = (b.x - anchor.x) / anchor.w; |
| | | encode.y = (b.y - anchor.y) / anchor.h; |
| | | encode.w = log2(b.w / anchor.w); |
| | | encode.h = log2(b.h / anchor.h); |
| | | return encode; |
| | | } |
| | | |
| | | box decode_box(box b, box anchor) |
| | | { |
| | | box decode; |
| | | decode.x = b.x * anchor.w + anchor.x; |
| | | decode.y = b.y * anchor.h + anchor.y; |
| | | decode.w = pow(2., b.w) * anchor.w; |
| | | decode.h = pow(2., b.h) * anchor.h; |
| | | return decode; |
| | | } |