Tutorial

The code shown below lies in source files in `this https://github.com/abhishekbajpayee/openfv-samples`_ repository. In addition, all data used in these tutorials can be found in `this https://github.com/abhishekbajpayee/openfv-sample-data`_ repository.

Calibration Tutorial

This tutorial details a sample that utilizes the multiCamCalibration class to calibrate a set of cameras. The source code discussed in this tutorial is in the calibrate.cpp file in the samples folder in the openfv root.

Firstly, we include the std_include.h file. This include all the requires standard libraries that openfv depends on. Generally, this will be the first line in any code that uses openfv. As an alternative, once can also individually include the libraries included by this file.

#include "std_include.h"

We then proceed to include the required openfv headers for this sample.

#include "calibration.h"
#include "tools.h"

Here, we include the calibration.h and tools.h files. The tools.h header defines the init_logging function that we later call inside our main function. We then proceed to define the use of the cv and std namespaces. Alternatively, one can call the respective functions using cv:: and std:: and so on.

using namespace cv;
using namespace std;

Since we already have the gflags library installed, we will utilize the functionality it provides to make life easy for ourselves and define some command line flags that we can pass to our final executable to modify code behavior.

// Defining command line flags to use
DEFINE_string(path, "../temp/", "Calibration path");
DEFINE_int32(hgrid, 5, "Horizontal grid size");
DEFINE_int32(vgrid, 5, "Horizontal grid size");
DEFINE_double(gridsize, 5, "Physical grid size");
DEFINE_bool(ref, false, "Refractive flag");
DEFINE_bool(mtiff, false, "Multipage tiff flag");
DEFINE_int32(skip, 1, "Frames to skip");
DEFINE_bool(show_corners, false, "Show detected corners");

Explain flags here?

We then define a main function and the first things we do inside this function are - parse the command line flags and initialize logging via the glog library. All openfv code generates logs and redirects output via the glog library. As a result, it is recommended that this must be called prior to utilizing any openfv code.

int main(int argc, char** argv) {

    // Parsing flags
    google::ParseCommandLineFlags(&argc, &argv, true);
    init_logging(argc, argv);

}

We then add a few more lines of code to our main function. We call the multiCamCalibration constructor using the data that will be passed to the code through the command line flags defined earlier and then run the calibration process. The fourth argument to the constructor being 1 indicates that the easy or dummy mode will be used.

// Uses dummy mode
multiCamCalibration calibration(FLAGS_path, Size(FLAGS_hgrid, FLAGS_vgrid), FLAGS_gridsize, FLAGS_ref, 1, FLAGS_mtiff, FLAGS_skip, FLAGS_show_corners);
calibration.run();

We then the last few lines to our main function to show some output once the code finishes running.

LOG(INFO)<<"Done!";

return 1;

The final function that we end up with looks like:

int main(int argc, char** argv) {

    // Parsing flags
    google::ParseCommandLineFlags(&argc, &argv, true);
    init_logging(argc, argv);

    // Uses dummy mode
    multiCamCalibration calibration(FLAGS_path, Size(FLAGS_hgrid, FLAGS_vgrid), FLAGS_ref, 1, FLAGS_mtiff, FLAGS_skip, FLAGS_show_corners);
    calibration.run();

    LOG(INFO)<<"DONE!";

    return 1;

}

In order to build this executable, you can navigate to the samples directory in the openfv root and execute the following lines at the terminal.

$ mkdir bin
$ cd bin
$ cmake ..
$ make calibrate

You might have to specify certain include and library directories when building the makefile using cmake as:

$ cmake -D CUDA_INC_DIR /path/to/cuda -D [other paths] ...

The paths that might need to be specified are:

  • CUDA_INC_DIR: Path to CUDA include directory (default /usr/local/cuda/include)
  • PYTHON_INC_DIR: Path to the Python include directory (default /usr/include/python2.7)
  • PYTHON_LIBS: Path to Python library (default /usr/lib/libpython2.7.so)
  • EIGEN_INC_DIR: Path to Eigen include directory (default /usr/include/eigen3)
  • OFV_INC_DIR: Path to OpenFV include directory (example openfv/include)
  • OFV_LIB_DIR: Path to OpenFV libraries (example openfv/bin/lib)

You can now run the calibration code by executing:

$ ./calibrate --path /path/to/openfv-sample-data/pinhole_calibration_data/ --hgrid 6 --vgrid 5

The default values for the rest of the command line flags will be used since the dataset in pinhole_calibration_data is not refractive, has physical grid size of 5 mm and contains data in jpg files. The code will ask you to enter the center camera number and the image number to use in order to define the origin. If everything goes as anticipated, this should calibrate well and write the results to an output file. The final reprojection error should ideally be of the order of 1 or less (the lesser the better).

Refocusing Tutorial

This tutorial details a sample that utilizes saRefocus to refocus images from a camera array. The source code discussed in this tutorial is in the refocus.cpp file in the samples folder in the openfv root.

We first include openfv.h which includes all headers required for an openfv project.

#include "openfv.h"

We then define the use of the cv and std namespaces.

using namespace cv;
using namespace std;

Define command line variables .

DEFINE_bool(live, false, "live refocusing");
DEFINE_bool(fhelp, false, "show config file options");

DEFINE_bool(dump_stack, false, "dump stack");
DEFINE_string(save_path, "", "stack save path");
DEFINE_string(config_file, "", "config file path");
DEFINE_double(zmin, -10, "zmin");
DEFINE_double(zmax, 10, "zmax");
DEFINE_double(dz, 0.1, "dz");
DEFINE_double(thresh, 0, "thresholding level");

We define our main function, parse command line flags and initialize glog logging.

int main(int argc, char** argv) {

    google::ParseCommandLineFlags(&argc, &argv, true);
    google::InitGoogleLogging(argv[0]);
    FLAGS_logtostderr=1;

}

Next, we define a refocus_settings variable to store the settings from our refocus config file, and call the saRefocus constructor.

refocus_settings settings;
parse_refocus_settings(FLAGS_config_file, settings, FLAGS_fhelp);
saRefocus refocus(settings);

We then check if the user specified for this to be a live-refocusing session, and if so whether or not a GPU is to be used in computation.

if (FLAGS_live) {
    if (settings.use_gpu) {
        refocus.GPUliveView();
    } else {
        refocus.CPUliveView();
    }
}

Lastly, if the user has specified to dump_stack, and if so we initializeGPU and dump the stack in accordance with the defined command line variables.

 if (FLAGS_dump_stack) {
    refocus.initializeGPU();
    refocus.dump_stack(FLAGS_save_path, FLAGS_zmin, FLAGS_zmax, FLAGS_dz, FLAGS_thresh, "tif");
}

Our final main function:

int main(int argc, char** argv) {

    google::ParseCommandLineFlags(&argc, &argv, true);
    google::InitGoogleLogging(argv[0]);
    FLAGS_logtostderr=1;

    refocus_settings settings;
    parse_refocus_settings(FLAGS_config_file, settings, FLAGS_fhelp);
    saRefocus refocus(settings);

    if (FLAGS_live) {
        if (settings.use_gpu) {
            refocus.GPUliveView();
        } else {
            refocus.CPUliveView();
        }
    }

    if (FLAGS_dump_stack) {
        refocus.initializeGPU();
        refocus.dump_stack(FLAGS_save_path, FLAGS_zmin, FLAGS_zmax, FLAGS_dz, FLAGS_thresh, "tif");
    }

    return 1;

}

Once we compile and build this source file, we can use it as:

$ ./refocus --config_file <path to config file>

Here is a sample image of a refocused image:

_images/refocusingScreenShot.png

Running refocus sample live on sample_config.cfg