Example: vision_stereo_calib_example

C++ example source code:

/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2024, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */

#include <mrpt/gui/CDisplayWindow3D.h>
#include <mrpt/system/CTimeLogger.h>
#include <mrpt/system/filesystem.h>  // for ASSERT_FILE_EXISTS_
#include <mrpt/vision/chessboard_stereo_camera_calib.h>

#include <iostream>

using namespace mrpt;
using namespace mrpt::gui;
using namespace mrpt::vision;
using namespace mrpt::opengl;
using namespace mrpt::system;
using namespace mrpt::vision;
using namespace std;

// ------------------------------------------------------
//              TestStereoCalibrate
// ------------------------------------------------------
int TestStereoCalibrate(int argc, char** argv)
{
    CTimeLogger timlog;

    // Parse optional arguments:
    if (argc == 1 || ((argc - 1) & 1) != 0)
    {
        cout << "Usage:\n"
             << argv[0] << "left_image1 right_image1 [L2 R2] [L3 R3] [...]\n";
        return -1;
    }

    // The stereo calibration structures:
    TCalibrationStereoImageList calib_imgs;
    TStereoCalibResults calib_result;
    TStereoCalibParams calib_params;

    // ============ Set parameters ============
    calib_params.check_size_x = 7;
    calib_params.check_size_y = 9;
    calib_params.check_squares_length_X_meters = 22.83e-3;
    calib_params.check_squares_length_Y_meters = 24.31e-3;
    // calib_params.maxIters = 300;
    // calib_params.verbose = true;
    calib_params.optimize_k1 = true;
    calib_params.optimize_k2 = true;

    // Load images:
    const size_t nPairs = (argc >> 1);
    for (size_t i = 0; i < nPairs; i++)
    {
        const string sImgL = argv[1 + 2 * i + 0];
        const string sImgR = argv[1 + 2 * i + 1];
        ASSERT_FILE_EXISTS_(sImgL);
        ASSERT_FILE_EXISTS_(sImgR);

        calib_imgs.resize(calib_imgs.size() + 1);
        TImageStereoCalibData& stereo_dat = *calib_imgs.rbegin();

#if 1
        // Load all images in memory:
        if (!stereo_dat.left.img_original.loadFromFile(sImgL))
            THROW_EXCEPTION_FMT("Error loading: %s", sImgL.c_str());
        if (!stereo_dat.right.img_original.loadFromFile(sImgR))
            THROW_EXCEPTION_FMT("Error loading: %s", sImgR.c_str());
#else
        // Don't load images in memory until really needed.
        stereo_dat.left.img_original.setExternalStorage(sImgL);
        stereo_dat.right.img_original.setExternalStorage(sImgR);
#endif
    }

    // Run calibration:
    bool res = mrpt::vision::checkerBoardStereoCalibration(
        calib_imgs, calib_params, calib_result);

    if (!res)
    {
        std::cout << "Calibration returned an error status.\n";
        return -1;
    }
    else
    {
        // Calibration was OK:

        // Show detected corners:
        if (true)
        {
            mrpt::gui::CDisplayWindow3D win("Calibration results", 1000, 480);

            mrpt::opengl::Viewport::Ptr view1, view2;
            {
                mrpt::opengl::Scene::Ptr& scene = win.get3DSceneAndLock();
                view1 = scene->getViewport("main");
                view2 = scene->createViewport("right");

                // Split viewing area into two halves:
                view1->setViewportPosition(0, 0, 0.5, 1.0);
                view2->setViewportPosition(0.5, 0, 0.5, 1.0);

                win.unlockAccess3DScene();
            }

            for (size_t i = 0; i < nPairs; i++)
            {
                win.get3DSceneAndLock();

                view1->setImageView(
                    calib_imgs[i].left.img_rectified);  // img_checkboard );
                view2->setImageView(
                    calib_imgs[i].right.img_rectified);  // img_checkboard );

                win.setWindowTitle(mrpt::format(
                    "Detected corners: %u / %u",
                    static_cast<unsigned int>(i + 1),
                    static_cast<unsigned int>(nPairs)));

                win.unlockAccess3DScene();
                win.repaint();

                win.waitForKey();
            }
        }  // end show detected corners

        return 0;
    }
}

// ------------------------------------------------------
//                      MAIN
// ------------------------------------------------------
int main(int argc, char** argv)
{
    try
    {
        return TestStereoCalibrate(argc, argv);
    }
    catch (const std::exception& e)
    {
        std::cerr << "MRPT error: " << mrpt::exception_to_str(e) << std::endl;
        return -1;
    }
}