br.cpp 8.97 KB
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright 2012 The MITRE Corporation                                      *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 *     http://www.apache.org/licenses/LICENSE-2.0                            *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openbr.h>

/*!
 * \defgroup cli Command Line Interface
 * \brief Command line application for running algorithms and evaluating results.
 *
 * The easiest and fastest way to leverage the project, we use it all the time!
 * Commands are designed to mirror the \ref c_sdk and are evaluated in the order they are entered.
 * To get started, try running:
 * \code
 * $ br -help
 * \endcode
 *
 * See \ref examples for common use cases.
 */

static void help()
{
    printf("<arg> = Input; {arg} = Output; [arg] = Optional; (arg0|...|argN) = Choice\n"
           "\n"
           "==== Core Commands ====\n"
           "-train <gallery> ... <gallery> [{model}]\n"
           "-enroll <input_gallery> ... <input_gallery> {output_gallery}\n"
           "-compare <target_gallery> <query_gallery> [{output}]\n"
           "-eval <simmat> <mask> [{csv}]\n"
           "-plot <file> ... <file> {destination}\n"
           "\n"
           "==== Other Commands ====\n"
           "-fuse <simmat> ... <simmat> <mask> (None|MinMax|ZScore|WScore) (Min|Max|Sum[W1:W2:...:Wn]|Replace|Difference|None) {simmat}\n"
           "-cluster <simmat> ... <simmat> <aggressiveness> {csv}\n"
           "-makeMask <target_gallery> <query_gallery> {mask}\n"
           "-combineMasks <mask> ... <mask> {mask} (And|Or)\n"
           "-convert <(csv,simmat,mask)> {(csv,simmat,mask)}\n"
           "-reformat <target_sigset> <query_sigset> <simmat> {output}\n"
           "-evalClassification <predicted_gallery> <truth_gallery>\n"
           "-evalRegression <predicted_gallery> <truth_gallery>\n"
           "-evalClusters <clusters> <sigset>\n"
           "-confusion <file> <score>\n"
           "-plotMetadata <file> ... <file> <columns>\n"
           "\n"
           "==== Configuration ====\n"
           "-<key> <value>\n"
           "\n"
           "==== Miscellaneous ====\n"
           "-objects [abstraction [implementation]]\n"
           "-about\n"
           "-version\n"
           "-shell\n"
           "-exit\n");
}

static void check(bool condition, const char *error_message)
{
    if (!condition) {
        printf("%s\n", error_message);
        br_finalize();
        exit(1);
    }
}

int main(int argc, char *argv[])
{
    br_initialize(argc, argv);

    // Remove program name
    argv = &argv[1];
    argc--;

    if (argc == 0) printf("%s\nTry running 'br -help'\n", br_about());

    bool shell = false;
    while (shell || (argc > 0)) {
        const char *fun;
        int parc;
        const char **parv;
        if (shell) {
            printf("> ");
            br_read_line(&parc, &parv);
            if (parc == 0) continue;
            fun = parv[0];
            parc--;
            parv = &parv[1];
        } else /* argc > 0 */ {
            fun = &argv[0][1];
            parc = 0; while ((1+parc < argc) && (argv[1+parc][0] != '-')) parc++;
            parv = (const char **)&argv[1];
            argc = argc - (1+parc);
            argv = &argv[parc+1];
        }

        // Core Tasks
        if (!strcmp(fun, "train")) {
            check(parc >= 1, "Insufficient parameter count for 'train'.");
            br_train_n(parc == 1 ? 1 : parc-1, parv, parc == 1 ? "" : parv[parc-1]);
        } else if (!strcmp(fun, "enroll")) {
            check(parc >= 1, "Insufficient parameter count for 'enroll'.");
            if (parc == 1) br_enroll(parv[0]);
            else             br_enroll_n(parc-1, parv, parv[parc-1]);
        } else if (!strcmp(fun, "compare")) {
            check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'compare'.");
            br_compare(parv[0], parv[1], parc == 3 ? parv[2] : "");
        } else if (!strcmp(fun, "eval")) {
            check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'eval'.");
            br_eval(parv[0], parv[1], parc == 3 ? parv[2] : "");
        } else if (!strcmp(fun, "plot")) {
            check(parc >= 2, "Incorrect parameter count for 'plot'.");
            br_plot(parc-1, parv, parv[parc-1], true);
        }

        // Secondary Tasks
          else if (!strcmp(fun, "fuse")) {
            check(parc >= 5, "Insufficient parameter count for 'fuse'.");
            br_fuse(parc-4, parv, parv[parc-4], parv[parc-3], parv[parc-2], parv[parc-1]);
        } else if (!strcmp(fun, "cluster")) {
            check(parc >= 3, "Insufficient parameter count for 'cluster'.");
            br_cluster(parc-2, parv, atof(parv[parc-2]), parv[parc-1]);
        } else if (!strcmp(fun, "makeMask")) {
            check(parc == 3, "Incorrect parameter count for 'makeMask'.");
            br_make_mask(parv[0], parv[1], parv[2]);
        } else if (!strcmp(fun, "combineMasks")) {
            check(parc >= 4, "Insufficient parameter count for 'combineMasks'.");
            br_combine_masks(parc-2, parv, parv[parc-2], parv[parc-1]);
        } else if (!strcmp(fun, "convert")) {
            check(parc == 2, "Incorrect parameter count for 'convert'.");
            br_convert(parv[0], parv[1]);
        } else if (!strcmp(fun, "reformat")) {
            check(parc == 4, "Incorrect parameter count for 'reformat'.");
            br_reformat(parv[0], parv[1], parv[2], parv[3]);
        } else if (!strcmp(fun, "evalClassification")) {
            check(parc == 2, "Incorrect parameter count for 'evalClassification'.");
            br_eval_classification(parv[0], parv[1]);
        } else if (!strcmp(fun, "evalRegression")) {
            check(parc == 2, "Incorrect parameter count for 'evalRegression'.");
            br_eval_regression(parv[0], parv[1]);
        } else if (!strcmp(fun, "evalClusters")) {
            check(parc == 2, "Incorrect parameter count for 'evalClusters'.");
            br_eval_clustering(parv[0], parv[1]);
        } else if (!strcmp(fun, "confusion")) {
            check(parc == 2, "Incorrect parameter count for 'confusion'.");
            int true_positives, false_positives, true_negatives, false_negatives;
            br_confusion(parv[0], atof(parv[1]),
                         &true_positives, &false_positives, &true_negatives, &false_negatives);
            printf("True Positives = %d\nFalse Positives = %d\nTrue Negatives = %d\nFalseNegatives = %d\n",
                   true_positives, false_positives, true_negatives, false_negatives);
        } else if (!strcmp(fun, "plotMetadata")) {
            check(parc >= 2, "Incorrect parameter count for 'plotMetadata'.");
            br_plot_metadata(parc-1, parv, parv[parc-1], true);
        }

        // Miscellaneous
          else if (!strcmp(fun, "help")) {
            check(parc == 0, "No parameters expected for 'help'.");
            help();
        } else if (!strcmp(fun, "objects")) {
            check(parc <= 2, "Incorrect parameter count for 'objects'.");
            printf("%s\n", br_objects(parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*"));
        } else if (!strcmp(fun, "about")) {
            check(parc == 0, "No parameters expected for 'about'.");
            printf("%s\n", br_about());
        } else if (!strcmp(fun, "version")) {
            check(parc == 0, "No parameters expected for 'version'.");
            printf("%s\n", br_version());
        } else if (!strcmp(fun, "shell")) {
            check(parc == 0, "No parameters expected for 'shell'.");
            shell = true;
        } else if (!strcmp(fun, "exit")) {
            check(parc == 0, "No parameters expected for 'exit'.");
            shell = false;
        } else if (!strcmp(fun, "br")) {
            printf("That's me!\n");
        } else if (parc <= 1) {
            br_set_property(fun, parc >=1 ? parv[0] : "");
        } else {
            printf("Unrecognized function '%s'\n", fun);
        }
    }

    br_finalize();
    return 0;
}