Mercurial Hosting > traffic-intelligence
changeset 1186:7117a31555c1
Etienne Beauchamp s work on optimization with Nomad software
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Tue, 21 Jun 2022 17:06:06 -0400 |
parents | aa88acf06876 |
children | 25c85a7ecf09 |
files | scripts/nomad/README.md scripts/nomad/initial-parameters.txt scripts/nomad/nomad-parameters.txt scripts/nomad/optimize-with-nomad.py scripts/nomad/site-parameters-optimization.py |
diffstat | 5 files changed, 214 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/nomad/README.md Tue Jun 21 17:06:06 2022 -0400 @@ -0,0 +1,38 @@ +# Optimization tool + +---- +## usage +1. Make sure your data is structured like so: +``` + Data # Folder containing all the data + └── <Intersection name> # Intersection (e.g. montcalm-chartwell) + ├── <tracking configuration file>.cfg + ├── <Date 1> + │ ├── <Other subdirectories> # There can be as many subdirectories as you want + │ ├── <Video 1> + │ ├── <Ground truth database 1>_gt.sqlite + │ ├── homography.txt + │ ├── image.pg + │ ├── mask.png + │ └── point-correspondences.txt + ├── <Date 2> + └── <Date 3> + . + . + . +``` + +> Please note : You should have at least one ground truth database (with a name ending with "_gt.sqlite") for each date of the intersection. + +2. Select an intersection or several intersections for which you wish to find optimal tracking parameters, for instance: + + $ python3 optimize-with-nomad.py -t /media/disk2/etienne/Data/montcalm-chartwell/ /media/disk2/etienne/Data/montcalm-victorin/ --optimize-grouping-only + +> Please note : You cannot find the optimal parameters only for the grouping algorithm if there is not a database already created. You should first execute the tracking algorithm with basic parameters. + +3. Once the optimal parameters are found, tracking may be launched: + + $ cd $HOME/Data/montcalm-chartwell + $ feature-based-tracking tracking-visible.cfg --tf --video-filename 2019-11-27/Visible/2019-11-27T12\:20-05\:00.MP4 --database-filename 2019-11-27/Visible/2019-11-27T12\:20-05\:00.sqlite --homography-filename 2019-11-27/Visible/homography.txt --mask-filename 2019-11-27/Visible/mask.png --feature-quality 0.1 --min-feature-distanceklt 3.54964337411 --window-size 6 --min-tracking-error 0.01 --min-feature-time 15 + $ feature-based-tracking tracking-visible.cfg --gf --video-filename 2019-11-27/Visible/2019-11-27T12\:20-05\:00.MP4 --database-filename 2019-11-27/Visible/2019-11-27T12\:20-05\:00.sqlite --homography-filename 2019-11-27/Visible/homography.txt --mask-filename 2019-11-27/Visible/mask.png --mm-connection-distance 2 --mm-segmentation-distance 1.9 --min-nfeatures-group 4 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/nomad/initial-parameters.txt Tue Jun 21 17:06:06 2022 -0400 @@ -0,0 +1,1 @@ +0.1 3.54964337411 6 0.1833289751 15 2.5 0.5 3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/nomad/nomad-parameters.txt Tue Jun 21 17:06:06 2022 -0400 @@ -0,0 +1,29 @@ +DIMENSION 8 # number of variables + +BB_EXE "$python3 site-parameters-optimization.py" # 'site-parameters-optimization.py' is the blackbox program +BB_OUTPUT_TYPE OBJ # object will be minimized + +X0 initial-parameters.txt # starting point + +LOWER_BOUND ( 0 0 1 0.01 2 0.5 0.1 1 ) # all variables' lower bounds +UPPER_BOUND ( 1 10 10 0.3 100 100 100 15 ) # all variables' upper bounds + +MAX_BB_EVAL 500 # the algorithm terminates when + # n black-box evaluations have + # been made + +# TMP_DIR /tmp # indicates a directory where + # temporary files are put + # (increases performance by ~100% + # if you're working on a network + # account and if TMP_DIR is on a + # local disk) + +DISPLAY_DEGREE 2 + +# DISPLAY_ALL_EVAL yes + +DISPLAY_STATS BBE ( SOL ) OBJ # Display the number of evaluation (BBE), + # the current solution ( SOL ) and the objective + +# STATS_FILE test.txt BBE ( SOL ) OBJ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/nomad/optimize-with-nomad.py Tue Jun 21 17:06:06 2022 -0400 @@ -0,0 +1,29 @@ +import os +import argparse + +parser = argparse.ArgumentParser(description='The program is used to select the type of tracking to run with ' + 'tracking-mota.py with NOMAD', + epilog='''NOMAD - A blackbox optimization software: + C. Audet, S. Le Digabel, C. Tribes and V. Rochon Montplaisir. The NOMAD project. + Software available at https://www.gerad.ca/nomad. + + S. Le Digabel. Algorithm 909: NOMAD: Nonlinear Optimization with the MADS algorithm. + ACM Transactions on Mathematical Software, 37(4):44:1–44:15, 2011.''', + formatter_class=argparse.RawDescriptionHelpFormatter) + +parser.add_argument('-t', dest='intersections', nargs = '*', type = str, help='name of the intersection for which ' + 'the optimization is meant to be ran', + required=True) +parser.add_argument('--optimize-grouping-only', dest='optimizeGroupingOnly', + help='optimize only the grouping parameters and not the ones associated with feature tracking', + action='store_true') + +args = parser.parse_args() + +with open('arguments.txt', 'w') as f: + f.write(str(args.intersections)) + f.write("\n") + f.write(str(args.optimizeGroupingOnly)) + +os.system('nomad nomad-parameters.txt initial-parameters.txt') +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/nomad/site-parameters-optimization.py Tue Jun 21 17:06:06 2022 -0400 @@ -0,0 +1,117 @@ +#! /usr/bin/env python3 +import os +import sys +import glob +from trafficintelligence import storage, moving +import subprocess +import numpy as np + + +def loadParametersStartProcess(filename): + # load initial parameters from x.txt + f = open(filename, 'r+') + l = f.readline() + x = [s for s in l.strip().split(" ")] + f.close() + + # create para-value list + para = paraValueList(x) + + # run process including trackingfeature, groupfeature, load groundtruth, compute mota + print(process(para, intersections, optimizeGroupingOnly)) + +def paraValueList(x): + #create para-value list + #list of the 8 parameters and their values + pn = 8 + p = pn*[None] + p[0] = '--feature-quality' #]0.-0.4] + p[1] = '--min-feature-distanceklt' #]0.-6] + p[2] = '--window-size' #[1-10]integer + p[3] = '--min-tracking-error' #[0.01-0.3] + p[4] = '--min-feature-time' #[2-100]integer + p[5] = '--mm-connection-distance' #[0.5-100] + p[6] = '--mm-segmentation-distance' #[1-100] ~mm-connection-distance / 2.5 + p[7] = '--min-nfeatures-group' #[2-4] + + para = [] + for n in range(pn): + para = para + [p[n],x[n]] + + return para + +def process(para, intersections, optimizeGroupingOnly): + Mota = [] + gtDatabaseaAbsPaths = [] + configFileAbsPaths = [] + + cwd = os.getcwd() + # move to the location of the intersection + for intersectionPath in intersections: + intersectionAbsPath = os.path.abspath(intersectionPath) + os.chdir(intersectionAbsPath) + # iterate through all the subdirectories to find ground truth sqlite files + gtDatabaseaAbsPaths.extend([os.path.abspath(intersectionAbsPath + '/' + file) for file in glob.glob('**/*_gt.sqlite', recursive=True)]) + configFileAbsPaths.append(os.path.abspath(intersectionAbsPath + '/' + glob.glob('*.cfg', recursive=True)[0])) + os.chdir(cwd) + for gtDatabaseAbsPath, configFileAbsPath in zip(gtDatabaseaAbsPaths, configFileAbsPaths): + gtDatabaseBasename = gtDatabaseAbsPath[:-10] + videoFilename = gtDatabaseBasename + ".MP4" + databaseFilename = gtDatabaseBasename + ".sqlite" + gtDatabaseDirname = os.path.dirname(gtDatabaseAbsPath) + homographyFilename = gtDatabaseDirname + "/homography.txt" + maskFilename = gtDatabaseDirname + "/mask.png" + # Skip feature tracking if the user specified to optimize only grouping parameters + if not optimizeGroupingOnly: + # Track features + trackingFeature(para, configFileAbsPath, videoFilename, databaseFilename, homographyFilename, maskFilename) + # Group features + groupFeature(para, configFileAbsPath, videoFilename, databaseFilename, homographyFilename, maskFilename) + #load trajectory + objects = storage.loadTrajectoriesFromSqlite(databaseFilename, 'object') + #load ground truth + annotations = storage.loadTrajectoriesFromSqlite(gtDatabaseAbsPath, 'object') + # Appending negative mota because nomad minimizes the output + Mota.append(-computeMota(annotations, objects, Mota)) + + # Change to the previous directory + os.chdir(cwd) + + return np.mean(Mota) + +def trackingFeature(para, config, video, db, homo, mask): + # remove previous tracking + if os.path.exists(db): + os.remove(db) + # trackingfeature command parameters + tf = ['feature-based-tracking', config, '--tf', '--video-filename', video, '--database-filename', db, '--homography-filename', homo, '--mask-filename', mask] + # run in command line and print directly + subprocess.check_output(tf + para[0:10]) + +def groupFeature(para, config, video, db, homo, mask): + #remove previous grouping + storage.deleteFromSqlite(db, 'object') + #groupfeature command parameters + gf = ['feature-based-tracking', config, '--gf', '--video-filename', video, '--database-filename', db, '--homography-filename', homo, '--mask-filename', mask] + #run in command line and print directly + subprocess.check_output(gf + para[8:16]) # ['--min-feature-time', 'x', '--mm-connection-distance', 'x', '--mm-segmentation-distance', 'x', '--min-nfeatures-group', 'x'] + +def computeMota(annotations, objects, Mota): + matchingDistance = 500 + firstInstant = 0 + lastInstant = 50000 + return moving.computeClearMOT(annotations, objects, matchingDistance, firstInstant, lastInstant)[1] + + +if __name__ == "__main__": + # Load args that were given with select-arguments.py + with open('arguments.txt', 'r') as f: + args = f.read().split('\n') + intersections = args[0] + optimizeGroupingOnly = args[1] + # Convert string representation of list into list + intersections = eval(intersections) + + loadParametersStartProcess(sys.argv[1]) + sys.exit(0) +