box
nms_comparator
int nms_comparator(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;
}
ํจ์ ์ด๋ฆ: nms_comparator
์ ๋ ฅ:
void ํฌ์ธํฐํ pa
void ํฌ์ธํฐํ pb
๋์:
pa์ pb๊ฐ ๊ฐ๋ฆฌํค๋ detection ๊ตฌ์กฐ์ฒด a์ b๋ฅผ ๊ฐ์ ธ์, a์ b์ ํ๋ฅ (prob)์ด๋ ๊ฐ์ฒด(objectness)์ ์ฐจ์ด(diff)๋ฅผ ๊ณ์ฐํ์ฌ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ๋ค.
sort_class๊ฐ 0๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ ๊ฒฝ์ฐ์๋ prob์ ์ฐจ์ด๋ฅผ, ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ์๋ objectness์ ์ฐจ์ด๋ฅผ ์ด์ฉํ์ฌ ์ ๋ ฌํ๋ค.
์ค๋ช :
Non-Maximum Suppression(NMS) ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ๊ธฐ ์ํ comparator ํจ์์ด๋ค.
NMS๋ ๊ฐ์ฒด ํ์ง(Object Detection)์์ ์ค๋ณต๋๋ ๋ฐ์ค(Box)๋ฅผ ์ ๊ฑฐํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
NMS๋ฅผ ์ ์ฉํ๊ธฐ ์ ์, ๊ฐ์ฒด ๊ฒ์ถ ๋ชจ๋ธ์ด ์์ธกํ ์ฌ๋ฌ ๊ฐ์ ๋ฐ์ค๋ค์ ํ๋ฅ ๋ฑ์ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ๋๋ฐ, ์ด๋ ์ฌ์ฉ๋๋ ํจ์์ด๋ค.
a์ b๊ฐ ๊ฐ๋ฆฌํค๋ detection ๊ตฌ์กฐ์ฒด์ ์์ ์ค sort_class๋ฒ์งธ ํด๋์ค์ ๋ํ ํ๋ฅ (prob) ํน์ ๊ฐ์ฒด(objectness)์ ์ฐจ์ด(diff)๋ฅผ ๊ณ์ฐํ์ฌ ์ ๋ ฌํ๋ค.
ํจ์ ๋ด์์ qsort() ํจ์์ ํจ๊ป ์ฌ์ฉ๋์ด ์ ๋ ฌ์ ์ํํ๋ค.
do_nms_obj
void do_nms_obj(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(i = 0; i < total; ++i){
dets[i].sort_class = -1;
}
qsort(dets, total, sizeof(detection), nms_comparator);
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;
}
}
}
}
}
ํจ์ ์ด๋ฆ: do_nms_obj
์ ๋ ฅ:
detection *dets: detection ๊ตฌ์กฐ์ฒด ๋ฐฐ์ด ํฌ์ธํฐ
int total: detection ๋ฐฐ์ด์ ์ด ์์ ๊ฐ์
int classes: ๋ถ๋ฅ(classification) ์
float thresh: IOU(Intersection over Union) ์๊ณ๊ฐ
๋์:
์ ๋ ฅ์ผ๋ก ๋ฐ์ detection ๋ฐฐ์ด์์ objectness๊ฐ 0์ธ detection์ ๋ฐฐ์ด์ ๋์ผ๋ก ์ด๋์ํค๊ณ ํด๋น ์์๋ฅผ ๋ฐฐ์ด์์ ์ ๊ฑฐํจ
์ ๋ ฌ๋์ง ์์ detection ๋ฐฐ์ด์ class์ ํ๋ฅ ๊ฐ(prob) ๋๋ objectness ๊ฐ(objectness)์ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌ
์ ๋ ฌ๋ detection ๋ฐฐ์ด์์ IOU๊ฐ ์๊ณ๊ฐ(thresh) ์ด์์ธ detection ์์ ์ฐพ์์ ๋ฎ์ objectness ๊ฐ๊ณผ ํด๋น ์์ ๋ชจ๋ class์ ํ๋ฅ ๊ฐ์ 0์ผ๋ก ์ค์ ํจ
์ค๋ช :
non-maximum suppression(NMS) ์๊ณ ๋ฆฌ์ฆ์ ์ํํ๋ ํจ์๋ก, ์ ๋ ฅ์ผ๋ก ๋ฐ์ detection ๋ฐฐ์ด์์ ๊ฒน์น๋ ๋ฐ์ค๋ฅผ ์ ๊ฑฐํ๋ ์ญํ ์ ํจ
์ ๋ ฅ์ผ๋ก ๋ฐ์ detection ๊ตฌ์กฐ์ฒด ๋ฐฐ์ด ํฌ์ธํฐ(dets)๋ ๋ฐ์ค(bounding box)์ ์์น, ํฌ๊ธฐ, confidence(ํ๋ฅ ), class ํ๋ฅ ๋ฑ์ ํฌํจํ๋ ๊ตฌ์กฐ์ฒด ๋ฐฐ์ด์
ํจ์ ๋ด๋ถ์์๋ ๊ฐ์ฒด๋ฅผ ๊ฒ์ถํ detection ๊ตฌ์กฐ์ฒด ๋ฐฐ์ด(dets)์ objectness ๊ฐ์ผ๋ก ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ๊ณ , ๊ฒน์น๋ ๋ฐ์ค๋ฅผ ์ ๊ฑฐํจ
๊ฐ์ฒด๋ฅผ ๊ฒ์ถํ detection ๋ฐฐ์ด์์ objectness๊ฐ 0์ธ detection์ ์ ๊ฑฐํจ์ผ๋ก์จ, ๊ฒน์น๋ ๋ฐ์ค ์ค์์ objectness ๊ฐ์ด ๋ฎ์ ๋ฐ์ค๋ฅผ ์ ๊ฑฐํจ
objectness๊ฐ 0์ด ๋๋ฉด ํด๋น ๋ฐ์ค๋ ๊ฐ์ฒด๊ฐ ์๋๋ผ๊ณ ํ๋จํ๊ณ , ๊ทธ์ ํด๋นํ๋ class ํ๋ฅ ๊ฐ์ 0์ผ๋ก ์ค์ ํจ
์ด๋ฌํ ์ฒ๋ฆฌ๋ฅผ ๊ฑฐ์น detection ๋ฐฐ์ด์ ์ต์ข ์ ์ผ๋ก ๊ฒน์น๋ ๋ฐ์ค๋ฅผ ์ ๊ฑฐํ ํ์ ๊ฐ์ฒด ๊ฒ์ถ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋
do_nms_sort
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);
for(i = 0; i < total; ++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;
}
}
}
}
}
ํจ์ ์ด๋ฆ: do_nms_sort
์ ๋ ฅ:
detection *dets: ๊ฐ ํด๋์ค์ detection ๊ฒฐ๊ณผ๋ฅผ ๋ด๊ณ ์๋ ๋ฐฐ์ด
int total: ์ด detection ๊ฐ์
int classes: ํด๋์ค ๊ฐ์
float thresh: IoU ์๊ณ๊ฐ
๋์:
์ ๋ ฅ์ผ๋ก ๋ฐ์ detection ๋ฐฐ์ด์์ objectness ๊ฐ์ด 0์ธ detection์ ์ ๊ฑฐํ๋ค.
classes ๊ฐ์๋งํผ ๋ฐ๋ณตํ๋ฉฐ, ๊ฐ ํด๋์ค์ ๋ํ detection ๊ฒฐ๊ณผ๋ฅผ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ๋ค.
์ ๋ ฌ๋ detection ๊ฒฐ๊ณผ ์ค, ํ๋ฅ ๊ฐ์ด 0์ธ detection์ ์ ์ธํ๋ค.
์ดํ, ๊ฐ detection ๊ฒฐ๊ณผ์ bounding box์ ๋ค๋ฅธ detection ๊ฒฐ๊ณผ์ bounding box์ IoU๋ฅผ ๊ณ์ฐํ์ฌ, ์๊ณ๊ฐ(thresh)๋ณด๋ค ํฐ ๊ฒฝ์ฐ ํด๋น detection์ ํ๋ฅ ๊ฐ์ 0์ผ๋ก ๋ง๋ ๋ค.
์ค๋ช :
์ด ํจ์๋ Object Detection์์ NMS(Non-Maximum Suppression)์ ์ํํ๋ ํจ์๋ก, ํด๋์ค๋ณ๋ก detection ๊ฒฐ๊ณผ๋ฅผ ์ ๋ ฌํ์ฌ IoU ์๊ณ๊ฐ์ ๋๋ detection ๊ฒฐ๊ณผ๋ฅผ ์ ๊ฑฐํ๋ค.
์ด๋ฅผ ํตํด, ๊ฒน์น๋ ๋ฐ์ค๋ฅผ ์ ๊ฑฐํ๊ณ ์ต์ข detection ๊ฒฐ๊ณผ๋ฅผ ์ป๊ฒ ๋๋ค.
float_to_box
box float_to_box(float *f, int stride)
{
box b = {0};
b.x = f[0];
b.y = f[1*stride];
b.w = f[2*stride];
b.h = f[3*stride];
return b;
}
ํจ์ ์ด๋ฆ: float_to_box
์ ๋ ฅ:
float *f: 4๊ฐ์ ๊ฐ์ผ๋ก ์ด๋ฃจ์ด์ง 1์ฐจ์ float ๋ฐฐ์ด ํฌ์ธํฐ
int stride: ๋ฐฐ์ด์์ ๊ฐ ์ฌ์ด์ ๊ฐ๊ฒฉ
๋์:
์ฃผ์ด์ง float ๋ฐฐ์ด ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์๋ก์ด box ๊ตฌ์กฐ์ฒด๋ฅผ ๋ง๋ค๊ณ ๋ฐํํฉ๋๋ค.
box ๊ตฌ์กฐ์ฒด๋ x, y, w, h ๊ฐ์ ๊ฐ์ต๋๋ค.
x, y, w, h ๊ฐ์ ๊ฐ๊ฐ ๋ฐฐ์ด์ ์ฒซ ๋ฒ์งธ, stride ๋ฒ์งธ, 2stride ๋ฒ์งธ, 3stride ๋ฒ์งธ ๊ฐ์ผ๋ก ์ค์ ๋ฉ๋๋ค.
์ค๋ช :
์ด ํจ์๋ ์ฃผ๋ก YOLO์ ๊ฐ์ ๊ฐ์ฒด ๊ฒ์ถ ๋ชจ๋ธ์์ ์ฌ์ฉ๋ฉ๋๋ค.
๊ฐ์ฒด ๊ฒ์ถ ๋ชจ๋ธ์ bounding box๋ฅผ ์ถ๋ ฅ๊ฐ์ผ๋ก ๋ฐํํ๋๋ฐ, ์ด bounding box๋ (x,y,w,h) ํํ์ 4๊ฐ์ ๊ฐ์ ๊ฐ์ง๋๋ค.
๊ทธ๋ฌ๋ ์ด๋ฌํ ์ถ๋ ฅ๊ฐ์ float ๋ฐฐ์ด์ ํํ๋ก ๋ฐํ๋๊ธฐ ๋๋ฌธ์, ์ด๋ฅผ ์ ์ ํ ํํ์ ๊ตฌ์กฐ์ฒด๋ก ๋ณํํด์ฃผ๋ ํจ์๊ฐ ํ์ํฉ๋๋ค.
float_to_box ํจ์๋ ์ด๋ฌํ ๋ณํ์ ์ํํ๋ ํจ์ ์ค ํ๋์ ๋๋ค.
overlap
float overlap(float x1, float w1, float x2, float w2)
{
float l1 = x1 - w1/2;
float l2 = x2 - w2/2;
float left = l1 > l2 ? l1 : l2;
float r1 = x1 + w1/2;
float r2 = x2 + w2/2;
float right = r1 < r2 ? r1 : r2;
return right - left;
}
ํจ์ ์ด๋ฆ: overlap
์ ๋ ฅ:
๋ค ๊ฐ์ ์ค์(x1, w1, x2, w2)๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค.
๋์:
๋ ๊ฐ์ ๋ฐ์ค๊ฐ ๊ฒน์น๋ ์์ญ์ ๋๋น๋ฅผ ๊ณ์ฐํฉ๋๋ค.
๋ฐ์ค์ ์ค์ฌ ์ขํ์ ํญ์ ์ด์ฉํ์ฌ ์ผ์ชฝ ๋๊ณผ ์ค๋ฅธ์ชฝ ๋์ ๊ณ์ฐํ ๋ค ๊ฒน์น๋ ์์ญ์ ๋๋น๋ฅผ ๋ฐํํฉ๋๋ค.
์ค๋ช :
Object Detection์์ NMS(Non-Maximum Suppression) ๊ณผ์ ์์ ์ฌ์ฉ๋ฉ๋๋ค.
๋ฐ์ค๊ฐ ์๋ก ์ผ๋ง๋ ๊ฒน์น๋์ง๋ฅผ ๊ณ์ฐํ์ฌ IoU(Intersection over Union) ๊ฐ์ ๊ตฌํฉ๋๋ค.
๊ฒน์น๋ ์์ญ์ด ์์์๋ก IoU ๊ฐ์ ์์์ง๋ฉฐ, ์ผ์ ๊ฐ์ ๊ธฐ์ค์ผ๋ก IoU ๊ฐ์ด ์ดํ์ธ ๋ฐ์ค๋ค์ ์ ๊ฑฐํ์ฌ ์ค๋ณต ํ์ง๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
box_intersection
float box_intersection(box a, box b)
{
float w = overlap(a.x, a.w, b.x, b.w);
float h = overlap(a.y, a.h, b.y, b.h);
if(w < 0 || h < 0) return 0;
float area = w*h;
return area;
}
ํจ์ ์ด๋ฆ: box_intersection
์ ๋ ฅ:
box a, box b (bounding box ์ ๋ณด๋ฅผ ๋ํ๋ด๋ ๊ตฌ์กฐ์ฒด)
๋์:
๋ ๊ฐ์ bounding box a์ b๊ฐ ์ฃผ์ด์ก์ ๋, ์ด๋ค์ ๊ต์ฐจ ๋ฉด์ ์ ๊ณ์ฐํ๋ ํจ์์ด๋ค.
์ค๋ช :
overlap ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ bounding box์ x, y ์ขํ์ ๋ํ ๊ต์ฐจ ๋ถ๋ถ์ ๊ธธ์ด๋ฅผ ๊ณ์ฐํ ํ, ์ด๋ค ๊ธธ์ด๋ฅผ ๊ณฑํ์ฌ ๊ต์ฐจ ๋ฉด์ ์ ๊ณ์ฐํ๋ค.
๋ง์ฝ ๊ต์ฐจํ๋ ๋ถ๋ถ์ด ์๋ค๋ฉด ๋ฉด์ ์ 0์ด ๋๋ค.
box_union
float box_union(box a, box b)
{
float i = box_intersection(a, b);
float u = a.w*a.h + b.w*b.h - i;
return u;
}
ํจ์ ์ด๋ฆ: box_union
์ ๋ ฅ:
๋ ๊ฐ์ box(a, b)
๋์:
์ ๋ ฅ์ผ๋ก ๋ฐ์ ๋ ๊ฐ์ box์ union์ ๊ณ์ฐํ์ฌ ๋ฐํํ๋ค. union์ ๋ box๊ฐ ์ฐจ์งํ๋ ๋ฉด์ ์ ํฉ์น ๊ฐ์ด๋ค.
์ค๋ช :
์ ๋ ฅ์ผ๋ก ๋ฐ์ ๋ ๊ฐ์ box a, b์ ๋ํด์, ๊ฐ box์ ๋ฉด์ (w*h)์ ๋ํ ํ์ box_intersection() ํจ์๋ฅผ ํธ์ถํ์ฌ ๊ต์ฐจํ๋ ์์ญ์ ๋ฉด์ (i)์ ๊ตฌํ๋ค.
๊ทธ๋ฆฌ๊ณ ๋ box์ ๋ฉด์ ์ ํฉ์์ ๊ต์ฐจํ๋ ์์ญ(i)์ ๋บ ๊ฐ์ ๋ฐํํ๋ค.
์ด ๊ฐ์ด ์ ๋ ฅ์ผ๋ก ๋ฐ์ ๋ box์ union ๊ฐ์ด ๋๋ค.
box_iou
float box_iou(box a, box b)
{
return box_intersection(a, b)/box_union(a, b);
}
IOU๋ฅผ ๊ณ์ฐํฉ๋๋ค.
box_rmse
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));
}
ํจ์ ์ด๋ฆ: box_rmse
์ ๋ ฅ:
box ๊ตฌ์กฐ์ฒด์ธ a์ b
๋์:
๋ ๊ฐ์ box ๊ตฌ์กฐ์ฒด a์ b์ ์ขํ๊ฐ์ ์ด์ฉํ์ฌ root mean square error(RMSE)์ ๊ณ์ฐํ๋ค.
์ค๋ช :
box ๊ตฌ์กฐ์ฒด๋ ๋ฐ์ด๋ฉ ๋ฐ์ค๋ฅผ ๋ํ๋ด๋ ๊ตฌ์กฐ์ฒด์ด๋ค. ์ด ํจ์๋ ๋ ๊ฐ์ box ๊ตฌ์กฐ์ฒด a์ b๊ฐ ์ฃผ์ด์ก์ ๋, ๊ฐ ์ขํ๊ฐ(x, y, w, h)์ ์ด์ฉํ์ฌ RMSE๋ฅผ ๊ณ์ฐํ๋ค.
RMSE๋ ์์ธก๊ฐ๊ณผ ์ค์ ๊ฐ์ ์ฐจ์ด๋ฅผ ๊ณ์ฐํ ๋ ๋ง์ด ์ฌ์ฉ๋๋ฉฐ, ์ฐจ์ด์ ์ ๊ณฑ์ ํ๊ท ๋ด๊ณ ๋ค์ ๋ฃจํธ๋ฅผ ์์ด ๊ฐ์ด๋ค.
๋ฐ๋ผ์ ์ด ํจ์์์๋ ๊ฐ ์ขํ๊ฐ์ ์ฐจ์ด๋ฅผ ์ ๊ณฑํ์ฌ ํ๊ท ์ ๋ด๊ณ ๋ค์ ๋ฃจํธ๋ฅผ ์ทจํ ๊ฐ์ ๋ฐํํ๋ค.
derivative
dbox derivative(box a, box b)
{
dbox d;
d.dx = 0;
d.dw = 0;
float l1 = a.x - a.w/2;
float l2 = b.x - b.w/2;
if (l1 > l2){
d.dx -= 1;
d.dw += .5;
}
float r1 = a.x + a.w/2;
float r2 = b.x + b.w/2;
if(r1 < r2){
d.dx += 1;
d.dw += .5;
}
if (l1 > r2) {
d.dx = -1;
d.dw = 0;
}
if (r1 < l2){
d.dx = 1;
d.dw = 0;
}
d.dy = 0;
d.dh = 0;
float t1 = a.y - a.h/2;
float t2 = b.y - b.h/2;
if (t1 > t2){
d.dy -= 1;
d.dh += .5;
}
float b1 = a.y + a.h/2;
float b2 = b.y + b.h/2;
if(b1 < b2){
d.dy += 1;
d.dh += .5;
}
if (t1 > b2) {
d.dy = -1;
d.dh = 0;
}
if (b1 < t2){
d.dy = 1;
d.dh = 0;
}
return d;
}
ํจ์ ์ด๋ฆ: dbox derivative(box a, box b)
์ ๋ ฅ:
๋ฐ์ค a์ ๋ฐ์ค b
๋์:
์ ๋ ฅ๋ ๋ ์์์ ๊ต์ฐจ ์์ญ(intersection)์ ๋ํ ๋ฏธ๋ถ๊ฐ(๋ํจ์)์ ๊ณ์ฐํฉ๋๋ค.
์ค๋ช :
์์ a์ b์ ๊ต์ฐจ ์์ญ์ ๋ํ ๋ฏธ๋ถ๊ฐ(๋ํจ์)์ ๊ณ์ฐํ๊ธฐ ์ํด ์ ๋ ฅ๋ ๋ ์์์ ์์น, ๋๋น, ๋์ด๋ฅผ ์ด์ฉํ์ฌ l1, l2, r1, r2, t1, t2, b1, b2 ๋ณ์๋ฅผ ๊ณ์ฐํฉ๋๋ค.
l1, l2๋ ์์ a์ b์ ์ผ์ชฝ ๋ ์ขํ, r1, r2๋ ์์ a์ b์ ์ค๋ฅธ์ชฝ ๋ ์ขํ, t1, t2๋ ์์ a์ b์ ์์ชฝ ๋ ์ขํ, b1, b2๋ ์์ a์ b์ ์๋์ชฝ ๋ ์ขํ์ ๋๋ค.
๊ณ์ฐ๋ ๋ณ์๋ฅผ ์ด์ฉํ์ฌ ๊ต์ฐจ ์์ญ์ ๋ํ ๋ฏธ๋ถ๊ฐ(๋ํจ์)์ ๊ณ์ฐํฉ๋๋ค. ์์ a์ b์ ๊ต์ฐจ ์์ญ์ด ์์ ํ ๊ฒน์น์ง ์๋ ๊ฒฝ์ฐ, ๋ฏธ๋ถ๊ฐ์ 0์ด ๋ฉ๋๋ค.
ํจ์๋ ๊ต์ฐจ ์์ญ์ ๋ํ ๋ฏธ๋ถ๊ฐ(๋ํจ์)์ dbox ๊ตฌ์กฐ์ฒด์ ์ ์ฅํ์ฌ ๋ฐํํฉ๋๋ค. ๋ฐํ๋ ๋ฏธ๋ถ๊ฐ์ dintersect ํจ์์์ ๊ต์ฐจ ์์ญ์ ๋๋น์ ๋์ด๋ฅผ ์ด์ฉํ์ฌ ๊ณ์ฐ๋ ๊ต์ฐจ ์์ญ์ ๋ํ ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํ๋๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
dintersect
dbox dintersect(box a, box b)
{
float w = overlap(a.x, a.w, b.x, b.w);
float h = overlap(a.y, a.h, b.y, b.h);
dbox dover = derivative(a, b);
dbox di;
di.dw = dover.dw*h;
di.dx = dover.dx*h;
di.dh = dover.dh*w;
di.dy = dover.dy*w;
return di;
}
ํจ์ ์ด๋ฆ: dintersect
์ ๋ ฅ:
๋ฐ์ค a์ ๋ฐ์ค b
๋์:
์ ๋ ฅ๋ ๋ ์์์ ๊ต์ฐจ ์์ญ(intersection)์ ๊ณ์ฐํ๊ณ , ๊ต์ฐจ ์์ญ์ ๋๋น์ ๋์ด๋ฅผ ์ด์ฉํ์ฌ ๋ฏธ๋ถ๊ฐ(๋ํจ์)์ ๊ณ์ฐํฉ๋๋ค.
์ค๋ช :
์ ๋ ฅ๋ ๋ ์์์ ๊ต์ฐจ ์์ญ์ ๊ณ์ฐํ๊ธฐ ์ํด overlap ํจ์๋ฅผ ํธ์ถํฉ๋๋ค. overlap ํจ์๋ ๋ ๊ฐ์ ์ ๋ถ์ด ๊ฒน์น๋ ๊ธธ์ด(๋๋น ๋๋ ๋์ด)๋ฅผ ๊ณ์ฐํด์ฃผ๋ ํจ์์ ๋๋ค. overlap ํจ์๋ฅผ ์ด์ฉํ์ฌ ๊ต์ฐจ ์์ญ์ ๋๋น(w)์ ๋์ด(h)๋ฅผ ๊ตฌํ๊ณ , ์์ a์ b์ ๊ต์ฐจ ์์ญ์ ๋ํ ๋ฏธ๋ถ๊ฐ(๋ํจ์)์ ๊ณ์ฐํ๋ derivative ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.
derivative ํจ์๋ ์์ a์ b์ ๊ต์ฐจ ์์ญ์ ๋ํ ๋ฏธ๋ถ๊ฐ(๋ํจ์)์ ๊ณ์ฐํ๋ ํจ์๋ก, ์ ๋ ฅ๋ ๋ ์์์ ์์น, ๋๋น, ๋์ด๋ฅผ ์ด์ฉํ์ฌ ๊ณ์ฐํฉ๋๋ค. ๊ณ์ฐ๋ ๋ฏธ๋ถ๊ฐ์ ์ด์ฉํ์ฌ ์์ a์ b์ ๊ต์ฐจ ์์ญ์ ๋ํ ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํ๊ณ , ์ด ๊ฐ์ dbox ๊ตฌ์กฐ์ฒด์ ์ ์ฅํ์ฌ ๋ฐํํฉ๋๋ค.
๋ฐํ๋๋ dbox ๊ตฌ์กฐ์ฒด์๋ ๊ต์ฐจ ์์ญ์ ๋ํ ๋๋น์ ๋์ด์ ๋ํ ๋ฏธ๋ถ๊ฐ์ด ์ ์ฅ๋์ด ์์ต๋๋ค. ์ด ๊ฐ์ ์ด์ฉํ์ฌ ์ญ์ ํ(backpropagation)๋ฅผ ์ํํ๊ฑฐ๋, ์ต์ ํ(optimization) ์๊ณ ๋ฆฌ์ฆ์์ ๋ฏธ๋ถ๊ฐ์ ์ด์ฉํ์ฌ ๊ฒฝ์ฌํ๊ฐ๋ฒ(gradient descent) ๋ฑ์ ์ํํ ์ ์์ต๋๋ค.
dunion
dbox dunion(box a, box b)
{
dbox du;
dbox di = dintersect(a, b);
du.dw = a.h - di.dw;
du.dh = a.w - di.dh;
du.dx = -di.dx;
du.dy = -di.dy;
return du;
}
ํจ์ ์ด๋ฆ: dunion
์ ๋ ฅ: ๋ฐ์ค a์ ๋ฐ์ค b
๋์:
๋ฐ์ค a์ ๋ฐ์ค b์ ์ ๋์จ์ ๊ณ์ฐํ์ฌ, ๋ ๋ฐ์ค๋ฅผ ๋ชจ๋ ํฌํจํ๋ ๊ฐ์ฅ ์์ ๋ฐ์ค๋ฅผ ๋ฐํํฉ๋๋ค.
์ค๋ช :
์ ๋ ฅ์ผ๋ก ์ฃผ์ด์ง ๋ ๋ฐ์ค a, b์ ๋ํด์, ๋ ๋ฐ์ค๊ฐ ๊ณตํต์ผ๋ก ๊ฐ์ง๋ ์์ญ์ ๋์ด๋ฅผ ๊ณ์ฐํ๊ณ , ์ด๋ฅผ ์ด์ฉํ์ฌ ๋ ๋ฐ์ค๋ฅผ ๋ชจ๋ ํฌํจํ๋ ๊ฐ์ฅ ์์ ๋ฐ์ค์ ๋์ด๋ฅผ ๊ตฌํฉ๋๋ค.
์ดํ, du ๊ตฌ์กฐ์ฒด์ ์ด ์์ ๋ฐ์ค์ ํญ๊ณผ ๋์ด์ ์ฐจ์ด, ๊ทธ๋ฆฌ๊ณ ์ค์ฌ ์ขํ์ ์ฐจ์ด๋ฅผ ์ ์ฅํ์ฌ ๋ฐํํฉ๋๋ค.
์ด๋, dintersect ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ ๋ฐ์ค์ ์ธํฐ์น์ ์ ๊ณ์ฐํฉ๋๋ค.
test
void test_dunion()
{
box a = {0, 0, 1, 1};
box dxa= {0+.0001, 0, 1, 1};
box dya= {0, 0+.0001, 1, 1};
box dwa= {0, 0, 1+.0001, 1};
box dha= {0, 0, 1, 1+.0001};
box b = {.5, .5, .2, .2};
dbox di = dunion(a,b);
printf("Union: %f %f %f %f\n", di.dx, di.dy, di.dw, di.dh);
float inter = box_union(a, b);
float xinter = box_union(dxa, b);
float yinter = box_union(dya, b);
float winter = box_union(dwa, b);
float hinter = box_union(dha, b);
xinter = (xinter - inter)/(.0001);
yinter = (yinter - inter)/(.0001);
winter = (winter - inter)/(.0001);
hinter = (hinter - inter)/(.0001);
printf("Union Manual %f %f %f %f\n", xinter, yinter, winter, hinter);
}
void test_dintersect()
{
box a = {0, 0, 1, 1};
box dxa= {0+.0001, 0, 1, 1};
box dya= {0, 0+.0001, 1, 1};
box dwa= {0, 0, 1+.0001, 1};
box dha= {0, 0, 1, 1+.0001};
box b = {.5, .5, .2, .2};
dbox di = dintersect(a,b);
printf("Inter: %f %f %f %f\n", di.dx, di.dy, di.dw, di.dh);
float inter = box_intersection(a, b);
float xinter = box_intersection(dxa, b);
float yinter = box_intersection(dya, b);
float winter = box_intersection(dwa, b);
float hinter = box_intersection(dha, b);
xinter = (xinter - inter)/(.0001);
yinter = (yinter - inter)/(.0001);
winter = (winter - inter)/(.0001);
hinter = (hinter - inter)/(.0001);
printf("Inter Manual %f %f %f %f\n", xinter, yinter, winter, hinter);
}
void test_box()
{
test_dintersect();
test_dunion();
box a = {0, 0, 1, 1};
box dxa= {0+.00001, 0, 1, 1};
box dya= {0, 0+.00001, 1, 1};
box dwa= {0, 0, 1+.00001, 1};
box dha= {0, 0, 1, 1+.00001};
box b = {.5, 0, .2, .2};
float iou = box_iou(a,b);
iou = (1-iou)*(1-iou);
printf("%f\n", iou);
dbox d = diou(a, b);
printf("%f %f %f %f\n", d.dx, d.dy, d.dw, d.dh);
float xiou = box_iou(dxa, b);
float yiou = box_iou(dya, b);
float wiou = box_iou(dwa, b);
float hiou = box_iou(dha, b);
xiou = ((1-xiou)*(1-xiou) - iou)/(.00001);
yiou = ((1-yiou)*(1-yiou) - iou)/(.00001);
wiou = ((1-wiou)*(1-wiou) - iou)/(.00001);
hiou = ((1-hiou)*(1-hiou) - iou)/(.00001);
printf("manual %f %f %f %f\n", xiou, yiou, wiou, hiou);
}
Inter: 0.100000 0.100000 0.050000 0.050000
Inter Manual 0.100015 0.100015 0.050012 0.050012
Union: -0.100000 -0.100000 0.950000 0.950000
Union Manual -0.100136 -0.100136 0.950098 0.950098
IOU : 0.500000 0.000000 -0.800000 -0.800000
IOU manual : -0.390865 0.001386 -0.156757 0.039369
์คํ ๊ฒฐ๊ณผ ์ ๋๋ค. ๋ญ๊ฐ Inter, Union์ ๋ฏธ๋ถ ๊ฐ์ด ๋ค์ด ๋ง๋๋ฐ IOU๊ฐ ๋ค๋ฅธ ๊ฒ ๊ฐ์ต๋๋ค. ๋ฌธ์ ๋ฅผ ์ฐพ์๋ณด๋ test_iou์ diou๋ darknet์์ ๋์ํ์ง ์๋ ์ฝ๋๋ผ๊ณ ํฉ๋๋ค. ๊ทธ๋์ diou์ ๋ญ๋น ์ฝ๋๊ฐ ์๋๋ด ๋๋ค.
|| 1
์ด ๋ถ๋ถ์ ์ง์ฐ๊ณ ๋ค์ ์คํํ๋ฉด ์๋์ ๊ฐ์ด ๋์ต๋๋ค.
IOU: 0.392006 0.000000 0.158310 -0.037693
IOU manual -0.390865 0.001386 -0.156757 0.039369
ํจ์ ์ด๋ฆ: test_dunion()
์ ๋ ฅ: ์์
๋์: dunion() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋ฐ์ค์ ํฉ์งํฉ์ ๊ณ์ฐํ๊ณ , ์๋์ผ๋ก ๊ณ์ฐํ ๊ฐ๊ณผ ๋น๊ตํ์ฌ ์ ํ์ฑ์ ๊ฒ์ฆํฉ๋๋ค.
์ค๋ช : ๋ ๊ฐ์ ๋ฐ์ค๋ฅผ ์์ฑํ๊ณ , dunion() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ํฉ์งํฉ์ ๊ณ์ฐํฉ๋๋ค. ์ดํ, ์๋์ผ๋ก ์์ฑํ ๊ฐ๊ณผ ๋น๊ตํ์ฌ ์ ํ์ฑ์ ๊ฒ์ฆํฉ๋๋ค.
ํจ์ ์ด๋ฆ: test_dintersect()
์ ๋ ฅ: ์์
๋์: dintersect() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋ฐ์ค์ ๊ต์งํฉ์ ๊ณ์ฐํ๊ณ , ์๋์ผ๋ก ๊ณ์ฐํ ๊ฐ๊ณผ ๋น๊ตํ์ฌ ์ ํ์ฑ์ ๊ฒ์ฆํฉ๋๋ค.
์ค๋ช : ๋ ๊ฐ์ ๋ฐ์ค๋ฅผ ์์ฑํ๊ณ , dintersect() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ต์งํฉ์ ๊ณ์ฐํฉ๋๋ค. ์ดํ, ์๋์ผ๋ก ์์ฑํ ๊ฐ๊ณผ ๋น๊ตํ์ฌ ์ ํ์ฑ์ ๊ฒ์ฆํฉ๋๋ค.
ํจ์ ์ด๋ฆ: test_box()
์ ๋ ฅ: ์์
๋์: box_iou() ํจ์์ diou() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋ฐ์ค์ IoU(Intersection over Union) ๊ฐ์ ๊ณ์ฐํ๊ณ , ์๋์ผ๋ก ๊ณ์ฐํ ๊ฐ๊ณผ ๋น๊ตํ์ฌ ์ ํ์ฑ์ ๊ฒ์ฆํฉ๋๋ค.
์ค๋ช : ๋ ๊ฐ์ ๋ฐ์ค๋ฅผ ์์ฑํ๊ณ , box_iou() ํจ์์ diou() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ IoU ๊ฐ์ ๊ณ์ฐํฉ๋๋ค. ์ดํ, ์๋์ผ๋ก ์์ฑํ ๊ฐ๊ณผ ๋น๊ตํ์ฌ ์ ํ์ฑ์ ๊ฒ์ฆํฉ๋๋ค. ๋ํ, ์์ ์ ์ํ test_dunion() ํจ์์ test_dintersect() ํจ์๋ฅผ ํธ์ถํ์ฌ ํด๋น ํจ์๋ค์ ์ ํ์ฑ๋ ๊ฒ์ฆํฉ๋๋ค.
diou
dbox diou(box a, box b)
{
float u = box_union(a,b);
float i = box_intersection(a,b);
dbox di = dintersect(a,b);
dbox du = dunion(a,b);
dbox dd = {0,0,0,0};
if(i <= 0 || 1) { // ์ด์ํ ๋ญ๋น ์ฝ๋
dd.dx = b.x - a.x;
dd.dy = b.y - a.y;
dd.dw = b.w - a.w;
dd.dh = b.h - a.h;
return dd;
}
dd.dx = 2*pow((1-(i/u)),1)*(di.dx*u - du.dx*i)/(u*u);
dd.dy = 2*pow((1-(i/u)),1)*(di.dy*u - du.dy*i)/(u*u);
dd.dw = 2*pow((1-(i/u)),1)*(di.dw*u - du.dw*i)/(u*u);
dd.dh = 2*pow((1-(i/u)),1)*(di.dh*u - du.dh*i)/(u*u);
return dd;
}
ํจ์ ์ด๋ฆ: dbox_diou
์ ๋ ฅ:
๋ฐ์ค a์ ๋ฐ์ค b
๋์:
๋ ์์์ ๊ต์ฐจ ๋ถํผ(dbox_intersection)์ ํฉ์งํฉ ๋ถํผ(dbox_union)๋ฅผ ๊ณ์ฐํ ํ, ๊ต์ฐจํ ์์ญ์ ๋ฏธ๋ถ(dbox)์ ๊ตฌํฉ๋๋ค.
๊ต์ฐจ ๋ถํผ๊ฐ 0 ์ดํ๊ฑฐ๋ 1 ์ด์์ธ ๊ฒฝ์ฐ, ๋ ์์์ ์์น ์ฐจ์ด๋ฅผ ๋ฏธ๋ถํ ๊ฐ์ ๋ฐํํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด, ๋ ์์์ ๊ต์ฐจํ ์์ญ์ ๋น์จ์ ๋ฐ๋ผ ๋ฏธ๋ถ ๊ฐ์ ๊ณ์ฐํฉ๋๋ค.
์ค๋ช :
์ด ํจ์๋ ๋ ๊ฐ์ ์์์ ์์น์ ํฌ๊ธฐ ์ฐจ์ด์ ๋ํ ๋ฏธ๋ถ ๊ฐ์ ๊ณ์ฐํฉ๋๋ค.
์์์ ์์น์ ํฌ๊ธฐ ์ฐจ์ด๊ฐ ์์ ๊ฒฝ์ฐ, ์ด ๋ฏธ๋ถ ๊ฐ์ ์์๋ฅผ ์ด๋ํ๊ฑฐ๋ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ ๋ ํ์ํ ์ ๋ณด๊ฐ ๋ ์ ์์ต๋๋ค.
์ด ํจ์๋ YOLOv3์ ๊ฐ์ ๋ฅ๋ฌ๋ ๋ชจ๋ธ์์ ๋ฌผ์ฒด ๊ฒ์ถ๊ณผ ๊ฐ์ ์์ ์ ์ํํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
do_nms
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 < 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;
else probs[j][k] = 0;
}
}
}
}
}
ํจ์ ์ด๋ฆ: do_nms
์ ๋ ฅ:
boxes: ๋ฐ์ค ์ขํ ์ ๋ณด๋ฅผ ๋ด์ ๋ฐฐ์ด
probs: ๋ฐ์ค์ ๋ํ ๊ฐ ํด๋์ค์ ํ๋ฅ ์ ๋ณด๋ฅผ ๋ด์ 2์ฐจ์ ๋ฐฐ์ด
total: ์ ์ฒด ๋ฐ์ค์ ๊ฐ์
classes: ๋ถ๋ฅํ ํด๋์ค์ ๊ฐ์
thresh: IoU ์๊ณ๊ฐ
๋์:
๋ฐ์ค๋ค์ ํ๋์ฉ ๊ฒ์ฌํ๋ฉด์ ํด๋น ๋ฐ์ค๊ฐ ์ด๋ค ํด๋์ค์๋ ์ํ์ง ์์ผ๋ฉด ๋ค์ ๋ฐ์ค๋ฅผ ๊ฒ์ฌํ๋ค.
์ํ ํด๋์ค๊ฐ ์กด์ฌํ๋ ๋ฐ์ค๋ค ์ค IoU ๊ฐ์ด ์๊ณ๊ฐ(thresh)๋ณด๋ค ํฌ๋ค๋ฉด, ํ๋ฅ ๊ฐ์ด ์์ ๋ฐ์ค๋ ํด๋น ํด๋์ค์ ๋ํ ํ๋ฅ ๊ฐ์ 0์ผ๋ก ๋ง๋ ๋ค.
์ค๋ช :
Non-maximum suppression(NMS) ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ ํจ์๋ก, ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ํ๋ด๋ ์ค๋ณต๋ ๋ฐ์ค๋ฅผ ์ ๊ฑฐํ๋ ์ญํ ์ ํ๋ค.
์ ๋ ฅ์ผ๋ก ๋ฐ์ ๋ฐ์ค์ ํด๋์ค๋ณ ํ๋ฅ ์ ๋ณด๋ฅผ ์ด์ฉํด IoU ๊ฐ์ ๊ณ์ฐํ๊ณ , IoU ๊ฐ์ด ์๊ณ๊ฐ์ ๋๋ ๋ฐ์ค ์ค ํ๋ฅ ๊ฐ์ด ์์ ๋ฐ์ค๋ ์ ๊ฑฐํ๋ค.
์ด ๊ณผ์ ์ ๊ฑฐ์ณ ์ต์ข ์ ์ผ๋ก ๋จ์ ๋ฐ์ค๋ค์ ์ค๋ณต์ด ์ ๊ฑฐ๋ ํ๋ณด ๊ฐ์ฒด๋ค์ด ๋๋ค.
encode_box
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;
}
ํจ์ ์ด๋ฆ: encode_box
์ ๋ ฅ:
๋ฐ์ค a์ ๋ฐ์ค b
๋์:
์ ๋ ฅ์ผ๋ก ๋ฐ์ box b์ anchor๋ฅผ ์ด์ฉํ์ฌ bounding box ์ ๋ณด๋ฅผ ์ธ์ฝ๋ฉํฉ๋๋ค.
์ค๋ช :
encode_box ํจ์๋ bounding box regression์ ์ํด ์ ๋ ฅ์ผ๋ก ๋ฐ์ bounding box ์ ๋ณด์ anchor ์ ๋ณด๋ฅผ ์ด์ฉํ์ฌ bounding box ์ ๋ณด๋ฅผ ์ธ์ฝ๋ฉํฉ๋๋ค. ์ ๋ ฅ์ผ๋ก ๋ฐ์ b์ (x, y, w, h) ๊ฐ๊ณผ anchor์ (x, y, w, h) ๊ฐ์ ์ด์ฉํ์ฌ ์๋ก์ด bounding box ์ ๋ณด๋ฅผ ๊ณ์ฐํฉ๋๋ค. ์๋ก์ด bounding box ์ ๋ณด encode์ (x, y, w, h) ๊ฐ์ ๋ค์๊ณผ ๊ฐ์ด ๊ณ์ฐ๋ฉ๋๋ค.
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)
์ด๋ ๊ฒ ์ธ์ฝ๋ฉ๋ bounding box ์ ๋ณด๋ ๋ชจ๋ธ ํ์ต ์ bounding box regression์ ์ํํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
decode_box
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;
}
ํจ์ ์ด๋ฆ: decode_box
์ ๋ ฅ:
๋ฐ์ค a์ ๋ฐ์ค b
๋์:
anchor๋ฅผ ๊ธฐ์ค์ผ๋ก b์์ ๋์ฝ๋ฉ๋ box๋ฅผ ๋ฐํํฉ๋๋ค. x, y, w, h ๊ฐ์ ์๋ก ๊ณ์ฐํ์ฌ ๋ฐํํฉ๋๋ค.
์ค๋ช :
๋์ฝ๋ฉ์ ์ธ์ฝ๋ฉ๋ ์์์ ์ต์ปค ์์๋ฅผ ๊ธฐ์ค์ผ๋ก ์์ธก๋ ์์์ ์ขํ์ ํฌ๊ธฐ๋ฅผ ๋ณต์ํ๋ ์์ ์ ๋๋ค.
์ด ํจ์๋ ์ ๋ ฅ์ผ๋ก ๋ฐ์ ์ธ์ฝ๋ฉ๋ box b์ ์ต์ปค ์์ anchor๋ฅผ ์ด์ฉํ์ฌ ์์ธก๋ ์์์ ์ค์ ๊ฐ์ ๊ณ์ฐํ์ฌ box ๊ตฌ์กฐ์ฒด๋ก ๋ฐํํฉ๋๋ค.
x, y, w, h ๊ฐ์ ๊ณ์ฐํ๊ธฐ ์ํด ์ธ์ฝ๋ฉ๋ ๊ฐ b์ anchor ๊ฐ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๋ฐํ๋ ๊ฐ์ ๋์ฝ๋ฉ๋ ์์์ ์ขํ์ ํฌ๊ธฐ๋ฅผ ๋ํ๋ ๋๋ค.
Last updated
Was this helpful?