From 1b5afb45838e603fa6780762eb8cc59246dc2d81 Mon Sep 17 00:00:00 2001
From: IlyaOvodov <b@ovdv.ru>
Date: Tue, 08 May 2018 11:09:35 +0000
Subject: [PATCH] Output improvements for detector results: When printing detector results, output was done in random order, obfuscating results for interpreting. Now: 1. Text output includes coordinates of rects in (left,right,top,bottom in pixels) along with label and score 2. Text output is sorted by rect lefts to simplify finding appropriate rects on image 3. If several class probs are > thresh for some detection, the most probable is written first and coordinates for others are not repeated 4. Rects are imprinted in image in order by their best class prob, so most probable rects are always on top and not overlayed by less probable ones 5. Most probable label for rect is always written first Also: 6. Message about low GPU memory include required amount

---
 src/detector.c |  653 +++++++++++++++++++++++++++++++---------------------------
 1 files changed, 350 insertions(+), 303 deletions(-)

diff --git a/src/detector.c b/src/detector.c
index 77175b4..a38ed18 100644
--- a/src/detector.c
+++ b/src/detector.c
@@ -86,12 +86,13 @@
     args.n = imgs;
     args.m = plist->size;
     args.classes = classes;
+    args.flip = net.flip;
     args.jitter = jitter;
     args.num_boxes = l.max_boxes;
-	args.small_object = l.small_object;
+	args.small_object = net.small_object;
     args.d = &buffer;
     args.type = DETECTION_DATA;
-	args.threads = 64;	// 8
+	args.threads = 16;	// 64
 
     args.angle = net.angle;
     args.exposure = net.exposure;
@@ -99,6 +100,7 @@
     args.hue = net.hue;
 
 #ifdef OPENCV
+	args.threads = 3;
 	IplImage* img = NULL;
 	float max_img_loss = 5;
 	int number_of_lines = 100;
@@ -108,7 +110,7 @@
 #endif	//OPENCV
 
     pthread_t load_thread = load_data(args);
-    clock_t time;
+    double time;
     int count = 0;
     //while(i*imgs < N*120){
     while(get_current_batch(net) < net.max_batches){
@@ -131,7 +133,7 @@
             }
             net = nets[0];
         }
-        time=clock();
+        time=what_time_is_it_now();
         pthread_join(load_thread, 0);
         train = buffer;
         load_thread = load_data(args);
@@ -153,9 +155,9 @@
            save_image(im, "truth11");
          */
 
-        printf("Loaded: %lf seconds\n", sec(clock()-time));
+        printf("Loaded: %lf seconds\n", (what_time_is_it_now()-time));
 
-        time=clock();
+        time=what_time_is_it_now();
         float loss = 0;
 #ifdef GPU
         if(ngpus == 1){
@@ -166,11 +168,11 @@
 #else
         loss = train_network(net, train);
 #endif
-        if (avg_loss < 0) avg_loss = loss;
+        if (avg_loss < 0 || avg_loss != avg_loss) avg_loss = loss;	// if(-inf or nan)
         avg_loss = avg_loss*.9 + loss*.1;
 
         i = get_current_batch(net);
-        printf("%d: %f, %f avg, %f rate, %lf seconds, %d images\n", get_current_batch(net), loss, avg_loss, get_current_rate(net), sec(clock()-time), i*imgs);
+        printf("\n %d: %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);
 
 #ifdef OPENCV
 		if(!dont_show)
@@ -204,301 +206,294 @@
 
 static int get_coco_image_id(char *filename)
 {
-    char *p = strrchr(filename, '_');
-    return atoi(p+1);
+	char *p = strrchr(filename, '/');
+	char *c = strrchr(filename, '_');
+	if (c) p = c;
+	return atoi(p + 1);
 }
 
-static void print_cocos(FILE *fp, char *image_path, box *boxes, float **probs, int num_boxes, int classes, int w, int h)
+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 = boxes[i].x - boxes[i].w/2.;
-        float xmax = boxes[i].x + boxes[i].w/2.;
-        float ymin = boxes[i].y - boxes[i].h/2.;
-        float ymax = boxes[i].y + boxes[i].h/2.;
+	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;
+		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;
+		float bx = xmin;
+		float by = ymin;
+		float bw = xmax - xmin;
+		float bh = ymax - ymin;
 
-        for(j = 0; j < classes; ++j){
-            if (probs[i][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, probs[i][j]);
-        }
-    }
+		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]);
+		}
+	}
 }
 
-void print_detector_detections(FILE **fps, char *id, box *boxes, float **probs, int total, int classes, int w, int h)
+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 = boxes[i].x - boxes[i].w/2.;
-        float xmax = boxes[i].x + boxes[i].w/2.;
-        float ymin = boxes[i].y - boxes[i].h/2.;
-        float ymax = boxes[i].y + boxes[i].h/2.;
+	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 < 0) xmin = 0;
-        if (ymin < 0) ymin = 0;
-        if (xmax > w) xmax = w;
-        if (ymax > h) ymax = h;
+		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 (probs[i][j]) fprintf(fps[j], "%s %f %f %f %f %f\n", id, probs[i][j],
-                    xmin, ymin, xmax, ymax);
-        }
-    }
+		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);
+		}
+	}
 }
 
-void print_imagenet_detections(FILE *fp, int id, box *boxes, float **probs, int total, int classes, int w, int h)
+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 = boxes[i].x - boxes[i].w/2.;
-        float xmax = boxes[i].x + boxes[i].w/2.;
-        float ymin = boxes[i].y - boxes[i].h/2.;
-        float ymax = boxes[i].y + boxes[i].h/2.;
+	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;
+		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_id = j;
-            if (probs[i][class_id]) fprintf(fp, "%d %d %f %f %f %f %f\n", id, j+1, probs[i][class_id],
-                    xmin, ymin, xmax, ymax);
-        }
-    }
+		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);
+		}
+	}
 }
 
-void validate_detector(char *datacfg, char *cfgfile, char *weightfile)
+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);
+	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 = parse_network_cfg_custom(cfgfile, 1);
-    if(weightfile){
-        load_weights(&net, weightfile);
-    }
-    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));
+	network net = parse_network_cfg_custom(cfgfile, 1);	// set batch=1
+	if (weightfile) {
+		load_weights(&net, weightfile);
+	}
+	//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));
 
-    char *base = "comp4_det_test_";
-    list *plist = get_paths(valid_images);
-    char **paths = (char **)list_to_array(plist);
+	list *plist = get_paths(valid_images);
+	char **paths = (char **)list_to_array(plist);
 
-    layer l = net.layers[net.n-1];
-    int classes = l.classes;
+	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")){
-        snprintf(buff, 1024, "%s/coco_results.json", prefix);
-        fp = fopen(buff, "w");
-        fprintf(fp, "[\n");
-        coco = 1;
-    } else if(0==strcmp(type, "imagenet")){
-        snprintf(buff, 1024, "%s/imagenet-detection.txt", prefix);
-        fp = fopen(buff, "w");
-        imagenet = 1;
-        classes = 200;
-    } else {
-        fps = calloc(classes, sizeof(FILE *));
-        for(j = 0; j < classes; ++j){
-            snprintf(buff, 1024, "%s/%s%s.txt", prefix, base, names[j]);
-            fps[j] = fopen(buff, "w");
-        }
-    }
+	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");
+		}
+	}
 
 
-    box *boxes = calloc(l.w*l.h*l.n, sizeof(box));
-    float **probs = calloc(l.w*l.h*l.n, sizeof(float *));
-    for(j = 0; j < l.w*l.h*l.n; ++j) probs[j] = calloc(classes, sizeof(float *));
+	int m = plist->size;
+	int i = 0;
+	int t;
 
-    int m = plist->size;
-    int i=0;
-    int t;
+	float thresh = .005;
+	float nms = .45;
 
-    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));
 
-	int detection_count = 0;
+	load_args args = { 0 };
+	args.w = net.w;
+	args.h = net.h;
+	args.type = IMAGE_DATA;
+	//args.type = LETTERBOX_DATA;
 
-    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;
-
-    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);
-    }
-    time_t start = time(0);
-    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;
-            get_region_boxes(l, w, h, thresh, probs, boxes, 0, map);
-            if (nms) do_nms_sort(boxes, probs, l.w*l.h*l.n, classes, nms);
-
-			int x, y;
-			for (x = 0; x < (l.w*l.h*l.n); ++x) {
-				for (y = 0; y < classes; ++y) 
-				{
-					if (probs[x][y]) ++detection_count;
-				}
+	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);
+	}
+	time_t start = time(0);
+	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;
+			int letterbox = (args.type == LETTERBOX_DATA);
+			detection *dets = get_network_boxes(&net, w, h, thresh, .5, map, 0, &nboxes, letterbox);
+			if (nms) do_nms_sort(dets, nboxes, classes, nms);
+			if (coco) {
+				print_cocos(fp, path, dets, nboxes, classes, w, h);
 			}
-
-            if (coco){
-                print_cocos(fp, path, boxes, probs, l.w*l.h*l.n, classes, w, h);
-            } else if (imagenet){
-                print_imagenet_detections(fp, i+t-nthreads+1, boxes, probs, l.w*l.h*l.n, classes, w, h);
-            } else {
-                print_detector_detections(fps, id, boxes, probs, l.w*l.h*l.n, classes, w, h);
-            }
-            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);
-    }
-	printf("\n detection_count = %d \n", detection_count);
-    fprintf(stderr, "Total Detection Time: %f Seconds\n", (double)(time(0) - start));
+			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", time(0) - start);
 }
 
 void validate_detector_recall(char *datacfg, char *cfgfile, char *weightfile)
 {
-    network net = parse_network_cfg_custom(cfgfile, 1);
-    if(weightfile){
-        load_weights(&net, weightfile);
-    }
-    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));
+	network net = parse_network_cfg_custom(cfgfile, 1);	// set batch=1
+	if (weightfile) {
+		load_weights(&net, weightfile);
+	}
+	//set_batch_network(&net, 1);
+	fuse_conv_batchnorm(net);
+	srand(time(0));
 
+	//list *plist = get_paths("data/coco_val_5k.list");
 	list *options = read_data_cfg(datacfg);
 	char *valid_images = option_find_str(options, "valid", "data/train.txt");
-    list *plist = get_paths(valid_images);
-    char **paths = (char **)list_to_array(plist);
+	list *plist = get_paths(valid_images);
+	char **paths = (char **)list_to_array(plist);
 
-    layer l = net.layers[net.n-1];
-    int classes = l.classes;
+	layer l = net.layers[net.n - 1];
 
-    int j, k;
-    box *boxes = calloc(l.w*l.h*l.n, sizeof(box));
-    float **probs = calloc(l.w*l.h*l.n, sizeof(float *));
-    for(j = 0; j < l.w*l.h*l.n; ++j) probs[j] = calloc(classes, sizeof(float *));
+	int j, k;
 
-    int m = plist->size;
-    int i=0;
+	int m = plist->size;
+	int i = 0;
 
-	float thresh = .001;// .001;	// .2;
-    float iou_thresh = .5;
-    float nms = .4;
+	float thresh = .001;
+	float iou_thresh = .5;
+	float nms = .4;
 
-	int detection_count = 0, truth_count = 0;
+	int total = 0;
+	int correct = 0;
+	int proposals = 0;
+	float avg_iou = 0;
 
-    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;
+		int letterbox = 0;
+		detection *dets = get_network_boxes(&net, sized.w, sized.h, thresh, .5, 0, 1, &nboxes, letterbox);
+		if (nms) do_nms_obj(dets, nboxes, 1, nms);
 
-    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);
-        get_region_boxes(l, 1, 1, thresh, probs, boxes, 1, 0);
-        if (nms) do_nms(boxes, probs, l.w*l.h*l.n, 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, ".png", ".txt", labelpath);
+		find_replace(labelpath, ".bmp", ".txt", labelpath);
+		find_replace(labelpath, ".JPG", ".txt", labelpath);
+		find_replace(labelpath, ".JPEG", ".txt", labelpath);
 
-        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);
-	find_replace(labelpath, ".png", ".txt", labelpath);
-
-        int num_labels = 0;
-        box_label *truth = read_boxes(labelpath, &num_labels);
-		truth_count += num_labels;
-        for(k = 0; k < l.w*l.h*l.n; ++k){
-            if(probs[k][0] > thresh){
-                ++proposals;
-            }
-        }
+		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(boxes[k], t);
-				if (probs[k][0] > thresh && iou > best_iou) {
+			for (k = 0; k < nboxes; ++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);
-    }
-	printf("\n truth_count = %d \n", truth_count);
+			avg_iou += best_iou;
+			if (best_iou > iou_thresh) {
+				++correct;
+			}
+		}
+		//fprintf(stderr, " %s - %s - ", paths[i], labelpath);
+		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);
+	}
 }
 
 typedef struct {
@@ -532,12 +527,12 @@
 	int *map = 0;
 	if (mapf) map = read_map(mapf);
 
-	network net = parse_network_cfg_custom(cfgfile, 1);
+	network net = parse_network_cfg_custom(cfgfile, 1);	// set batch=1
 	if (weightfile) {
 		load_weights(&net, weightfile);
 	}
-	set_batch_network(&net, 1);
-	fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay);
+	//set_batch_network(&net, 1);
+	fuse_conv_batchnorm(net);
 	srand(time(0));
 
 	list *plist = get_paths(valid_images);
@@ -553,10 +548,6 @@
 	layer l = net.layers[net.n - 1];
 	int classes = l.classes;
 
-	box *boxes = calloc(l.w*l.h*l.n, sizeof(box));
-	float **probs = calloc(l.w*l.h*l.n, sizeof(float *));
-	for (j = 0; j < l.w*l.h*l.n; ++j) probs[j] = calloc(classes, sizeof(float *));
-
 	int m = plist->size;
 	int i = 0;
 	int t;
@@ -576,6 +567,7 @@
 	args.w = net.w;
 	args.h = net.h;
 	args.type = IMAGE_DATA;
+	//args.type = LETTERBOX_DATA;
 
 	//const float thresh_calc_avg_iou = 0.24;
 	float avg_iou = 0;
@@ -614,15 +606,22 @@
 			char *id = basecfg(path);
 			float *X = val_resized[t].data;
 			network_predict(net, X);
-			get_region_boxes(l, 1, 1, thresh, probs, boxes, 0, map);
-			if (nms) do_nms_sort(boxes, probs, l.w*l.h*l.n, classes, nms);
+
+			int nboxes = 0;
+			int letterbox = (args.type == LETTERBOX_DATA);
+			float hier_thresh = 0;
+			detection *dets = get_network_boxes(&net, 1, 1, thresh, hier_thresh, 0, 0, &nboxes, letterbox);
+			//detection *dets = get_network_boxes(&net, val[t].w, val[t].h, thresh, hier_thresh, 0, 1, &nboxes, letterbox); // for letterbox=1
+			if (nms) do_nms_sort(dets, nboxes, l.classes, 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);
 			find_replace(labelpath, ".png", ".txt", labelpath);
+			find_replace(labelpath, ".bmp", ".txt", 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);
 			int i, j;
@@ -646,15 +645,17 @@
 				truth_dif = read_boxes(labelpath_dif, &num_labels_dif);
 			}
 
-			for (i = 0; i < (l.w*l.h*l.n); ++i) {
+			const int checkpoint_detections_count = detections_count;
+
+			for (i = 0; i < nboxes; ++i) {
 
 				int class_id;
 				for (class_id = 0; class_id < classes; ++class_id) {
-					float prob = probs[i][class_id];
+					float prob = dets[i].prob[class_id];
 					if (prob > 0) {
 						detections_count++;
 						detections = realloc(detections, detections_count * sizeof(box_prob));
-						detections[detections_count - 1].b = boxes[i];
+						detections[detections_count - 1].b = dets[i].bbox;
 						detections[detections_count - 1].p = prob;
 						detections[detections_count - 1].image_index = image_index;
 						detections[detections_count - 1].class_id = class_id;
@@ -667,8 +668,8 @@
 						{
 							box t = { truth[j].x, truth[j].y, truth[j].w, truth[j].h };
 							//printf(" IoU = %f, prob = %f, class_id = %d, truth[j].id = %d \n", 
-							//	box_iou(boxes[i], t), prob, class_id, truth[j].id);
-							float current_iou = box_iou(boxes[i], t);
+							//	box_iou(dets[i].bbox, t), prob, class_id, truth[j].id);
+							float current_iou = box_iou(dets[i].bbox, t);
 							if (current_iou > iou_thresh && class_id == truth[j].id) {
 								if (current_iou > max_iou) {
 									max_iou = current_iou;
@@ -686,7 +687,7 @@
 							// if object is difficult then remove detection
 							for (j = 0; j < num_labels_dif; ++j) {
 								box t = { truth_dif[j].x, truth_dif[j].y, truth_dif[j].w, truth_dif[j].h };
-								float current_iou = box_iou(boxes[i], t);
+								float current_iou = box_iou(dets[i].bbox, t);
 								if (current_iou > iou_thresh && class_id == truth_dif[j].id) {
 									--detections_count;
 									break;
@@ -696,7 +697,13 @@
 
 						// calc avg IoU, true-positives, false-positives for required Threshold
 						if (prob > thresh_calc_avg_iou) {
-							if (truth_index > -1) {
+							int z, found = 0;
+							for (z = checkpoint_detections_count; z < detections_count-1; ++z)
+								if (detections[z].unique_truth_index == truth_index) {
+									found = 1; break;
+								}
+
+							if(truth_index > -1 && found == 0) {
 								avg_iou += max_iou;
 								++tp_for_thresh;
 							}
@@ -709,13 +716,15 @@
 			
 			unique_truth_count += num_labels;
 
+			free_detections(dets, nboxes);
 			free(id);
 			free_image(val[t]);
 			free_image(val_resized[t]);
 		}
 	}
 
-	avg_iou = avg_iou / (tp_for_thresh + fp_for_thresh);
+	if((tp_for_thresh + fp_for_thresh) > 0)
+		avg_iou = avg_iou / (tp_for_thresh + fp_for_thresh);
 
 	
 	// SORT(detections)
@@ -830,9 +839,28 @@
 }
 
 #ifdef OPENCV
-void calc_anchors(char *datacfg, int num_of_clusters, int final_width, int final_height, int show)
+typedef struct {
+	float w, h;
+} anchors_t;
+
+int anchors_comparator(const void *pa, const void *pb)
 {
-	printf("\n num_of_clusters = %d, final_width = %d, final_height = %d \n", num_of_clusters, final_width, final_height);
+	anchors_t a = *(anchors_t *)pa;
+	anchors_t b = *(anchors_t *)pb;
+	float diff = b.w*b.h - a.w*a.h;
+	if (diff < 0) return 1;
+	else if (diff > 0) return -1;
+	return 0;
+}
+
+void calc_anchors(char *datacfg, int num_of_clusters, int width, int height, int show)
+{
+	printf("\n num_of_clusters = %d, width = %d, height = %d \n", num_of_clusters, width, height);
+	if (width < 0 || height < 0) {
+		printf("Usage: darknet detector calc_anchors data/voc.data -num_of_clusters 9 -width 416 -height 416 \n");
+		printf("Error: set width and height \n");
+		return;
+	}
 
 	//float pointsdata[] = { 1,1, 2,2, 6,6, 5,5, 10,10 };
 	float *rel_width_height_array = calloc(1000, sizeof(float));
@@ -853,8 +881,10 @@
 		find_replace(path, "images", "labels", labelpath);
 		find_replace(labelpath, "JPEGImages", "labels", labelpath);
 		find_replace(labelpath, ".jpg", ".txt", labelpath);
-		find_replace(labelpath, ".JPEG", ".txt", labelpath);
 		find_replace(labelpath, ".png", ".txt", labelpath);
+		find_replace(labelpath, ".bmp", ".txt", 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);
 		//printf(" new path: %s \n", labelpath);
@@ -862,8 +892,8 @@
 		{
 			number_of_boxes++;
 			rel_width_height_array = realloc(rel_width_height_array, 2 * number_of_boxes * sizeof(float));
-			rel_width_height_array[number_of_boxes * 2 - 2] = truth[j].w * final_width;
-			rel_width_height_array[number_of_boxes * 2 - 1] = truth[j].h * final_height;
+			rel_width_height_array[number_of_boxes * 2 - 2] = truth[j].w * width;
+			rel_width_height_array[number_of_boxes * 2 - 1] = truth[j].h * height;
 			printf("\r loaded \t image: %d \t box: %d", i+1, number_of_boxes);
 		}
 	}
@@ -896,7 +926,10 @@
 		cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10000, 0), attemps, 
 		0, KMEANS_PP_CENTERS,
 		centers, &compactness);
-	
+
+	// sort anchors
+	qsort(centers->data.fl, num_of_clusters, 2*sizeof(float), anchors_comparator);
+
 	//orig 2.0 anchors = 1.08,1.19,  3.42,4.41,  6.63,11.38,  9.42,5.11,  16.62,10.52
 	//float orig_anch[] = { 1.08,1.19,  3.42,4.41,  6.63,11.38,  9.42,5.11,  16.62,10.52 };
 	// worse than ours (even for 19x19 final size - for input size 608x608)
@@ -953,9 +986,12 @@
 	printf("anchors = ");
 	for (i = 0; i < num_of_clusters; ++i) {
 		sprintf(buff, "%2.4f,%2.4f", centers->data.fl[i * 2], centers->data.fl[i * 2 + 1]);
-		printf("%s, ", buff);
+		printf("%s", buff);
 		fwrite(buff, sizeof(char), strlen(buff), fw);
-		if (i + 1 < num_of_clusters) fwrite(", ", sizeof(char), 2, fw);;
+		if (i + 1 < num_of_clusters) {
+			fwrite(", ", sizeof(char), 2, fw);
+			printf(", ");
+		}
 	}
 	printf("\n");
 	fclose(fw);
@@ -967,15 +1003,15 @@
 		for (j = 0; j < num_of_clusters; ++j) {
 			CvPoint pt1, pt2;
 			pt1.x = pt1.y = 0;
-			pt2.x = centers->data.fl[j * 2] * img_size / final_width;
-			pt2.y = centers->data.fl[j * 2 + 1] * img_size / final_height;
+			pt2.x = centers->data.fl[j * 2] * img_size / width;
+			pt2.y = centers->data.fl[j * 2 + 1] * img_size / height;
 			cvRectangle(img, pt1, pt2, CV_RGB(255, 255, 255), 1, 8, 0);
 		}
 
 		for (i = 0; i < number_of_boxes; ++i) {
 			CvPoint pt;
-			pt.x = points->data.fl[i * 2] * img_size / final_width;
-			pt.y = points->data.fl[i * 2 + 1] * img_size / final_height;
+			pt.x = points->data.fl[i * 2] * img_size / width;
+			pt.y = points->data.fl[i * 2 + 1] * img_size / height;
 			int cluster_idx = labels->data.i[i];
 			int red_id = (cluster_idx * (uint64_t)123 + 55) % 255;
 			int green_id = (cluster_idx * (uint64_t)321 + 33) % 255;
@@ -995,25 +1031,27 @@
 	cvReleaseMat(&labels);
 }
 #else
-void calc_anchors(char *datacfg, int num_of_clusters, int final_width, int final_height, int show) {
+void calc_anchors(char *datacfg, int num_of_clusters, int width, int height, int show) {
 	printf(" k-means++ can't be used without OpenCV, because there is used cvKMeans2 implementation \n");
 }
 #endif // OPENCV
 
-void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh, float hier_thresh, int dont_show)
+void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh,
+				   float hier_thresh, int dont_show, int ext_output)
 {
     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 = parse_network_cfg_custom(cfgfile, 1);
+    network net = parse_network_cfg_custom(cfgfile, 1); // set batch=1
     if(weightfile){
         load_weights(&net, weightfile);
     }
-    set_batch_network(&net, 1);
+    //set_batch_network(&net, 1);
+	fuse_conv_batchnorm(net);
     srand(2222222);
-    clock_t time;
+    double time;
     char buff[256];
     char *input = buff;
     int j;
@@ -1021,7 +1059,8 @@
     while(1){
         if(filename){
             strncpy(input, filename, 256);
-			if (input[strlen(input) - 1] == 0x0d) input[strlen(input) - 1] = 0;
+			if(strlen(input) > 0)
+				if (input[strlen(input) - 1] == 0x0d) input[strlen(input) - 1] = 0;
         } else {
             printf("Enter Image Path: ");
             fflush(stdout);
@@ -1030,9 +1069,9 @@
             strtok(input, "\n");
         }
         image im = load_image_color(input,0,0);
-		int letter = 0;
-        image sized = resize_image(im, net.w, net.h);
-		//image sized = letterbox_image(im, net.w, net.h); letter = 1;
+		int letterbox = 0;
+        //image sized = resize_image(im, net.w, net.h);
+		image sized = letterbox_image(im, net.w, net.h); letterbox = 1;
         layer l = net.layers[net.n-1];
 
         //box *boxes = calloc(l.w*l.h*l.n, sizeof(box));
@@ -1040,16 +1079,17 @@
         //for(j = 0; j < l.w*l.h*l.n; ++j) probs[j] = calloc(l.classes, sizeof(float *));
 
         float *X = sized.data;
-        time=clock();
+        time= what_time_is_it_now();
         network_predict(net, X);
-        printf("%s: Predicted in %f seconds.\n", input, sec(clock()-time));
+		//network_predict_image(&net, im); letterbox = 1;
+        printf("%s: Predicted in %f seconds.\n", input, (what_time_is_it_now()-time));
         //get_region_boxes(l, 1, 1, thresh, probs, boxes, 0, 0);
-		// if (nms) do_nms_sort(boxes, probs, l.w*l.h*l.n, l.classes, nms);
+		// if (nms) do_nms_sort_v2(boxes, probs, l.w*l.h*l.n, l.classes, nms);
 		//draw_detections(im, l.w*l.h*l.n, thresh, boxes, probs, names, alphabet, l.classes);
 		int nboxes = 0;
-		detection *dets = get_network_boxes(&net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes, letter);
-		if (nms) do_nms_sort_v3(dets, nboxes, l.classes, nms);
-		draw_detections_v3(im, dets, nboxes, thresh, names, alphabet, l.classes);
+		detection *dets = get_network_boxes(&net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes, letterbox);
+		if (nms) do_nms_sort(dets, nboxes, l.classes, nms);
+		draw_detections_v3(im, dets, nboxes, thresh, names, alphabet, l.classes, ext_output);
 		free_detections(dets, nboxes);
         save_image(im, "predictions");
 		if (!dont_show) {
@@ -1076,14 +1116,18 @@
 	int show = find_arg(argc, argv, "-show");
 	int http_stream_port = find_int_arg(argc, argv, "-http_port", -1);
 	char *out_filename = find_char_arg(argc, argv, "-out_filename", 0);
+	char *outfile = find_char_arg(argc, argv, "-out", 0);
     char *prefix = find_char_arg(argc, argv, "-prefix", 0);
     float thresh = find_float_arg(argc, argv, "-thresh", .25);	// 0.24
 	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 num_of_clusters = find_int_arg(argc, argv, "-num_of_clusters", 5);
-	int final_width = find_int_arg(argc, argv, "-final_width", 13);
-	int final_heigh = find_int_arg(argc, argv, "-final_heigh", 13);
+	int width = find_int_arg(argc, argv, "-width", -1);
+	int height = find_int_arg(argc, argv, "-height", -1);
+	// extended output in test mode (output of rect bound coords)
+	// and for recall mode (extended output table-like format with results for best_class fit)
+	int ext_output = find_arg(argc, argv, "-ext_output");
     if(argc < 4){
         fprintf(stderr, "usage: %s %s [train/test/valid] [cfg] [weights (optional)]\n", argv[0], argv[1]);
         return;
@@ -1117,22 +1161,25 @@
     char *cfg = argv[4];
     char *weights = (argc > 5) ? argv[5] : 0;
 	if(weights)
-		if (weights[strlen(weights) - 1] == 0x0d) weights[strlen(weights) - 1] = 0;
+		if(strlen(weights) > 0)
+			if (weights[strlen(weights) - 1] == 0x0d) weights[strlen(weights) - 1] = 0;
     char *filename = (argc > 6) ? argv[6]: 0;
-    if(0==strcmp(argv[2], "test")) test_detector(datacfg, cfg, weights, filename, thresh, hier_thresh, dont_show);
+    if(0==strcmp(argv[2], "test")) test_detector(datacfg, cfg, weights, filename, thresh, hier_thresh, dont_show, ext_output);
     else if(0==strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear, dont_show);
-    else if(0==strcmp(argv[2], "valid")) validate_detector(datacfg, cfg, weights);
+    else if(0==strcmp(argv[2], "valid")) validate_detector(datacfg, cfg, weights, outfile);
     else if(0==strcmp(argv[2], "recall")) validate_detector_recall(datacfg, cfg, weights);
 	else if(0==strcmp(argv[2], "map")) validate_detector_map(datacfg, cfg, weights, thresh);
-	else if(0==strcmp(argv[2], "calc_anchors")) calc_anchors(datacfg, num_of_clusters, final_width, final_heigh, show);
+	else if(0==strcmp(argv[2], "calc_anchors")) calc_anchors(datacfg, num_of_clusters, width, height, show);
     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);
 		if(filename)
-			if (filename[strlen(filename) - 1] == 0x0d) filename[strlen(filename) - 1] = 0;
+			if(strlen(filename) > 0)
+				if (filename[strlen(filename) - 1] == 0x0d) filename[strlen(filename) - 1] = 0;
         demo(cfg, weights, thresh, hier_thresh, cam_index, filename, names, classes, frame_skip, prefix, out_filename,
 			http_stream_port, dont_show);
     }
+	else printf(" There isn't such command: %s", argv[2]);
 }

--
Gitblit v1.10.0