Example: vision_stereo_rectify
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/config/CConfigFile.h> #include <mrpt/gui/CDisplayWindow3D.h> #include <mrpt/hwdrivers/CCameraSensor.h> #include <mrpt/opengl/Scene.h> #include <mrpt/system/CTimeLogger.h> #include <mrpt/system/filesystem.h> // for ASSERT_FILE_EXISTS_ #include <mrpt/vision/CStereoRectifyMap.h> #include <chrono> #include <iostream> #include <thread> using namespace mrpt; using namespace mrpt::opengl; using namespace mrpt::gui; using namespace mrpt::vision; using namespace mrpt::system; using namespace mrpt::img; using namespace mrpt::obs; using namespace mrpt::system; using namespace mrpt::config; using namespace mrpt::img; using namespace std; // ------------------------------------------------------ // TestStereoRectify // ------------------------------------------------------ void TestStereoRectify(int argc, char** argv) { CTimeLogger timlog; mrpt::vision::CStereoRectifyMap rectifyMap; // Parse optional arguments: if (argc != 1 && argc != 2) { cout << "Usage:\n" << argv[0] << " ==> Run with default camera parameters (from rawlog file)\n" << argv[0] << "[params.cfg] ==> Load stereo camera parameters from cfg file\n"; } if (argc == 2) { const string sCfgFile = argv[1]; ASSERT_FILE_EXISTS_(sCfgFile); // Load params from file: mrpt::img::TStereoCamera params; params.loadFromConfigFile( "CAMERA_PARAMS", mrpt::config::CConfigFile(sCfgFile)); // Prepare rectify map: timlog.enter("rectifyMap.setFromCamParams"); rectifyMap.setFromCamParams(params); timlog.leave("rectifyMap.setFromCamParams"); } // Show to the user a list of possible camera drivers and creates and open // the selected camera. cout << "Please, select the input stereo camera or rawlog file (with " "stereo images)...\n"; mrpt::hwdrivers::CCameraSensor::Ptr cam = mrpt::hwdrivers::prepareVideoSourceFromUserSelection(); if (!cam) return; cout << "Video stream open OK\n"; // Create 3D window: CDisplayWindow3D win("Demo of stereo rectification", 1280, 600); // Create 2 viewports, one for each image: std::vector<Viewport::Ptr> gl_views(2); { Scene::Ptr& theScene = win.get3DSceneAndLock(); gl_views[0] = theScene->getViewport("main"); ASSERT_(gl_views[0]); gl_views[1] = theScene->createViewport("right_image"); // Assign sizes: gl_views[0]->setViewportPosition(0, 0, .5, 1.); gl_views[1]->setViewportPosition(.5, 0, .5, 1.); // IMPORTANT!!! IF NOT UNLOCKED, THE WINDOW WILL NOT BE UPDATED! win.unlockAccess3DScene(); } win.setPos(10, 10); // win.addTextMessage(... bool enable_rectify = true; bool enable_draw_epipolar_lines = true; CImage img_left_rectified, img_right_rectified; // Declared here to serve as a memory buffer // (avoid deallocating/allocating) cout << "Close the window to end.\n"; while (win.isOpen()) { win.addTextMessage(5, 5, format("%.02fFPS", win.getRenderingFPS()), 0); win.addTextMessage( 5, 25, format( "'r': Switch rectify (Now is: %s) | '+'/'-': Modify " "alpha (Now is: %.02f)", enable_rectify ? "ON" : "OFF", rectifyMap.getAlpha()), 10); win.addTextMessage( 5, 50, format( "'s': Switch resize output to 320x240 (Now is: %s) | 'c': " "Switch no-disparity (Now is: %s) | 'e': Switch epipolar lines", rectifyMap.isEnabledResizeOutput() ? "ON" : "OFF", rectifyMap.isEnabledBothCentersCoincide() ? "ON" : "OFF"), 11); std::this_thread::sleep_for(1ms); // Grab new video frame: CObservation::Ptr obs = cam->getNextFrame(); if (obs) { if (IS_CLASS(*obs, CObservationStereoImages)) { // Get the observation object: CObservationStereoImages::Ptr o = std::dynamic_pointer_cast<CObservationStereoImages>(obs); // If the rectification maps are still not ready, prepare them // now: if (!rectifyMap.isSet()) { timlog.enter("rectifyMap.setFromCamParams"); rectifyMap.setFromCamParams(*o); timlog.leave("rectifyMap.setFromCamParams"); /*mrpt::img::TStereoCamera params; o->getStereoCameraParams(params); cout << params.dumpAsText() << endl;*/ } win.get3DSceneAndLock(); if (enable_rectify) { // Rectify: timlog.enter("rectifyMap.rectify()"); rectifyMap.rectify( o->imageLeft, o->imageRight, img_left_rectified, img_right_rectified); timlog.leave("rectifyMap.rectify()"); } else { // Don't rectify: img_left_rectified = o->imageLeft; img_right_rectified = o->imageRight; } // Draw lines: if (enable_draw_epipolar_lines) { const unsigned int LINES_SEP = 40; const unsigned int w = img_left_rectified.getWidth(); const unsigned int h = img_left_rectified.getHeight(); for (unsigned int y = 0; y < h; y += LINES_SEP) { img_left_rectified.line( 0, y, w - 1, y, mrpt::img::TColor::red(), 2); img_right_rectified.line( 0, y, w - 1, y, mrpt::img::TColor::red(), 2); } } gl_views[0]->setImageView(img_left_rectified); gl_views[1]->setImageView(img_right_rectified); win.addTextMessage( 150, 5, mrpt::system::timeToString(o->timestamp), 2); win.unlockAccess3DScene(); win.repaint(); } if (win.keyHit()) { mrptKeyModifier kmods; int key = win.getPushedKey(&kmods); if (key == MRPTK_ESCAPE) break; if (key == 'r' || key == 'R') enable_rectify = !enable_rectify; if (key == 'e' || key == 'E') enable_draw_epipolar_lines = !enable_draw_epipolar_lines; if (key == '+' || key == '-') { double alpha = rectifyMap.getAlpha() + (key == '-' ? -0.1 : 0.1); alpha = std::min(1., std::max(0., alpha)); rectifyMap.setAlpha(alpha); } if (key == 's' || key == 'S') { rectifyMap.enableResizeOutput( !rectifyMap.isEnabledResizeOutput(), 320, 240); } if (key == 'c' || key == 'C') { rectifyMap.enableBothCentersCoincide( !rectifyMap.isEnabledBothCentersCoincide()); } } } } } // ------------------------------------------------------ // MAIN // ------------------------------------------------------ int main(int argc, char** argv) { try { TestStereoRectify(argc, argv); return 0; } catch (const std::exception& e) { std::cerr << "MRPT error: " << mrpt::exception_to_str(e) << std::endl; return -1; } }