diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 1f33a47b114..b59a4710719 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -124,7 +124,7 @@ jobs: CUDA_PATH: "/usr/local/cuda" CUDA_TOOLKIT_ROOT_DIR: "/usr/local/cuda" LD_LIBRARY_PATH: "/usr/local/cuda/lib64:/usr/local/cuda/lib64/stubs:$LD_LIBRARY_PATH" - run: ${{ github.workspace }}/build.ps1 -UseVCPKG -DoNotUpdateVCPKG -EnableOPENCV -EnableCUDA -EnableCUDNN -DisableInteractive -DoNotUpdateTOOL + run: ${{ github.workspace }}/build.ps1 -UseVCPKG -DoNotUpdateVCPKG -EnableOPENCV -EnableCUDA -EnableCUDNN -DisableInteractive -DoNotUpdateTOOL -BuildInstaller - uses: actions/upload-artifact@v3 with: @@ -410,7 +410,7 @@ jobs: - name: 'Build' shell: pwsh - run: ${{ github.workspace }}/build.ps1 -UseVCPKG -DoNotUpdateVCPKG -EnableOPENCV -DisableInteractive -DoNotUpdateTOOL + run: ${{ github.workspace }}/build.ps1 -UseVCPKG -DoNotUpdateVCPKG -EnableOPENCV -DisableInteractive -DoNotUpdateTOOL -BuildInstaller - uses: actions/upload-artifact@v3 with: @@ -506,7 +506,7 @@ jobs: - name: 'Build' shell: pwsh - run: ${{ github.workspace }}/build.ps1 -UseVCPKG -ForceLocalVCPKG -DoNotUpdateVCPKG -EnableOPENCV -DisableInteractive -DoNotUpdateTOOL + run: ${{ github.workspace }}/build.ps1 -UseVCPKG -ForceLocalVCPKG -DoNotUpdateVCPKG -EnableOPENCV -DisableInteractive -DoNotUpdateTOOL -BuildInstaller - uses: actions/upload-artifact@v3 with: diff --git a/CMakeLists.txt b/CMakeLists.txt index 8587793345a..8766e59524f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ option(VCPKG_BUILD_OPENCV_WITH_CUDA "Build OpenCV with CUDA extension integratio option(VCPKG_USE_OPENCV2 "Use legacy OpenCV 2" OFF) option(VCPKG_USE_OPENCV3 "Use legacy OpenCV 3" OFF) option(VCPKG_USE_OPENCV4 "Use OpenCV 4" ON) +option(USE_NSIS "Use NSIS as a CPack backend on Windows" ON) if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET}) message(STATUS "Setting default vcpkg target triplet to $ENV{VCPKG_DEFAULT_TRIPLET}") @@ -667,15 +668,9 @@ install( if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg.json) file(READ ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg.json VCPKG_JSON_STRING) string(JSON CPACK_PACKAGE_NAME GET ${VCPKG_JSON_STRING} name) - string(JSON CPACK_BUNDLE_NAME GET ${VCPKG_JSON_STRING} name) string(JSON CPACK_PACKAGE_HOMEPAGE_URL GET ${VCPKG_JSON_STRING} homepage) string(JSON CPACK_PACKAGE_DESCRIPTION GET ${VCPKG_JSON_STRING} description) - string(JSON CPACK_NSIS_DISPLAY_NAME GET ${VCPKG_JSON_STRING} description) - string(JSON CPACK_NSIS_PACKAGE_NAME GET ${VCPKG_JSON_STRING} description) set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) - set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/src/darknet.ico") - set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/src/darknet.ico") - set(CPACK_BUNDLE_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/src/darknet.ico") if(UNIX AND NOT APPLE) find_program(LSB_RELEASE_EXEC lsb_release) @@ -685,14 +680,26 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg.json) ) if(LSB_RELEASE_ID_SHORT STREQUAL "Ubuntu") set(CPACK_GENERATOR "DEB") + set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Darknet") else() set(CPACK_GENERATOR "RPM") endif() + elseif(APPLE) + set(CPACK_GENERATOR "DragNDrop") elseif(WIN32) set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) - set(CPACK_NSIS_MODIFY_PATH "ON") - set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON") - set(CPACK_GENERATOR "NSIS") + if(USE_NSIS) + set(CPACK_GENERATOR "NSIS") + string(JSON CPACK_NSIS_PACKAGE_NAME GET ${VCPKG_JSON_STRING} name) + string(JSON CPACK_NSIS_DISPLAY_NAME GET ${VCPKG_JSON_STRING} name) + set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL "ON") + set(CPACK_NSIS_MODIFY_PATH OFF) #disable extra page for adding to PATH, because it's broken on Win10+ due to NSIS not supporting MAX_PATH + set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/src/darknet.ico") + set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/src/darknet.ico") + else() + set(CPACK_GENERATOR "WIX") + #set(CPACK_WIX_UPGRADE_GUID "") # IMPORTANT! It has to be unique for every project!! + endif() endif() include(CPack) diff --git a/README.md b/README.md index 64a7ff4e150..d9de132a86d 100644 --- a/README.md +++ b/README.md @@ -581,6 +581,8 @@ It will create `.txt`-file for each `.jpg`-image-file - in the same directory an 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 yolov4.conv.137 -map` +8.2. One can also set the `-mAP_epochs` in the training command if less or more frequent mAP calculation is needed. For example in order to calculate mAP for each 2 Epochs run `darknet.exe detector train data/obj.data yolo-obj.cfg yolov4.conv.137 -map -mAP_epochs 2` + 9. After training is complete - get result `yolo-obj_final.weights` from path `build\darknet\x64\backup\` - After each 100 iterations you can stop and later start training from this point. For example, after 2000 iterations you can stop training, and later just start training using: `darknet.exe detector train data/obj.data yolo-obj.cfg backup\yolo-obj_2000.weights` diff --git a/build.ps1 b/build.ps1 index b9e3205569e..a85fcca7b8b 100755 --- a/build.ps1 +++ b/build.ps1 @@ -6,7 +6,7 @@ build Created By: Stefano Sinigardi Created Date: February 18, 2019 - Last Modified Date: August 31, 2023 + Last Modified Date: September 10, 2023 .DESCRIPTION Build tool using CMake, trying to properly setup the environment around compiler @@ -193,7 +193,7 @@ param ( $global:DisableInteractive = $DisableInteractive -$build_ps1_version = "3.5.0" +$build_ps1_version = "3.5.1" $script_name = $MyInvocation.MyCommand.Name Import-Module -Name $PSScriptRoot/scripts/utils.psm1 -Force @@ -210,9 +210,12 @@ else { $BuildLogPath = "$PSCustomScriptRoot/build.log" $ReleaseInstallPrefix = "$PSCustomScriptRoot" $DebugInstallPrefix = "$PSCustomScriptRoot/debug" -$DebugBuildSetup = " -DCMAKE_INSTALL_PREFIX=$DebugInstallPrefix -DCMAKE_BUILD_TYPE=Debug" -$ReleaseBuildSetup = " -DCMAKE_INSTALL_PREFIX=$ReleaseInstallPrefix -DCMAKE_BUILD_TYPE=Release" - +$DebugBuildSetup = " -DCMAKE_BUILD_TYPE=Debug " +$ReleaseBuildSetup = " -DCMAKE_BUILD_TYPE=Release " +if (-Not $BuildInstaller) { + $DebugBuildSetup = $DebugBuildSetup + " -DCMAKE_INSTALL_PREFIX=$DebugInstallPrefix " + $ReleaseBuildSetup = $ReleaseBuildSetup + " -DCMAKE_INSTALL_PREFIX=$ReleaseInstallPrefix " +} Start-Transcript -Path $BuildLogPath Write-Host "Build script version ${build_ps1_version}, utils module version ${utils_psm1_version}" @@ -819,6 +822,11 @@ if ($ForceVCPKGCacheRemoval -and (-Not $UseVCPKG)) { Write-Host "VCPKG is not enabled, so local vcpkg binary cache will not be deleted even if requested" -ForegroundColor Yellow } +if ($BuildInstaller) { + Write-Host "You requested to build an installer, so enabling this option if supported" -ForegroundColor Yellow + $AdditionalBuildSetup = $AdditionalBuildSetup + " -DENABLE_INSTALLER=ON" +} + if (($ForceOpenCVVersion -eq 2) -and $UseVCPKG) { Write-Host "You requested OpenCV version 2, so vcpkg will install that version" -ForegroundColor Yellow Write-Host "This requires using vcpkg.json.opencv23 as manifest file" -ForegroundColor Yellow @@ -1012,7 +1020,12 @@ else { MyThrow("Config failed! Exited with error code $exitCode.") } Write-Host "Building release CMake project" -ForegroundColor Green - $proc = Start-Process -NoNewWindow -PassThru -FilePath $CMAKE_EXE -ArgumentList "--build . ${releaseConfig} --parallel ${NumberOfBuildWorkers} --target install" + if ($BuildInstaller) { + $proc = Start-Process -NoNewWindow -PassThru -FilePath $CMAKE_EXE -ArgumentList "--build . ${releaseConfig} --parallel ${NumberOfBuildWorkers}" + } + else { + $proc = Start-Process -NoNewWindow -PassThru -FilePath $CMAKE_EXE -ArgumentList "--build . ${releaseConfig} --parallel ${NumberOfBuildWorkers} --target install" + } $handle = $proc.Handle $proc.WaitForExit() $exitCode = $proc.ExitCode diff --git a/include/darknet.h b/include/darknet.h index d82cda2841a..55ab50d5da8 100644 --- a/include/darknet.h +++ b/include/darknet.h @@ -1052,7 +1052,7 @@ LIB_API void reset_rnn(network *net); LIB_API float *network_predict_image(network *net, image im); LIB_API float *network_predict_image_letterbox(network *net, image im); LIB_API float validate_detector_map(char *datacfg, char *cfgfile, char *weightfile, float thresh_calc_avg_iou, const float iou_thresh, const int map_points, int letter_box, network *existing_net); -LIB_API void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, int ngpus, int clear, int dont_show, int calc_map, float thresh, float iou_thresh, int mjpeg_port, int show_imgs, int benchmark_layers, char* chart_path); +LIB_API void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, int ngpus, int clear, int dont_show, int calc_map, float thresh, float iou_thresh, int mjpeg_port, int show_imgs, int benchmark_layers, char* chart_path, int mAP_epochs); LIB_API void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh, float hier_thresh, int dont_show, int ext_output, int save_labels, char *outfile, int letter_box, int benchmark_layers); LIB_API int network_width(network *net); diff --git a/src/coco.c b/src/coco.c index ec49ae013d3..1ccb3bc8b63 100644 --- a/src/coco.c +++ b/src/coco.c @@ -374,10 +374,9 @@ void test_coco(char *cfgfile, char *weightfile, char *filename, float thresh) show_image(im, "predictions"); free_image(im); free_image(sized); - + free_alphabet(alphabet); wait_until_press_key_cv(); destroy_all_windows_cv(); - if (filename) break; } free(boxes); diff --git a/src/data.c b/src/data.c index 7d2a4659906..17b675cc667 100644 --- a/src/data.c +++ b/src/data.c @@ -1238,6 +1238,15 @@ data load_data_detection(int n, char **paths, int m, int w, int h, int c, int bo int swidth = ow - pleft - pright; int sheight = oh - ptop - pbot; + if (swidth <= 0 || sheight <= 0 || (ow - pleft) <= 0 || (oh - ptop) <= 0 ) { + printf("\n WARNING: invalid resize. Resetting swidth: %d , sheight: %d, pleft: %d, ptop: %d \n", dw, dh, 0 ,0); + printf("\n Original values: \n swidth = %d, sheight = %d, pleft = %d, pright = %d, ptop = %d, pbot = %d, ow = %d, oh = %d \n", swidth, sheight, pleft, pright, ptop, pbot, ow, oh); + swidth = ow; + sheight = oh; + pleft = 0; + ptop = 0; + } + float sx = (float)swidth / ow; float sy = (float)sheight / oh; diff --git a/src/demo.c b/src/demo.c index e9017a0bd8c..7a258f3e70f 100644 --- a/src/demo.c +++ b/src/demo.c @@ -413,14 +413,7 @@ void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int free_ptrs((void **)names, net.layers[net.n - 1].classes); - const int nsize = 8; - for (j = 0; j < nsize; ++j) { - for (i = 32; i < 127; ++i) { - free_image(alphabet[j][i]); - } - free(alphabet[j]); - } - free(alphabet); + free_alphabet(alphabet); free_network(net); //cudaProfilerStop(); } diff --git a/src/detector.c b/src/detector.c index 3799063187b..5171ee86a49 100644 --- a/src/detector.c +++ b/src/detector.c @@ -23,7 +23,7 @@ int check_mistakes = 0; 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, float thresh, float iou_thresh, int mjpeg_port, int show_imgs, int benchmark_layers, char* chart_path) +void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, int ngpus, int clear, int dont_show, int calc_map, float thresh, float iou_thresh, int mjpeg_port, int show_imgs, int benchmark_layers, char* chart_path, int mAP_epochs) { list *options = read_data_cfg(datacfg); char *train_images = option_find_str(options, "train", "data/train.txt"); @@ -304,7 +304,7 @@ void train_detector(char *datacfg, char *cfgfile, char *weightfile, int *gpus, i const int iteration = get_current_iteration(net); //i = get_current_batch(net); - int calc_map_for_each = 4 * train_images_num / (net.batch * net.subdivisions); // calculate mAP for each 4 Epochs + int calc_map_for_each = mAP_epochs * train_images_num / (net.batch * net.subdivisions); // calculate mAP every mAP_epochs calc_map_for_each = fmax(calc_map_for_each, 100); int next_map_calc = iter_map + calc_map_for_each; next_map_calc = fmax(next_map_calc, net.burn_in); @@ -1778,17 +1778,7 @@ void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filenam free_ptrs((void**)names, net.layers[net.n - 1].classes); free_list_contents_kvp(options); free_list(options); - - int i; - const int nsize = 8; - for (j = 0; j < nsize; ++j) { - for (i = 32; i < 127; ++i) { - free_image(alphabet[j][i]); - } - free(alphabet[j]); - } - free(alphabet); - + free_alphabet(alphabet); free_network(net); } @@ -2000,6 +1990,8 @@ void run_detector(int argc, char **argv) int ext_output = find_arg(argc, argv, "-ext_output"); int save_labels = find_arg(argc, argv, "-save_labels"); char* chart_path = find_char_arg(argc, argv, "-chart", 0); + // While training, decide after how many epochs mAP will be calculated. Default value is 4 which means the mAP will be calculated after each 4 epochs + int mAP_epochs = find_int_arg(argc, argv, "-mAP_epochs", 4); if (argc < 4) { fprintf(stderr, "usage: %s %s [train/test/valid/demo/map] [data] [cfg] [weights (optional)]\n", argv[0], argv[1]); return; @@ -2038,7 +2030,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, letter_box, benchmark_layers); - else if (0 == strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear, dont_show, calc_map, thresh, iou_thresh, mjpeg_port, show_imgs, benchmark_layers, chart_path); + else if (0 == strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear, dont_show, calc_map, thresh, iou_thresh, mjpeg_port, show_imgs, benchmark_layers, chart_path, mAP_epochs); 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, map_points, letter_box, NULL); diff --git a/src/image.c b/src/image.c index ca9f26651eb..3775837b2b4 100644 --- a/src/image.c +++ b/src/image.c @@ -280,6 +280,19 @@ image **load_alphabet() return alphabets; } +void free_alphabet(image **alphabet) +{ + int i, j; + const int nsize = 8; + for (j = 0; j < nsize; ++j) { + for (i = 32; i < 127; ++i) { + free_image(alphabet[j][i]); + } + free(alphabet[j]); + } + free(alphabet); +} + // Creates array of detections with prob > thresh and fills best_class for them diff --git a/src/image.h b/src/image.h index 90e6a04868b..65ccb7c7122 100644 --- a/src/image.h +++ b/src/image.h @@ -88,6 +88,7 @@ image load_image(char *filename, int w, int h, int c); image load_image_stb_resize(char *filename, int w, int h, int c); //LIB_API image load_image_color(char *filename, int w, int h); image **load_alphabet(); +void free_alphabet(image **alphabet); //float get_pixel(image m, int x, int y, int c); //float get_pixel_extend(image m, int x, int y, int c); diff --git a/src/image_opencv.cpp b/src/image_opencv.cpp index 7ff18bfe862..459d9bf0f37 100644 --- a/src/image_opencv.cpp +++ b/src/image_opencv.cpp @@ -1331,8 +1331,8 @@ extern "C" image image_data_augmentation(mat_cv* mat, int w, int h, // Mat -> image out = mat_to_image(sized); } - catch (...) { - cerr << "OpenCV can't augment image: " << w << " x " << h << " \n"; + catch (const std::exception& e) { + cerr << "OpenCV can't augment image: " << w << " x " << h << " \n" << e.what() << " \n"; out = mat_to_image(*(cv::Mat*)mat); } return out; diff --git a/src/parser.c b/src/parser.c index 3bf4683d996..16a2b905f7b 100644 --- a/src/parser.c +++ b/src/parser.c @@ -2006,12 +2006,12 @@ void save_weights_upto(network net, char *filename, int cutoff, int save_ema) FILE *fp = fopen(filename, "wb"); if(!fp) file_error(filename); - int major = MAJOR_VERSION; - int minor = MINOR_VERSION; - int revision = PATCH_VERSION; - fwrite(&major, sizeof(int), 1, fp); - fwrite(&minor, sizeof(int), 1, fp); - fwrite(&revision, sizeof(int), 1, fp); + int32_t major = MAJOR_VERSION; + int32_t minor = MINOR_VERSION; + int32_t revision = PATCH_VERSION; + fwrite(&major, sizeof(int32_t), 1, fp); + fwrite(&minor, sizeof(int32_t), 1, fp); + fwrite(&revision, sizeof(int32_t), 1, fp); (*net.seen) = get_current_iteration(net) * net.batch * net.subdivisions; // remove this line, when you will save to weights-file both: seen & cur_iteration fwrite(net.seen, sizeof(uint64_t), 1, fp); @@ -2267,12 +2267,12 @@ void load_weights_upto(network *net, char *filename, int cutoff) FILE *fp = fopen(filename, "rb"); if(!fp) file_error(filename); - int major; - int minor; - int revision; - fread(&major, sizeof(int), 1, fp); - fread(&minor, sizeof(int), 1, fp); - fread(&revision, sizeof(int), 1, fp); + int32_t major; + int32_t minor; + int32_t revision; + fread(&major, sizeof(int32_t), 1, fp); + fread(&minor, sizeof(int32_t), 1, fp); + fread(&revision, sizeof(int32_t), 1, fp); if ((major * 10 + minor) >= 2) { printf("\n seen 64"); uint64_t iseen = 0; diff --git a/src/yolo.c b/src/yolo.c index f13d460aca0..dfd497dfc80 100644 --- a/src/yolo.c +++ b/src/yolo.c @@ -328,11 +328,11 @@ void test_yolo(char *cfgfile, char *weightfile, char *filename, float thresh) free_image(im); free_image(sized); - + free_alphabet(alphabet); wait_until_press_key_cv(); destroy_all_windows_cv(); - if (filename) break; + if (filename) break; } free(boxes); for(j = 0; j < l.side*l.side*l.n; ++j) {