From 70260cda242729d712c5ca09b3efbd5b504960f0 Mon Sep 17 00:00:00 2001 From: AlexeyAB Date: Sat, 12 Jan 2019 13:45:37 +0300 Subject: [PATCH] Added -mjpeg_port 8090 for Training. Loss-chart saved to chart.png even when used -dont_show. mAP is calculated during training even without OpenCV. --- README.md | 5 +- .../darknet/x64/darknet_demo_mjpeg_stream.cmd | 2 +- json_mjpeg_streams.sh | 2 +- src/classifier.c | 16 ++--- src/coco.c | 4 +- src/demo.c | 10 +-- src/demo.h | 2 +- src/detector.c | 68 +++++++++---------- src/image.c | 28 +++++--- src/yolo.c | 4 +- 10 files changed, 75 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 7e1802ca..9e918ac5 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ On Linux use `./darknet` instead of `darknet.exe`, like this:`./darknet detector * Yolo v3 COCO for **net-videocam** - Smart WebCam: `darknet.exe detector demo data/coco.data cfg/yolov3.cfg yolov3.weights http://192.168.0.80:8080/video?dummy=param.mjpg` * **Yolo v3 - save result to the file res.avi**: `darknet.exe detector demo data/coco.data cfg/yolov3.cfg yolov3.weights -thresh 0.25 test.mp4 -out_filename res.avi` * **Yolo v3 Tiny** COCO - video: `darknet.exe detector demo data/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights test.mp4` -* **JSON and MJPEG server** that allows multiple connections from your soft or Web-browser `ip-address:8070` or 8090: `./darknet detector demo ./cfg/coco.data ./cfg/yolov3.cfg ./yolov3.weights test50.mp4 -json_port 8070 -http_port 8090 -ext_output` +* **JSON and MJPEG server** that allows multiple connections from your soft or Web-browser `ip-address:8070` or 8090: `./darknet detector demo ./cfg/coco.data ./cfg/yolov3.cfg ./yolov3.weights test50.mp4 -json_port 8070 -mjpeg_port 8090 -ext_output` * **Yolo v3 Tiny** on GPU #0: `darknet.exe detector demo data/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights -i 0 test.mp4` * Alternative method Yolo v3 COCO - image: `darknet.exe detect cfg/yolov3.cfg yolov3.weights -i 0 -thresh 0.25` * 186 MB Yolo9000 - image: `darknet.exe detector test cfg/combine9k.data yolo9000.cfg yolo9000.weights` @@ -340,7 +340,8 @@ It will create `.txt`-file for each `.jpg`-image-file - in the same directory an * (file `yolo-obj_last.weights` will be saved to the `build\darknet\x64\backup\` for each 100 iterations) * (file `yolo-obj_xxxx.weights` will be saved to the `build\darknet\x64\backup\` for each 1000 iterations) - * (To disable Loss-Window use `darknet.exe detector train data/obj.data yolo-obj.cfg darknet53.conv.74 -dont_show`, if you train on computer without monitor like a cloud Amazaon EC2) + * (to disable Loss-Window use `darknet.exe detector train data/obj.data yolo-obj.cfg darknet53.conv.74 -dont_show`, if you train on computer without monitor like a cloud Amazon EC2) + * (to see the mAP & Loss-chart during training on remote server without GUI, use command `darknet.exe detector train data/obj.data yolo-obj.cfg darknet53.conv.74 -dont_show -mjpeg_port 8090 -map` then open URL `http://ip-address:8090` in Chrome/Firefox browser) 8.1. For training with mAP (mean average precisions) calculation for each 4 Epochs (set `valid=valid.txt` or `train.txt` in `obj.data` file) and run: `darknet.exe detector train data/obj.data yolo-obj.cfg darknet53.conv.74 -map` diff --git a/build/darknet/x64/darknet_demo_mjpeg_stream.cmd b/build/darknet/x64/darknet_demo_mjpeg_stream.cmd index 95bfb3b4..a1dffac5 100644 --- a/build/darknet/x64/darknet_demo_mjpeg_stream.cmd +++ b/build/darknet/x64/darknet_demo_mjpeg_stream.cmd @@ -1,7 +1,7 @@ rem Run this file and then open URL in Chrome/Firefox: rem http://localhost:8090 rem Or open: http://ip-address:8090 -darknet.exe detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights test.mp4 -i 0 -http_port 8090 -dont_show -ext_output +darknet.exe detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights test.mp4 -i 0 -mjpeg_port 8090 -dont_show -ext_output pause \ No newline at end of file diff --git a/json_mjpeg_streams.sh b/json_mjpeg_streams.sh index 23ce450c..0bf180b6 100644 --- a/json_mjpeg_streams.sh +++ b/json_mjpeg_streams.sh @@ -2,5 +2,5 @@ # Or open: http://ip-address:8070 and http://ip-address:8090 # to get run: sudo ifconfig -./darknet detector demo ./cfg/coco.data ./cfg/yolov3.cfg ./yolov3.weights test50.mp4 -json_port 8070 -http_port 8090 -ext_output +./darknet detector demo ./cfg/coco.data ./cfg/yolov3.cfg ./yolov3.weights test50.mp4 -json_port 8070 -mjpeg_port 8090 -ext_output diff --git a/src/classifier.c b/src/classifier.c index d124f632..26a7a3fe 100644 --- a/src/classifier.c +++ b/src/classifier.c @@ -24,8 +24,9 @@ image get_image_from_stream(CvCapture *cap); image get_image_from_stream_cpp(CvCapture *cap); #include "http_stream.h" -IplImage* draw_train_chart(float max_img_loss, int max_batches, int number_of_lines, int img_size); -void draw_train_loss(IplImage* img, int img_size, float avg_loss, float max_img_loss, int current_batch, int max_batches, float precision, int draw_precision); +IplImage* draw_train_chart(float max_img_loss, int max_batches, int number_of_lines, int img_size, int dont_show); +void draw_train_loss(IplImage* img, int img_size, float avg_loss, float max_img_loss, int current_batch, int max_batches, + float precision, int draw_precision, int dont_show, int mjpeg_port); #endif @@ -41,7 +42,7 @@ float *get_regression_values(char **labels, int n) return v; } -void train_classifier(char *datacfg, char *cfgfile, char *weightfile, int *gpus, int ngpus, int clear, int dont_show) +void train_classifier(char *datacfg, char *cfgfile, char *weightfile, int *gpus, int ngpus, int clear, int dont_show, int mjpeg_port) { int i; @@ -114,8 +115,7 @@ void train_classifier(char *datacfg, char *cfgfile, char *weightfile, int *gpus, float max_img_loss = 5; int number_of_lines = 100; int img_size = 1000; - if (!dont_show) - img = draw_train_chart(max_img_loss, net.max_batches, number_of_lines, img_size); + img = draw_train_chart(max_img_loss, net.max_batches, number_of_lines, img_size, dont_show); #endif //OPENCV data train; @@ -152,8 +152,7 @@ void train_classifier(char *datacfg, char *cfgfile, char *weightfile, int *gpus, printf("%d, %.3f: %f, %f avg, %f rate, %lf seconds, %d images\n", get_current_batch(net), (float)(*net.seen)/N, loss, avg_loss, get_current_rate(net), sec(clock()-time), *net.seen); #ifdef OPENCV - if(!dont_show) - draw_train_loss(img, img_size, avg_loss, max_img_loss, i, net.max_batches, -1, 0); + draw_train_loss(img, img_size, avg_loss, max_img_loss, i, net.max_batches, -1, 0, dont_show, mjpeg_port); #endif // OPENCV if (i >= (iter_save + 100)) { @@ -1186,6 +1185,7 @@ void run_classifier(int argc, char **argv) return; } + int mjpeg_port = find_int_arg(argc, argv, "-mjpeg_port", -1); char *gpu_list = find_char_arg(argc, argv, "-gpus", 0); int *gpus = 0; int gpu = 0; @@ -1221,7 +1221,7 @@ void run_classifier(int argc, char **argv) int layer = layer_s ? atoi(layer_s) : -1; if(0==strcmp(argv[2], "predict")) predict_classifier(data, cfg, weights, filename, top); else if(0==strcmp(argv[2], "try")) try_classifier(data, cfg, weights, filename, atoi(layer_s)); - else if(0==strcmp(argv[2], "train")) train_classifier(data, cfg, weights, gpus, ngpus, clear, dont_show); + else if(0==strcmp(argv[2], "train")) train_classifier(data, cfg, weights, gpus, ngpus, clear, dont_show, mjpeg_port); else if(0==strcmp(argv[2], "demo")) demo_classifier(data, cfg, weights, cam_index, filename); else if(0==strcmp(argv[2], "gun")) gun_classifier(data, cfg, weights, cam_index, filename); else if(0==strcmp(argv[2], "threat")) threat_classifier(data, cfg, weights, cam_index, filename); diff --git a/src/coco.c b/src/coco.c index 62f6770a..aff8e5a0 100644 --- a/src/coco.c +++ b/src/coco.c @@ -365,7 +365,7 @@ void test_coco(char *cfgfile, char *weightfile, char *filename, float thresh) void run_coco(int argc, char **argv) { int dont_show = find_arg(argc, argv, "-dont_show"); - int http_stream_port = find_int_arg(argc, argv, "-http_port", -1); + int mjpeg_port = find_int_arg(argc, argv, "-mjpeg_port", -1); int json_port = find_int_arg(argc, argv, "-json_port", -1); char *out_filename = find_char_arg(argc, argv, "-out_filename", 0); char *prefix = find_char_arg(argc, argv, "-prefix", 0); @@ -388,5 +388,5 @@ void run_coco(int argc, char **argv) else if(0==strcmp(argv[2], "valid")) validate_coco(cfg, weights); else if(0==strcmp(argv[2], "recall")) validate_coco_recall(cfg, weights); else if(0==strcmp(argv[2], "demo")) demo(cfg, weights, thresh, hier_thresh, cam_index, filename, coco_classes, 80, frame_skip, - prefix, out_filename, http_stream_port, json_port, dont_show, ext_output); + prefix, out_filename, mjpeg_port, json_port, dont_show, ext_output); } diff --git a/src/demo.c b/src/demo.c index 10b90861..6de7ec43 100644 --- a/src/demo.c +++ b/src/demo.c @@ -139,7 +139,7 @@ double get_wall_time() } void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes, - int frame_skip, char *prefix, char *out_filename, int http_stream_port, int json_port, int dont_show, int ext_output) + int frame_skip, char *prefix, char *out_filename, int mjpeg_port, int json_port, int dont_show, int ext_output) { in_img = det_img = show_img = NULL; //skip = frame_skip; @@ -279,10 +279,10 @@ void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int if(show_img) save_cv_jpg(show_img, buff); } - // if you run it with param -http_port 8090 then open URL in your web-browser: http://localhost:8090 - if (http_stream_port > 0 && show_img) { + // if you run it with param -mjpeg_port 8090 then open URL in your web-browser: http://localhost:8090 + if (mjpeg_port > 0 && show_img) { //int port = 8090; - int port = http_stream_port; + int port = mjpeg_port; int timeout = 200; int jpeg_quality = 30; // 1 - 100 send_mjpeg(show_img, port, timeout, jpeg_quality); @@ -364,7 +364,7 @@ void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int } #else void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes, - int frame_skip, char *prefix, char *out_filename, int http_stream_port, int json_port, int dont_show, int ext_output) + int frame_skip, char *prefix, char *out_filename, int mjpeg_port, int json_port, int dont_show, int ext_output) { fprintf(stderr, "Demo needs OpenCV for webcam images.\n"); } diff --git a/src/demo.h b/src/demo.h index c6b5246e..5db79346 100644 --- a/src/demo.h +++ b/src/demo.h @@ -3,6 +3,6 @@ #include "image.h" void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes, - int frame_skip, char *prefix, char *out_filename, int http_stream_port, int json_port, int dont_show, int ext_output); + int frame_skip, char *prefix, char *out_filename, int mjpeg_port, int json_port, int dont_show, int ext_output); #endif diff --git a/src/detector.c b/src/detector.c index 455366e3..5c4805c3 100644 --- a/src/detector.c +++ b/src/detector.c @@ -26,8 +26,9 @@ #pragma comment(lib, "opencv_highgui" OPENCV_VERSION ".lib") #endif -IplImage* draw_train_chart(float max_img_loss, int max_batches, int number_of_lines, int img_size); -void draw_train_loss(IplImage* img, int img_size, float avg_loss, float max_img_loss, int current_batch, int max_batches, float precision, int draw_precision); +IplImage* draw_train_chart(float max_img_loss, int max_batches, int number_of_lines, int img_size, int dont_show); +void draw_train_loss(IplImage* img, int img_size, float avg_loss, float max_img_loss, int current_batch, int max_batches, + float precision, int draw_precision, int dont_show, int mjpeg_port); #define CV_RGB(r, g, b) cvScalar( (b), (g), (r), 0 ) #endif // OPENCV @@ -38,7 +39,7 @@ int check_mistakes; 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 }; -void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, int ngpus, int clear, int dont_show, int calc_map) +void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, int ngpus, int clear, int dont_show, int calc_map, int mjpeg_port) { list *options = read_data_cfg(datacfg); char *train_images = option_find_str(options, "train", "data/train.txt"); @@ -158,8 +159,7 @@ void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, i float max_img_loss = 5; int number_of_lines = 100; int img_size = 1000; - if (!dont_show) - img = draw_train_chart(max_img_loss, net.max_batches, number_of_lines, img_size); + img = draw_train_chart(max_img_loss, net.max_batches, number_of_lines, img_size, dont_show); #endif //OPENCV pthread_t load_thread = load_data(args); @@ -238,42 +238,42 @@ void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, i avg_loss = avg_loss*.9 + loss*.1; i = get_current_batch(net); + if (mean_average_precision > 0) { + printf("\n Last accuracy mAP@0.5 = %2.2f %% ", mean_average_precision*100); + } if (net.cudnn_half) { if (i < net.burn_in * 3) printf("\n Tensor Cores are disabled until the first %d iterations are reached.", 3 * net.burn_in); else printf("\n Tensor Cores are used."); } printf("\n %d: %f, %f avg loss, %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) { - int draw_precision = 0; - int calc_map_for_each = 4 * train_images_num / (net.batch * net.subdivisions); // calculate mAP for each 4 Epochs - if (calc_map && (i >= (iter_map + calc_map_for_each) || i == net.max_batches) && i >= net.burn_in && i >= 1000) { - if (l.random) { - printf("Resizing to initial size: %d x %d \n", init_w, init_h); - args.w = init_w; - args.h = init_h; - pthread_join(load_thread, 0); - train = buffer; - load_thread = load_data(args); - int k; - for (k = 0; k < ngpus; ++k) { - resize_network(nets + k, init_w, init_h); - } - net = nets[0]; + int draw_precision = 0; + int calc_map_for_each = 4 * train_images_num / (net.batch * net.subdivisions); // calculate mAP for each 4 Epochs + if (calc_map && (i >= (iter_map + calc_map_for_each) || i == net.max_batches) && i >= net.burn_in && i >= 1000) { + if (l.random) { + printf("Resizing to initial size: %d x %d \n", init_w, init_h); + args.w = init_w; + args.h = init_h; + pthread_join(load_thread, 0); + train = buffer; + load_thread = load_data(args); + int k; + for (k = 0; k < ngpus; ++k) { + resize_network(nets + k, init_w, init_h); } - - // combine Training and Validation networks - network net_combined = combine_train_valid_networks(net, net_map); - - iter_map = i; - mean_average_precision = validate_detector_map(datacfg, cfgfile, weightfile, 0.25, 0.5, &net_combined); - printf("\n mean_average_precision = %f \n", mean_average_precision); - draw_precision = 1; + net = nets[0]; } - draw_train_loss(img, img_size, avg_loss, max_img_loss, i, net.max_batches, mean_average_precision, draw_precision); + // combine Training and Validation networks + network net_combined = combine_train_valid_networks(net, net_map); + + iter_map = i; + mean_average_precision = validate_detector_map(datacfg, cfgfile, weightfile, 0.25, 0.5, &net_combined); + printf("\n mean_average_precision = %f \n", mean_average_precision); + draw_precision = 1; } +#ifdef OPENCV + draw_train_loss(img, img_size, avg_loss, max_img_loss, i, net.max_batches, mean_average_precision, draw_precision, dont_show, mjpeg_port); #endif // OPENCV //if (i % 1000 == 0 || (i < 1000 && i % 100 == 0)) { @@ -1378,7 +1378,7 @@ void run_detector(int argc, char **argv) int show = find_arg(argc, argv, "-show"); int calc_map = find_arg(argc, argv, "-map"); check_mistakes = find_arg(argc, argv, "-check_mistakes"); - int http_stream_port = find_int_arg(argc, argv, "-http_port", -1); + int mjpeg_port = find_int_arg(argc, argv, "-mjpeg_port", -1); int json_port = find_int_arg(argc, argv, "-json_port", -1); char *out_filename = find_char_arg(argc, argv, "-out_filename", 0); char *outfile = find_char_arg(argc, argv, "-out", 0); @@ -1433,7 +1433,7 @@ void run_detector(int argc, char **argv) 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, ext_output, save_labels, outfile); - else if (0 == strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear, dont_show, calc_map); + else if (0 == strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear, dont_show, calc_map, mjpeg_port); 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, iou_thresh, NULL); @@ -1447,7 +1447,7 @@ void run_detector(int argc, char **argv) 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, json_port, dont_show, ext_output); + mjpeg_port, json_port, dont_show, ext_output); free_list_contents_kvp(options); free_list(options); diff --git a/src/image.c b/src/image.c index a4443cdd..3f32e242 100644 --- a/src/image.c +++ b/src/image.c @@ -708,7 +708,7 @@ void draw_detections_cv(IplImage* show_img, int num, float thresh, box *boxes, f } } -IplImage* draw_train_chart(float max_img_loss, int max_batches, int number_of_lines, int img_size) +IplImage* draw_train_chart(float max_img_loss, int max_batches, int number_of_lines, int img_size, int dont_show) { int img_offset = 50; int draw_size = img_size - img_offset; @@ -750,16 +750,19 @@ IplImage* draw_train_chart(float max_img_loss, int max_batches, int number_of_li sprintf(max_batches_buff, "in cfg max_batches=%d", max_batches); cvPutText(img, max_batches_buff, cvPoint(draw_size - 195, img_size - 10), &font, CV_RGB(0, 0, 0)); cvPutText(img, "Press 's' to save: chart.png", cvPoint(5, img_size - 10), &font, CV_RGB(0, 0, 0)); - printf(" If error occurs - run training with flag: -dont_show \n"); - cvNamedWindow("average loss", CV_WINDOW_NORMAL); - cvMoveWindow("average loss", 0, 0); - cvResizeWindow("average loss", img_size, img_size); - cvShowImage("average loss", img); - cvWaitKey(20); + if (!dont_show) { + printf(" If error occurs - run training with flag: -dont_show \n"); + cvNamedWindow("average loss", CV_WINDOW_NORMAL); + cvMoveWindow("average loss", 0, 0); + cvResizeWindow("average loss", img_size, img_size); + cvShowImage("average loss", img); + cvWaitKey(20); + } return img; } -void draw_train_loss(IplImage* img, int img_size, float avg_loss, float max_img_loss, int current_batch, int max_batches, float precision, int draw_precision) +void draw_train_loss(IplImage* img, int img_size, float avg_loss, float max_img_loss, int current_batch, int max_batches, + float precision, int draw_precision, int dont_show, int mjpeg_port) { int img_offset = 50; int draw_size = img_size - img_offset; @@ -806,8 +809,11 @@ void draw_train_loss(IplImage* img, int img_size, float avg_loss, float max_img_ pt1.y += 15; cvPutText(img, char_buff, pt1, &font, CV_RGB(0, 0, 0)); - cvShowImage("average loss", img); - int k = cvWaitKey(20); + int k = 0; + if (!dont_show) { + cvShowImage("average loss", img); + k = cvWaitKey(20); + } if (k == 's' || current_batch == (max_batches - 1) || current_batch % 100 == 0) { //cvSaveImage("chart.jpg", img, 0); save_cv_png(img, "chart.png"); @@ -815,6 +821,8 @@ void draw_train_loss(IplImage* img, int img_size, float avg_loss, float max_img_ } else cvPutText(img, "- Saved", cvPoint(250, img_size - 10), &font, CV_RGB(255, 255, 255)); + + if (mjpeg_port) send_mjpeg(img, mjpeg_port, 2000, 80); } #endif // OPENCV diff --git a/src/yolo.c b/src/yolo.c index 916e5474..56eb814e 100644 --- a/src/yolo.c +++ b/src/yolo.c @@ -338,7 +338,7 @@ void test_yolo(char *cfgfile, char *weightfile, char *filename, float thresh) void run_yolo(int argc, char **argv) { int dont_show = find_arg(argc, argv, "-dont_show"); - int http_stream_port = find_int_arg(argc, argv, "-http_port", -1); + int mjpeg_port = find_int_arg(argc, argv, "-mjpeg_port", -1); int json_port = find_int_arg(argc, argv, "-json_port", -1); char *out_filename = find_char_arg(argc, argv, "-out_filename", 0); char *prefix = find_char_arg(argc, argv, "-prefix", 0); @@ -360,5 +360,5 @@ void run_yolo(int argc, char **argv) else if(0==strcmp(argv[2], "valid")) validate_yolo(cfg, weights); else if(0==strcmp(argv[2], "recall")) validate_yolo_recall(cfg, weights); else if(0==strcmp(argv[2], "demo")) demo(cfg, weights, thresh, hier_thresh, cam_index, filename, voc_names, 20, frame_skip, - prefix, out_filename, http_stream_port, json_port, dont_show, ext_output); + prefix, out_filename, mjpeg_port, json_port, dont_show, ext_output); }