LensCalibration.hpp
00001 //
00002 // Distortion correction for SAL3D.
00003 // Copyright 2010 AQSENSE, S.L.
00004 //
00005 #if !defined (AQSENSE_SAL3DPP_LENS_DISTORTION_HPP)
00006 #define AQSENSE_SAL3DPP_LENS_DISTORTION_HPP
00007 
00008 #if defined (_MSC_VER) && (_MSC_VER >= 1020)
00009 #pragma once
00010 #endif
00011 
00012 #include <sal3d/lensdistortion.h>
00013 #include <sal3d/lenscalib.h>
00014 #include <sal3dpp/RangeMap.hpp>
00015 #include <sal3dpp/Common.hpp>
00016 #include <vector>
00017 #include <algorithm>
00018 
00019 namespace sal3d
00020 {
00047     namespace LensDistortion
00048     {
00080         inline Model
00081         calibrateTsai(const std::vector<sal3d::Frame> &frames,
00082                 int patternRows, int patternCols,
00083                 int &nvalid, std::vector<Point2D> &points)
00084         {
00085             std::vector<sal3d_frame> c_frames;
00086             std::vector<sal3d_point2d> c_points2d;
00087 
00088             for(unsigned int i=0; i < frames.size(); ++i)
00089                 c_frames.push_back(frames[i].c_frame());
00090 
00091             c_points2d.resize (patternRows * patternCols);
00092 
00093             sal3d_lens_distortion c_model;
00094             Error e;
00095             sal3d_lens_distortion_calibrate_tsai(&c_frames[0],
00096                     c_frames.size(), patternRows,
00097                     patternCols, &nvalid, &c_model, &c_points2d[0],
00098                     &e.e);
00099             if (e.e.value < 0)
00100                 throw e;
00101 
00102             points.resize(c_points2d.size());
00103             for(unsigned int i=0; i < points.size(); ++i)
00104                 points[i] = Point2D(c_points2d[i]);
00105 
00106             return Model(c_model);
00107         }
00108 
00134         inline Model
00135         calibrateTsai(const std::vector<sal3d::Frame> &frames,
00136                 int patternRows, int patternCols)
00137         {
00138             int nvalid = 0;
00139             std::vector<Point2D> points (patternRows *
00140                     patternCols);
00141 
00142             return calibrateTsai (frames, patternRows,
00143                     patternCols, nvalid, points);
00144         }
00145 
00171         inline Model
00172         calibrateTsai(const sal3d::Frame &frame, int patternRows,
00173                 int patternCols)
00174         {
00175             std::vector<sal3d::Frame> frames;
00176             frames.push_back (frame);
00177 
00178             return calibrateTsai (frames, patternRows,
00179                     patternCols);
00180         }
00181 
00214         inline Model
00215         calibrateDotsTsai(const std::vector<sal3d::Frame> &frames,
00216                 int &patternRows, int &patternCols,
00217                 int &nvalid, std::vector<Point2D> &points)
00218         {
00219             std::vector<sal3d_frame> c_frames;
00220             std::vector<sal3d_point2d> c_points2d(1);
00221 
00222             for(unsigned int i=0; i < frames.size(); ++i)
00223                 c_frames.push_back(frames[i].c_frame());
00224 
00225             sal3d_lens_distortion c_model;
00226             Error e;
00227             sal3d_lens_distortion_calibrate_dots_tsai(&c_frames[0],
00228                     c_frames.size(), &patternRows,
00229                     &patternCols, &nvalid, &c_model, &c_points2d[0],
00230                     &e.e);
00231             if (e.e.value < 0)
00232                 throw e;
00233 
00234             /* Second time calibration, just to get all points found */
00235             const int nmax = patternRows * patternCols;
00236             c_points2d.resize(nmax);
00237             sal3d_lens_distortion_calibrate_dots_tsai(&c_frames[0],
00238                     c_frames.size(), &patternRows,
00239                     &patternCols, &nvalid, &c_model, &c_points2d[0],
00240                     &e.e);
00241             if (e.e.value < 0)
00242                 throw e;
00243 
00244             points.resize(nmax);
00245             for(int i=0; i < nmax; ++i)
00246                 points[i] = Point2D(c_points2d[i]);
00247 
00248             return Model(c_model);
00249         }
00250 
00270         inline Model
00271         calibrateDotsTsai(const std::vector<sal3d::Frame> &frames)
00272         {
00273             int nvalid = 0;
00274             int patternRows = 0;
00275             int patternCols = 0;
00276             std::vector<Point2D> points;
00277 
00278             return calibrateDotsTsai (frames, patternRows,
00279                     patternCols, nvalid, points);
00280         }
00281 
00301         inline Model
00302         calibrateDotsTsai(const sal3d::Frame &frame)
00303         {
00304             std::vector<sal3d::Frame> frames;
00305             frames.push_back (frame);
00306 
00307             return calibrateDotsTsai (frames);
00308         }
00309 
00329         inline Model
00330         calibrateDotsCubic(const sal3d::Frame &frame)
00331         {
00332             sal3d_lens_distortion c_model;
00333             Error e;
00334             sal3d_lens_distortion_calibrate_dots_cubic(
00335                     frame.c_frame(), &c_model, 0, 0, 0, &e.e);
00336             if (e.e.value < 0)
00337                 throw e;
00338 
00339             return Model(c_model);
00340         }
00341 
00342 
00367         inline Model
00368         calibrateDotsCubic(const sal3d::Frame &frame,
00369                 int &patternRows, int &patternCols,
00370                 std::vector<Point2D> &points)
00371         {
00372             /* We allocate as forecasted by the user calling */
00373             int nmax = patternRows * patternCols;
00374             std::vector<sal3d_point2d> c_points2d(nmax);
00375 
00376             sal3d_lens_distortion c_model;
00377             Error e;
00378             sal3d_lens_distortion_calibrate_dots_cubic(
00379                     frame.c_frame(),
00380                     &c_model, &patternRows, &patternCols, &c_points2d[0],
00381                     &e.e);
00382             if (e.e.value < 0)
00383                 throw e;
00384 
00385             /* Second time calibration, just to get all points found */
00386             nmax = patternRows * patternCols;
00387             c_points2d.resize(nmax);
00388             sal3d_lens_distortion_calibrate_dots_cubic(
00389                     frame.c_frame(), 
00390                     &c_model, &patternRows, &patternCols, &c_points2d[0],
00391                     &e.e);
00392             if (e.e.value < 0)
00393                 throw e;
00394 
00395             points.resize(nmax);
00396             for(int i=0; i < nmax; ++i)
00397                 points[i] = Point2D(c_points2d[i]);
00398 
00399             return Model(c_model);
00400         }
00401 
00428         inline Model
00429         calibrateCubic(const sal3d::Frame &frame,
00430                 int patternRows, int patternCols,
00431                 std::vector<Point2D> &points)
00432         {
00433             /* We allocate as forecasted by the user calling */
00434             int nmax = patternRows * patternCols;
00435             std::vector<sal3d_point2d> c_points2d(nmax);
00436 
00437             sal3d_lens_distortion c_model;
00438 
00439             Error e;
00440             sal3d_lens_distortion_calibrate_cubic(
00441                     frame.c_frame(), patternRows, patternCols, &c_model,
00442                     &c_points2d[0], &e.e);
00443             if (e.e.value < 0)
00444                 throw e;
00445 
00446             /* If the user forecasted more than needed, return the points as
00447              * found. If the user forecasted less, return as much as the
00448              * forecast then, but with a vector size of the new rows*cols,
00449              * so he can traverse them. */
00450             nmax = std::min(nmax, patternRows * patternCols);
00451             points.resize(nmax);
00452             for(int i=0; i < nmax; ++i)
00453                 points[i] = Point2D(c_points2d[i]);
00454 
00455             return Model(c_model);
00456         }
00457 
00458     }
00459 }
00460 
00461 #endif //AQSENSE_SAL3DPP_LENS_DISTORTION_HPP