#include "darknet.h"
static int coco_ids[] = {1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,27,28,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,70,72,73,74,75,76,77,78,79,80,81,82,84,85,86,87,88,89,90};
train_detector
void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, int ngpus, int clear)
{
list *options = read_data_cfg(datacfg);
char *train_images = option_find_str(options, "train", "data/train.list");
char *backup_directory = option_find_str(options, "backup", "/backup/");
srand(time(0));
char *base = basecfg(cfgfile);
printf("%s\n", base);
float avg_loss = -1;
network **nets = calloc(ngpus, sizeof(network));
srand(time(0));
int seed = rand();
int i;
for(i = 0; i < ngpus; ++i){
srand(seed);
#ifdef GPU
cuda_set_device(gpus[i]);
#endif
nets[i] = load_network(cfgfile, weightfile, clear);
nets[i]->learning_rate *= ngpus;
}
srand(time(0));
network *net = nets[0];
int imgs = net->batch * net->subdivisions * ngpus;
printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", net->learning_rate, net->momentum, net->decay);
data train, buffer;
layer l = net->layers[net->n - 1];
int classes = l.classes;
float jitter = l.jitter;
list *plist = get_paths(train_images);
//int N = plist->size;
char **paths = (char **)list_to_array(plist);
load_args args = get_base_args(net);
args.coords = l.coords;
args.paths = paths;
args.n = imgs;
args.m = plist->size;
args.classes = classes;
args.jitter = jitter;
args.num_boxes = l.max_boxes;
args.d = &buffer;
args.type = DETECTION_DATA;
//args.type = INSTANCE_DATA;
args.threads = 64;
pthread_t load_thread = load_data(args);
double time;
int count = 0;
//while(i*imgs < N*120){
while(get_current_batch(net) < net->max_batches){
if(l.random && count++%10 == 0){
printf("Resizing\n");
int dim = (rand() % 10 + 10) * 32;
if (get_current_batch(net)+200 > net->max_batches) dim = 608;
//int dim = (rand() % 4 + 16) * 32;
printf("%d\n", dim);
args.w = dim;
args.h = dim;
pthread_join(load_thread, 0);
train = buffer;
free_data(train);
load_thread = load_data(args);
#pragma omp parallel for
for(i = 0; i < ngpus; ++i){
resize_network(nets[i], dim, dim);
}
net = nets[0];
}
time=what_time_is_it_now();
pthread_join(load_thread, 0);
train = buffer;
load_thread = load_data(args);
/*
int k;
for(k = 0; k < l.max_boxes; ++k){
box b = float_to_box(train.y.vals[10] + 1 + k*5);
if(!b.x) break;
printf("loaded: %f %f %f %f\n", b.x, b.y, b.w, b.h);
}
*/
/*
int zz;
for(zz = 0; zz < train.X.cols; ++zz){
image im = float_to_image(net->w, net->h, 3, train.X.vals[zz]);
int k;
for(k = 0; k < l.max_boxes; ++k){
box b = float_to_box(train.y.vals[zz] + k*5, 1);
printf("%f %f %f %f\n", b.x, b.y, b.w, b.h);
draw_bbox(im, b, 1, 1,0,0);
}
show_image(im, "truth11");
cvWaitKey(0);
save_image(im, "truth11");
}
*/
printf("Loaded: %lf seconds\n", what_time_is_it_now()-time);
time=what_time_is_it_now();
float loss = 0;
#ifdef GPU
if(ngpus == 1){
loss = train_network(net, train);
} else {
loss = train_networks(nets, ngpus, train, 4);
}
#else
loss = train_network(net, train);
#endif
if (avg_loss < 0) avg_loss = loss;
avg_loss = avg_loss*.9 + loss*.1;
i = get_current_batch(net);
printf("%ld: %f, %f avg, %f rate, %lf seconds, %d images\n", get_current_batch(net), loss, avg_loss, get_current_rate(net), what_time_is_it_now()-time, i*imgs);
if(i%100==0){
#ifdef GPU
if(ngpus != 1) sync_nets(nets, ngpus, 0);
#endif
char buff[256];
sprintf(buff, "%s/%s.backup", backup_directory, base);
save_weights(net, buff);
}
if(i%10000==0 || (i < 1000 && i%100 == 0)){
#ifdef GPU
if(ngpus != 1) sync_nets(nets, ngpus, 0);
#endif
char buff[256];
sprintf(buff, "%s/%s_%d.weights", backup_directory, base, i);
save_weights(net, buff);
}
free_data(train);
}
#ifdef GPU
if(ngpus != 1) sync_nets(nets, ngpus, 0);
#endif
char buff[256];
sprintf(buff, "%s/%s_final.weights", backup_directory, base);
save_weights(net, buff);
}
ํจ์ ์ด๋ฆ: train_detector
์
๋ ฅ:
datacfg: ๋ฌธ์์ด ํฌ์ธํฐ, ๋ฐ์ดํฐ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ cfg ํ์ผ ๊ฒฝ๋ก
cfgfile: ๋ฌธ์์ด ํฌ์ธํฐ, ๋ชจ๋ธ์ ๊ตฌ์กฐ๋ฅผ ์ง์ ํ๋ .cfg ํ์ผ ๊ฒฝ๋ก
weightfile: ๋ฌธ์์ด ํฌ์ธํฐ, ์ฌ์ ํ์ต๋ ๋ชจ๋ธ์ ๊ฐ์ค์น ํ์ผ ๊ฒฝ๋ก
gpus: ์ ์ ํฌ์ธํฐ, ์ฌ์ฉํ GPU ๋๋ฐ์ด์ค ๋ฒํธ ๋ฐฐ์ด
ngpus: ์ ์, ์ฌ์ฉํ GPU ๋๋ฐ์ด์ค ์
clear: ์ ์, 1์ด๋ฉด ๋คํธ์ํฌ์ ์ด์ ์ํ๋ฅผ ์ง์ฐ๊ณ ์๋ก์ด ์ํ๋ก ์์, 0์ด๋ฉด ๊ณ์ ์ด์ด์ ํ์ต
๋์:
์
๋ ฅ์ผ๋ก ์ฃผ์ด์ง ๋ฐ์ดํฐ(cfg, cfgfile, weightfile)๋ฅผ ์ด์ฉํ์ฌ ๋คํธ์ํฌ ๋ชจ๋ธ์ ํ์ต์ํค๋ ํจ์์
๋๋ค.
์
๋ ฅ์ผ๋ก ๋ฐ์ ngpus ๊ฐ์๋งํผ์ GPU ๋๋ฐ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ณ๋ ฌ ํ์ต์ ์ํํฉ๋๋ค.
ํ์ต ์ค์๋ ์
๋ ฅ ์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ๋คํธ์ํฌ์ ์
๋ ฅ์ผ๋ก ์ ๊ณตํ๊ณ , ๊ทธ์ ๋ฐ๋ฅธ ์์ค ๊ฐ์ ๊ณ์ฐํ์ฌ ๊ฐ์ค์น๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค.
ํ์ต ์ค์๋ ์ค๊ฐ์ค๊ฐ์ ๋คํธ์ํฌ์ ๊ฐ์ค์น๋ฅผ ์ ์ฅํ ์๋ ์์ต๋๋ค.
์ค๋ช
:
์ด ํจ์๋ darknet ํ๋ ์์ํฌ์์ ์ฌ์ฉ๋๋ ํจ์๋ก, YOLO ๊ฐ์ฒด ๊ฒ์ถ ์๊ณ ๋ฆฌ์ฆ์ ํ์ต์ํค๋๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
์ด ํจ์๋ ์
๋ ฅ์ผ๋ก ๋ฐ์ cfg, cfgfile, weightfile์ ์ด์ฉํ์ฌ ๋คํธ์ํฌ ๋ชจ๋ธ์ ์ด๊ธฐํํ ํ, ngpus ๊ฐ์๋งํผ์ GPU๋ฅผ ์ฌ์ฉํ์ฌ ๋คํธ์ํฌ๋ฅผ ๋ณ๋ ฌ ํ์ต์ํต๋๋ค.
์ด ํจ์์์ ์ฌ์ฉํ๋ load_data ํจ์๋ ๋ฐ์ดํฐ๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๋ก๋ํ๋ฉฐ, ๊ทธ์ ๋ฐ๋ฅธ ์๋ ํฅ์์ ๊ฐ์ ธ์ต๋๋ค.
ํจ์ ๋ด๋ถ์์๋ ๋คํธ์ํฌ์ ํ์ต๋ฅ , ๋ชจ๋ฉํ
, ๊ฐ์ค์น ๊ฐ์ ๊ณ์ ๋ฑ์ ์ถ๋ ฅํ๋ฉฐ, ํ์ต์ด ์งํ๋จ์ ๋ฐ๋ผ ํ์ฌ๊น์ง์ ํ๊ท ์์ค ๊ฐ์ ์ถ๋ ฅํฉ๋๋ค.
ํ์ต ์ค์๋ ๋คํธ์ํฌ์ ๊ฐ์ค์น๋ฅผ ์ ์ฅํ์ฌ, ํ์ต์ ์ค๋จํ๊ณ ๋ค์ ์์ํ ๋ ์ด์ ์ํ์์ ์ด์ด์ ํ์ตํ ์ ์๋๋ก ํฉ๋๋ค.
get_coco_image_id
static int get_coco_image_id(char *filename)
{
char *p = strrchr(filename, '/');
char *c = strrchr(filename, '_');
if(c) p = c;
return atoi(p+1);
}
ํจ์ ์ด๋ฆ: get_coco_image_id
์
๋ ฅ:
filename (๋ฌธ์์ด ํฌ์ธํฐ)
๋์:
์
๋ ฅ๋ ํ์ผ ๊ฒฝ๋ก์์ ๋ง์ง๋ง์ผ๋ก '/'๊ฐ ๋ฑ์ฅํ๋ ์์น์ '_'๊ฐ ๋ฑ์ฅํ๋ ์์น๋ฅผ ์ฐพ์, ๊ทธ ์ค ๋ ๋์ค์ ๋ฑ์ฅํ ์์น๋ฅผ p ๋ณ์์ ์ ์ฅํ๋ค. ๋ง์ฝ '_'๊ฐ ์กด์ฌํ๋ค๋ฉด, p ๋ณ์๋ฅผ c ๋ณ์๋ก ๋์ฒดํ๋ค.
๊ทธ๋ฆฌ๊ณ p ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ๋ฌธ์์ด์์ ์ซ์ ๋ถ๋ถ์ ์ถ์ถํ์ฌ ์ ์ํ์ผ๋ก ๋ฐํํ๋ค.
์ค๋ช
:
COCO ๋ฐ์ดํฐ์
์์ ์ด๋ฏธ์ง ํ์ผ ์ด๋ฆ์ ์ผ๋ถ์๋ ํด๋น ์ด๋ฏธ์ง์ ID ๊ฐ์ด ํฌํจ๋์ด ์๋ค.
์ด ํจ์๋ ํ์ผ ์ด๋ฆ์์ ID ๊ฐ์ ์ถ์ถํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค.
์
๋ ฅ์ผ๋ก๋ ํ์ผ ์ด๋ฆ์ ์ ๋ฌํ๋ฉฐ, ํ์ผ ์ด๋ฆ์ ํฌํจ๋ ID ๊ฐ์ ์ ์ํ์ผ๋ก ๋ฐํํ๋ค.
print_cocos
static void print_cocos(FILE *fp, char *image_path, detection *dets, int num_boxes, int classes, int w, int h)
{
int i, j;
int image_id = get_coco_image_id(image_path);
for(i = 0; i < num_boxes; ++i){
float xmin = dets[i].bbox.x - dets[i].bbox.w/2.;
float xmax = dets[i].bbox.x + dets[i].bbox.w/2.;
float ymin = dets[i].bbox.y - dets[i].bbox.h/2.;
float ymax = dets[i].bbox.y + dets[i].bbox.h/2.;
if (xmin < 0) xmin = 0;
if (ymin < 0) ymin = 0;
if (xmax > w) xmax = w;
if (ymax > h) ymax = h;
float bx = xmin;
float by = ymin;
float bw = xmax - xmin;
float bh = ymax - ymin;
for(j = 0; j < classes; ++j){
if (dets[i].prob[j]) fprintf(fp, "{\"image_id\":%d, \"category_id\":%d, \"bbox\":[%f, %f, %f, %f], \"score\":%f},\n", image_id, coco_ids[j], bx, by, bw, bh, dets[i].prob[j]);
}
}
}
ํจ์ ์ด๋ฆ: print_cocos
์
๋ ฅ:
FILE *fp: ์ถ๋ ฅ ํ์ผ ํฌ์ธํฐ
char *image_path: ์ด๋ฏธ์ง ํ์ผ ๊ฒฝ๋ก
detection *dets: ๊ฐ์ฒด ๊ฒ์ถ ๊ฒฐ๊ณผ ๋ฐฐ์ด ํฌ์ธํฐ
int num_boxes: ๊ฒ์ถ๋ ๊ฐ์ฒด์ ์
int classes: ํด๋์ค์ ์
int h: ์ด๋ฏธ์ง์ ๋์ด
๋์:
COCO ํ์์ผ๋ก ๊ฒ์ถ๋ ๊ฐ์ฒด๋ฅผ ์ถ๋ ฅ ํ์ผ์ ์ฐ๋ ํจ์์ด๋ค.
get_coco_image_id ํจ์๋ฅผ ์ด์ฉํ์ฌ ์ด๋ฏธ์ง์ ID๋ฅผ ๊ฐ์ ธ์จ๋ค.
๊ฐ ๊ฐ์ฒด์ ๋ํด ๊ฒฝ๊ณ ์์(bounding box)๋ฅผ COCO ํ์์ผ๋ก ๋ณํํ์ฌ ์ถ๋ ฅ ํ์ผ์ ์ด๋ค.
์ค๋ช
:
ํจ์๋ COCO ํ์์ผ๋ก ๊ฒ์ถ๋ ๊ฐ์ฒด๋ฅผ ์ถ๋ ฅ ํ์ผ์ ์ด๋ค.
๋จผ์ ์ด๋ฏธ์ง ๊ฒฝ๋ก๋ฅผ ์ด์ฉํ์ฌ ์ด๋ฏธ์ง ID๋ฅผ ๊ฐ์ ธ์จ๋ค.
๊ฐ ๊ฐ์ฒด์ ๊ฒฝ๊ณ ์์๋ฅผ COCO ํ์์ผ๋ก ๋ณํํ์ฌ ์ถ๋ ฅ ํ์ผ์ ์ด๋ค.
์ถ๋ ฅ ํ์ผ์๋ "image_id", "category_id", "bbox", "score"์ ์ ๋ณด๊ฐ ํฌํจ๋๋ค.
์ถ๋ ฅ ํ์ผ์ JSON ํ์์ผ๋ก ์์ฑ๋๋ค.
๊ฐ ๊ฐ์ฒด์ ํ๋ฅ (prob)์ด 0๋ณด๋ค ํฐ ๊ฒฝ์ฐ์๋ง ์ถ๋ ฅ๋๋ค.
print_detector_detections
void print_detector_detections(FILE **fps, char *id, detection *dets, int total, int classes, int w, int h)
{
int i, j;
for(i = 0; i < total; ++i){
float xmin = dets[i].bbox.x - dets[i].bbox.w/2. + 1;
float xmax = dets[i].bbox.x + dets[i].bbox.w/2. + 1;
float ymin = dets[i].bbox.y - dets[i].bbox.h/2. + 1;
float ymax = dets[i].bbox.y + dets[i].bbox.h/2. + 1;
if (xmin < 1) xmin = 1;
if (ymin < 1) ymin = 1;
if (xmax > w) xmax = w;
if (ymax > h) ymax = h;
for(j = 0; j < classes; ++j){
if (dets[i].prob[j]) fprintf(fps[j], "%s %f %f %f %f %f\n", id, dets[i].prob[j],
xmin, ymin, xmax, ymax);
}
}
}
ํจ์ ์ด๋ฆ: print_detector_detections
์
๋ ฅ:
FILE **fps: ์ถ๋ ฅ ํ์ผ ํฌ์ธํฐ์ ๋ฐฐ์ด
detection *dets: ๊ฐ์ฒด ํ์ง ๊ฒฐ๊ณผ ๋ฐฐ์ด
int total: ๊ฐ์ฒด ํ์ง ๊ฒฐ๊ณผ ๋ฐฐ์ด์ ํฌ๊ธฐ
int classes: ํด๋์ค ์
int w: ์ด๋ฏธ์ง ๊ฐ๋ก ๊ธธ์ด
int h: ์ด๋ฏธ์ง ์ธ๋ก ๊ธธ์ด
๋์:
๊ฐ์ฒด ํ์ง ๊ฒฐ๊ณผ(detection) ๋ฐฐ์ด์ ๊ฐ์ ธ์์, ์ด๋ฏธ์ง์ ID, ํด๋์ค, ๋ฐ์ค ์ขํ(x, y, w, h) ๋ฐ ํด๋์ค ํ๋ฅ ์ ํฌํจํ๋ ํ
์คํธ ํ์ผ์ ์ถ๋ ฅํ๋ค.
์ค๋ช
:
ํจ์๋ ๊ฐ์ฒด ํ์ง ๊ฒฐ๊ณผ(detection)๋ฅผ ๊ฐ์ ธ์์, ํด๋น ๊ฐ์ฒด๊ฐ ์ํ ํด๋์ค์ ํ
์คํธ ํ์ผ ํฌ์ธํฐ๋ฅผ ๊ฐ์ ธ์จ๋ค.
๊ทธ๋ฆฌ๊ณ ํด๋น ๊ฐ์ฒด์ ํด๋์ค ํ๋ฅ ์ด 0์ด ์๋ ๊ฒฝ์ฐ, ๊ฐ์ฒด์ ์ด๋ฏธ์ง ID, ํด๋์ค ID, ๋ฐ์ค ์ขํ(x, y, w, h) ๋ฐ ํด๋์ค ํ๋ฅ ์ ํด๋น ํด๋์ค์ ํ
์คํธ ํ์ผ์ ์ถ๋ ฅํ๋ค.
๋ฐ์ค ์ขํ๋ ์ด๋ฏธ์ง์ ๊ฒฝ๊ณ๋ฅผ ๋ฒ์ด๋์ง ์๋๋ก ์กฐ์ ๋๋ค.
์ด ํจ์๋ YOLO ์๊ณ ๋ฆฌ์ฆ์ ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ๊ฐ์ฒด ํ์ง ์๊ณ ๋ฆฌ์ฆ์์ ์ฌ์ฉ๋๋ค.
print_imagenet_detections
void print_imagenet_detections(FILE *fp, int id, detection *dets, int total, int classes, int w, int h)
{
int i, j;
for(i = 0; i < total; ++i){
float xmin = dets[i].bbox.x - dets[i].bbox.w/2.;
float xmax = dets[i].bbox.x + dets[i].bbox.w/2.;
float ymin = dets[i].bbox.y - dets[i].bbox.h/2.;
float ymax = dets[i].bbox.y + dets[i].bbox.h/2.;
if (xmin < 0) xmin = 0;
if (ymin < 0) ymin = 0;
if (xmax > w) xmax = w;
if (ymax > h) ymax = h;
for(j = 0; j < classes; ++j){
int class = j;
if (dets[i].prob[class]) fprintf(fp, "%d %d %f %f %f %f %f\n", id, j+1, dets[i].prob[class],
xmin, ymin, xmax, ymax);
}
}
}
ํจ์ ์ด๋ฆ: print_imagenet_detections
์
๋ ฅ:
FILE* fp: ์ถ๋ ฅ ํ์ผ ํฌ์ธํฐ
detection* dets: ๊ฐ์ฒด ๊ฒ์ถ ๊ฒฐ๊ณผ
int classes: ํด๋์ค ๊ฐ์
int w: ์ด๋ฏธ์ง ๊ฐ๋ก ํฌ๊ธฐ
int h: ์ด๋ฏธ์ง ์ธ๋ก ํฌ๊ธฐ
๋์:
์ด๋ฏธ์ง๋ท ํฌ๋งท์ผ๋ก ๊ฐ์ฒด ๊ฒ์ถ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ ํจ์์ด๋ค.
๊ฐ ๊ฐ์ฒด์ ์ขํ์ ํด๋์ค๋ณ ํ๋ฅ ์ ์ถ๋ ฅ ํ์ผ ํฌ์ธํฐ์ ์ด๋ค.
์ค๋ช
:
ํจ์ ๋ด๋ถ์์ for๋ฌธ์ ๋๋ฉด์, ๋ชจ๋ ๊ฐ์ฒด์ ๋ํด ์๋์ ์์
์ ์ํํ๋ค.
๊ฐ์ฒด์ bounding box ์ขํ๋ฅผ xmin, ymin, xmax, ymax ๋ณ์์ ์ ์ฅํ๋ค.
์ด๋ฏธ์ง ๊ฒฝ๊ณ๋ฅผ ๋ฒ์ด๋๋ ๊ฒฝ์ฐ, ๊ฒฝ๊ณ ๋ด๋ถ๋ก ์กฐ์ ํ๋ค.
ํด๋์ค ๊ฐ์๋งํผ for๋ฌธ์ ๋๋ฉฐ, ํด๋น ํด๋์ค์ ํ๋ฅ ์ด 0์ด ์๋ ๊ฒฝ์ฐ, ์ถ๋ ฅ ํ์ผ ํฌ์ธํฐ์ ๊ฐ์ฒด ์ ๋ณด๋ฅผ ์ด๋ค.
์ด๋ฏธ์ง ID, ํด๋์ค ID, ํ๋ฅ , xmin, ymin, xmax, ymax ์์ผ๋ก ์ถ๋ ฅํ๋ค.
validate_detector_flip
void validate_detector_flip(char *datacfg, char *cfgfile, char *weightfile, char *outfile)
{
int j;
list *options = read_data_cfg(datacfg);
char *valid_images = option_find_str(options, "valid", "data/train.list");
char *name_list = option_find_str(options, "names", "data/names.list");
char *prefix = option_find_str(options, "results", "results");
char **names = get_labels(name_list);
char *mapf = option_find_str(options, "map", 0);
int *map = 0;
if (mapf) map = read_map(mapf);
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 2);
fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net->learning_rate, net->momentum, net->decay);
srand(time(0));
list *plist = get_paths(valid_images);
char **paths = (char **)list_to_array(plist);
layer l = net->layers[net->n-1];
int classes = l.classes;
char buff[1024];
char *type = option_find_str(options, "eval", "voc");
FILE *fp = 0;
FILE **fps = 0;
int coco = 0;
int imagenet = 0;
if(0==strcmp(type, "coco")){
if(!outfile) outfile = "coco_results";
snprintf(buff, 1024, "%s/%s.json", prefix, outfile);
fp = fopen(buff, "w");
fprintf(fp, "[\n");
coco = 1;
} else if(0==strcmp(type, "imagenet")){
if(!outfile) outfile = "imagenet-detection";
snprintf(buff, 1024, "%s/%s.txt", prefix, outfile);
fp = fopen(buff, "w");
imagenet = 1;
classes = 200;
} else {
if(!outfile) outfile = "comp4_det_test_";
fps = calloc(classes, sizeof(FILE *));
for(j = 0; j < classes; ++j){
snprintf(buff, 1024, "%s/%s%s.txt", prefix, outfile, names[j]);
fps[j] = fopen(buff, "w");
}
}
int m = plist->size;
int i=0;
int t;
float thresh = .005;
float nms = .45;
int nthreads = 4;
image *val = calloc(nthreads, sizeof(image));
image *val_resized = calloc(nthreads, sizeof(image));
image *buf = calloc(nthreads, sizeof(image));
image *buf_resized = calloc(nthreads, sizeof(image));
pthread_t *thr = calloc(nthreads, sizeof(pthread_t));
image input = make_image(net->w, net->h, net->c*2);
load_args args = {0};
args.w = net->w;
args.h = net->h;
//args.type = IMAGE_DATA;
args.type = LETTERBOX_DATA;
for(t = 0; t < nthreads; ++t){
args.path = paths[i+t];
args.im = &buf[t];
args.resized = &buf_resized[t];
thr[t] = load_data_in_thread(args);
}
double start = what_time_is_it_now();
for(i = nthreads; i < m+nthreads; i += nthreads){
fprintf(stderr, "%d\n", i);
for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
pthread_join(thr[t], 0);
val[t] = buf[t];
val_resized[t] = buf_resized[t];
}
for(t = 0; t < nthreads && i+t < m; ++t){
args.path = paths[i+t];
args.im = &buf[t];
args.resized = &buf_resized[t];
thr[t] = load_data_in_thread(args);
}
for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
char *path = paths[i+t-nthreads];
char *id = basecfg(path);
copy_cpu(net->w*net->h*net->c, val_resized[t].data, 1, input.data, 1);
flip_image(val_resized[t]);
copy_cpu(net->w*net->h*net->c, val_resized[t].data, 1, input.data + net->w*net->h*net->c, 1);
network_predict(net, input.data);
int w = val[t].w;
int h = val[t].h;
int num = 0;
detection *dets = get_network_boxes(net, w, h, thresh, .5, map, 0, &num);
if (nms) do_nms_sort(dets, num, classes, nms);
if (coco){
print_cocos(fp, path, dets, num, classes, w, h);
} else if (imagenet){
print_imagenet_detections(fp, i+t-nthreads+1, dets, num, classes, w, h);
} else {
print_detector_detections(fps, id, dets, num, classes, w, h);
}
free_detections(dets, num);
free(id);
free_image(val[t]);
free_image(val_resized[t]);
}
}
for(j = 0; j < classes; ++j){
if(fps) fclose(fps[j]);
}
if(coco){
fseek(fp, -2, SEEK_CUR);
fprintf(fp, "\n]\n");
fclose(fp);
}
fprintf(stderr, "Total Detection Time: %f Seconds\n", what_time_is_it_now() - start);
}
ํจ์ ์ด๋ฆ: validate_detector_flip
์
๋ ฅ:
datacfg: ๋ฐ์ดํฐ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ ๋ฌธ์์ด ํฌ์ธํฐ
cfgfile: ๋ชจ๋ธ ๊ตฌ์ฑ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ ๋ฌธ์์ด ํฌ์ธํฐ
weightfile: ๋ชจ๋ธ ๊ฐ์ค์น ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ ๋ฌธ์์ด ํฌ์ธํฐ
outfile: ์ถ๋ ฅ ํ์ผ ์ด๋ฆ์ ์ง์ ํ๋ ๋ฌธ์์ด ํฌ์ธํฐ
๋์:
์ฃผ์ด์ง ๋ชจ๋ธ ํ์ผ(cfgfile, weightfile)๊ณผ ๋ฐ์ดํฐ ํ์ผ(datacfg)์ ์ฌ์ฉํ์ฌ ๋คํธ์ํฌ๋ฅผ ๋ก๋ํฉ๋๋ค.
valid_images์ ์ง์ ๋ ๊ฒฝ๋ก์์ ์ด๋ฏธ์ง ๋ฆฌ์คํธ๋ฅผ ์ฝ์ด๋ค์
๋๋ค.
name_list์ ์ง์ ๋ ๊ฒฝ๋ก์์ ํด๋์ค ์ด๋ฆ ๋ฆฌ์คํธ๋ฅผ ์ฝ์ด๋ค์
๋๋ค.
coco ๋๋ imagenet ํ๊ฐ ๋ฐฉ์์ด ์ง์ ๋๋ฉด ๊ฐ๊ฐ coco_results ๋๋ imagenet-detection ํ์ผ์ ์ถ๋ ฅํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด comp4_det_test_ ์ด๋ฆ์ผ๋ก ํด๋์ค๋ง๋ค ๊ฐ๋ณ ์ถ๋ ฅ ํ์ผ์ ์์ฑํฉ๋๋ค.
์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ๋ค์ด๊ณ ๋คํธ์ํฌ์์ ์์ธกํฉ๋๋ค.
๋ค์ค ์ค๋ ๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๋ถ๋ฌ๋ค์
๋๋ค.
์์ธก๋ ๊ฒฐ๊ณผ์ ๋ํด nms(non-maximum suppression) ๋ฐ ํด๋์ค๋ณ๋ก ์ ๋ ฌ์ ์ํํฉ๋๋ค.
์ค๋ช
:
์ด ํจ์๋ Darknet ํ๋ ์์ํฌ์ YOLO ๊ฐ์ฒด ๊ฒ์ถ ๋ชจ๋ธ์ ์ฑ๋ฅ์ ํ๊ฐํ๋ ํจ์์
๋๋ค.
validate_detector ํจ์์ ์ ์ฌํ์ง๋ง, ์ด๋ฏธ์ง๋ฅผ ์ํ ๋ฐฉํฅ์ผ๋ก ๋ค์ง์ด์ ๋ค์ ์์ธกํ๋ "flip" ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์์ต๋๋ค.
๋ค์ค ์ค๋ ๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ์ฌ ์ฒ๋ฆฌ ์๋๋ฅผ ๋์
๋๋ค.
์ถ๋ ฅ ํ์ผ์ ํ์์ coco ๋๋ imagenet ๋ฐฉ์์ ๋ฐ๋ฅด๊ฑฐ๋ ํด๋์ค๋ณ๋ก ๊ฐ๋ณ ํ์ผ๋ก ์ถ๋ ฅํ ์ ์์ต๋๋ค.
validate_detector
void validate_detector(char *datacfg, char *cfgfile, char *weightfile, char *outfile)
{
int j;
list *options = read_data_cfg(datacfg);
char *valid_images = option_find_str(options, "valid", "data/train.list");
char *name_list = option_find_str(options, "names", "data/names.list");
char *prefix = option_find_str(options, "results", "results");
char **names = get_labels(name_list);
char *mapf = option_find_str(options, "map", 0);
int *map = 0;
if (mapf) map = read_map(mapf);
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net->learning_rate, net->momentum, net->decay);
srand(time(0));
list *plist = get_paths(valid_images);
char **paths = (char **)list_to_array(plist);
layer l = net->layers[net->n-1];
int classes = l.classes;
char buff[1024];
char *type = option_find_str(options, "eval", "voc");
FILE *fp = 0;
FILE **fps = 0;
int coco = 0;
int imagenet = 0;
if(0==strcmp(type, "coco")){
if(!outfile) outfile = "coco_results";
snprintf(buff, 1024, "%s/%s.json", prefix, outfile);
fp = fopen(buff, "w");
fprintf(fp, "[\n");
coco = 1;
} else if(0==strcmp(type, "imagenet")){
if(!outfile) outfile = "imagenet-detection";
snprintf(buff, 1024, "%s/%s.txt", prefix, outfile);
fp = fopen(buff, "w");
imagenet = 1;
classes = 200;
} else {
if(!outfile) outfile = "comp4_det_test_";
fps = calloc(classes, sizeof(FILE *));
for(j = 0; j < classes; ++j){
snprintf(buff, 1024, "%s/%s%s.txt", prefix, outfile, names[j]);
fps[j] = fopen(buff, "w");
}
}
int m = plist->size;
int i=0;
int t;
float thresh = .005;
float nms = .45;
int nthreads = 4;
image *val = calloc(nthreads, sizeof(image));
image *val_resized = calloc(nthreads, sizeof(image));
image *buf = calloc(nthreads, sizeof(image));
image *buf_resized = calloc(nthreads, sizeof(image));
pthread_t *thr = calloc(nthreads, sizeof(pthread_t));
load_args args = {0};
args.w = net->w;
args.h = net->h;
//args.type = IMAGE_DATA;
args.type = LETTERBOX_DATA;
for(t = 0; t < nthreads; ++t){
args.path = paths[i+t];
args.im = &buf[t];
args.resized = &buf_resized[t];
thr[t] = load_data_in_thread(args);
}
double start = what_time_is_it_now();
for(i = nthreads; i < m+nthreads; i += nthreads){
fprintf(stderr, "%d\n", i);
for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
pthread_join(thr[t], 0);
val[t] = buf[t];
val_resized[t] = buf_resized[t];
}
for(t = 0; t < nthreads && i+t < m; ++t){
args.path = paths[i+t];
args.im = &buf[t];
args.resized = &buf_resized[t];
thr[t] = load_data_in_thread(args);
}
for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
char *path = paths[i+t-nthreads];
char *id = basecfg(path);
float *X = val_resized[t].data;
network_predict(net, X);
int w = val[t].w;
int h = val[t].h;
int nboxes = 0;
detection *dets = get_network_boxes(net, w, h, thresh, .5, map, 0, &nboxes);
if (nms) do_nms_sort(dets, nboxes, classes, nms);
if (coco){
print_cocos(fp, path, dets, nboxes, classes, w, h);
} else if (imagenet){
print_imagenet_detections(fp, i+t-nthreads+1, dets, nboxes, classes, w, h);
} else {
print_detector_detections(fps, id, dets, nboxes, classes, w, h);
}
free_detections(dets, nboxes);
free(id);
free_image(val[t]);
free_image(val_resized[t]);
}
}
for(j = 0; j < classes; ++j){
if(fps) fclose(fps[j]);
}
if(coco){
fseek(fp, -2, SEEK_CUR);
fprintf(fp, "\n]\n");
fclose(fp);
}
fprintf(stderr, "Total Detection Time: %f Seconds\n", what_time_is_it_now() - start);
}
ํจ์ ์ด๋ฆ: validate_detector
์
๋ ฅ:
char *datacfg: ๋ฐ์ดํฐ ๊ตฌ์ฑ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฌธ์์ด ํฌ์ธํฐ
char *cfgfile: ๋ชจ๋ธ ๊ตฌ์ฑ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฌธ์์ด ํฌ์ธํฐ
char *weightfile: ๋ชจ๋ธ ๊ฐ์ค์น ํ์ผ ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฌธ์์ด ํฌ์ธํฐ
char *outfile: ์ถ๋ ฅ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฌธ์์ด ํฌ์ธํฐ
๋์:
์ฃผ์ด์ง ๋ชจ๋ธ๊ณผ ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ์ฌ ๊ฒ์ถ๊ธฐ(valid detector)๋ฅผ ๊ฒ์ฆํ๋ ํจ์์
๋๋ค.
ํจ์๋ ์
๋ ฅ๋ ๋ฐ์ดํฐ ๊ตฌ์ฑ ํ์ผ, ๋ชจ๋ธ ๊ตฌ์ฑ ํ์ผ, ๋ชจ๋ธ ๊ฐ์ค์น ํ์ผ, ์ถ๋ ฅ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ชจ๋ธ์ ๋ก๋ํ๊ณ , ๊ฒ์ฆ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
๊ฐ์ ธ์จ ๊ฒ์ฆ ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ์ฌ ๋ชจ๋ธ์ ํ๊ฐํ๊ณ , ๊ฐ ๊ฐ์ฒด ๊ฒ์ถ์ ์์ธก ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅ ํ์ผ์ ์ ์ฅํฉ๋๋ค.
์ค๋ช
:
options: ๋ฐ์ดํฐ ๊ตฌ์ฑ ํ์ผ์์ ์ฝ์ด์จ ์ต์
๋ฆฌ์คํธ
valid_images: ๊ฒ์ฆ ๋ฐ์ดํฐ ๋ฆฌ์คํธ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฌธ์์ด ํฌ์ธํฐ
name_list: ๊ฐ์ฒด ํด๋์ค ์ด๋ฆ ๋ฆฌ์คํธ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฌธ์์ด ํฌ์ธํฐ
prefix: ์ถ๋ ฅ ํ์ผ ๊ฒฝ๋ก์ prefix๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฌธ์์ด ํฌ์ธํฐ
names: ๊ฐ์ฒด ํด๋์ค ์ด๋ฆ ๋ฐฐ์ด
mapf: ํด๋์ค ์ด๋ฆ ๋งคํ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฌธ์์ด ํฌ์ธํฐ
map: ํด๋์ค ์ด๋ฆ ๋งคํ ๋ฐฐ์ด
l: ๋ชจ๋ธ์ ๋ง์ง๋ง ๋ ์ด์ด
classes: ๊ฐ์ฒด ํด๋์ค์ ๊ฐ์
type: ๊ฒ์ฆ ๋ฐ์ดํฐ์ ํ์(voc, coco, imagenet)
fp: ์ถ๋ ฅ ํ์ผ์ ํ์ผ ํฌ์ธํฐ
fps: ํด๋์ค๋ณ ์ถ๋ ฅ ํ์ผ์ ํ์ผ ํฌ์ธํฐ ๋ฐฐ์ด
coco: coco ๋ฐ์ดํฐ์ธ์ง ์ฌ๋ถ
imagenet: imagenet ๋ฐ์ดํฐ์ธ์ง ์ฌ๋ถ
thresh: ๊ฐ์ฒด ๊ฒ์ถ์ ์ํ ์๊ณ๊ฐ
nms: ๋น์ต๋ ์ต์ ์๊ณ๊ฐ
nthreads: ์ฌ์ฉํ ์ค๋ ๋์ ๊ฐ์
val, val_resized, buf, buf_resized: ์ด๋ฏธ์ง์ ํฌ๊ธฐ๊ฐ ์กฐ์ ๋ ์ด๋ฏธ์ง์ ๋ฐฐ์ด
thr: ์ด๋ฏธ์ง ๋ก๋ฉ์ ์ํ ์ค๋ ๋ ๋ฐฐ์ด
args: ์ด๋ฏธ์ง ๋ก๋ฉ ์ธ์ ๊ตฌ์กฐ์ฒด
i, t: ๋ฐ๋ณต๋ฌธ ์ธ๋ฑ์ค
start: ํจ์ ์์ ์๊ฐ
plist: ๊ฒ์ฆ ๋ฐ์ดํฐ ๋ฆฌ์คํธ
paths: ๊ฒ์ฆ ๋ฐ์ดํฐ ๊ฒฝ๋ก ๋ฐฐ์ด
id: ๊ฒ์ฆ ๋ฐ์ดํฐ์ ๊ธฐ๋ณธ ํ์ผ ์ด๋ฆ (ํ์ฅ์ ์ ์ธ)
X: ๋ชจ๋ธ์ ์
๋ ฅ๋ ์ด๋ฏธ์ง ๋ฐ์ดํฐ ๋ฐฐ์ด
w, h: ์
๋ ฅ ์ด๋ฏธ์ง์ ๊ฐ๋ก, ์ธ๋ก ํฌ๊ธฐ
nboxes: ๊ฒ์ถ๋ ๊ฐ์ฒด์ ๊ฐ์
dets: ๊ฐ์ฒด ๊ฒ์ถ ์ ๋ณด๋ฅผ ๋ด์ ๋ฐฐ์ด
validate_detector_recall
void validate_detector_recall(char *cfgfile, char *weightfile)
{
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net->learning_rate, net->momentum, net->decay);
srand(time(0));
list *plist = get_paths("data/coco_val_5k.list");
char **paths = (char **)list_to_array(plist);
layer l = net->layers[net->n-1];
int j, k;
int m = plist->size;
int i=0;
float thresh = .001;
float iou_thresh = .5;
float nms = .4;
int total = 0;
int correct = 0;
int proposals = 0;
float avg_iou = 0;
for(i = 0; i < m; ++i){
char *path = paths[i];
image orig = load_image_color(path, 0, 0);
image sized = resize_image(orig, net->w, net->h);
char *id = basecfg(path);
network_predict(net, sized.data);
int nboxes = 0;
detection *dets = get_network_boxes(net, sized.w, sized.h, thresh, .5, 0, 1, &nboxes);
if (nms) do_nms_obj(dets, nboxes, 1, nms);
char labelpath[4096];
find_replace(path, "images", "labels", labelpath);
find_replace(labelpath, "JPEGImages", "labels", labelpath);
find_replace(labelpath, ".jpg", ".txt", labelpath);
find_replace(labelpath, ".JPEG", ".txt", labelpath);
int num_labels = 0;
box_label *truth = read_boxes(labelpath, &num_labels);
for(k = 0; k < nboxes; ++k){
if(dets[k].objectness > thresh){
++proposals;
}
}
for (j = 0; j < num_labels; ++j) {
++total;
box t = {truth[j].x, truth[j].y, truth[j].w, truth[j].h};
float best_iou = 0;
for(k = 0; k < l.w*l.h*l.n; ++k){
float iou = box_iou(dets[k].bbox, t);
if(dets[k].objectness > thresh && iou > best_iou){
best_iou = iou;
}
}
avg_iou += best_iou;
if(best_iou > iou_thresh){
++correct;
}
}
fprintf(stderr, "%5d %5d %5d\tRPs/Img: %.2f\tIOU: %.2f%%\tRecall:%.2f%%\n", i, correct, total, (float)proposals/(i+1), avg_iou*100/total, 100.*correct/total);
free(id);
free_image(orig);
free_image(sized);
}
}
ํจ์ ์ด๋ฆ: validate_detector_recall
์
๋ ฅ:
cfgfile: YOLO ๋ชจ๋ธ ๊ตฌ์ฑ ํ์ผ ๊ฒฝ๋ก
weightfile: YOLO ๋ชจ๋ธ ๊ฐ์ค์น ํ์ผ ๊ฒฝ๋ก
๋์:
์ฃผ์ด์ง cfgfile๊ณผ weightfile๋ก YOLO ๋ชจ๋ธ์ ๋ก๋ํ๊ณ , coco_val_5k.list ํ์ผ์ ์๋ ์ด๋ฏธ์ง๋ฅผ ์ด์ฉํ์ฌ ๊ฒ์ถ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํ๋ค.
๊ฒ์ถ ๊ฒฐ๊ณผ์ ์ค์ ๋ผ๋ฒจ ์ฌ์ด์ IoU(IoU threshold๋ 0.5๋ก ๊ณ ์ )๋ฅผ ๊ณ์ฐํ๊ณ , ์ด๋ฅผ ์ด์ฉํ์ฌ Recall์ ๊ณ์ฐํ๋ค.
์ค๋ช
:
์ฃผ์ด์ง YOLO ๋ชจ๋ธ(cfgfile, weightfile)์ ๋ก๋ํ๊ณ , coco_val_5k.list ํ์ผ์ ์๋ ์ด๋ฏธ์ง๋ค์ ์ด์ฉํ์ฌ ๊ฒ์ถ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํ๋ค.
๋ชจ๋ธ์ ์ด์ฉํ์ฌ ์ด๋ฏธ์ง์์ ๊ฐ์ฒด๋ฅผ ๊ฒ์ถํ ํ, ๊ฒ์ถ๋ ๊ฐ์ฒด์ ์ค์ ๋ผ๋ฒจ ์ฌ์ด์ IoU(IoU threshold๋ 0.5๋ก ๊ณ ์ )๋ฅผ ๊ณ์ฐํ๊ณ , ์ด๋ฅผ ์ด์ฉํ์ฌ Recall ๊ฐ์ ๊ณ์ฐํ๋ค.
์ด ๊ณผ์ ์ ๋ชจ๋ ์ด๋ฏธ์ง์ ๋ํด ๋ฐ๋ณตํ๋ฉฐ, ์ด ๊ฒ์ถ๋ ๊ฐ์ฒด ์, ์ ํํ๊ฒ ๊ฒ์ถ๋ ๊ฐ์ฒด ์, ์ ์ฒด ๋ผ๋ฒจ ์, ๊ทธ๋ฆฌ๊ณ RPs/Img(์ด๋ฏธ์ง ๋น ํ๊ท ์ถ๋ก ์), ํ๊ท IoU, Recall ๊ฐ์ ์ถ๋ ฅํ๋ค.
test_detector
void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh, float hier_thresh, char *outfile, int fullscreen)
{
list *options = read_data_cfg(datacfg);
char *name_list = option_find_str(options, "names", "data/names.list");
char **names = get_labels(name_list);
image **alphabet = load_alphabet();
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
srand(2222222);
double time;
char buff[256];
char *input = buff;
float nms=.45;
while(1){
if(filename){
strncpy(input, filename, 256);
} else {
printf("Enter Image Path: ");
fflush(stdout);
input = fgets(input, 256, stdin);
if(!input) return;
strtok(input, "\n");
}
image im = load_image_color(input,0,0);
image sized = letterbox_image(im, net->w, net->h);
//image sized = resize_image(im, net->w, net->h);
//image sized2 = resize_max(im, net->w);
//image sized = crop_image(sized2, -((net->w - sized2.w)/2), -((net->h - sized2.h)/2), net->w, net->h);
//resize_network(net, sized.w, sized.h);
layer l = net->layers[net->n-1];
float *X = sized.data;
time=what_time_is_it_now();
network_predict(net, X);
printf("%s: Predicted in %f seconds.\n", input, what_time_is_it_now()-time);
int nboxes = 0;
detection *dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes);
//printf("%d\n", nboxes);
//if (nms) do_nms_obj(boxes, probs, l.w*l.h*l.n, l.classes, nms);
if (nms) do_nms_sort(dets, nboxes, l.classes, nms);
draw_detections(im, dets, nboxes, thresh, names, alphabet, l.classes);
free_detections(dets, nboxes);
if(outfile){
save_image(im, outfile);
}
else{
save_image(im, "predictions");
#ifdef OPENCV
make_window("predictions", 512, 512, 0);
show_image(im, "predictions", 0);
#endif
}
free_image(im);
free_image(sized);
if (filename) break;
}
}
ํจ์ ์ด๋ฆ: test_detector
์
๋ ฅ:
datacfg: ๋ฐ์ดํฐ ์ค์ ํ์ผ ๊ฒฝ๋ก (๋ฌธ์์ด)
cfgfile: ๋คํธ์ํฌ ์ค์ ํ์ผ ๊ฒฝ๋ก (๋ฌธ์์ด)
weightfile: ํ์ต๋ ๊ฐ์ค์น ํ์ผ ๊ฒฝ๋ก (๋ฌธ์์ด)
filename: ์
๋ ฅ ์ด๋ฏธ์ง ํ์ผ ๊ฒฝ๋ก (๋ฌธ์์ด ๋๋ NULL)
thresh: ๊ฐ์ฒด ํ์ง๋ฅผ ์ํ ์๊ณ๊ฐ (์ค์)
hier_thresh: ๊ณ์ธต์ ์๊ณ๊ฐ (์ค์)
outfile: ์ถ๋ ฅ ์ด๋ฏธ์ง ํ์ผ ๊ฒฝ๋ก (๋ฌธ์์ด ๋๋ NULL)
fullscreen: ์ ์ฒด ํ๋ฉด ๋ชจ๋ ์ฌ๋ถ (์ ์)
๋์: ์
๋ ฅ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ฒด ํ์งํ๊ธฐ ์ํด Darknet ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฒ๋ฆฌํ๊ณ , ๊ฒฐ๊ณผ ์ด๋ฏธ์ง๋ฅผ ์ถ๋ ฅํ๋ ํจ์์
๋๋ค.
read_data_cfg ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ ์ค์ ํ์ผ์ ์ฝ์ด๋ค์
๋๋ค.
option_find_str ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ ์ค์ ํ์ผ์์ names ํค ๊ฐ์ ์ฐพ์์ name_list ๋ณ์์ ์ ์ฅํฉ๋๋ค.
get_labels ํจ์๋ฅผ ์ด์ฉํ์ฌ names ํ์ผ์์ ํด๋์ค ์ด๋ฆ์ ๊ฐ์ ธ์ names ๋ณ์์ ์ ์ฅํฉ๋๋ค.
load_alphabet ํจ์๋ฅผ ์ด์ฉํ์ฌ ์ํ๋ฒณ ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ alphabet ๋ณ์์ ์ ์ฅํฉ๋๋ค.
load_network ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋คํธ์ํฌ ์ค์ ํ์ผ๊ณผ ํ์ต๋ ๊ฐ์ค์น ํ์ผ์ ๋ก๋ํ๊ณ , net ๋ณ์์ ์ ์ฅํฉ๋๋ค.
set_batch_network ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ฐฐ์น ํฌ๊ธฐ๋ฅผ 1๋ก ์ค์ ํฉ๋๋ค.
srand ํจ์๋ฅผ ์ด์ฉํ์ฌ ์๋๊ฐ์ ์ค์ ํฉ๋๋ค.
์
๋ ฅ ์ด๋ฏธ์ง ํ์ผ ๊ฒฝ๋ก๊ฐ ์ฃผ์ด์ก์ ๊ฒฝ์ฐ, input ๋ณ์์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๋ณต์ฌํฉ๋๋ค.
์
๋ ฅ ์ด๋ฏธ์ง ํ์ผ ๊ฒฝ๋ก๊ฐ ์ฃผ์ด์ง์ง ์์์ ๊ฒฝ์ฐ, ํ์ค ์
๋ ฅ์ผ๋ก๋ถํฐ ์
๋ ฅ ์ด๋ฏธ์ง ํ์ผ ๊ฒฝ๋ก๋ฅผ ๋ฐ์ input ๋ณ์์ ์ ์ฅํฉ๋๋ค.
load_image_color ํจ์๋ฅผ ์ด์ฉํ์ฌ ์
๋ ฅ ์ด๋ฏธ์ง๋ฅผ ๋ก๋ํ๊ณ , im ๋ณ์์ ์ ์ฅํฉ๋๋ค.
letterbox_image ํจ์๋ฅผ ์ด์ฉํ์ฌ ์
๋ ฅ ์ด๋ฏธ์ง๋ฅผ ๋คํธ์ํฌ ์
๋ ฅ ํฌ๊ธฐ๋ก ๋ณํํ ํ, sized ๋ณ์์ ์ ์ฅํฉ๋๋ค.
network->layers[net->n-1]์ ์ด์ฉํ์ฌ ์ถ๋ ฅ ๋ ์ด์ด์ ์ ๋ณด๋ฅผ l ๋ณ์์ ์ ์ฅํฉ๋๋ค.
sized.data๋ฅผ ์ด์ฉํ์ฌ ๋คํธ์ํฌ์ ์
๋ ฅํ ๋ฐ์ดํฐ X๋ฅผ ์์ฑํฉ๋๋ค.
network_predict ํจ์๋ฅผ ์ด์ฉํ์ฌ ๊ฐ์ฒด ํ์ง๋ฅผ ์ํํฉ๋๋ค.
get_network_boxes ํจ์๋ฅผ ์ด์ฉํ์ฌ ํ์ง๋ ๊ฐ์ฒด ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ dets ๋ณ์์ ์ ์ฅํฉ๋๋ค.
nms๊ฐ 0๋ณด๋ค ํฐ ๊ฒฝ์ฐ, do_nms_sort ํจ์๋ฅผ ์ด์ฉํ์ฌ non-maximum suppression์ ์ํํฉ๋๋ค.
draw_detections ํจ์๋ฅผ ์ด์ฉํ์ฌ ํ์ง๋ ๊ฐ์ฒด์ ๋ํ ๊ฒฝ๊ณ ์์๋ฅผ ์ด๋ฏธ์ง์ ๊ทธ๋ฆฝ๋๋ค.
free_detections ํจ์๋ฅผ ์ด์ฉํ์ฌ ํ์ง๋ ๊ฐ์ฒด ์ ๋ณด๋ฅผ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ํฉ๋๋ค.
outfile์ด ์ฃผ์ด์ก์ ๊ฒฝ์ฐ, save_image ํจ์๋ฅผ ์ด์ฉํ์ฌ ์ถ๋ ฅ ์ด๋ฏธ์ง๋ฅผ ํ์ผ๋ก ์ ์ฅํฉ๋๋ค.
outfile์ด ์ฃผ์ด์ง์ง ์์์ ๊ฒฝ์ฐ, save_image ํจ์๋ฅผ ์ด์ฉํ์ฌ ์ถ๋ ฅ ์ด๋ฏธ์ง๋ฅผ "predictions"๋ผ๋ ํ์ผ ์ด๋ฆ์ผ๋ก ์ ์ฅํฉ๋๋ค.
run_detector
void run_detector(int argc, char **argv)
{
char *prefix = find_char_arg(argc, argv, "-prefix", 0);
float thresh = find_float_arg(argc, argv, "-thresh", .5);
float hier_thresh = find_float_arg(argc, argv, "-hier", .5);
int cam_index = find_int_arg(argc, argv, "-c", 0);
int frame_skip = find_int_arg(argc, argv, "-s", 0);
int avg = find_int_arg(argc, argv, "-avg", 3);
if(argc < 4){
fprintf(stderr, "usage: %s %s [train/test/valid] [cfg] [weights (optional)]\n", argv[0], argv[1]);
return;
}
char *gpu_list = find_char_arg(argc, argv, "-gpus", 0);
char *outfile = find_char_arg(argc, argv, "-out", 0);
int *gpus = 0;
int gpu = 0;
int ngpus = 0;
if(gpu_list){
printf("%s\n", gpu_list);
int len = strlen(gpu_list);
ngpus = 1;
int i;
for(i = 0; i < len; ++i){
if (gpu_list[i] == ',') ++ngpus;
}
gpus = calloc(ngpus, sizeof(int));
for(i = 0; i < ngpus; ++i){
gpus[i] = atoi(gpu_list);
gpu_list = strchr(gpu_list, ',')+1;
}
} else {
gpu = gpu_index;
gpus = &gpu;
ngpus = 1;
}
int clear = find_arg(argc, argv, "-clear");
int fullscreen = find_arg(argc, argv, "-fullscreen");
int width = find_int_arg(argc, argv, "-w", 0);
int height = find_int_arg(argc, argv, "-h", 0);
int fps = find_int_arg(argc, argv, "-fps", 0);
//int class = find_int_arg(argc, argv, "-class", 0);
char *datacfg = argv[3];
char *cfg = argv[4];
char *weights = (argc > 5) ? argv[5] : 0;
char *filename = (argc > 6) ? argv[6]: 0;
if(0==strcmp(argv[2], "test")) test_detector(datacfg, cfg, weights, filename, thresh, hier_thresh, outfile, fullscreen);
else if(0==strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear);
else if(0==strcmp(argv[2], "valid")) validate_detector(datacfg, cfg, weights, outfile);
else if(0==strcmp(argv[2], "valid2")) validate_detector_flip(datacfg, cfg, weights, outfile);
else if(0==strcmp(argv[2], "recall")) validate_detector_recall(cfg, weights);
else if(0==strcmp(argv[2], "demo")) {
list *options = read_data_cfg(datacfg);
int classes = option_find_int(options, "classes", 20);
char *name_list = option_find_str(options, "names", "data/names.list");
char **names = get_labels(name_list);
demo(cfg, weights, thresh, cam_index, filename, names, classes, frame_skip, prefix, avg, hier_thresh, width, height, fps, fullscreen);
}
//else if(0==strcmp(argv[2], "extract")) extract_detector(datacfg, cfg, weights, cam_index, filename, class, thresh, frame_skip);
//else if(0==strcmp(argv[2], "censor")) censor_detector(datacfg, cfg, weights, cam_index, filename, class, thresh, frame_skip);
}
ํจ์ ์ด๋ฆ: run_detector
์
๋ ฅ:
argc: ์ ์ ๊ฐ์ผ๋ก, ์ ๋ฌ๋ ๋ช
๋ นํ ์ธ์(argument)์ ๊ฐ์๋ฅผ ๋ํ๋
๋๋ค.
argv: ๋ฌธ์์ด ๋ฐฐ์ด๋ก, ์ ๋ฌ๋ ๋ช
๋ นํ ์ธ์์ ๊ฐ๋ค์ ์ ์ฅํฉ๋๋ค.
๋์:
argc์ argv๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ์ธ์๋ค์ ์ถ์ถํ๊ณ ์ ์ฅํฉ๋๋ค.
argc๊ฐ 4๋ณด๋ค ์์ ๊ฒฝ์ฐ, ์ฌ์ฉ๋ฒ์ ์ถ๋ ฅํ๊ณ ํจ์๋ฅผ ์ข
๋ฃํฉ๋๋ค.
-gpus ์ต์
์ ๋ํ ๊ฐ์ ์ถ์ถํ๊ณ , ,๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ถ๋ฆฌํ์ฌ ๊ฐ GPU ๋ฒํธ๋ฅผ ์ ์ฅํฉ๋๋ค.
GPU ๋ฒํธ๊ฐ ์ง์ ๋์ง ์์ ๊ฒฝ์ฐ, ๊ธฐ๋ณธ GPU ๋ฒํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
-clear, -fullscreen, -w, -h, -fps ๋ฑ์ ์ธ์๋ค์ ์ถ์ถํ๊ณ ์ ์ฅํฉ๋๋ค.
datacfg, cfg, weights, filename ๋ฑ์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ถ์ถํ๊ณ ์ ์ฅํฉ๋๋ค.
argv[2] ๊ฐ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋์์ ์ํํฉ๋๋ค:
"test": test_detector ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ํ
ํฐ๋ฅผ ํ
์คํธํฉ๋๋ค.
"train": train_detector ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ํ
ํฐ๋ฅผ ํ๋ จํฉ๋๋ค.
"valid": validate_detector ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ํ
ํฐ๋ฅผ ๊ฒ์ฆํฉ๋๋ค.
"valid2": validate_detector_flip ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ํ
ํฐ๋ฅผ ๋ค์ง์ด์ ๊ฒ์ฆํฉ๋๋ค.
"recall": validate_detector_recall ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ํ
ํฐ์ ๋ฆฌ์ฝ(recall) ๊ฐ์ ๊ฒ์ฆํฉ๋๋ค.
"demo": ๋ค์ํ ์ต์
๋ค์ ์ค์ ํ ํ demo ํจ์๋ฅผ ํธ์ถํ์ฌ ์ค์๊ฐ ๋ฐ๋ชจ๋ฅผ ์คํํฉ๋๋ค.
์ค๋ช
:
์์ ์ฝ๋๋ run_detector๋ผ๋ ํจ์๋ฅผ ์ ์ํ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค.
์ด ํจ์๋ ์ ๋ฌ๋ ๋ช
๋ นํ ์ธ์๋ฅผ ๋ถ์ํ๊ณ , ํด๋น ์ธ์์ ๋ฐ๋ผ ๋ค๋ฅธ ๋์์ ์ํํฉ๋๋ค.
ํจ์์ ๋์์ ์ธ์๋ค์ ์ถ์ถํ์ฌ ํ์ํ ๊ฐ๋ค์ ์ด๊ธฐํํ ํ, ํด๋นํ๋ ๋์ ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.