00001 #include "box.h" 00002 #include <stdio.h> 00003 #include <math.h> 00004 #include <stdlib.h> 00005 00006 box float_to_box(float *f) 00007 { 00008 box b; 00009 b.x = f[0]; 00010 b.y = f[1]; 00011 b.w = f[2]; 00012 b.h = f[3]; 00013 return b; 00014 } 00015 00016 dbox derivative(box a, box b) 00017 { 00018 dbox d; 00019 d.dx = 0; 00020 d.dw = 0; 00021 float l1 = a.x - a.w/2; 00022 float l2 = b.x - b.w/2; 00023 if (l1 > l2){ 00024 d.dx -= 1; 00025 d.dw += .5; 00026 } 00027 float r1 = a.x + a.w/2; 00028 float r2 = b.x + b.w/2; 00029 if(r1 < r2){ 00030 d.dx += 1; 00031 d.dw += .5; 00032 } 00033 if (l1 > r2) { 00034 d.dx = -1; 00035 d.dw = 0; 00036 } 00037 if (r1 < l2){ 00038 d.dx = 1; 00039 d.dw = 0; 00040 } 00041 00042 d.dy = 0; 00043 d.dh = 0; 00044 float t1 = a.y - a.h/2; 00045 float t2 = b.y - b.h/2; 00046 if (t1 > t2){ 00047 d.dy -= 1; 00048 d.dh += .5; 00049 } 00050 float b1 = a.y + a.h/2; 00051 float b2 = b.y + b.h/2; 00052 if(b1 < b2){ 00053 d.dy += 1; 00054 d.dh += .5; 00055 } 00056 if (t1 > b2) { 00057 d.dy = -1; 00058 d.dh = 0; 00059 } 00060 if (b1 < t2){ 00061 d.dy = 1; 00062 d.dh = 0; 00063 } 00064 return d; 00065 } 00066 00067 float overlap(float x1, float w1, float x2, float w2) 00068 { 00069 float l1 = x1 - w1/2; 00070 float l2 = x2 - w2/2; 00071 float left = l1 > l2 ? l1 : l2; 00072 float r1 = x1 + w1/2; 00073 float r2 = x2 + w2/2; 00074 float right = r1 < r2 ? r1 : r2; 00075 return right - left; 00076 } 00077 00078 float box_intersection(box a, box b) 00079 { 00080 float w = overlap(a.x, a.w, b.x, b.w); 00081 float h = overlap(a.y, a.h, b.y, b.h); 00082 if(w < 0 || h < 0) return 0; 00083 float area = w*h; 00084 return area; 00085 } 00086 00087 float box_union(box a, box b) 00088 { 00089 float i = box_intersection(a, b); 00090 float u = a.w*a.h + b.w*b.h - i; 00091 return u; 00092 } 00093 00094 float box_iou(box a, box b) 00095 { 00096 return box_intersection(a, b)/box_union(a, b); 00097 } 00098 00099 float box_rmse(box a, box b) 00100 { 00101 return sqrt(pow(a.x-b.x, 2) + 00102 pow(a.y-b.y, 2) + 00103 pow(a.w-b.w, 2) + 00104 pow(a.h-b.h, 2)); 00105 } 00106 00107 dbox dintersect(box a, box b) 00108 { 00109 float w = overlap(a.x, a.w, b.x, b.w); 00110 float h = overlap(a.y, a.h, b.y, b.h); 00111 dbox dover = derivative(a, b); 00112 dbox di; 00113 00114 di.dw = dover.dw*h; 00115 di.dx = dover.dx*h; 00116 di.dh = dover.dh*w; 00117 di.dy = dover.dy*w; 00118 00119 return di; 00120 } 00121 00122 dbox dunion(box a, box b) 00123 { 00124 dbox du; 00125 00126 dbox di = dintersect(a, b); 00127 du.dw = a.h - di.dw; 00128 du.dh = a.w - di.dh; 00129 du.dx = -di.dx; 00130 du.dy = -di.dy; 00131 00132 return du; 00133 } 00134 00135 00136 void test_dunion() 00137 { 00138 box a = {0, 0, 1, 1}; 00139 box dxa= {0+.0001, 0, 1, 1}; 00140 box dya= {0, 0+.0001, 1, 1}; 00141 box dwa= {0, 0, 1+.0001, 1}; 00142 box dha= {0, 0, 1, 1+.0001}; 00143 00144 box b = {.5, .5, .2, .2}; 00145 dbox di = dunion(a,b); 00146 printf("Union: %f %f %f %f\n", di.dx, di.dy, di.dw, di.dh); 00147 float inter = box_union(a, b); 00148 float xinter = box_union(dxa, b); 00149 float yinter = box_union(dya, b); 00150 float winter = box_union(dwa, b); 00151 float hinter = box_union(dha, b); 00152 xinter = (xinter - inter)/(.0001); 00153 yinter = (yinter - inter)/(.0001); 00154 winter = (winter - inter)/(.0001); 00155 hinter = (hinter - inter)/(.0001); 00156 printf("Union Manual %f %f %f %f\n", xinter, yinter, winter, hinter); 00157 } 00158 void test_dintersect() 00159 { 00160 box a = {0, 0, 1, 1}; 00161 box dxa= {0+.0001, 0, 1, 1}; 00162 box dya= {0, 0+.0001, 1, 1}; 00163 box dwa= {0, 0, 1+.0001, 1}; 00164 box dha= {0, 0, 1, 1+.0001}; 00165 00166 box b = {.5, .5, .2, .2}; 00167 dbox di = dintersect(a,b); 00168 printf("Inter: %f %f %f %f\n", di.dx, di.dy, di.dw, di.dh); 00169 float inter = box_intersection(a, b); 00170 float xinter = box_intersection(dxa, b); 00171 float yinter = box_intersection(dya, b); 00172 float winter = box_intersection(dwa, b); 00173 float hinter = box_intersection(dha, b); 00174 xinter = (xinter - inter)/(.0001); 00175 yinter = (yinter - inter)/(.0001); 00176 winter = (winter - inter)/(.0001); 00177 hinter = (hinter - inter)/(.0001); 00178 printf("Inter Manual %f %f %f %f\n", xinter, yinter, winter, hinter); 00179 } 00180 00181 void test_box() 00182 { 00183 test_dintersect(); 00184 test_dunion(); 00185 box a = {0, 0, 1, 1}; 00186 box dxa= {0+.00001, 0, 1, 1}; 00187 box dya= {0, 0+.00001, 1, 1}; 00188 box dwa= {0, 0, 1+.00001, 1}; 00189 box dha= {0, 0, 1, 1+.00001}; 00190 00191 box b = {.5, 0, .2, .2}; 00192 00193 float iou = box_iou(a,b); 00194 iou = (1-iou)*(1-iou); 00195 printf("%f\n", iou); 00196 dbox d = diou(a, b); 00197 printf("%f %f %f %f\n", d.dx, d.dy, d.dw, d.dh); 00198 00199 float xiou = box_iou(dxa, b); 00200 float yiou = box_iou(dya, b); 00201 float wiou = box_iou(dwa, b); 00202 float hiou = box_iou(dha, b); 00203 xiou = ((1-xiou)*(1-xiou) - iou)/(.00001); 00204 yiou = ((1-yiou)*(1-yiou) - iou)/(.00001); 00205 wiou = ((1-wiou)*(1-wiou) - iou)/(.00001); 00206 hiou = ((1-hiou)*(1-hiou) - iou)/(.00001); 00207 printf("manual %f %f %f %f\n", xiou, yiou, wiou, hiou); 00208 } 00209 00210 dbox diou(box a, box b) 00211 { 00212 float u = box_union(a,b); 00213 float i = box_intersection(a,b); 00214 dbox di = dintersect(a,b); 00215 dbox du = dunion(a,b); 00216 dbox dd = {0,0,0,0}; 00217 00218 if(i <= 0 || 1) { 00219 dd.dx = b.x - a.x; 00220 dd.dy = b.y - a.y; 00221 dd.dw = b.w - a.w; 00222 dd.dh = b.h - a.h; 00223 return dd; 00224 } 00225 00226 dd.dx = 2*pow((1-(i/u)),1)*(di.dx*u - du.dx*i)/(u*u); 00227 dd.dy = 2*pow((1-(i/u)),1)*(di.dy*u - du.dy*i)/(u*u); 00228 dd.dw = 2*pow((1-(i/u)),1)*(di.dw*u - du.dw*i)/(u*u); 00229 dd.dh = 2*pow((1-(i/u)),1)*(di.dh*u - du.dh*i)/(u*u); 00230 return dd; 00231 } 00232 00233 typedef struct{ 00234 int index; 00235 int class; 00236 float **probs; 00237 } sortable_bbox; 00238 00239 int nms_comparator(const void *pa, const void *pb) 00240 { 00241 sortable_bbox a = *(sortable_bbox *)pa; 00242 sortable_bbox b = *(sortable_bbox *)pb; 00243 float diff = a.probs[a.index][b.class] - b.probs[b.index][b.class]; 00244 if(diff < 0) return 1; 00245 else if(diff > 0) return -1; 00246 return 0; 00247 } 00248 00249 void do_nms_sort(box *boxes, float **probs, int total, int classes, float thresh) 00250 { 00251 int i, j, k; 00252 sortable_bbox *s = calloc(total, sizeof(sortable_bbox)); 00253 00254 for(i = 0; i < total; ++i){ 00255 s[i].index = i; 00256 s[i].class = 0; 00257 s[i].probs = probs; 00258 } 00259 00260 for(k = 0; k < classes; ++k){ 00261 for(i = 0; i < total; ++i){ 00262 s[i].class = k; 00263 } 00264 qsort(s, total, sizeof(sortable_bbox), nms_comparator); 00265 for(i = 0; i < total; ++i){ 00266 if(probs[s[i].index][k] == 0) continue; 00267 box a = boxes[s[i].index]; 00268 for(j = i+1; j < total; ++j){ 00269 box b = boxes[s[j].index]; 00270 if (box_iou(a, b) > thresh){ 00271 probs[s[j].index][k] = 0; 00272 } 00273 } 00274 } 00275 } 00276 free(s); 00277 } 00278 00279 void do_nms(box *boxes, float **probs, int total, int classes, float thresh) 00280 { 00281 int i, j, k; 00282 for(i = 0; i < total; ++i){ 00283 int any = 0; 00284 for(k = 0; k < classes; ++k) any = any || (probs[i][k] > 0); 00285 if(!any) { 00286 continue; 00287 } 00288 for(j = i+1; j < total; ++j){ 00289 if (box_iou(boxes[i], boxes[j]) > thresh){ 00290 for(k = 0; k < classes; ++k){ 00291 if (probs[i][k] < probs[j][k]) probs[i][k] = 0; 00292 else probs[j][k] = 0; 00293 } 00294 } 00295 } 00296 } 00297 } 00298 00299 box encode_box(box b, box anchor) 00300 { 00301 box encode; 00302 encode.x = (b.x - anchor.x) / anchor.w; 00303 encode.y = (b.y - anchor.y) / anchor.h; 00304 encode.w = log2(b.w / anchor.w); 00305 encode.h = log2(b.h / anchor.h); 00306 return encode; 00307 } 00308 00309 box decode_box(box b, box anchor) 00310 { 00311 box decode; 00312 decode.x = b.x * anchor.w + anchor.x; 00313 decode.y = b.y * anchor.h + anchor.y; 00314 decode.w = pow(2., b.w) * anchor.w; 00315 decode.h = pow(2., b.h) * anchor.h; 00316 return decode; 00317 }