diff --git a/apps/createsamples/CMakeLists.txt b/apps/createsamples/CMakeLists.txt index 7fb2b679c2..108119908a 100644 --- a/apps/createsamples/CMakeLists.txt +++ b/apps/createsamples/CMakeLists.txt @@ -1,4 +1,4 @@ file(GLOB SRCS *.cpp) ocv_add_application(opencv_createsamples - MODULES opencv_core opencv_imgproc opencv_objdetect opencv_imgcodecs opencv_highgui opencv_calib3d opencv_features2d opencv_videoio + MODULES opencv_core opencv_imgproc opencv_objdetect opencv_imgcodecs opencv_highgui opencv_3d opencv_features2d opencv_videoio SRCS ${SRCS}) diff --git a/apps/createsamples/utility.cpp b/apps/createsamples/utility.cpp index 5176f14836..63862b53c7 100644 --- a/apps/createsamples/utility.cpp +++ b/apps/createsamples/utility.cpp @@ -52,7 +52,7 @@ #include "opencv2/imgcodecs.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" #if defined __GNUC__ && __GNUC__ >= 8 #pragma GCC diagnostic ignored "-Wclass-memaccess" diff --git a/apps/interactive-calibration/CMakeLists.txt b/apps/interactive-calibration/CMakeLists.txt index dacbb13c79..85d121a20b 100644 --- a/apps/interactive-calibration/CMakeLists.txt +++ b/apps/interactive-calibration/CMakeLists.txt @@ -1,4 +1,4 @@ -set(DEPS opencv_core opencv_imgproc opencv_features2d opencv_highgui opencv_calib3d opencv_videoio) +set(DEPS opencv_core opencv_imgproc opencv_features2d opencv_highgui opencv_3d opencv_calib opencv_videoio) if(${BUILD_opencv_aruco}) list(APPEND DEPS opencv_aruco) endif() diff --git a/apps/interactive-calibration/calibController.cpp b/apps/interactive-calibration/calibController.cpp index efe937bfd9..ba6c9f320b 100644 --- a/apps/interactive-calibration/calibController.cpp +++ b/apps/interactive-calibration/calibController.cpp @@ -8,9 +8,12 @@ #include #include -#include +#include +#include #include +using namespace cv; + double calib::calibController::estimateCoverageQuality() { int gridSize = 10; diff --git a/apps/interactive-calibration/frameProcessor.cpp b/apps/interactive-calibration/frameProcessor.cpp index 90904a42cd..e62d4320df 100644 --- a/apps/interactive-calibration/frameProcessor.cpp +++ b/apps/interactive-calibration/frameProcessor.cpp @@ -5,7 +5,8 @@ #include "frameProcessor.hpp" #include "rotationConverters.hpp" -#include +#include +#include #include #include diff --git a/apps/interactive-calibration/frameProcessor.hpp b/apps/interactive-calibration/frameProcessor.hpp index 6fd788dc7f..fe6cacdec5 100644 --- a/apps/interactive-calibration/frameProcessor.hpp +++ b/apps/interactive-calibration/frameProcessor.hpp @@ -6,7 +6,7 @@ #define FRAME_PROCESSOR_HPP #include -#include +#include #ifdef HAVE_OPENCV_ARUCO #include #endif diff --git a/apps/interactive-calibration/main.cpp b/apps/interactive-calibration/main.cpp index 6468c88ce7..78a356ab23 100644 --- a/apps/interactive-calibration/main.cpp +++ b/apps/interactive-calibration/main.cpp @@ -3,7 +3,8 @@ // of this distribution and at http://opencv.org/license.html. #include -#include +#include +#include #include #include diff --git a/apps/interactive-calibration/rotationConverters.cpp b/apps/interactive-calibration/rotationConverters.cpp index 421d15a924..c9dfdf3989 100644 --- a/apps/interactive-calibration/rotationConverters.cpp +++ b/apps/interactive-calibration/rotationConverters.cpp @@ -6,12 +6,15 @@ #include -#include +#include +#include #include #define CALIB_PI 3.14159265358979323846 #define CALIB_PI_2 1.57079632679489661923 +using namespace cv; + void calib::Euler(const cv::Mat& src, cv::Mat& dst, int argType) { if((src.rows == 3) && (src.cols == 3)) diff --git a/apps/traincascade/CMakeLists.txt b/apps/traincascade/CMakeLists.txt index ef80ce8b2f..ec90ebbff3 100644 --- a/apps/traincascade/CMakeLists.txt +++ b/apps/traincascade/CMakeLists.txt @@ -1,5 +1,5 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS -Woverloaded-virtual -Winconsistent-missing-override -Wsuggest-override) file(GLOB SRCS *.cpp) ocv_add_application(opencv_traincascade - MODULES opencv_core opencv_imgproc opencv_objdetect opencv_imgcodecs opencv_highgui opencv_calib3d opencv_features2d + MODULES opencv_core opencv_imgproc opencv_objdetect opencv_imgcodecs opencv_highgui opencv_3d opencv_features2d SRCS ${SRCS}) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index f48e0b0943..67a65e262f 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -123,9 +123,9 @@ endif() set(STD_OPENCV_LIBS opencv-data) set(STD_OPENCV_DEV libopencv-dev) -foreach(module calib3d core dnn features2d flann gapi highgui +foreach(module 3d calib core dnn features2d flann gapi highgui imgcodecs imgproc ml objdetect - photo stitching ts video videoio) + photo stereo stitching ts video videoio) if(HAVE_opencv_${module}) list(APPEND STD_OPENCV_LIBS "libopencv-${module}4.0") list(APPEND STD_OPENCV_DEV "libopencv-${module}-dev") diff --git a/cmake/cl2cpp.cmake b/cmake/cl2cpp.cmake index a9d1b6789d..192b2bc44f 100644 --- a/cmake/cl2cpp.cmake +++ b/cmake/cl2cpp.cmake @@ -12,7 +12,12 @@ endif() string(REGEX REPLACE "\\.cpp$" ".hpp" OUTPUT_HPP "${OUTPUT}") get_filename_component(OUTPUT_HPP_NAME "${OUTPUT_HPP}" NAME) -set(nested_namespace_start "namespace ${MODULE_NAME}\n{") +if (MODULE_NAME MATCHES "^[0-9].+") + set(MANGLED_MODULE_NAME "_${MODULE_NAME}") +else() + set(MANGLED_MODULE_NAME "${MODULE_NAME}") +endif() +set(nested_namespace_start "namespace ${MANGLED_MODULE_NAME}\n{") set(nested_namespace_end "}") set(STR_CPP "// This file is auto-generated. Do not edit! diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index c19fe967b7..1245bf275a 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -109,7 +109,12 @@ if(DOXYGEN_FOUND) list(APPEND deps ${bib_file}) endif() # Reference entry - set(one_ref "\t- ${m}. @ref ${m}\n") + if("${m}" MATCHES "^[0-9].+") + set(ref_m "_${m} \"${m}\"") + else() + set(ref_m "${m}") + endif() + set(one_ref "\t- ${m}. @ref ${ref_m}\n") list(FIND OPENCV_MODULES_EXTRA ${m} _pos) if(${_pos} EQUAL -1) set(refs_main "${refs_main}${one_ref}") diff --git a/doc/py_tutorials/py_calib3d/py_pose/py_pose.markdown b/doc/py_tutorials/py_calib3d/py_pose/py_pose.markdown index a1a612d6f6..2f032eaa57 100644 --- a/doc/py_tutorials/py_calib3d/py_pose/py_pose.markdown +++ b/doc/py_tutorials/py_calib3d/py_pose/py_pose.markdown @@ -5,7 +5,7 @@ Goal ---- In this section, - - We will learn to exploit calib3d module to create some 3D effects in images. + - We will learn to exploit 3d module to create some 3D effects in images. Basics ------ diff --git a/doc/py_tutorials/py_feature2d/py_table_of_contents_feature2d.markdown b/doc/py_tutorials/py_feature2d/py_table_of_contents_feature2d.markdown index ee6019139c..8e66f308f7 100644 --- a/doc/py_tutorials/py_feature2d/py_table_of_contents_feature2d.markdown +++ b/doc/py_tutorials/py_feature2d/py_table_of_contents_feature2d.markdown @@ -51,4 +51,4 @@ Feature Detection and Description {#tutorial_py_table_of_contents_feature2d} - @subpage tutorial_py_feature_homography - Now we know about feature matching. Let's mix it up with calib3d module to find objects in a complex image. + Now we know about feature matching. Let's mix it up with 3d module to find objects in a complex image. diff --git a/doc/tutorials/calib3d/real_time_pose/real_time_pose.markdown b/doc/tutorials/calib3d/real_time_pose/real_time_pose.markdown index 98a44b232b..9888d29230 100644 --- a/doc/tutorials/calib3d/real_time_pose/real_time_pose.markdown +++ b/doc/tutorials/calib3d/real_time_pose/real_time_pose.markdown @@ -55,7 +55,7 @@ plane: \f[s\ \left [ \begin{matrix} u \\ v \\ 1 \end{matrix} \right ] = \left [ \begin{matrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{matrix} \right ] \left [ \begin{matrix} r_{11} & r_{12} & r_{13} & t_1 \\ r_{21} & r_{22} & r_{23} & t_2 \\ r_{31} & r_{32} & r_{33} & t_3 \end{matrix} \right ] \left [ \begin{matrix} X \\ Y \\ Z\\ 1 \end{matrix} \right ]\f] -The complete documentation of how to manage with this equations is in @ref calib3d . +The complete documentation of how to manage with this equations is in @ref _3d "3d". Source code ----------- diff --git a/doc/tutorials/calib3d/usac.markdown b/doc/tutorials/calib3d/usac.markdown index 27d590be3a..46dba4b79e 100644 --- a/doc/tutorials/calib3d/usac.markdown +++ b/doc/tutorials/calib3d/usac.markdown @@ -10,7 +10,7 @@ title: 'Google Summer of Code: Improvement of Random Sample Consensus in OpenCV' Contribution ============ -The integrated part to OpenCV `calib3d` module is RANSAC-based universal +The integrated part to OpenCV `3d` module is RANSAC-based universal framework USAC (`namespace usac`) written in C++. The framework includes different state-of-the-arts methods for sampling, verification or local optimization. The main advantage of the framework is its independence to diff --git a/doc/tutorials/introduction/config_reference/config_reference.markdown b/doc/tutorials/introduction/config_reference/config_reference.markdown index 3d65710630..1cabf23200 100644 --- a/doc/tutorials/introduction/config_reference/config_reference.markdown +++ b/doc/tutorials/introduction/config_reference/config_reference.markdown @@ -138,7 +138,7 @@ cmake \ Each module is a subdirectory of the `modules` directory. It is possible to disable one module: ```.sh -cmake -DBUILD_opencv_calib3d=OFF ../opencv +cmake -DBUILD_opencv_3d=OFF ../opencv ``` The opposite option is to build only specified modules and all modules they depend on: diff --git a/doc/tutorials/introduction/linux_eclipse/linux_eclipse.markdown b/doc/tutorials/introduction/linux_eclipse/linux_eclipse.markdown index 76f1b2aecf..6416b1806f 100644 --- a/doc/tutorials/introduction/linux_eclipse/linux_eclipse.markdown +++ b/doc/tutorials/introduction/linux_eclipse/linux_eclipse.markdown @@ -112,7 +112,7 @@ Making a project since I plan to use the whole bunch: opencv_core opencv_imgproc opencv_imgcodecs opencv_highgui opencv_ml opencv_videoio opencv_video opencv_features2d - opencv_calib3d opencv_objdetect opencv_flann + opencv_3d opencv_objdetect opencv_flann ![](images/a10.png) diff --git a/include/opencv2/opencv.hpp b/include/opencv2/opencv.hpp index d17b94a4ea..8eb58bac04 100644 --- a/include/opencv2/opencv.hpp +++ b/include/opencv2/opencv.hpp @@ -52,8 +52,11 @@ #include "opencv2/core.hpp" // Then the optional modules are checked -#ifdef HAVE_OPENCV_CALIB3D -#include "opencv2/calib3d.hpp" +#ifdef HAVE_OPENCV_3D +#include "opencv2/3d.hpp" +#endif +#ifdef HAVE_OPENCV_CALIB +#include "opencv2/calib.hpp" #endif #ifdef HAVE_OPENCV_FEATURES2D #include "opencv2/features2d.hpp" @@ -82,6 +85,9 @@ #ifdef HAVE_OPENCV_PHOTO #include "opencv2/photo.hpp" #endif +#ifdef HAVE_OPENCV_STEREO +#include "opencv2/stereo.hpp" +#endif #ifdef HAVE_OPENCV_STITCHING #include "opencv2/stitching.hpp" #endif diff --git a/modules/calib3d/CMakeLists.txt b/modules/3d/CMakeLists.txt similarity index 70% rename from modules/calib3d/CMakeLists.txt rename to modules/3d/CMakeLists.txt index 7b1bace28a..9bed964dd7 100644 --- a/modules/calib3d/CMakeLists.txt +++ b/modules/3d/CMakeLists.txt @@ -3,10 +3,10 @@ set(the_description "Camera Calibration and 3D Reconstruction") ocv_add_dispatched_file(undistort SSE2 AVX2) set(debug_modules "") -if(DEBUG_opencv_calib3d) +if(DEBUG_opencv_3d) list(APPEND debug_modules opencv_highgui) endif() -ocv_define_module(calib3d opencv_imgproc opencv_features2d opencv_flann ${debug_modules} +ocv_define_module(3d opencv_imgproc opencv_features2d opencv_flann ${debug_modules} WRAP java objc python js ) ocv_target_link_libraries(${the_module} ${LAPACK_LIBRARIES}) diff --git a/modules/calib3d/doc/calib3d.bib b/modules/3d/doc/3d.bib similarity index 100% rename from modules/calib3d/doc/calib3d.bib rename to modules/3d/doc/3d.bib diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/3d/include/opencv2/3d.hpp similarity index 53% rename from modules/calib3d/include/opencv2/calib3d.hpp rename to modules/3d/include/opencv2/3d.hpp index 228a4f3f44..7591a354fc 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/3d/include/opencv2/3d.hpp @@ -1,57 +1,17 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html -#ifndef OPENCV_CALIB3D_HPP -#define OPENCV_CALIB3D_HPP +#ifndef OPENCV_3D_HPP +#define OPENCV_3D_HPP #include "opencv2/core.hpp" -#include "opencv2/features2d.hpp" -#include "opencv2/core/affine.hpp" +#include "opencv2/core/types_c.h" /** - @defgroup calib3d Camera Calibration and 3D Reconstruction + @defgroup _3d 3D vision functionality -The functions in this section use a so-called pinhole camera model. The view of a scene +Most of the functions in this section use a so-called pinhole camera model. The view of a scene is obtained by projecting a scene's 3D point \f$P_w\f$ into the image plane using a perspective transformation which forms the corresponding pixel \f$p\f$. Both \f$P_w\f$ and \f$p\f$ are represented in homogeneous coordinates, i.e. as 3D and 2D homogeneous vector respectively. You will @@ -399,45 +359,11 @@ R & t \\ - (Python) A camera calibration sample can be found at opencv_source_code/samples/python/calibrate.py - @{ - @defgroup calib3d_fisheye Fisheye camera model - - Definitions: Let P be a point in 3D of coordinates X in the world reference frame (stored in the - matrix X) The coordinate vector of P in the camera reference frame is: - - \f[Xc = R X + T\f] - - where R is the rotation matrix corresponding to the rotation vector om: R = rodrigues(om); call x, y - and z the 3 coordinates of Xc: - - \f[x = Xc_1 \\ y = Xc_2 \\ z = Xc_3\f] - - The pinhole projection coordinates of P is [a; b] where - - \f[a = x / z \ and \ b = y / z \\ r^2 = a^2 + b^2 \\ \theta = atan(r)\f] - - Fisheye distortion: - - \f[\theta_d = \theta (1 + k_1 \theta^2 + k_2 \theta^4 + k_3 \theta^6 + k_4 \theta^8)\f] - - The distorted point coordinates are [x'; y'] where - - \f[x' = (\theta_d / r) a \\ y' = (\theta_d / r) b \f] - - Finally, conversion into pixel coordinates: The final pixel coordinates vector [u; v] where: - - \f[u = f_x (x' + \alpha y') + c_x \\ - v = f_y y' + c_y\f] - - @defgroup calib3d_c C API - - @} */ -namespace cv -{ +namespace cv { -//! @addtogroup calib3d +//! @addtogroup _3d //! @{ //! type of the robust estimation algorithm @@ -477,49 +403,6 @@ enum SolvePnPMethod { #endif }; -enum { CALIB_CB_ADAPTIVE_THRESH = 1, - CALIB_CB_NORMALIZE_IMAGE = 2, - CALIB_CB_FILTER_QUADS = 4, - CALIB_CB_FAST_CHECK = 8, - CALIB_CB_EXHAUSTIVE = 16, - CALIB_CB_ACCURACY = 32, - CALIB_CB_LARGER = 64, - CALIB_CB_MARKER = 128 - }; - -enum { CALIB_CB_SYMMETRIC_GRID = 1, - CALIB_CB_ASYMMETRIC_GRID = 2, - CALIB_CB_CLUSTERING = 4 - }; - -enum { CALIB_NINTRINSIC = 18, - CALIB_USE_INTRINSIC_GUESS = 0x00001, - CALIB_FIX_ASPECT_RATIO = 0x00002, - CALIB_FIX_PRINCIPAL_POINT = 0x00004, - CALIB_ZERO_TANGENT_DIST = 0x00008, - CALIB_FIX_FOCAL_LENGTH = 0x00010, - CALIB_FIX_K1 = 0x00020, - CALIB_FIX_K2 = 0x00040, - CALIB_FIX_K3 = 0x00080, - CALIB_FIX_K4 = 0x00800, - CALIB_FIX_K5 = 0x01000, - CALIB_FIX_K6 = 0x02000, - CALIB_RATIONAL_MODEL = 0x04000, - CALIB_THIN_PRISM_MODEL = 0x08000, - CALIB_FIX_S1_S2_S3_S4 = 0x10000, - CALIB_TILTED_MODEL = 0x40000, - CALIB_FIX_TAUX_TAUY = 0x80000, - CALIB_USE_QR = 0x100000, //!< use QR instead of SVD decomposition for solving. Faster but potentially less precise - CALIB_FIX_TANGENT_DIST = 0x200000, - // only for stereo - CALIB_FIX_INTRINSIC = 0x00100, - CALIB_SAME_FOCAL_LENGTH = 0x00200, - // for stereo rectification - CALIB_ZERO_DISPARITY = 0x00400, - CALIB_USE_LU = (1 << 17), //!< use LU instead of SVD decomposition for solving. much faster but potentially less precise - CALIB_USE_EXTRINSIC_GUESS = (1 << 22) //!< for stereoCalibrate - }; - //! the algorithm for finding fundamental matrix enum { FM_7POINT = 1, //!< 7-point algorithm FM_8POINT = 2, //!< 8-point algorithm @@ -527,21 +410,6 @@ enum { FM_7POINT = 1, //!< 7-point algorithm FM_RANSAC = 8 //!< RANSAC algorithm. It needs at least 15 points. 7-point algorithm is used. }; -enum HandEyeCalibrationMethod -{ - CALIB_HAND_EYE_TSAI = 0, //!< A New Technique for Fully Autonomous and Efficient 3D Robotics Hand/Eye Calibration @cite Tsai89 - CALIB_HAND_EYE_PARK = 1, //!< Robot Sensor Calibration: Solving AX = XB on the Euclidean Group @cite Park94 - CALIB_HAND_EYE_HORAUD = 2, //!< Hand-eye Calibration @cite Horaud95 - CALIB_HAND_EYE_ANDREFF = 3, //!< On-line Hand-Eye Calibration @cite Andreff99 - CALIB_HAND_EYE_DANIILIDIS = 4 //!< Hand-Eye Calibration Using Dual Quaternions @cite Daniilidis98 -}; - -enum RobotWorldHandEyeCalibrationMethod -{ - CALIB_ROBOT_WORLD_HAND_EYE_SHAH = 0, //!< Solving the robot-world/hand-eye calibration problem using the kronecker product @cite Shah2013SolvingTR - CALIB_ROBOT_WORLD_HAND_EYE_LI = 1 //!< Simultaneous robot-world and hand-eye calibration using dual-quaternions and kronecker product @cite Li2010SimultaneousRA -}; - enum SamplingMethod { SAMPLING_UNIFORM, SAMPLING_PROGRESSIVE_NAPSAC, SAMPLING_NAPSAC, SAMPLING_PROSAC }; enum LocalOptimMethod {LOCAL_OPTIM_NULL, LOCAL_OPTIM_INNER_LO, LOCAL_OPTIM_INNER_AND_ITER_LO, @@ -593,8 +461,6 @@ can be found in: */ CV_EXPORTS_W void Rodrigues( InputArray src, OutputArray dst, OutputArray jacobian = noArray() ); - - /** Levenberg-Marquardt solver. Starting with the specified vector of parameters it optimizes the target vector criteria "err" (finds local minima of each target vector component absolute value). @@ -658,8 +524,6 @@ public: static Ptr create(const Ptr& cb, int maxIters, double eps); }; - - /** @example samples/cpp/tutorial_code/features2D/Homography/pose_from_homography.cpp An example program about pose estimation from coplanar points @@ -1050,9 +914,9 @@ a 3D point expressed in the world frame into the camera frame: - If you are using Python: - Numpy array slices won't work as input because solvePnP requires contiguous arrays (enforced by the assertion using cv::Mat::checkVector() around line 55 of - modules/calib3d/src/solvepnp.cpp version 2.4.9) + modules/3d/src/solvepnp.cpp version 2.4.9) - The P3P algorithm requires image points to be in an array of shape (N,1,2) due - to its calling of cv::undistortPoints (around line 75 of modules/calib3d/src/solvepnp.cpp version 2.4.9) + to its calling of cv::undistortPoints (around line 75 of modules/3d/src/solvepnp.cpp version 2.4.9) which requires 2-channel information. - Thus, given some data D = np.array(...) where D.shape = (N,M), in order to use a subset of it as, e.g., imagePoints, one must effectively copy it into a new array: imagePoints = @@ -1078,7 +942,7 @@ a 3D point expressed in the world frame into the camera frame: CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, - bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE ); + bool useExtrinsicGuess = false, int flags = 0 ); /** @brief Finds an object pose from 3D-2D point correspondences using the RANSAC scheme. @@ -1112,7 +976,7 @@ makes the function resistant to outliers. @note - An example of how to use solvePNPRansac for object detection can be found at - opencv_source_code/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/ + opencv_source_code/samples/cpp/tutorial_code/3d/real_time_pose_estimation/ - The default method used to estimate the camera pose for the Minimal Sample Sets step is #SOLVEPNP_EPNP. Exceptions are: - if you choose #SOLVEPNP_P3P or #SOLVEPNP_AP3P, these methods will be used. @@ -1126,8 +990,7 @@ CV_EXPORTS_W bool solvePnPRansac( InputArray objectPoints, InputArray imagePoint OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess = false, int iterationsCount = 100, float reprojectionError = 8.0, double confidence = 0.99, - OutputArray inliers = noArray(), int flags = SOLVEPNP_ITERATIVE ); - + OutputArray inliers = noArray(), int flags = 0 ); /* Finds rotation and translation vector. @@ -1193,7 +1056,8 @@ to a Levenberg-Marquardt iterative minimization @cite Madsen04 @cite Eade13 proc CV_EXPORTS_W void solvePnPRefineLM( InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, InputOutputArray rvec, InputOutputArray tvec, - TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 20, FLT_EPSILON)); + TermCriteria criteria = TermCriteria(TermCriteria::EPS + + TermCriteria::COUNT, 20, FLT_EPSILON)); /** @brief Refine a pose (the translation and the rotation that transform a 3D point expressed in the object coordinate frame to the camera coordinate frame) from a 3D-2D point correspondences and starting from an initial solution. @@ -1222,7 +1086,8 @@ virtual visual servoing (VVS) @cite Chaumette06 @cite Marchand16 scheme. CV_EXPORTS_W void solvePnPRefineVVS( InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, InputOutputArray rvec, InputOutputArray tvec, - TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 20, FLT_EPSILON), + TermCriteria criteria = TermCriteria(TermCriteria::EPS + + TermCriteria::COUNT, 20, FLT_EPSILON), double VVSlambda = 1); /** @brief Finds an object pose from 3D-2D point correspondences. @@ -1391,9 +1256,9 @@ a 3D point expressed in the world frame into the camera frame: - If you are using Python: - Numpy array slices won't work as input because solvePnP requires contiguous arrays (enforced by the assertion using cv::Mat::checkVector() around line 55 of - modules/calib3d/src/solvepnp.cpp version 2.4.9) + modules/3d/src/solvepnp.cpp version 2.4.9) - The P3P algorithm requires image points to be in an array of shape (N,1,2) due - to its calling of cv::undistortPoints (around line 75 of modules/calib3d/src/solvepnp.cpp version 2.4.9) + to its calling of undistortPoints (around line 75 of modules/3d/src/solvepnp.cpp version 2.4.9) which requires 2-channel information. - Thus, given some data D = np.array(...) where D.shape = (N,M), in order to use a subset of it as, e.g., imagePoints, one must effectively copy it into a new array: imagePoints = @@ -1418,195 +1283,11 @@ a 3D point expressed in the world frame into the camera frame: CV_EXPORTS_W int solvePnPGeneric( InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, - bool useExtrinsicGuess = false, SolvePnPMethod flags = SOLVEPNP_ITERATIVE, + bool useExtrinsicGuess = false, + int flags = 0, InputArray rvec = noArray(), InputArray tvec = noArray(), OutputArray reprojectionError = noArray() ); -/** @brief Finds an initial camera intrinsic matrix from 3D-2D point correspondences. - -@param objectPoints Vector of vectors of the calibration pattern points in the calibration pattern -coordinate space. In the old interface all the per-view vectors are concatenated. See -calibrateCamera for details. -@param imagePoints Vector of vectors of the projections of the calibration pattern points. In the -old interface all the per-view vectors are concatenated. -@param imageSize Image size in pixels used to initialize the principal point. -@param aspectRatio If it is zero or negative, both \f$f_x\f$ and \f$f_y\f$ are estimated independently. -Otherwise, \f$f_x = f_y * \texttt{aspectRatio}\f$ . - -The function estimates and returns an initial camera intrinsic matrix for the camera calibration process. -Currently, the function only supports planar calibration patterns, which are patterns where each -object point has z-coordinate =0. - */ -CV_EXPORTS_W Mat initCameraMatrix2D( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints, - Size imageSize, double aspectRatio = 1.0 ); - -/** @brief Finds the positions of internal corners of the chessboard. - -@param image Source chessboard view. It must be an 8-bit grayscale or color image. -@param patternSize Number of inner corners per a chessboard row and column -( patternSize = cv::Size(points_per_row,points_per_colum) = cv::Size(columns,rows) ). -@param corners Output array of detected corners. -@param flags Various operation flags that can be zero or a combination of the following values: -- **CALIB_CB_ADAPTIVE_THRESH** Use adaptive thresholding to convert the image to black -and white, rather than a fixed threshold level (computed from the average image brightness). -- **CALIB_CB_NORMALIZE_IMAGE** Normalize the image gamma with equalizeHist before -applying fixed or adaptive thresholding. -- **CALIB_CB_FILTER_QUADS** Use additional criteria (like contour area, perimeter, -square-like shape) to filter out false quads extracted at the contour retrieval stage. -- **CALIB_CB_FAST_CHECK** Run a fast check on the image that looks for chessboard corners, -and shortcut the call if none is found. This can drastically speed up the call in the -degenerate condition when no chessboard is observed. - -The function attempts to determine whether the input image is a view of the chessboard pattern and -locate the internal chessboard corners. The function returns a non-zero value if all of the corners -are found and they are placed in a certain order (row by row, left to right in every row). -Otherwise, if the function fails to find all the corners or reorder them, it returns 0. For example, -a regular chessboard has 8 x 8 squares and 7 x 7 internal corners, that is, points where the black -squares touch each other. The detected coordinates are approximate, and to determine their positions -more accurately, the function calls cornerSubPix. You also may use the function cornerSubPix with -different parameters if returned coordinates are not accurate enough. - -Sample usage of detecting and drawing chessboard corners: : -@code - Size patternsize(8,6); //interior number of corners - Mat gray = ....; //source image - vector corners; //this will be filled by the detected corners - - //CALIB_CB_FAST_CHECK saves a lot of time on images - //that do not contain any chessboard corners - bool patternfound = findChessboardCorners(gray, patternsize, corners, - CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE - + CALIB_CB_FAST_CHECK); - - if(patternfound) - cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1), - TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1)); - - drawChessboardCorners(img, patternsize, Mat(corners), patternfound); -@endcode -@note The function requires white space (like a square-thick border, the wider the better) around -the board to make the detection more robust in various environments. Otherwise, if there is no -border and the background is dark, the outer black squares cannot be segmented properly and so the -square grouping and ordering algorithm fails. - */ -CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, - int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE ); - -/* - Checks whether the image contains chessboard of the specific size or not. - If yes, nonzero value is returned. -*/ -CV_EXPORTS_W bool checkChessboard(InputArray img, Size size); - -/** @brief Finds the positions of internal corners of the chessboard using a sector based approach. - -@param image Source chessboard view. It must be an 8-bit grayscale or color image. -@param patternSize Number of inner corners per a chessboard row and column -( patternSize = cv::Size(points_per_row,points_per_colum) = cv::Size(columns,rows) ). -@param corners Output array of detected corners. -@param flags Various operation flags that can be zero or a combination of the following values: -- **CALIB_CB_NORMALIZE_IMAGE** Normalize the image gamma with equalizeHist before detection. -- **CALIB_CB_EXHAUSTIVE** Run an exhaustive search to improve detection rate. -- **CALIB_CB_ACCURACY** Up sample input image to improve sub-pixel accuracy due to aliasing effects. -- **CALIB_CB_LARGER** The detected pattern is allowed to be larger than patternSize (see description). -- **CALIB_CB_MARKER** The detected pattern must have a marker (see description). -This should be used if an accurate camera calibration is required. -@param meta Optional output arrray of detected corners (CV_8UC1 and size = cv::Size(columns,rows)). -Each entry stands for one corner of the pattern and can have one of the following values: -- 0 = no meta data attached -- 1 = left-top corner of a black cell -- 2 = left-top corner of a white cell -- 3 = left-top corner of a black cell with a white marker dot -- 4 = left-top corner of a white cell with a black marker dot (pattern origin in case of markers otherwise first corner) - -The function is analog to findchessboardCorners but uses a localized radon -transformation approximated by box filters being more robust to all sort of -noise, faster on larger images and is able to directly return the sub-pixel -position of the internal chessboard corners. The Method is based on the paper -@cite duda2018 "Accurate Detection and Localization of Checkerboard Corners for -Calibration" demonstrating that the returned sub-pixel positions are more -accurate than the one returned by cornerSubPix allowing a precise camera -calibration for demanding applications. - -In the case, the flags **CALIB_CB_LARGER** or **CALIB_CB_MARKER** are given, -the result can be recovered from the optional meta array. Both flags are -helpful to use calibration patterns exceeding the field of view of the camera. -These oversized patterns allow more accurate calibrations as corners can be -utilized, which are as close as possible to the image borders. For a -consistent coordinate system across all images, the optional marker (see image -below) can be used to move the origin of the board to the location where the -black circle is located. - -@note The function requires a white boarder with roughly the same width as one -of the checkerboard fields around the whole board to improve the detection in -various environments. In addition, because of the localized radon -transformation it is beneficial to use round corners for the field corners -which are located on the outside of the board. The following figure illustrates -a sample checkerboard optimized for the detection. However, any other checkerboard -can be used as well. -![Checkerboard](pics/checkerboard_radon.png) - */ -CV_EXPORTS_AS(findChessboardCornersSBWithMeta) -bool findChessboardCornersSB(InputArray image,Size patternSize, OutputArray corners, - int flags,OutputArray meta); -/** @overload */ -CV_EXPORTS_W inline -bool findChessboardCornersSB(InputArray image, Size patternSize, OutputArray corners, - int flags = 0) -{ - return findChessboardCornersSB(image, patternSize, corners, flags, noArray()); -} - -/** @brief Estimates the sharpness of a detected chessboard. - -Image sharpness, as well as brightness, are a critical parameter for accuracte -camera calibration. For accessing these parameters for filtering out -problematic calibraiton images, this method calculates edge profiles by traveling from -black to white chessboard cell centers. Based on this, the number of pixels is -calculated required to transit from black to white. This width of the -transition area is a good indication of how sharp the chessboard is imaged -and should be below ~3.0 pixels. - -@param image Gray image used to find chessboard corners -@param patternSize Size of a found chessboard pattern -@param corners Corners found by findChessboardCorners(SB) -@param rise_distance Rise distance 0.8 means 10% ... 90% of the final signal strength -@param vertical By default edge responses for horizontal lines are calculated -@param sharpness Optional output array with a sharpness value for calculated edge responses (see description) - -The optional sharpness array is of type CV_32FC1 and has for each calculated -profile one row with the following five entries: -* 0 = x coordinate of the underlying edge in the image -* 1 = y coordinate of the underlying edge in the image -* 2 = width of the transition area (sharpness) -* 3 = signal strength in the black cell (min brightness) -* 4 = signal strength in the white cell (max brightness) - -@return Scalar(average sharpness, average min brightness, average max brightness,0) -*/ -CV_EXPORTS_W Scalar estimateChessboardSharpness(InputArray image, Size patternSize, InputArray corners, - float rise_distance=0.8F,bool vertical=false, - OutputArray sharpness=noArray()); - - -//! finds subpixel-accurate positions of the chessboard corners -CV_EXPORTS_W bool find4QuadCornerSubpix( InputArray img, InputOutputArray corners, Size region_size ); - -/** @brief Renders the detected chessboard corners. - -@param image Destination image. It must be an 8-bit color image. -@param patternSize Number of inner corners per a chessboard row and column -(patternSize = cv::Size(points_per_row,points_per_column)). -@param corners Array of detected corners, the output of findChessboardCorners. -@param patternWasFound Parameter indicating whether the complete board was found or not. The -return value of findChessboardCorners should be passed here. - -The function draws individual chessboard corners detected either as red circles if the board was not -found, or as colored corners connected with lines if the board was found. - */ -CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize, - InputArray corners, bool patternWasFound ); /** @brief Draw axes of the world/object coordinate system from pose estimation. @sa solvePnP @@ -1627,963 +1308,30 @@ OX is drawn in red, OY in green and OZ in blue. CV_EXPORTS_W void drawFrameAxes(InputOutputArray image, InputArray cameraMatrix, InputArray distCoeffs, InputArray rvec, InputArray tvec, float length, int thickness=3); -struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters -{ - CV_WRAP CirclesGridFinderParameters(); - CV_PROP_RW cv::Size2f densityNeighborhoodSize; - CV_PROP_RW float minDensity; - CV_PROP_RW int kmeansAttempts; - CV_PROP_RW int minDistanceToAddKeypoint; - CV_PROP_RW int keypointScale; - CV_PROP_RW float minGraphConfidence; - CV_PROP_RW float vertexGain; - CV_PROP_RW float vertexPenalty; - CV_PROP_RW float existingVertexGain; - CV_PROP_RW float edgeGain; - CV_PROP_RW float edgePenalty; - CV_PROP_RW float convexHullFactor; - CV_PROP_RW float minRNGEdgeSwitchDist; - - enum GridType - { - SYMMETRIC_GRID, ASYMMETRIC_GRID - }; - GridType gridType; - - CV_PROP_RW float squareSize; //!< Distance between two adjacent points. Used by CALIB_CB_CLUSTERING. - CV_PROP_RW float maxRectifiedDistance; //!< Max deviation from prediction. Used by CALIB_CB_CLUSTERING. -}; - -#ifndef DISABLE_OPENCV_3_COMPATIBILITY -typedef CirclesGridFinderParameters CirclesGridFinderParameters2; -#endif - -/** @brief Finds centers in the grid of circles. - -@param image grid view of input circles; it must be an 8-bit grayscale or color image. -@param patternSize number of circles per row and column -( patternSize = Size(points_per_row, points_per_colum) ). -@param centers output array of detected centers. -@param flags various operation flags that can be one of the following values: -- **CALIB_CB_SYMMETRIC_GRID** uses symmetric pattern of circles. -- **CALIB_CB_ASYMMETRIC_GRID** uses asymmetric pattern of circles. -- **CALIB_CB_CLUSTERING** uses a special algorithm for grid detection. It is more robust to -perspective distortions but much more sensitive to background clutter. -@param blobDetector feature detector that finds blobs like dark circles on light background. -@param parameters struct for finding circles in a grid pattern. - -The function attempts to determine whether the input image contains a grid of circles. If it is, the -function locates centers of the circles. The function returns a non-zero value if all of the centers -have been found and they have been placed in a certain order (row by row, left to right in every -row). Otherwise, if the function fails to find all the corners or reorder them, it returns 0. - -Sample usage of detecting and drawing the centers of circles: : -@code - Size patternsize(7,7); //number of centers - Mat gray = ....; //source image - vector centers; //this will be filled by the detected centers - - bool patternfound = findCirclesGrid(gray, patternsize, centers); - - drawChessboardCorners(img, patternsize, Mat(centers), patternfound); -@endcode -@note The function requires white space (like a square-thick border, the wider the better) around -the board to make the detection more robust in various environments. - */ -CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, - OutputArray centers, int flags, - const Ptr &blobDetector, - const CirclesGridFinderParameters& parameters); - -/** @overload */ -CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, - OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID, - const Ptr &blobDetector = SimpleBlobDetector::create()); - -/** @brief Finds the camera intrinsic and extrinsic parameters from several views of a calibration -pattern. - -@param objectPoints In the new interface it is a vector of vectors of calibration pattern points in -the calibration pattern coordinate space (e.g. std::vector>). The outer -vector contains as many elements as the number of pattern views. If the same calibration pattern -is shown in each view and it is fully visible, all the vectors will be the same. Although, it is -possible to use partially occluded patterns or even different patterns in different views. Then, -the vectors will be different. Although the points are 3D, they all lie in the calibration pattern's -XY coordinate plane (thus 0 in the Z-coordinate), if the used calibration pattern is a planar rig. -In the old interface all the vectors of object points from different views are concatenated -together. -@param imagePoints In the new interface it is a vector of vectors of the projections of calibration -pattern points (e.g. std::vector>). imagePoints.size() and -objectPoints.size(), and imagePoints[i].size() and objectPoints[i].size() for each i, must be equal, -respectively. In the old interface all the vectors of object points from different views are -concatenated together. -@param imageSize Size of the image used only to initialize the camera intrinsic matrix. -@param cameraMatrix Input/output 3x3 floating-point camera intrinsic matrix -\f$\cameramatrix{A}\f$ . If CV\_CALIB\_USE\_INTRINSIC\_GUESS -and/or CALIB_FIX_ASPECT_RATIO are specified, some or all of fx, fy, cx, cy must be -initialized before calling the function. -@param distCoeffs Input/output vector of distortion coefficients -\f$\distcoeffs\f$. -@param rvecs Output vector of rotation vectors (@ref Rodrigues ) estimated for each pattern view -(e.g. std::vector>). That is, each i-th rotation vector together with the corresponding -i-th translation vector (see the next output parameter description) brings the calibration pattern -from the object coordinate space (in which object points are specified) to the camera coordinate -space. In more technical terms, the tuple of the i-th rotation and translation vector performs -a change of basis from object coordinate space to camera coordinate space. Due to its duality, this -tuple is equivalent to the position of the calibration pattern with respect to the camera coordinate -space. -@param tvecs Output vector of translation vectors estimated for each pattern view, see parameter -describtion above. -@param stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic -parameters. Order of deviations values: -\f$(f_x, f_y, c_x, c_y, k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6 , s_1, s_2, s_3, - s_4, \tau_x, \tau_y)\f$ If one of parameters is not estimated, it's deviation is equals to zero. -@param stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic -parameters. Order of deviations values: \f$(R_0, T_0, \dotsc , R_{M - 1}, T_{M - 1})\f$ where M is -the number of pattern views. \f$R_i, T_i\f$ are concatenated 1x3 vectors. - @param perViewErrors Output vector of the RMS re-projection error estimated for each pattern view. -@param flags Different flags that may be zero or a combination of the following values: -- **CALIB_USE_INTRINSIC_GUESS** cameraMatrix contains valid initial values of -fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image -center ( imageSize is used), and focal distances are computed in a least-squares fashion. -Note, that if intrinsic parameters are known, there is no need to use this function just to -estimate extrinsic parameters. Use solvePnP instead. -- **CALIB_FIX_PRINCIPAL_POINT** The principal point is not changed during the global -optimization. It stays at the center or at a different location specified when -CALIB_USE_INTRINSIC_GUESS is set too. -- **CALIB_FIX_ASPECT_RATIO** The functions consider only fy as a free parameter. The -ratio fx/fy stays the same as in the input cameraMatrix . When -CALIB_USE_INTRINSIC_GUESS is not set, the actual input values of fx and fy are -ignored, only their ratio is computed and used further. -- **CALIB_ZERO_TANGENT_DIST** Tangential distortion coefficients \f$(p_1, p_2)\f$ are set -to zeros and stay zero. -- **CALIB_FIX_K1,...,CALIB_FIX_K6** The corresponding radial distortion -coefficient is not changed during the optimization. If CALIB_USE_INTRINSIC_GUESS is -set, the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to 0. -- **CALIB_RATIONAL_MODEL** Coefficients k4, k5, and k6 are enabled. To provide the -backward compatibility, this extra flag should be explicitly specified to make the -calibration function use the rational model and return 8 coefficients. If the flag is not -set, the function computes and returns only 5 distortion coefficients. -- **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the -backward compatibility, this extra flag should be explicitly specified to make the -calibration function use the thin prism model and return 12 coefficients. If the flag is not -set, the function computes and returns only 5 distortion coefficients. -- **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during -the optimization. If CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the -supplied distCoeffs matrix is used. Otherwise, it is set to 0. -- **CALIB_TILTED_MODEL** Coefficients tauX and tauY are enabled. To provide the -backward compatibility, this extra flag should be explicitly specified to make the -calibration function use the tilted sensor model and return 14 coefficients. If the flag is not -set, the function computes and returns only 5 distortion coefficients. -- **CALIB_FIX_TAUX_TAUY** The coefficients of the tilted sensor model are not changed during -the optimization. If CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the -supplied distCoeffs matrix is used. Otherwise, it is set to 0. -@param criteria Termination criteria for the iterative optimization algorithm. - -@return the overall RMS re-projection error. - -The function estimates the intrinsic camera parameters and extrinsic parameters for each of the -views. The algorithm is based on @cite Zhang2000 and @cite BouguetMCT . The coordinates of 3D object -points and their corresponding 2D projections in each view must be specified. That may be achieved -by using an object with known geometry and easily detectable feature points. Such an object is -called a calibration rig or calibration pattern, and OpenCV has built-in support for a chessboard as -a calibration rig (see @ref findChessboardCorners). Currently, initialization of intrinsic -parameters (when CALIB_USE_INTRINSIC_GUESS is not set) is only implemented for planar calibration -patterns (where Z-coordinates of the object points must be all zeros). 3D calibration rigs can also -be used as long as initial cameraMatrix is provided. - -The algorithm performs the following steps: - -- Compute the initial intrinsic parameters (the option only available for planar calibration - patterns) or read them from the input parameters. The distortion coefficients are all set to - zeros initially unless some of CALIB_FIX_K? are specified. - -- Estimate the initial camera pose as if the intrinsic parameters have been already known. This is - done using solvePnP . - -- Run the global Levenberg-Marquardt optimization algorithm to minimize the reprojection error, - that is, the total sum of squared distances between the observed feature points imagePoints and - the projected (using the current estimates for camera parameters and the poses) object points - objectPoints. See projectPoints for details. - -@note - If you use a non-square (i.e. non-N-by-N) grid and @ref findChessboardCorners for calibration, - and @ref calibrateCamera returns bad values (zero distortion coefficients, \f$c_x\f$ and - \f$c_y\f$ very far from the image center, and/or large differences between \f$f_x\f$ and - \f$f_y\f$ (ratios of 10:1 or more)), then you are probably using patternSize=cvSize(rows,cols) - instead of using patternSize=cvSize(cols,rows) in @ref findChessboardCorners. - -@sa - calibrateCameraRO, findChessboardCorners, solvePnP, initCameraMatrix2D, stereoCalibrate, - undistort - */ -CV_EXPORTS_AS(calibrateCameraExtended) double calibrateCamera( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints, Size imageSize, - InputOutputArray cameraMatrix, InputOutputArray distCoeffs, - OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, - OutputArray stdDeviationsIntrinsics, - OutputArray stdDeviationsExtrinsics, - OutputArray perViewErrors, - int flags = 0, TermCriteria criteria = TermCriteria( - TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); - -/** @overload */ -CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints, Size imageSize, - InputOutputArray cameraMatrix, InputOutputArray distCoeffs, - OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, - int flags = 0, TermCriteria criteria = TermCriteria( - TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); - -/** @brief Finds the camera intrinsic and extrinsic parameters from several views of a calibration pattern. - -This function is an extension of calibrateCamera() with the method of releasing object which was -proposed in @cite strobl2011iccv. In many common cases with inaccurate, unmeasured, roughly planar -targets (calibration plates), this method can dramatically improve the precision of the estimated -camera parameters. Both the object-releasing method and standard method are supported by this -function. Use the parameter **iFixedPoint** for method selection. In the internal implementation, -calibrateCamera() is a wrapper for this function. - -@param objectPoints Vector of vectors of calibration pattern points in the calibration pattern -coordinate space. See calibrateCamera() for details. If the method of releasing object to be used, -the identical calibration board must be used in each view and it must be fully visible, and all -objectPoints[i] must be the same and all points should be roughly close to a plane. **The calibration -target has to be rigid, or at least static if the camera (rather than the calibration target) is -shifted for grabbing images.** -@param imagePoints Vector of vectors of the projections of calibration pattern points. See -calibrateCamera() for details. -@param imageSize Size of the image used only to initialize the intrinsic camera matrix. -@param iFixedPoint The index of the 3D object point in objectPoints[0] to be fixed. It also acts as -a switch for calibration method selection. If object-releasing method to be used, pass in the -parameter in the range of [1, objectPoints[0].size()-2], otherwise a value out of this range will -make standard calibration method selected. Usually the top-right corner point of the calibration -board grid is recommended to be fixed when object-releasing method being utilized. According to -\cite strobl2011iccv, two other points are also fixed. In this implementation, objectPoints[0].front -and objectPoints[0].back.z are used. With object-releasing method, accurate rvecs, tvecs and -newObjPoints are only possible if coordinates of these three fixed points are accurate enough. -@param cameraMatrix Output 3x3 floating-point camera matrix. See calibrateCamera() for details. -@param distCoeffs Output vector of distortion coefficients. See calibrateCamera() for details. -@param rvecs Output vector of rotation vectors estimated for each pattern view. See calibrateCamera() -for details. -@param tvecs Output vector of translation vectors estimated for each pattern view. -@param newObjPoints The updated output vector of calibration pattern points. The coordinates might -be scaled based on three fixed points. The returned coordinates are accurate only if the above -mentioned three fixed points are accurate. If not needed, noArray() can be passed in. This parameter -is ignored with standard calibration method. -@param stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic parameters. -See calibrateCamera() for details. -@param stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic parameters. -See calibrateCamera() for details. -@param stdDeviationsObjPoints Output vector of standard deviations estimated for refined coordinates -of calibration pattern points. It has the same size and order as objectPoints[0] vector. This -parameter is ignored with standard calibration method. - @param perViewErrors Output vector of the RMS re-projection error estimated for each pattern view. -@param flags Different flags that may be zero or a combination of some predefined values. See -calibrateCamera() for details. If the method of releasing object is used, the calibration time may -be much longer. CALIB_USE_QR or CALIB_USE_LU could be used for faster calibration with potentially -less precise and less stable in some rare cases. -@param criteria Termination criteria for the iterative optimization algorithm. - -@return the overall RMS re-projection error. - -The function estimates the intrinsic camera parameters and extrinsic parameters for each of the -views. The algorithm is based on @cite Zhang2000, @cite BouguetMCT and @cite strobl2011iccv. See -calibrateCamera() for other detailed explanations. -@sa - calibrateCamera, findChessboardCorners, solvePnP, initCameraMatrix2D, stereoCalibrate, undistort - */ -CV_EXPORTS_AS(calibrateCameraROExtended) double calibrateCameraRO( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints, Size imageSize, int iFixedPoint, - InputOutputArray cameraMatrix, InputOutputArray distCoeffs, - OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, - OutputArray newObjPoints, - OutputArray stdDeviationsIntrinsics, - OutputArray stdDeviationsExtrinsics, - OutputArray stdDeviationsObjPoints, - OutputArray perViewErrors, - int flags = 0, TermCriteria criteria = TermCriteria( - TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); - -/** @overload */ -CV_EXPORTS_W double calibrateCameraRO( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints, Size imageSize, int iFixedPoint, - InputOutputArray cameraMatrix, InputOutputArray distCoeffs, - OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, - OutputArray newObjPoints, - int flags = 0, TermCriteria criteria = TermCriteria( - TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); - -/** @brief Computes useful camera characteristics from the camera intrinsic matrix. - -@param cameraMatrix Input camera intrinsic matrix that can be estimated by calibrateCamera or -stereoCalibrate . -@param imageSize Input image size in pixels. -@param apertureWidth Physical width in mm of the sensor. -@param apertureHeight Physical height in mm of the sensor. -@param fovx Output field of view in degrees along the horizontal sensor axis. -@param fovy Output field of view in degrees along the vertical sensor axis. -@param focalLength Focal length of the lens in mm. -@param principalPoint Principal point in mm. -@param aspectRatio \f$f_y/f_x\f$ - -The function computes various useful camera characteristics from the previously estimated camera -matrix. - -@note - Do keep in mind that the unity measure 'mm' stands for whatever unit of measure one chooses for - the chessboard pitch (it can thus be any value). - */ -CV_EXPORTS_W void calibrationMatrixValues( InputArray cameraMatrix, Size imageSize, - double apertureWidth, double apertureHeight, - CV_OUT double& fovx, CV_OUT double& fovy, - CV_OUT double& focalLength, CV_OUT Point2d& principalPoint, - CV_OUT double& aspectRatio ); - -/** @brief Calibrates a stereo camera set up. This function finds the intrinsic parameters -for each of the two cameras and the extrinsic parameters between the two cameras. - -@param objectPoints Vector of vectors of the calibration pattern points. The same structure as -in @ref calibrateCamera. For each pattern view, both cameras need to see the same object -points. Therefore, objectPoints.size(), imagePoints1.size(), and imagePoints2.size() need to be -equal as well as objectPoints[i].size(), imagePoints1[i].size(), and imagePoints2[i].size() need to -be equal for each i. -@param imagePoints1 Vector of vectors of the projections of the calibration pattern points, -observed by the first camera. The same structure as in @ref calibrateCamera. -@param imagePoints2 Vector of vectors of the projections of the calibration pattern points, -observed by the second camera. The same structure as in @ref calibrateCamera. -@param cameraMatrix1 Input/output camera intrinsic matrix for the first camera, the same as in -@ref calibrateCamera. Furthermore, for the stereo case, additional flags may be used, see below. -@param distCoeffs1 Input/output vector of distortion coefficients, the same as in -@ref calibrateCamera. -@param cameraMatrix2 Input/output second camera intrinsic matrix for the second camera. See description for -cameraMatrix1. -@param distCoeffs2 Input/output lens distortion coefficients for the second camera. See -description for distCoeffs1. -@param imageSize Size of the image used only to initialize the camera intrinsic matrices. -@param R Output rotation matrix. Together with the translation vector T, this matrix brings -points given in the first camera's coordinate system to points in the second camera's -coordinate system. In more technical terms, the tuple of R and T performs a change of basis -from the first camera's coordinate system to the second camera's coordinate system. Due to its -duality, this tuple is equivalent to the position of the first camera with respect to the -second camera coordinate system. -@param T Output translation vector, see description above. -@param E Output essential matrix. -@param F Output fundamental matrix. -@param perViewErrors Output vector of the RMS re-projection error estimated for each pattern view. -@param flags Different flags that may be zero or a combination of the following values: -- **CALIB_FIX_INTRINSIC** Fix cameraMatrix? and distCoeffs? so that only R, T, E, and F -matrices are estimated. -- **CALIB_USE_INTRINSIC_GUESS** Optimize some or all of the intrinsic parameters -according to the specified flags. Initial values are provided by the user. -- **CALIB_USE_EXTRINSIC_GUESS** R and T contain valid initial values that are optimized further. -Otherwise R and T are initialized to the median value of the pattern views (each dimension separately). -- **CALIB_FIX_PRINCIPAL_POINT** Fix the principal points during the optimization. -- **CALIB_FIX_FOCAL_LENGTH** Fix \f$f^{(j)}_x\f$ and \f$f^{(j)}_y\f$ . -- **CALIB_FIX_ASPECT_RATIO** Optimize \f$f^{(j)}_y\f$ . Fix the ratio \f$f^{(j)}_x/f^{(j)}_y\f$ -. -- **CALIB_SAME_FOCAL_LENGTH** Enforce \f$f^{(0)}_x=f^{(1)}_x\f$ and \f$f^{(0)}_y=f^{(1)}_y\f$ . -- **CALIB_ZERO_TANGENT_DIST** Set tangential distortion coefficients for each camera to -zeros and fix there. -- **CALIB_FIX_K1,...,CALIB_FIX_K6** Do not change the corresponding radial -distortion coefficient during the optimization. If CALIB_USE_INTRINSIC_GUESS is set, -the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to 0. -- **CALIB_RATIONAL_MODEL** Enable coefficients k4, k5, and k6. To provide the backward -compatibility, this extra flag should be explicitly specified to make the calibration -function use the rational model and return 8 coefficients. If the flag is not set, the -function computes and returns only 5 distortion coefficients. -- **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the -backward compatibility, this extra flag should be explicitly specified to make the -calibration function use the thin prism model and return 12 coefficients. If the flag is not -set, the function computes and returns only 5 distortion coefficients. -- **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during -the optimization. If CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the -supplied distCoeffs matrix is used. Otherwise, it is set to 0. -- **CALIB_TILTED_MODEL** Coefficients tauX and tauY are enabled. To provide the -backward compatibility, this extra flag should be explicitly specified to make the -calibration function use the tilted sensor model and return 14 coefficients. If the flag is not -set, the function computes and returns only 5 distortion coefficients. -- **CALIB_FIX_TAUX_TAUY** The coefficients of the tilted sensor model are not changed during -the optimization. If CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the -supplied distCoeffs matrix is used. Otherwise, it is set to 0. -@param criteria Termination criteria for the iterative optimization algorithm. - -The function estimates the transformation between two cameras making a stereo pair. If one computes -the poses of an object relative to the first camera and to the second camera, -( \f$R_1\f$,\f$T_1\f$ ) and (\f$R_2\f$,\f$T_2\f$), respectively, for a stereo camera where the -relative position and orientation between the two cameras are fixed, then those poses definitely -relate to each other. This means, if the relative position and orientation (\f$R\f$,\f$T\f$) of the -two cameras is known, it is possible to compute (\f$R_2\f$,\f$T_2\f$) when (\f$R_1\f$,\f$T_1\f$) is -given. This is what the described function does. It computes (\f$R\f$,\f$T\f$) such that: - -\f[R_2=R R_1\f] -\f[T_2=R T_1 + T.\f] - -Therefore, one can compute the coordinate representation of a 3D point for the second camera's -coordinate system when given the point's coordinate representation in the first camera's coordinate -system: - -\f[\begin{bmatrix} -X_2 \\ -Y_2 \\ -Z_2 \\ -1 -\end{bmatrix} = \begin{bmatrix} -R & T \\ -0 & 1 -\end{bmatrix} \begin{bmatrix} -X_1 \\ -Y_1 \\ -Z_1 \\ -1 -\end{bmatrix}.\f] - - -Optionally, it computes the essential matrix E: - -\f[E= \vecthreethree{0}{-T_2}{T_1}{T_2}{0}{-T_0}{-T_1}{T_0}{0} R\f] - -where \f$T_i\f$ are components of the translation vector \f$T\f$ : \f$T=[T_0, T_1, T_2]^T\f$ . -And the function can also compute the fundamental matrix F: - -\f[F = cameraMatrix2^{-T}\cdot E \cdot cameraMatrix1^{-1}\f] - -Besides the stereo-related information, the function can also perform a full calibration of each of -the two cameras. However, due to the high dimensionality of the parameter space and noise in the -input data, the function can diverge from the correct solution. If the intrinsic parameters can be -estimated with high accuracy for each of the cameras individually (for example, using -calibrateCamera ), you are recommended to do so and then pass CALIB_FIX_INTRINSIC flag to the -function along with the computed intrinsic parameters. Otherwise, if all the parameters are -estimated at once, it makes sense to restrict some parameters, for example, pass -CALIB_SAME_FOCAL_LENGTH and CALIB_ZERO_TANGENT_DIST flags, which is usually a -reasonable assumption. - -Similarly to calibrateCamera, the function minimizes the total re-projection error for all the -points in all the available views from both cameras. The function returns the final value of the -re-projection error. - */ -CV_EXPORTS_AS(stereoCalibrateExtended) double stereoCalibrate( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, - InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1, - InputOutputArray cameraMatrix2, InputOutputArray distCoeffs2, - Size imageSize, InputOutputArray R,InputOutputArray T, OutputArray E, OutputArray F, - OutputArray perViewErrors, int flags = CALIB_FIX_INTRINSIC, - TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6) ); - -/// @overload -CV_EXPORTS_W double stereoCalibrate( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, - InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1, - InputOutputArray cameraMatrix2, InputOutputArray distCoeffs2, - Size imageSize, OutputArray R,OutputArray T, OutputArray E, OutputArray F, - int flags = CALIB_FIX_INTRINSIC, - TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6) ); - -/** @brief Computes rectification transforms for each head of a calibrated stereo camera. - -@param cameraMatrix1 First camera intrinsic matrix. -@param distCoeffs1 First camera distortion parameters. -@param cameraMatrix2 Second camera intrinsic matrix. -@param distCoeffs2 Second camera distortion parameters. -@param imageSize Size of the image used for stereo calibration. -@param R Rotation matrix from the coordinate system of the first camera to the second camera, -see @ref stereoCalibrate. -@param T Translation vector from the coordinate system of the first camera to the second camera, -see @ref stereoCalibrate. -@param R1 Output 3x3 rectification transform (rotation matrix) for the first camera. This matrix -brings points given in the unrectified first camera's coordinate system to points in the rectified -first camera's coordinate system. In more technical terms, it performs a change of basis from the -unrectified first camera's coordinate system to the rectified first camera's coordinate system. -@param R2 Output 3x3 rectification transform (rotation matrix) for the second camera. This matrix -brings points given in the unrectified second camera's coordinate system to points in the rectified -second camera's coordinate system. In more technical terms, it performs a change of basis from the -unrectified second camera's coordinate system to the rectified second camera's coordinate system. -@param P1 Output 3x4 projection matrix in the new (rectified) coordinate systems for the first -camera, i.e. it projects points given in the rectified first camera coordinate system into the -rectified first camera's image. -@param P2 Output 3x4 projection matrix in the new (rectified) coordinate systems for the second -camera, i.e. it projects points given in the rectified first camera coordinate system into the -rectified second camera's image. -@param Q Output \f$4 \times 4\f$ disparity-to-depth mapping matrix (see @ref reprojectImageTo3D). -@param flags Operation flags that may be zero or CALIB_ZERO_DISPARITY . If the flag is set, -the function makes the principal points of each camera have the same pixel coordinates in the -rectified views. And if the flag is not set, the function may still shift the images in the -horizontal or vertical direction (depending on the orientation of epipolar lines) to maximize the -useful image area. -@param alpha Free scaling parameter. If it is -1 or absent, the function performs the default -scaling. Otherwise, the parameter should be between 0 and 1. alpha=0 means that the rectified -images are zoomed and shifted so that only valid pixels are visible (no black areas after -rectification). alpha=1 means that the rectified image is decimated and shifted so that all the -pixels from the original images from the cameras are retained in the rectified images (no source -image pixels are lost). Any intermediate value yields an intermediate result between -those two extreme cases. -@param newImageSize New image resolution after rectification. The same size should be passed to -initUndistortRectifyMap (see the stereo_calib.cpp sample in OpenCV samples directory). When (0,0) -is passed (default), it is set to the original imageSize . Setting it to a larger value can help you -preserve details in the original image, especially when there is a big radial distortion. -@param validPixROI1 Optional output rectangles inside the rectified images where all the pixels -are valid. If alpha=0 , the ROIs cover the whole images. Otherwise, they are likely to be smaller -(see the picture below). -@param validPixROI2 Optional output rectangles inside the rectified images where all the pixels -are valid. If alpha=0 , the ROIs cover the whole images. Otherwise, they are likely to be smaller -(see the picture below). - -The function computes the rotation matrices for each camera that (virtually) make both camera image -planes the same plane. Consequently, this makes all the epipolar lines parallel and thus simplifies -the dense stereo correspondence problem. The function takes the matrices computed by stereoCalibrate -as input. As output, it provides two rotation matrices and also two projection matrices in the new -coordinates. The function distinguishes the following two cases: - -- **Horizontal stereo**: the first and the second camera views are shifted relative to each other - mainly along the x-axis (with possible small vertical shift). In the rectified images, the - corresponding epipolar lines in the left and right cameras are horizontal and have the same - y-coordinate. P1 and P2 look like: - - \f[\texttt{P1} = \begin{bmatrix} - f & 0 & cx_1 & 0 \\ - 0 & f & cy & 0 \\ - 0 & 0 & 1 & 0 - \end{bmatrix}\f] - - \f[\texttt{P2} = \begin{bmatrix} - f & 0 & cx_2 & T_x*f \\ - 0 & f & cy & 0 \\ - 0 & 0 & 1 & 0 - \end{bmatrix} ,\f] - - where \f$T_x\f$ is a horizontal shift between the cameras and \f$cx_1=cx_2\f$ if - CALIB_ZERO_DISPARITY is set. - -- **Vertical stereo**: the first and the second camera views are shifted relative to each other - mainly in the vertical direction (and probably a bit in the horizontal direction too). The epipolar - lines in the rectified images are vertical and have the same x-coordinate. P1 and P2 look like: - - \f[\texttt{P1} = \begin{bmatrix} - f & 0 & cx & 0 \\ - 0 & f & cy_1 & 0 \\ - 0 & 0 & 1 & 0 - \end{bmatrix}\f] - - \f[\texttt{P2} = \begin{bmatrix} - f & 0 & cx & 0 \\ - 0 & f & cy_2 & T_y*f \\ - 0 & 0 & 1 & 0 - \end{bmatrix},\f] - - where \f$T_y\f$ is a vertical shift between the cameras and \f$cy_1=cy_2\f$ if - CALIB_ZERO_DISPARITY is set. - -As you can see, the first three columns of P1 and P2 will effectively be the new "rectified" camera -matrices. The matrices, together with R1 and R2 , can then be passed to initUndistortRectifyMap to -initialize the rectification map for each camera. - -See below the screenshot from the stereo_calib.cpp sample. Some red horizontal lines pass through -the corresponding image regions. This means that the images are well rectified, which is what most -stereo correspondence algorithms rely on. The green rectangles are roi1 and roi2 . You see that -their interiors are all valid pixels. - -![image](pics/stereo_undistort.jpg) - */ -CV_EXPORTS_W void stereoRectify( InputArray cameraMatrix1, InputArray distCoeffs1, - InputArray cameraMatrix2, InputArray distCoeffs2, - Size imageSize, InputArray R, InputArray T, - OutputArray R1, OutputArray R2, - OutputArray P1, OutputArray P2, - OutputArray Q, int flags = CALIB_ZERO_DISPARITY, - double alpha = -1, Size newImageSize = Size(), - CV_OUT Rect* validPixROI1 = 0, CV_OUT Rect* validPixROI2 = 0 ); - -/** @brief Computes a rectification transform for an uncalibrated stereo camera. - -@param points1 Array of feature points in the first image. -@param points2 The corresponding points in the second image. The same formats as in -findFundamentalMat are supported. -@param F Input fundamental matrix. It can be computed from the same set of point pairs using -findFundamentalMat . -@param imgSize Size of the image. -@param H1 Output rectification homography matrix for the first image. -@param H2 Output rectification homography matrix for the second image. -@param threshold Optional threshold used to filter out the outliers. If the parameter is greater -than zero, all the point pairs that do not comply with the epipolar geometry (that is, the points -for which \f$|\texttt{points2[i]}^T*\texttt{F}*\texttt{points1[i]}|>\texttt{threshold}\f$ ) are -rejected prior to computing the homographies. Otherwise, all the points are considered inliers. - -The function computes the rectification transformations without knowing intrinsic parameters of the -cameras and their relative position in the space, which explains the suffix "uncalibrated". Another -related difference from stereoRectify is that the function outputs not the rectification -transformations in the object (3D) space, but the planar perspective transformations encoded by the -homography matrices H1 and H2 . The function implements the algorithm @cite Hartley99 . - -@note - While the algorithm does not need to know the intrinsic parameters of the cameras, it heavily - depends on the epipolar geometry. Therefore, if the camera lenses have a significant distortion, - it would be better to correct it before computing the fundamental matrix and calling this - function. For example, distortion coefficients can be estimated for each head of stereo camera - separately by using calibrateCamera . Then, the images can be corrected using undistort , or - just the point coordinates can be corrected with undistortPoints . - */ -CV_EXPORTS_W bool stereoRectifyUncalibrated( InputArray points1, InputArray points2, - InputArray F, Size imgSize, - OutputArray H1, OutputArray H2, - double threshold = 5 ); - -//! computes the rectification transformations for 3-head camera, where all the heads are on the same line. -CV_EXPORTS_W float rectify3Collinear( InputArray cameraMatrix1, InputArray distCoeffs1, - InputArray cameraMatrix2, InputArray distCoeffs2, - InputArray cameraMatrix3, InputArray distCoeffs3, - InputArrayOfArrays imgpt1, InputArrayOfArrays imgpt3, - Size imageSize, InputArray R12, InputArray T12, - InputArray R13, InputArray T13, - OutputArray R1, OutputArray R2, OutputArray R3, - OutputArray P1, OutputArray P2, OutputArray P3, - OutputArray Q, double alpha, Size newImgSize, - CV_OUT Rect* roi1, CV_OUT Rect* roi2, int flags ); - -/** @brief Returns the new camera intrinsic matrix based on the free scaling parameter. - -@param cameraMatrix Input camera intrinsic matrix. -@param distCoeffs Input vector of distortion coefficients -\f$\distcoeffs\f$. If the vector is NULL/empty, the zero distortion coefficients are -assumed. -@param imageSize Original image size. -@param alpha Free scaling parameter between 0 (when all the pixels in the undistorted image are -valid) and 1 (when all the source image pixels are retained in the undistorted image). See -stereoRectify for details. -@param newImgSize Image size after rectification. By default, it is set to imageSize . -@param validPixROI Optional output rectangle that outlines all-good-pixels region in the -undistorted image. See roi1, roi2 description in stereoRectify . -@param centerPrincipalPoint Optional flag that indicates whether in the new camera intrinsic matrix the -principal point should be at the image center or not. By default, the principal point is chosen to -best fit a subset of the source image (determined by alpha) to the corrected image. -@return new_camera_matrix Output new camera intrinsic matrix. - -The function computes and returns the optimal new camera intrinsic matrix based on the free scaling parameter. -By varying this parameter, you may retrieve only sensible pixels alpha=0 , keep all the original -image pixels if there is valuable information in the corners alpha=1 , or get something in between. -When alpha\>0 , the undistorted result is likely to have some black pixels corresponding to -"virtual" pixels outside of the captured distorted image. The original camera intrinsic matrix, distortion -coefficients, the computed new camera intrinsic matrix, and newImageSize should be passed to -initUndistortRectifyMap to produce the maps for remap . - */ -CV_EXPORTS_W Mat getOptimalNewCameraMatrix( InputArray cameraMatrix, InputArray distCoeffs, - Size imageSize, double alpha, Size newImgSize = Size(), - CV_OUT Rect* validPixROI = 0, - bool centerPrincipalPoint = false); - -/** @brief Computes Hand-Eye calibration: \f$_{}^{g}\textrm{T}_c\f$ - -@param[in] R_gripper2base Rotation part extracted from the homogeneous matrix that transforms a point -expressed in the gripper frame to the robot base frame (\f$_{}^{b}\textrm{T}_g\f$). -This is a vector (`vector`) that contains the rotation, `(3x3)` rotation matrices or `(3x1)` rotation vectors, -for all the transformations from gripper frame to robot base frame. -@param[in] t_gripper2base Translation part extracted from the homogeneous matrix that transforms a point -expressed in the gripper frame to the robot base frame (\f$_{}^{b}\textrm{T}_g\f$). -This is a vector (`vector`) that contains the `(3x1)` translation vectors for all the transformations -from gripper frame to robot base frame. -@param[in] R_target2cam Rotation part extracted from the homogeneous matrix that transforms a point -expressed in the target frame to the camera frame (\f$_{}^{c}\textrm{T}_t\f$). -This is a vector (`vector`) that contains the rotation, `(3x3)` rotation matrices or `(3x1)` rotation vectors, -for all the transformations from calibration target frame to camera frame. -@param[in] t_target2cam Rotation part extracted from the homogeneous matrix that transforms a point -expressed in the target frame to the camera frame (\f$_{}^{c}\textrm{T}_t\f$). -This is a vector (`vector`) that contains the `(3x1)` translation vectors for all the transformations -from calibration target frame to camera frame. -@param[out] R_cam2gripper Estimated `(3x3)` rotation part extracted from the homogeneous matrix that transforms a point -expressed in the camera frame to the gripper frame (\f$_{}^{g}\textrm{T}_c\f$). -@param[out] t_cam2gripper Estimated `(3x1)` translation part extracted from the homogeneous matrix that transforms a point -expressed in the camera frame to the gripper frame (\f$_{}^{g}\textrm{T}_c\f$). -@param[in] method One of the implemented Hand-Eye calibration method, see cv::HandEyeCalibrationMethod - -The function performs the Hand-Eye calibration using various methods. One approach consists in estimating the -rotation then the translation (separable solutions) and the following methods are implemented: - - R. Tsai, R. Lenz A New Technique for Fully Autonomous and Efficient 3D Robotics Hand/EyeCalibration \cite Tsai89 - - F. Park, B. Martin Robot Sensor Calibration: Solving AX = XB on the Euclidean Group \cite Park94 - - R. Horaud, F. Dornaika Hand-Eye Calibration \cite Horaud95 - -Another approach consists in estimating simultaneously the rotation and the translation (simultaneous solutions), -with the following implemented methods: - - N. Andreff, R. Horaud, B. Espiau On-line Hand-Eye Calibration \cite Andreff99 - - K. Daniilidis Hand-Eye Calibration Using Dual Quaternions \cite Daniilidis98 - -The following picture describes the Hand-Eye calibration problem where the transformation between a camera ("eye") -mounted on a robot gripper ("hand") has to be estimated. This configuration is called eye-in-hand. - -The eye-to-hand configuration consists in a static camera observing a calibration pattern mounted on the robot -end-effector. The transformation from the camera to the robot base frame can then be estimated by inputting -the suitable transformations to the function, see below. - -![](pics/hand-eye_figure.png) - -The calibration procedure is the following: - - a static calibration pattern is used to estimate the transformation between the target frame - and the camera frame - - the robot gripper is moved in order to acquire several poses - - for each pose, the homogeneous transformation between the gripper frame and the robot base frame is recorded using for - instance the robot kinematics -\f[ - \begin{bmatrix} - X_b\\ - Y_b\\ - Z_b\\ - 1 - \end{bmatrix} - = - \begin{bmatrix} - _{}^{b}\textrm{R}_g & _{}^{b}\textrm{t}_g \\ - 0_{1 \times 3} & 1 - \end{bmatrix} - \begin{bmatrix} - X_g\\ - Y_g\\ - Z_g\\ - 1 - \end{bmatrix} -\f] - - for each pose, the homogeneous transformation between the calibration target frame and the camera frame is recorded using - for instance a pose estimation method (PnP) from 2D-3D point correspondences -\f[ - \begin{bmatrix} - X_c\\ - Y_c\\ - Z_c\\ - 1 - \end{bmatrix} - = - \begin{bmatrix} - _{}^{c}\textrm{R}_t & _{}^{c}\textrm{t}_t \\ - 0_{1 \times 3} & 1 - \end{bmatrix} - \begin{bmatrix} - X_t\\ - Y_t\\ - Z_t\\ - 1 - \end{bmatrix} -\f] - -The Hand-Eye calibration procedure returns the following homogeneous transformation -\f[ - \begin{bmatrix} - X_g\\ - Y_g\\ - Z_g\\ - 1 - \end{bmatrix} - = - \begin{bmatrix} - _{}^{g}\textrm{R}_c & _{}^{g}\textrm{t}_c \\ - 0_{1 \times 3} & 1 - \end{bmatrix} - \begin{bmatrix} - X_c\\ - Y_c\\ - Z_c\\ - 1 - \end{bmatrix} -\f] - -This problem is also known as solving the \f$\mathbf{A}\mathbf{X}=\mathbf{X}\mathbf{B}\f$ equation: - - for an eye-in-hand configuration -\f[ - \begin{align*} - ^{b}{\textrm{T}_g}^{(1)} \hspace{0.2em} ^{g}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(1)} &= - \hspace{0.1em} ^{b}{\textrm{T}_g}^{(2)} \hspace{0.2em} ^{g}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} \\ - - (^{b}{\textrm{T}_g}^{(2)})^{-1} \hspace{0.2em} ^{b}{\textrm{T}_g}^{(1)} \hspace{0.2em} ^{g}\textrm{T}_c &= - \hspace{0.1em} ^{g}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} (^{c}{\textrm{T}_t}^{(1)})^{-1} \\ - - \textrm{A}_i \textrm{X} &= \textrm{X} \textrm{B}_i \\ - \end{align*} -\f] - - - for an eye-to-hand configuration -\f[ - \begin{align*} - ^{g}{\textrm{T}_b}^{(1)} \hspace{0.2em} ^{b}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(1)} &= - \hspace{0.1em} ^{g}{\textrm{T}_b}^{(2)} \hspace{0.2em} ^{b}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} \\ - - (^{g}{\textrm{T}_b}^{(2)})^{-1} \hspace{0.2em} ^{g}{\textrm{T}_b}^{(1)} \hspace{0.2em} ^{b}\textrm{T}_c &= - \hspace{0.1em} ^{b}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} (^{c}{\textrm{T}_t}^{(1)})^{-1} \\ - - \textrm{A}_i \textrm{X} &= \textrm{X} \textrm{B}_i \\ - \end{align*} -\f] - -\note -Additional information can be found on this [website](http://campar.in.tum.de/Chair/HandEyeCalibration). -\note -A minimum of 2 motions with non parallel rotation axes are necessary to determine the hand-eye transformation. -So at least 3 different poses are required, but it is strongly recommended to use many more poses. - - */ -CV_EXPORTS_W void calibrateHandEye( InputArrayOfArrays R_gripper2base, InputArrayOfArrays t_gripper2base, - InputArrayOfArrays R_target2cam, InputArrayOfArrays t_target2cam, - OutputArray R_cam2gripper, OutputArray t_cam2gripper, - HandEyeCalibrationMethod method=CALIB_HAND_EYE_TSAI ); - -/** @brief Computes Robot-World/Hand-Eye calibration: \f$_{}^{w}\textrm{T}_b\f$ and \f$_{}^{c}\textrm{T}_g\f$ - -@param[in] R_world2cam Rotation part extracted from the homogeneous matrix that transforms a point -expressed in the world frame to the camera frame (\f$_{}^{c}\textrm{T}_w\f$). -This is a vector (`vector`) that contains the rotation, `(3x3)` rotation matrices or `(3x1)` rotation vectors, -for all the transformations from world frame to the camera frame. -@param[in] t_world2cam Translation part extracted from the homogeneous matrix that transforms a point -expressed in the world frame to the camera frame (\f$_{}^{c}\textrm{T}_w\f$). -This is a vector (`vector`) that contains the `(3x1)` translation vectors for all the transformations -from world frame to the camera frame. -@param[in] R_base2gripper Rotation part extracted from the homogeneous matrix that transforms a point -expressed in the robot base frame to the gripper frame (\f$_{}^{g}\textrm{T}_b\f$). -This is a vector (`vector`) that contains the rotation, `(3x3)` rotation matrices or `(3x1)` rotation vectors, -for all the transformations from robot base frame to the gripper frame. -@param[in] t_base2gripper Rotation part extracted from the homogeneous matrix that transforms a point -expressed in the robot base frame to the gripper frame (\f$_{}^{g}\textrm{T}_b\f$). -This is a vector (`vector`) that contains the `(3x1)` translation vectors for all the transformations -from robot base frame to the gripper frame. -@param[out] R_base2world Estimated `(3x3)` rotation part extracted from the homogeneous matrix that transforms a point -expressed in the robot base frame to the world frame (\f$_{}^{w}\textrm{T}_b\f$). -@param[out] t_base2world Estimated `(3x1)` translation part extracted from the homogeneous matrix that transforms a point -expressed in the robot base frame to the world frame (\f$_{}^{w}\textrm{T}_b\f$). -@param[out] R_gripper2cam Estimated `(3x3)` rotation part extracted from the homogeneous matrix that transforms a point -expressed in the gripper frame to the camera frame (\f$_{}^{c}\textrm{T}_g\f$). -@param[out] t_gripper2cam Estimated `(3x1)` translation part extracted from the homogeneous matrix that transforms a point -expressed in the gripper frame to the camera frame (\f$_{}^{c}\textrm{T}_g\f$). -@param[in] method One of the implemented Robot-World/Hand-Eye calibration method, see cv::RobotWorldHandEyeCalibrationMethod - -The function performs the Robot-World/Hand-Eye calibration using various methods. One approach consists in estimating the -rotation then the translation (separable solutions): - - M. Shah, Solving the robot-world/hand-eye calibration problem using the kronecker product \cite Shah2013SolvingTR - -Another approach consists in estimating simultaneously the rotation and the translation (simultaneous solutions), -with the following implemented method: - - A. Li, L. Wang, and D. Wu, Simultaneous robot-world and hand-eye calibration using dual-quaternions and kronecker product \cite Li2010SimultaneousRA - -The following picture describes the Robot-World/Hand-Eye calibration problem where the transformations between a robot and a world frame -and between a robot gripper ("hand") and a camera ("eye") mounted at the robot end-effector have to be estimated. - -![](pics/robot-world_hand-eye_figure.png) - -The calibration procedure is the following: - - a static calibration pattern is used to estimate the transformation between the target frame - and the camera frame - - the robot gripper is moved in order to acquire several poses - - for each pose, the homogeneous transformation between the gripper frame and the robot base frame is recorded using for - instance the robot kinematics -\f[ - \begin{bmatrix} - X_g\\ - Y_g\\ - Z_g\\ - 1 - \end{bmatrix} - = - \begin{bmatrix} - _{}^{g}\textrm{R}_b & _{}^{g}\textrm{t}_b \\ - 0_{1 \times 3} & 1 - \end{bmatrix} - \begin{bmatrix} - X_b\\ - Y_b\\ - Z_b\\ - 1 - \end{bmatrix} -\f] - - for each pose, the homogeneous transformation between the calibration target frame (the world frame) and the camera frame is recorded using - for instance a pose estimation method (PnP) from 2D-3D point correspondences -\f[ - \begin{bmatrix} - X_c\\ - Y_c\\ - Z_c\\ - 1 - \end{bmatrix} - = - \begin{bmatrix} - _{}^{c}\textrm{R}_w & _{}^{c}\textrm{t}_w \\ - 0_{1 \times 3} & 1 - \end{bmatrix} - \begin{bmatrix} - X_w\\ - Y_w\\ - Z_w\\ - 1 - \end{bmatrix} -\f] - -The Robot-World/Hand-Eye calibration procedure returns the following homogeneous transformations -\f[ - \begin{bmatrix} - X_w\\ - Y_w\\ - Z_w\\ - 1 - \end{bmatrix} - = - \begin{bmatrix} - _{}^{w}\textrm{R}_b & _{}^{w}\textrm{t}_b \\ - 0_{1 \times 3} & 1 - \end{bmatrix} - \begin{bmatrix} - X_b\\ - Y_b\\ - Z_b\\ - 1 - \end{bmatrix} -\f] -\f[ - \begin{bmatrix} - X_c\\ - Y_c\\ - Z_c\\ - 1 - \end{bmatrix} - = - \begin{bmatrix} - _{}^{c}\textrm{R}_g & _{}^{c}\textrm{t}_g \\ - 0_{1 \times 3} & 1 - \end{bmatrix} - \begin{bmatrix} - X_g\\ - Y_g\\ - Z_g\\ - 1 - \end{bmatrix} -\f] - -This problem is also known as solving the \f$\mathbf{A}\mathbf{X}=\mathbf{Z}\mathbf{B}\f$ equation, with: - - \f$\mathbf{A} \Leftrightarrow \hspace{0.1em} _{}^{c}\textrm{T}_w\f$ - - \f$\mathbf{X} \Leftrightarrow \hspace{0.1em} _{}^{w}\textrm{T}_b\f$ - - \f$\mathbf{Z} \Leftrightarrow \hspace{0.1em} _{}^{c}\textrm{T}_g\f$ - - \f$\mathbf{B} \Leftrightarrow \hspace{0.1em} _{}^{g}\textrm{T}_b\f$ - -\note -At least 3 measurements are required (input vectors size must be greater or equal to 3). - - */ -CV_EXPORTS_W void calibrateRobotWorldHandEye( InputArrayOfArrays R_world2cam, InputArrayOfArrays t_world2cam, - InputArrayOfArrays R_base2gripper, InputArrayOfArrays t_base2gripper, - OutputArray R_base2world, OutputArray t_base2world, - OutputArray R_gripper2cam, OutputArray t_gripper2cam, - RobotWorldHandEyeCalibrationMethod method=CALIB_ROBOT_WORLD_HAND_EYE_SHAH ); - /** @brief Converts points from Euclidean to homogeneous space. @param src Input vector of N-dimensional points. @param dst Output vector of N+1-dimensional points. +@param dtype The desired output array depth (either CV_32F or CV_64F are currently supported). + If it's -1, then it's set automatically to CV_32F or CV_64F, depending on the input depth. The function converts points from Euclidean to homogeneous space by appending 1's to the tuple of point coordinates. That is, each point (x1, x2, ..., xn) is converted to (x1, x2, ..., xn, 1). */ -CV_EXPORTS_W void convertPointsToHomogeneous( InputArray src, OutputArray dst ); +CV_EXPORTS_W void convertPointsToHomogeneous( InputArray src, OutputArray dst, int dtype=-1 ); /** @brief Converts points from homogeneous to Euclidean space. @param src Input vector of N-dimensional points. @param dst Output vector of N-1-dimensional points. +@param dtype The desired output array depth (either CV_32F or CV_64F are currently supported). + If it's -1, then it's set automatically to CV_32F or CV_64F, depending on the input depth. The function converts points homogeneous to Euclidean space using perspective projection. That is, each point (x1, x2, ... x(n-1), xn) is converted to (x1/xn, x2/xn, ..., x(n-1)/xn). When xn=0, the output point coordinates will be (0,0,0,...). */ -CV_EXPORTS_W void convertPointsFromHomogeneous( InputArray src, OutputArray dst ); +CV_EXPORTS_W void convertPointsFromHomogeneous( InputArray src, OutputArray dst, int dtype=-1 ); /** @brief Converts points to/from homogeneous coordinates. @@ -2929,7 +1677,8 @@ This function differs from the one above that it outputs the triangulated 3D poi the cheirality check. */ CV_EXPORTS_W int recoverPose( InputArray E, InputArray points1, InputArray points2, - InputArray cameraMatrix, OutputArray R, OutputArray t, double distanceThresh, InputOutputArray mask = noArray(), + InputArray cameraMatrix, OutputArray R, OutputArray t, + double distanceThresh, InputOutputArray mask = noArray(), OutputArray triangulatedPoints = noArray()); /** @brief For points in an image of a stereo pair, computes the corresponding epilines in the other image. @@ -3004,75 +1753,6 @@ geometric distance between points \f$a\f$ and \f$b\f$ ) subject to the epipolar CV_EXPORTS_W void correctMatches( InputArray F, InputArray points1, InputArray points2, OutputArray newPoints1, OutputArray newPoints2 ); -/** @brief Filters off small noise blobs (speckles) in the disparity map - -@param img The input 16-bit signed disparity image -@param newVal The disparity value used to paint-off the speckles -@param maxSpeckleSize The maximum speckle size to consider it a speckle. Larger blobs are not -affected by the algorithm -@param maxDiff Maximum difference between neighbor disparity pixels to put them into the same -blob. Note that since StereoBM, StereoSGBM and may be other algorithms return a fixed-point -disparity map, where disparity values are multiplied by 16, this scale factor should be taken into -account when specifying this parameter value. -@param buf The optional temporary buffer to avoid memory allocation within the function. - */ -CV_EXPORTS_W void filterSpeckles( InputOutputArray img, double newVal, - int maxSpeckleSize, double maxDiff, - InputOutputArray buf = noArray() ); - -//! computes valid disparity ROI from the valid ROIs of the rectified images (that are returned by cv::stereoRectify()) -CV_EXPORTS_W Rect getValidDisparityROI( Rect roi1, Rect roi2, - int minDisparity, int numberOfDisparities, - int blockSize ); - -//! validates disparity using the left-right check. The matrix "cost" should be computed by the stereo correspondence algorithm -CV_EXPORTS_W void validateDisparity( InputOutputArray disparity, InputArray cost, - int minDisparity, int numberOfDisparities, - int disp12MaxDisp = 1 ); - -/** @brief Reprojects a disparity image to 3D space. - -@param disparity Input single-channel 8-bit unsigned, 16-bit signed, 32-bit signed or 32-bit -floating-point disparity image. The values of 8-bit / 16-bit signed formats are assumed to have no -fractional bits. If the disparity is 16-bit signed format, as computed by @ref StereoBM or -@ref StereoSGBM and maybe other algorithms, it should be divided by 16 (and scaled to float) before -being used here. -@param _3dImage Output 3-channel floating-point image of the same size as disparity. Each element of -_3dImage(x,y) contains 3D coordinates of the point (x,y) computed from the disparity map. If one -uses Q obtained by @ref stereoRectify, then the returned points are represented in the first -camera's rectified coordinate system. -@param Q \f$4 \times 4\f$ perspective transformation matrix that can be obtained with -@ref stereoRectify. -@param handleMissingValues Indicates, whether the function should handle missing values (i.e. -points where the disparity was not computed). If handleMissingValues=true, then pixels with the -minimal disparity that corresponds to the outliers (see StereoMatcher::compute ) are transformed -to 3D points with a very large Z value (currently set to 10000). -@param ddepth The optional output array depth. If it is -1, the output image will have CV_32F -depth. ddepth can also be set to CV_16S, CV_32S or CV_32F. - -The function transforms a single-channel disparity map to a 3-channel image representing a 3D -surface. That is, for each pixel (x,y) and the corresponding disparity d=disparity(x,y) , it -computes: - -\f[\begin{bmatrix} -X \\ -Y \\ -Z \\ -W -\end{bmatrix} = Q \begin{bmatrix} -x \\ -y \\ -\texttt{disparity} (x,y) \\ -z -\end{bmatrix}.\f] - -@sa - To reproject a sparse set of points {(x,y,d),...} to 3D space, use perspectiveTransform. - */ -CV_EXPORTS_W void reprojectImageTo3D( InputArray disparity, - OutputArray _3dImage, InputArray Q, - bool handleMissingValues = false, - int ddepth = -1 ); /** @brief Calculates the Sampson Distance between two points. @@ -3370,185 +2050,6 @@ CV_EXPORTS_W void filterHomographyDecompByVisibleRefpoints(InputArrayOfArrays ro OutputArray possibleSolutions, InputArray pointsMask = noArray()); -/** @brief The base class for stereo correspondence algorithms. - */ -class CV_EXPORTS_W StereoMatcher : public Algorithm -{ -public: - enum { DISP_SHIFT = 4, - DISP_SCALE = (1 << DISP_SHIFT) - }; - - /** @brief Computes disparity map for the specified stereo pair - - @param left Left 8-bit single-channel image. - @param right Right image of the same size and the same type as the left one. - @param disparity Output disparity map. It has the same size as the input images. Some algorithms, - like StereoBM or StereoSGBM compute 16-bit fixed-point disparity map (where each disparity value - has 4 fractional bits), whereas other algorithms output 32-bit floating-point disparity map. - */ - CV_WRAP virtual void compute( InputArray left, InputArray right, - OutputArray disparity ) = 0; - - CV_WRAP virtual int getMinDisparity() const = 0; - CV_WRAP virtual void setMinDisparity(int minDisparity) = 0; - - CV_WRAP virtual int getNumDisparities() const = 0; - CV_WRAP virtual void setNumDisparities(int numDisparities) = 0; - - CV_WRAP virtual int getBlockSize() const = 0; - CV_WRAP virtual void setBlockSize(int blockSize) = 0; - - CV_WRAP virtual int getSpeckleWindowSize() const = 0; - CV_WRAP virtual void setSpeckleWindowSize(int speckleWindowSize) = 0; - - CV_WRAP virtual int getSpeckleRange() const = 0; - CV_WRAP virtual void setSpeckleRange(int speckleRange) = 0; - - CV_WRAP virtual int getDisp12MaxDiff() const = 0; - CV_WRAP virtual void setDisp12MaxDiff(int disp12MaxDiff) = 0; -}; - - -/** @brief Class for computing stereo correspondence using the block matching algorithm, introduced and -contributed to OpenCV by K. Konolige. - */ -class CV_EXPORTS_W StereoBM : public StereoMatcher -{ -public: - enum { PREFILTER_NORMALIZED_RESPONSE = 0, - PREFILTER_XSOBEL = 1 - }; - - CV_WRAP virtual int getPreFilterType() const = 0; - CV_WRAP virtual void setPreFilterType(int preFilterType) = 0; - - CV_WRAP virtual int getPreFilterSize() const = 0; - CV_WRAP virtual void setPreFilterSize(int preFilterSize) = 0; - - CV_WRAP virtual int getPreFilterCap() const = 0; - CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; - - CV_WRAP virtual int getTextureThreshold() const = 0; - CV_WRAP virtual void setTextureThreshold(int textureThreshold) = 0; - - CV_WRAP virtual int getUniquenessRatio() const = 0; - CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; - - CV_WRAP virtual int getSmallerBlockSize() const = 0; - CV_WRAP virtual void setSmallerBlockSize(int blockSize) = 0; - - CV_WRAP virtual Rect getROI1() const = 0; - CV_WRAP virtual void setROI1(Rect roi1) = 0; - - CV_WRAP virtual Rect getROI2() const = 0; - CV_WRAP virtual void setROI2(Rect roi2) = 0; - - /** @brief Creates StereoBM object - - @param numDisparities the disparity search range. For each pixel algorithm will find the best - disparity from 0 (default minimum disparity) to numDisparities. The search range can then be - shifted by changing the minimum disparity. - @param blockSize the linear size of the blocks compared by the algorithm. The size should be odd - (as the block is centered at the current pixel). Larger block size implies smoother, though less - accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher - chance for algorithm to find a wrong correspondence. - - The function create StereoBM object. You can then call StereoBM::compute() to compute disparity for - a specific stereo pair. - */ - CV_WRAP static Ptr create(int numDisparities = 0, int blockSize = 21); -}; - -/** @brief The class implements the modified H. Hirschmuller algorithm @cite HH08 that differs from the original -one as follows: - -- By default, the algorithm is single-pass, which means that you consider only 5 directions -instead of 8. Set mode=StereoSGBM::MODE_HH in createStereoSGBM to run the full variant of the -algorithm but beware that it may consume a lot of memory. -- The algorithm matches blocks, not individual pixels. Though, setting blockSize=1 reduces the -blocks to single pixels. -- Mutual information cost function is not implemented. Instead, a simpler Birchfield-Tomasi -sub-pixel metric from @cite BT98 is used. Though, the color images are supported as well. -- Some pre- and post- processing steps from K. Konolige algorithm StereoBM are included, for -example: pre-filtering (StereoBM::PREFILTER_XSOBEL type) and post-filtering (uniqueness -check, quadratic interpolation and speckle filtering). - -@note - - (Python) An example illustrating the use of the StereoSGBM matching algorithm can be found - at opencv_source_code/samples/python/stereo_match.py - */ -class CV_EXPORTS_W StereoSGBM : public StereoMatcher -{ -public: - enum - { - MODE_SGBM = 0, - MODE_HH = 1, - MODE_SGBM_3WAY = 2, - MODE_HH4 = 3 - }; - - CV_WRAP virtual int getPreFilterCap() const = 0; - CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; - - CV_WRAP virtual int getUniquenessRatio() const = 0; - CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; - - CV_WRAP virtual int getP1() const = 0; - CV_WRAP virtual void setP1(int P1) = 0; - - CV_WRAP virtual int getP2() const = 0; - CV_WRAP virtual void setP2(int P2) = 0; - - CV_WRAP virtual int getMode() const = 0; - CV_WRAP virtual void setMode(int mode) = 0; - - /** @brief Creates StereoSGBM object - - @param minDisparity Minimum possible disparity value. Normally, it is zero but sometimes - rectification algorithms can shift images, so this parameter needs to be adjusted accordingly. - @param numDisparities Maximum disparity minus minimum disparity. The value is always greater than - zero. In the current implementation, this parameter must be divisible by 16. - @param blockSize Matched block size. It must be an odd number \>=1 . Normally, it should be - somewhere in the 3..11 range. - @param P1 The first parameter controlling the disparity smoothness. See below. - @param P2 The second parameter controlling the disparity smoothness. The larger the values are, - the smoother the disparity is. P1 is the penalty on the disparity change by plus or minus 1 - between neighbor pixels. P2 is the penalty on the disparity change by more than 1 between neighbor - pixels. The algorithm requires P2 \> P1 . See stereo_match.cpp sample where some reasonably good - P1 and P2 values are shown (like 8\*number_of_image_channels\*blockSize\*blockSize and - 32\*number_of_image_channels\*blockSize\*blockSize , respectively). - @param disp12MaxDiff Maximum allowed difference (in integer pixel units) in the left-right - disparity check. Set it to a non-positive value to disable the check. - @param preFilterCap Truncation value for the prefiltered image pixels. The algorithm first - computes x-derivative at each pixel and clips its value by [-preFilterCap, preFilterCap] interval. - The result values are passed to the Birchfield-Tomasi pixel cost function. - @param uniquenessRatio Margin in percentage by which the best (minimum) computed cost function - value should "win" the second best value to consider the found match correct. Normally, a value - within the 5-15 range is good enough. - @param speckleWindowSize Maximum size of smooth disparity regions to consider their noise speckles - and invalidate. Set it to 0 to disable speckle filtering. Otherwise, set it somewhere in the - 50-200 range. - @param speckleRange Maximum disparity variation within each connected component. If you do speckle - filtering, set the parameter to a positive value, it will be implicitly multiplied by 16. - Normally, 1 or 2 is good enough. - @param mode Set it to StereoSGBM::MODE_HH to run the full-scale two-pass dynamic programming - algorithm. It will consume O(W\*H\*numDisparities) bytes, which is large for 640x480 stereo and - huge for HD-size pictures. By default, it is set to false . - - The first constructor initializes StereoSGBM with all the default parameters. So, you only have to - set StereoSGBM::numDisparities at minimum. The second constructor enables you to set each parameter - to a custom value. - */ - CV_WRAP static Ptr create(int minDisparity = 0, int numDisparities = 16, int blockSize = 3, - int P1 = 0, int P2 = 0, int disp12MaxDiff = 0, - int preFilterCap = 0, int uniquenessRatio = 0, - int speckleWindowSize = 0, int speckleRange = 0, - int mode = StereoSGBM::MODE_SGBM); -}; - - //! cv::undistort mode enum UndistortTypes { @@ -3699,6 +2200,61 @@ CV_EXPORTS_W Mat getDefaultNewCameraMatrix(InputArray cameraMatrix, Size imgsize = Size(), bool centerPrincipalPoint = false); +/** @brief Returns the inscribed and bounding rectangles for the "undisorted" image plane. + +The functions emulates undistortion of the image plane using the specified camera matrix, +distortion coefficients, the optional 3D rotation and the "new" camera matrix. In the case of +noticeable radial (or maybe pinclusion) distortion the rectangular image plane is distorted and +turns into some convex or concave shape. The function computes approximate inscribed (inner) and +bounding (outer) rectangles after such undistortion. The rectangles can be used to adjust +the newCameraMatrix so that the result image, for example, fits all the data from the original image +(at the expense of possibly big "black" areas) or, for another example, gets rid of black areas at the expense +some lost data near the original image edge. The function #getOptimalNewCameraMatrix uses this function +to compute the optimal new camera matrix. + +@param cameraMatrix the original camera matrix. +@param distCoeffs distortion coefficients. +@param R the optional 3D rotation, applied before projection (see stereoRectify etc.) +@param newCameraMatrix the new camera matrix after undistortion. Usually it matches the original cameraMatrix. +@param imgSize the size of the image plane. +@param inner the output maximal inscribed rectangle of the undistorted image plane. +@param outer the output minimal bounding rectangle of the undistorted image plane. + */ +CV_EXPORTS void getUndistortRectangles(InputArray cameraMatrix, InputArray distCoeffs, + InputArray R, InputArray newCameraMatrix, Size imgSize, + Rect_& inner, Rect_& outer ); + +/** @brief Returns the new camera intrinsic matrix based on the free scaling parameter. + +@param cameraMatrix Input camera intrinsic matrix. +@param distCoeffs Input vector of distortion coefficients +\f$\distcoeffs\f$. If the vector is NULL/empty, the zero distortion coefficients are +assumed. +@param imageSize Original image size. +@param alpha Free scaling parameter between 0 (when all the pixels in the undistorted image are +valid) and 1 (when all the source image pixels are retained in the undistorted image). See +stereoRectify for details. +@param newImgSize Image size after rectification. By default, it is set to imageSize . +@param validPixROI Optional output rectangle that outlines all-good-pixels region in the +undistorted image. See roi1, roi2 description in stereoRectify . +@param centerPrincipalPoint Optional flag that indicates whether in the new camera intrinsic matrix the +principal point should be at the image center or not. By default, the principal point is chosen to +best fit a subset of the source image (determined by alpha) to the corrected image. +@return new_camera_matrix Output new camera intrinsic matrix. + +The function computes and returns the optimal new camera intrinsic matrix based on the free scaling parameter. +By varying this parameter, you may retrieve only sensible pixels alpha=0 , keep all the original +image pixels if there is valuable information in the corners alpha=1 , or get something in between. +When alpha\>0 , the undistorted result is likely to have some black pixels corresponding to +"virtual" pixels outside of the captured distorted image. The original camera intrinsic matrix, distortion +coefficients, the computed new camera intrinsic matrix, and newImageSize should be passed to +initUndistortRectifyMap to produce the maps for remap . + */ +CV_EXPORTS_W Mat getOptimalNewCameraMatrix( InputArray cameraMatrix, InputArray distCoeffs, + Size imageSize, double alpha, Size newImgSize = Size(), + CV_OUT Rect* validPixROI = 0, + bool centerPrincipalPoint = false); + /** @brief Computes the ideal point coordinates from the observed point coordinates. The function is similar to #undistort and #initUndistortRectifyMap but it operates on a @@ -3738,288 +2294,28 @@ of 4, 5, 8, 12 or 14 elements. If the vector is NULL/empty, the zero distortion #stereoRectify can be passed here. If the matrix is empty, the identity transformation is used. @param P New camera matrix (3x3) or new projection matrix (3x4) \f$\begin{bmatrix} {f'}_x & 0 & {c'}_x & t_x \\ 0 & {f'}_y & {c'}_y & t_y \\ 0 & 0 & 1 & t_z \end{bmatrix}\f$. P1 or P2 computed by #stereoRectify can be passed here. If the matrix is empty, the identity new camera matrix is used. +@param criteria termination criteria for the iterative point undistortion algorithm */ CV_EXPORTS_W void undistortPoints(InputArray src, OutputArray dst, InputArray cameraMatrix, InputArray distCoeffs, - InputArray R = noArray(), InputArray P = noArray()); -/** @overload - @note Default version of #undistortPoints does 5 iterations to compute undistorted points. - */ -CV_EXPORTS_AS(undistortPointsIter) -void undistortPoints(InputArray src, OutputArray dst, - InputArray cameraMatrix, InputArray distCoeffs, - InputArray R, InputArray P, TermCriteria criteria); + InputArray R = noArray(), InputArray P = noArray(), + TermCriteria criteria=TermCriteria(TermCriteria::MAX_ITER, 5, 0.01)); -//! @} calib3d - -/** @brief The methods in this namespace use a so-called fisheye camera model. - @ingroup calib3d_fisheye -*/ -namespace fisheye -{ -//! @addtogroup calib3d_fisheye -//! @{ - - enum{ - CALIB_USE_INTRINSIC_GUESS = 1 << 0, - CALIB_RECOMPUTE_EXTRINSIC = 1 << 1, - CALIB_CHECK_COND = 1 << 2, - CALIB_FIX_SKEW = 1 << 3, - CALIB_FIX_K1 = 1 << 4, - CALIB_FIX_K2 = 1 << 5, - CALIB_FIX_K3 = 1 << 6, - CALIB_FIX_K4 = 1 << 7, - CALIB_FIX_INTRINSIC = 1 << 8, - CALIB_FIX_PRINCIPAL_POINT = 1 << 9 - }; - - /** @brief Projects points using fisheye model - - @param objectPoints Array of object points, 1xN/Nx1 3-channel (or vector\ ), where N is - the number of points in the view. - @param imagePoints Output array of image points, 2xN/Nx2 1-channel or 1xN/Nx1 2-channel, or - vector\. - @param affine - @param K Camera intrinsic matrix \f$cameramatrix{K}\f$. - @param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. - @param alpha The skew coefficient. - @param jacobian Optional output 2Nx15 jacobian matrix of derivatives of image points with respect - to components of the focal lengths, coordinates of the principal point, distortion coefficients, - rotation vector, translation vector, and the skew. In the old interface different components of - the jacobian are returned via different output parameters. - - The function computes projections of 3D points to the image plane given intrinsic and extrinsic - camera parameters. Optionally, the function computes Jacobians - matrices of partial derivatives of - image points coordinates (as functions of all the input parameters) with respect to the particular - parameters, intrinsic and/or extrinsic. - */ - CV_EXPORTS void projectPoints(InputArray objectPoints, OutputArray imagePoints, const Affine3d& affine, - InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray()); - - /** @overload */ - CV_EXPORTS_W void projectPoints(InputArray objectPoints, OutputArray imagePoints, InputArray rvec, InputArray tvec, - InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray()); - - /** @brief Distorts 2D points using fisheye model. - - @param undistorted Array of object points, 1xN/Nx1 2-channel (or vector\ ), where N is - the number of points in the view. - @param K Camera intrinsic matrix \f$cameramatrix{K}\f$. - @param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. - @param alpha The skew coefficient. - @param distorted Output array of image points, 1xN/Nx1 2-channel, or vector\ . - - Note that the function assumes the camera intrinsic matrix of the undistorted points to be identity. - This means if you want to transform back points undistorted with undistortPoints() you have to - multiply them with \f$P^{-1}\f$. - */ - CV_EXPORTS_W void distortPoints(InputArray undistorted, OutputArray distorted, InputArray K, InputArray D, double alpha = 0); - - /** @brief Undistorts 2D points using fisheye model - - @param distorted Array of object points, 1xN/Nx1 2-channel (or vector\ ), where N is the - number of points in the view. - @param K Camera intrinsic matrix \f$cameramatrix{K}\f$. - @param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. - @param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 - 1-channel or 1x1 3-channel - @param P New camera intrinsic matrix (3x3) or new projection matrix (3x4) - @param undistorted Output array of image points, 1xN/Nx1 2-channel, or vector\ . - */ - CV_EXPORTS_W void undistortPoints(InputArray distorted, OutputArray undistorted, - InputArray K, InputArray D, InputArray R = noArray(), InputArray P = noArray()); - - /** @brief Computes undistortion and rectification maps for image transform by cv::remap(). If D is empty zero - distortion is used, if R or P is empty identity matrixes are used. - - @param K Camera intrinsic matrix \f$cameramatrix{K}\f$. - @param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. - @param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 - 1-channel or 1x1 3-channel - @param P New camera intrinsic matrix (3x3) or new projection matrix (3x4) - @param size Undistorted image size. - @param m1type Type of the first output map that can be CV_32FC1 or CV_16SC2 . See convertMaps() - for details. - @param map1 The first output map. - @param map2 The second output map. - */ - CV_EXPORTS_W void initUndistortRectifyMap(InputArray K, InputArray D, InputArray R, InputArray P, - const cv::Size& size, int m1type, OutputArray map1, OutputArray map2); - - /** @brief Transforms an image to compensate for fisheye lens distortion. - - @param distorted image with fisheye lens distortion. - @param undistorted Output image with compensated fisheye lens distortion. - @param K Camera intrinsic matrix \f$cameramatrix{K}\f$. - @param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. - @param Knew Camera intrinsic matrix of the distorted image. By default, it is the identity matrix but you - may additionally scale and shift the result by using a different matrix. - @param new_size the new size - - The function transforms an image to compensate radial and tangential lens distortion. - - The function is simply a combination of fisheye::initUndistortRectifyMap (with unity R ) and remap - (with bilinear interpolation). See the former function for details of the transformation being - performed. - - See below the results of undistortImage. - - a\) result of undistort of perspective camera model (all possible coefficients (k_1, k_2, k_3, - k_4, k_5, k_6) of distortion were optimized under calibration) - - b\) result of fisheye::undistortImage of fisheye camera model (all possible coefficients (k_1, k_2, - k_3, k_4) of fisheye distortion were optimized under calibration) - - c\) original image was captured with fisheye lens - - Pictures a) and b) almost the same. But if we consider points of image located far from the center - of image, we can notice that on image a) these points are distorted. - - ![image](pics/fisheye_undistorted.jpg) - */ - CV_EXPORTS_W void undistortImage(InputArray distorted, OutputArray undistorted, - InputArray K, InputArray D, InputArray Knew = cv::noArray(), const Size& new_size = Size()); - - /** @brief Estimates new camera intrinsic matrix for undistortion or rectification. - - @param K Camera intrinsic matrix \f$cameramatrix{K}\f$. - @param image_size Size of the image - @param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. - @param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 - 1-channel or 1x1 3-channel - @param P New camera intrinsic matrix (3x3) or new projection matrix (3x4) - @param balance Sets the new focal length in range between the min focal length and the max focal - length. Balance is in range of [0, 1]. - @param new_size the new size - @param fov_scale Divisor for new focal length. - */ - CV_EXPORTS_W void estimateNewCameraMatrixForUndistortRectify(InputArray K, InputArray D, const Size &image_size, InputArray R, - OutputArray P, double balance = 0.0, const Size& new_size = Size(), double fov_scale = 1.0); - - /** @brief Performs camera calibaration - - @param objectPoints vector of vectors of calibration pattern points in the calibration pattern - coordinate space. - @param imagePoints vector of vectors of the projections of calibration pattern points. - imagePoints.size() and objectPoints.size() and imagePoints[i].size() must be equal to - objectPoints[i].size() for each i. - @param image_size Size of the image used only to initialize the camera intrinsic matrix. - @param K Output 3x3 floating-point camera intrinsic matrix - \f$\cameramatrix{A}\f$ . If - fisheye::CALIB_USE_INTRINSIC_GUESS/ is specified, some or all of fx, fy, cx, cy must be - initialized before calling the function. - @param D Output vector of distortion coefficients \f$\distcoeffsfisheye\f$. - @param rvecs Output vector of rotation vectors (see Rodrigues ) estimated for each pattern view. - That is, each k-th rotation vector together with the corresponding k-th translation vector (see - the next output parameter description) brings the calibration pattern from the model coordinate - space (in which object points are specified) to the world coordinate space, that is, a real - position of the calibration pattern in the k-th pattern view (k=0.. *M* -1). - @param tvecs Output vector of translation vectors estimated for each pattern view. - @param flags Different flags that may be zero or a combination of the following values: - - **fisheye::CALIB_USE_INTRINSIC_GUESS** cameraMatrix contains valid initial values of - fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image - center ( imageSize is used), and focal distances are computed in a least-squares fashion. - - **fisheye::CALIB_RECOMPUTE_EXTRINSIC** Extrinsic will be recomputed after each iteration - of intrinsic optimization. - - **fisheye::CALIB_CHECK_COND** The functions will check validity of condition number. - - **fisheye::CALIB_FIX_SKEW** Skew coefficient (alpha) is set to zero and stay zero. - - **fisheye::CALIB_FIX_K1..fisheye::CALIB_FIX_K4** Selected distortion coefficients - are set to zeros and stay zero. - - **fisheye::CALIB_FIX_PRINCIPAL_POINT** The principal point is not changed during the global -optimization. It stays at the center or at a different location specified when CALIB_USE_INTRINSIC_GUESS is set too. - @param criteria Termination criteria for the iterative optimization algorithm. - */ - CV_EXPORTS_W double calibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, const Size& image_size, - InputOutputArray K, InputOutputArray D, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags = 0, - TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); - - /** @brief Stereo rectification for fisheye camera model - - @param K1 First camera intrinsic matrix. - @param D1 First camera distortion parameters. - @param K2 Second camera intrinsic matrix. - @param D2 Second camera distortion parameters. - @param imageSize Size of the image used for stereo calibration. - @param R Rotation matrix between the coordinate systems of the first and the second - cameras. - @param tvec Translation vector between coordinate systems of the cameras. - @param R1 Output 3x3 rectification transform (rotation matrix) for the first camera. - @param R2 Output 3x3 rectification transform (rotation matrix) for the second camera. - @param P1 Output 3x4 projection matrix in the new (rectified) coordinate systems for the first - camera. - @param P2 Output 3x4 projection matrix in the new (rectified) coordinate systems for the second - camera. - @param Q Output \f$4 \times 4\f$ disparity-to-depth mapping matrix (see reprojectImageTo3D ). - @param flags Operation flags that may be zero or CALIB_ZERO_DISPARITY . If the flag is set, - the function makes the principal points of each camera have the same pixel coordinates in the - rectified views. And if the flag is not set, the function may still shift the images in the - horizontal or vertical direction (depending on the orientation of epipolar lines) to maximize the - useful image area. - @param newImageSize New image resolution after rectification. The same size should be passed to - initUndistortRectifyMap (see the stereo_calib.cpp sample in OpenCV samples directory). When (0,0) - is passed (default), it is set to the original imageSize . Setting it to larger value can help you - preserve details in the original image, especially when there is a big radial distortion. - @param balance Sets the new focal length in range between the min focal length and the max focal - length. Balance is in range of [0, 1]. - @param fov_scale Divisor for new focal length. - */ - CV_EXPORTS_W void stereoRectify(InputArray K1, InputArray D1, InputArray K2, InputArray D2, const Size &imageSize, InputArray R, InputArray tvec, - OutputArray R1, OutputArray R2, OutputArray P1, OutputArray P2, OutputArray Q, int flags, const Size &newImageSize = Size(), - double balance = 0.0, double fov_scale = 1.0); - - /** @brief Performs stereo calibration - - @param objectPoints Vector of vectors of the calibration pattern points. - @param imagePoints1 Vector of vectors of the projections of the calibration pattern points, - observed by the first camera. - @param imagePoints2 Vector of vectors of the projections of the calibration pattern points, - observed by the second camera. - @param K1 Input/output first camera intrinsic matrix: - \f$\vecthreethree{f_x^{(j)}}{0}{c_x^{(j)}}{0}{f_y^{(j)}}{c_y^{(j)}}{0}{0}{1}\f$ , \f$j = 0,\, 1\f$ . If - any of fisheye::CALIB_USE_INTRINSIC_GUESS , fisheye::CALIB_FIX_INTRINSIC are specified, - some or all of the matrix components must be initialized. - @param D1 Input/output vector of distortion coefficients \f$\distcoeffsfisheye\f$ of 4 elements. - @param K2 Input/output second camera intrinsic matrix. The parameter is similar to K1 . - @param D2 Input/output lens distortion coefficients for the second camera. The parameter is - similar to D1 . - @param imageSize Size of the image used only to initialize camera intrinsic matrix. - @param R Output rotation matrix between the 1st and the 2nd camera coordinate systems. - @param T Output translation vector between the coordinate systems of the cameras. - @param flags Different flags that may be zero or a combination of the following values: - - **fisheye::CALIB_FIX_INTRINSIC** Fix K1, K2? and D1, D2? so that only R, T matrices - are estimated. - - **fisheye::CALIB_USE_INTRINSIC_GUESS** K1, K2 contains valid initial values of - fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image - center (imageSize is used), and focal distances are computed in a least-squares fashion. - - **fisheye::CALIB_RECOMPUTE_EXTRINSIC** Extrinsic will be recomputed after each iteration - of intrinsic optimization. - - **fisheye::CALIB_CHECK_COND** The functions will check validity of condition number. - - **fisheye::CALIB_FIX_SKEW** Skew coefficient (alpha) is set to zero and stay zero. - - **fisheye::CALIB_FIX_K1..4** Selected distortion coefficients are set to zeros and stay - zero. - @param criteria Termination criteria for the iterative optimization algorithm. - */ - CV_EXPORTS_W double stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, - InputOutputArray K1, InputOutputArray D1, InputOutputArray K2, InputOutputArray D2, Size imageSize, - OutputArray R, OutputArray T, int flags = fisheye::CALIB_FIX_INTRINSIC, - TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); - -//! @} calib3d_fisheye -} // end namespace fisheye - -} //end namespace cv - -#if 0 //def __cplusplus ////////////////////////////////////////////////////////////////////////////////////////// + +// the old-style Levenberg-Marquardt solver; to be removed soon class CV_EXPORTS CvLevMarq { public: CvLevMarq(); CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria= - cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), - bool completeSymmFlag=false ); + cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), + bool completeSymmFlag=false ); ~CvLevMarq(); void init( int nparams, int nerrs, CvTermCriteria criteria= - cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), - bool completeSymmFlag=false ); + cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), + bool completeSymmFlag=false ); bool update( const CvMat*& param, CvMat*& J, CvMat*& err ); bool updateAlt( const CvMat*& param, CvMat*& JtJ, CvMat*& JtErr, double*& errNorm ); @@ -4045,6 +2341,8 @@ public: bool completeSymmFlag; int solveMethod; }; -#endif + +//! @} _3d +} //end namespace cv #endif diff --git a/modules/calib3d/misc/java/gen_dict.json b/modules/3d/misc/java/gen_dict.json similarity index 67% rename from modules/calib3d/misc/java/gen_dict.json rename to modules/3d/misc/java/gen_dict.json index 160aaab103..29748f7d28 100644 --- a/modules/calib3d/misc/java/gen_dict.json +++ b/modules/3d/misc/java/gen_dict.json @@ -1,14 +1,7 @@ { - "class_ignore_list": [ - "CirclesGridFinderParameters" - ], - "namespaces_dict": { - "cv.fisheye": "fisheye" - }, "func_arg_fix" : { "findFundamentalMat" : { "points1" : {"ctype" : "vector_Point2f"}, "points2" : {"ctype" : "vector_Point2f"} }, - "cornerSubPix" : { "corners" : {"ctype" : "vector_Point2f"} }, "findHomography" : { "srcPoints" : {"ctype" : "vector_Point2f"}, "dstPoints" : {"ctype" : "vector_Point2f"} }, "solvePnP" : { "objectPoints" : {"ctype" : "vector_Point3f"}, @@ -21,10 +14,6 @@ "dst" : {"ctype" : "vector_Point2f"} }, "projectPoints" : { "objectPoints" : {"ctype" : "vector_Point3f"}, "imagePoints" : {"ctype" : "vector_Point2f"}, - "distCoeffs" : {"ctype" : "vector_double" } }, - "initCameraMatrix2D" : { "objectPoints" : {"ctype" : "vector_vector_Point3f"}, - "imagePoints" : {"ctype" : "vector_vector_Point2f"} }, - "findChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} }, - "drawChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} } + "distCoeffs" : {"ctype" : "vector_double" } } } } diff --git a/modules/calib3d/misc/java/test/Calib3dTest.java b/modules/3d/misc/java/test/Cv3dTest.java similarity index 57% rename from modules/calib3d/misc/java/test/Calib3dTest.java rename to modules/3d/misc/java/test/Cv3dTest.java index 28c3479f3f..00fadfebc0 100644 --- a/modules/calib3d/misc/java/test/Calib3dTest.java +++ b/modules/3d/misc/java/test/Cv3dTest.java @@ -1,8 +1,8 @@ -package org.opencv.test.calib3d; +package org.opencv.test.cv3d; import java.util.ArrayList; -import org.opencv.calib3d.Calib3d; +import org.opencv.cv3d.Cv3d; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; @@ -15,7 +15,7 @@ import org.opencv.core.Size; import org.opencv.test.OpenCVTestCase; import org.opencv.imgproc.Imgproc; -public class Calib3dTest extends OpenCVTestCase { +public class Cv3dTest extends OpenCVTestCase { Size size; @@ -26,18 +26,6 @@ public class Calib3dTest extends OpenCVTestCase { size = new Size(3, 3); } - public void testCalibrateCameraListOfMatListOfMatSizeMatMatListOfMatListOfMat() { - fail("Not yet implemented"); - } - - public void testCalibrateCameraListOfMatListOfMatSizeMatMatListOfMatListOfMatInt() { - fail("Not yet implemented"); - } - - public void testCalibrationMatrixValues() { - fail("Not yet implemented"); - } - public void testComposeRTMatMatMatMatMatMat() { Mat rvec1 = new Mat(3, 1, CvType.CV_32F); rvec1.put(0, 0, 0.5302828, 0.19925919, 0.40105945); @@ -56,7 +44,7 @@ public class Calib3dTest extends OpenCVTestCase { Mat outTvec = new Mat(3, 1, CvType.CV_32F); outTvec.put(0, 0, 1.4560841, 1.0680628, 0.81598103); - Calib3d.composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3); + Cv3d.composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3); assertMatEqual(outRvec, rvec3, EPS); assertMatEqual(outTvec, tvec3, EPS); @@ -155,10 +143,6 @@ public class Calib3dTest extends OpenCVTestCase { fail("Not yet implemented"); } - public void testDrawChessboardCorners() { - fail("Not yet implemented"); - } - public void testEstimateAffine3DMatMatMatMat() { fail("Not yet implemented"); } @@ -171,113 +155,6 @@ public class Calib3dTest extends OpenCVTestCase { fail("Not yet implemented"); } - public void testFilterSpecklesMatDoubleIntDouble() { - gray_16s_1024.copyTo(dst); - Point center = new Point(gray_16s_1024.rows() / 2., gray_16s_1024.cols() / 2.); - Imgproc.circle(dst, center, 1, Scalar.all(4096)); - - assertMatNotEqual(gray_16s_1024, dst); - Calib3d.filterSpeckles(dst, 1024.0, 100, 0.); - assertMatEqual(gray_16s_1024, dst); - } - - public void testFilterSpecklesMatDoubleIntDoubleMat() { - fail("Not yet implemented"); - } - - public void testFindChessboardCornersMatSizeMat() { - Size patternSize = new Size(9, 6); - MatOfPoint2f corners = new MatOfPoint2f(); - Calib3d.findChessboardCorners(grayChess, patternSize, corners); - assertFalse(corners.empty()); - } - - public void testFindChessboardCornersMatSizeMatInt() { - Size patternSize = new Size(9, 6); - MatOfPoint2f corners = new MatOfPoint2f(); - Calib3d.findChessboardCorners(grayChess, patternSize, corners, Calib3d.CALIB_CB_ADAPTIVE_THRESH + Calib3d.CALIB_CB_NORMALIZE_IMAGE - + Calib3d.CALIB_CB_FAST_CHECK); - assertFalse(corners.empty()); - } - - public void testFind4QuadCornerSubpix() { - Size patternSize = new Size(9, 6); - MatOfPoint2f corners = new MatOfPoint2f(); - Size region_size = new Size(5, 5); - Calib3d.findChessboardCorners(grayChess, patternSize, corners); - Calib3d.find4QuadCornerSubpix(grayChess, corners, region_size); - assertFalse(corners.empty()); - } - - public void testFindCirclesGridMatSizeMat() { - int size = 300; - Mat img = new Mat(size, size, CvType.CV_8U); - img.setTo(new Scalar(255)); - Mat centers = new Mat(); - - assertFalse(Calib3d.findCirclesGrid(img, new Size(5, 5), centers)); - - for (int i = 0; i < 5; i++) - for (int j = 0; j < 5; j++) { - Point pt = new Point(size * (2 * i + 1) / 10, size * (2 * j + 1) / 10); - Imgproc.circle(img, pt, 10, new Scalar(0), -1); - } - - assertTrue(Calib3d.findCirclesGrid(img, new Size(5, 5), centers)); - - assertEquals(25, centers.rows()); - assertEquals(1, centers.cols()); - assertEquals(CvType.CV_32FC2, centers.type()); - } - - public void testFindCirclesGridMatSizeMatInt() { - int size = 300; - Mat img = new Mat(size, size, CvType.CV_8U); - img.setTo(new Scalar(255)); - Mat centers = new Mat(); - - assertFalse(Calib3d.findCirclesGrid(img, new Size(3, 5), centers, Calib3d.CALIB_CB_CLUSTERING - | Calib3d.CALIB_CB_ASYMMETRIC_GRID)); - - int step = size * 2 / 15; - int offsetx = size / 6; - int offsety = (size - 4 * step) / 2; - for (int i = 0; i < 3; i++) - for (int j = 0; j < 5; j++) { - Point pt = new Point(offsetx + (2 * i + j % 2) * step, offsety + step * j); - Imgproc.circle(img, pt, 10, new Scalar(0), -1); - } - - assertTrue(Calib3d.findCirclesGrid(img, new Size(3, 5), centers, Calib3d.CALIB_CB_CLUSTERING - | Calib3d.CALIB_CB_ASYMMETRIC_GRID)); - - assertEquals(15, centers.rows()); - assertEquals(1, centers.cols()); - assertEquals(CvType.CV_32FC2, centers.type()); - } - - public void testFindFundamentalMatListOfPointListOfPoint() { - fail("Not yet implemented"); -/* - int minFundamentalMatPoints = 8; - - MatOfPoint2f pts = new MatOfPoint2f(); - pts.alloc(minFundamentalMatPoints); - - for (int i = 0; i < minFundamentalMatPoints; i++) { - double x = Math.random() * 100 - 50; - double y = Math.random() * 100 - 50; - pts.put(i, 0, x, y); //add(new Point(x, y)); - } - - Mat fm = Calib3d.findFundamentalMat(pts, pts); - - truth = new Mat(3, 3, CvType.CV_64F); - truth.put(0, 0, 0, -0.577, 0.288, 0.577, 0, 0.288, -0.288, -0.288, 0); - assertMatEqual(truth, fm, EPS); -*/ - } - public void testFindFundamentalMatListOfPointListOfPointInt() { fail("Not yet implemented"); } @@ -309,7 +186,7 @@ public class Calib3dTest extends OpenCVTestCase { transformedPoints.put(i, 0, y, x); } - Mat hmg = Calib3d.findHomography(originalPoints, transformedPoints); + Mat hmg = Cv3d.findHomography(originalPoints, transformedPoints); truth = new Mat(3, 3, CvType.CV_64F); truth.put(0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1); @@ -349,14 +226,6 @@ public class Calib3dTest extends OpenCVTestCase { fail("Not yet implemented"); } - public void testInitCameraMatrix2DListOfMatListOfMatSize() { - fail("Not yet implemented"); - } - - public void testInitCameraMatrix2DListOfMatListOfMatSizeDouble() { - fail("Not yet implemented"); - } - public void testMatMulDeriv() { fail("Not yet implemented"); } @@ -377,124 +246,20 @@ public class Calib3dTest extends OpenCVTestCase { fail("Not yet implemented"); } - public void testReprojectImageTo3DMatMatMat() { - Mat transformMatrix = new Mat(4, 4, CvType.CV_64F); - transformMatrix.put(0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - - Mat disparity = new Mat(matSize, matSize, CvType.CV_32F); - - float[] disp = new float[matSize * matSize]; - for (int i = 0; i < matSize; i++) - for (int j = 0; j < matSize; j++) - disp[i * matSize + j] = i - j; - disparity.put(0, 0, disp); - - Mat _3dPoints = new Mat(); - - Calib3d.reprojectImageTo3D(disparity, _3dPoints, transformMatrix); - - assertEquals(CvType.CV_32FC3, _3dPoints.type()); - assertEquals(matSize, _3dPoints.rows()); - assertEquals(matSize, _3dPoints.cols()); - - truth = new Mat(matSize, matSize, CvType.CV_32FC3); - - float[] _truth = new float[matSize * matSize * 3]; - for (int i = 0; i < matSize; i++) - for (int j = 0; j < matSize; j++) { - _truth[(i * matSize + j) * 3 + 0] = i; - _truth[(i * matSize + j) * 3 + 1] = j; - _truth[(i * matSize + j) * 3 + 2] = i - j; - } - truth.put(0, 0, _truth); - - assertMatEqual(truth, _3dPoints, EPS); - } - - public void testReprojectImageTo3DMatMatMatBoolean() { - Mat transformMatrix = new Mat(4, 4, CvType.CV_64F); - transformMatrix.put(0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - - Mat disparity = new Mat(matSize, matSize, CvType.CV_32F); - - float[] disp = new float[matSize * matSize]; - for (int i = 0; i < matSize; i++) - for (int j = 0; j < matSize; j++) - disp[i * matSize + j] = i - j; - disp[0] = -Float.MAX_VALUE; - disparity.put(0, 0, disp); - - Mat _3dPoints = new Mat(); - - Calib3d.reprojectImageTo3D(disparity, _3dPoints, transformMatrix, true); - - assertEquals(CvType.CV_32FC3, _3dPoints.type()); - assertEquals(matSize, _3dPoints.rows()); - assertEquals(matSize, _3dPoints.cols()); - - truth = new Mat(matSize, matSize, CvType.CV_32FC3); - - float[] _truth = new float[matSize * matSize * 3]; - for (int i = 0; i < matSize; i++) - for (int j = 0; j < matSize; j++) { - _truth[(i * matSize + j) * 3 + 0] = i; - _truth[(i * matSize + j) * 3 + 1] = j; - _truth[(i * matSize + j) * 3 + 2] = i - j; - } - _truth[2] = 10000; - truth.put(0, 0, _truth); - - assertMatEqual(truth, _3dPoints, EPS); - } - - public void testReprojectImageTo3DMatMatMatBooleanInt() { - Mat transformMatrix = new Mat(4, 4, CvType.CV_64F); - transformMatrix.put(0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - - Mat disparity = new Mat(matSize, matSize, CvType.CV_32F); - - float[] disp = new float[matSize * matSize]; - for (int i = 0; i < matSize; i++) - for (int j = 0; j < matSize; j++) - disp[i * matSize + j] = i - j; - disparity.put(0, 0, disp); - - Mat _3dPoints = new Mat(); - - Calib3d.reprojectImageTo3D(disparity, _3dPoints, transformMatrix, false, CvType.CV_16S); - - assertEquals(CvType.CV_16SC3, _3dPoints.type()); - assertEquals(matSize, _3dPoints.rows()); - assertEquals(matSize, _3dPoints.cols()); - - truth = new Mat(matSize, matSize, CvType.CV_16SC3); - - short[] _truth = new short[matSize * matSize * 3]; - for (short i = 0; i < matSize; i++) - for (short j = 0; j < matSize; j++) { - _truth[(i * matSize + j) * 3 + 0] = i; - _truth[(i * matSize + j) * 3 + 1] = j; - _truth[(i * matSize + j) * 3 + 2] = (short) (i - j); - } - truth.put(0, 0, _truth); - - assertMatEqual(truth, _3dPoints, EPS); - } - public void testRodriguesMatMat() { Mat r = new Mat(3, 1, CvType.CV_32F); Mat R = new Mat(3, 3, CvType.CV_32F); r.put(0, 0, Math.PI, 0, 0); - Calib3d.Rodrigues(r, R); + Cv3d.Rodrigues(r, R); truth = new Mat(3, 3, CvType.CV_32F); truth.put(0, 0, 1, 0, 0, 0, -1, 0, 0, 0, -1); assertMatEqual(truth, R, EPS); Mat r2 = new Mat(); - Calib3d.Rodrigues(R, r2); + Cv3d.Rodrigues(R, r2); assertMatEqual(r, r2, EPS); } @@ -542,7 +307,7 @@ public class Calib3dTest extends OpenCVTestCase { Mat rvec = new Mat(); Mat tvec = new Mat(); - Calib3d.solvePnP(points3d, points2d, intrinsics, new MatOfDouble(), rvec, tvec); + Cv3d.solvePnP(points3d, points2d, intrinsics, new MatOfDouble(), rvec, tvec); Mat truth_rvec = new Mat(3, 1, CvType.CV_64F); truth_rvec.put(0, 0, 0, Math.PI / 2, 0); @@ -620,38 +385,10 @@ public class Calib3dTest extends OpenCVTestCase { Mat lines = new Mat(); Mat truth = new Mat(1, 1, CvType.CV_32FC3); truth.put(0, 0, -0.70735186, 0.70686162, -0.70588124); - Calib3d.computeCorrespondEpilines(left, 1, fundamental, lines); + Cv3d.computeCorrespondEpilines(left, 1, fundamental, lines); assertMatEqual(truth, lines, EPS); } - public void testConstants() - { - // calib3d.hpp: some constants have conflict with constants from 'fisheye' namespace - assertEquals(1, Calib3d.CALIB_USE_INTRINSIC_GUESS); - assertEquals(2, Calib3d.CALIB_FIX_ASPECT_RATIO); - assertEquals(4, Calib3d.CALIB_FIX_PRINCIPAL_POINT); - assertEquals(8, Calib3d.CALIB_ZERO_TANGENT_DIST); - assertEquals(16, Calib3d.CALIB_FIX_FOCAL_LENGTH); - assertEquals(32, Calib3d.CALIB_FIX_K1); - assertEquals(64, Calib3d.CALIB_FIX_K2); - assertEquals(128, Calib3d.CALIB_FIX_K3); - assertEquals(0x0800, Calib3d.CALIB_FIX_K4); - assertEquals(0x1000, Calib3d.CALIB_FIX_K5); - assertEquals(0x2000, Calib3d.CALIB_FIX_K6); - assertEquals(0x4000, Calib3d.CALIB_RATIONAL_MODEL); - assertEquals(0x8000, Calib3d.CALIB_THIN_PRISM_MODEL); - assertEquals(0x10000, Calib3d.CALIB_FIX_S1_S2_S3_S4); - assertEquals(0x40000, Calib3d.CALIB_TILTED_MODEL); - assertEquals(0x80000, Calib3d.CALIB_FIX_TAUX_TAUY); - assertEquals(0x100000, Calib3d.CALIB_USE_QR); - assertEquals(0x200000, Calib3d.CALIB_FIX_TANGENT_DIST); - assertEquals(0x100, Calib3d.CALIB_FIX_INTRINSIC); - assertEquals(0x200, Calib3d.CALIB_SAME_FOCAL_LENGTH); - assertEquals(0x400, Calib3d.CALIB_ZERO_DISPARITY); - assertEquals((1 << 17), Calib3d.CALIB_USE_LU); - assertEquals((1 << 22), Calib3d.CALIB_USE_EXTRINSIC_GUESS); - } - public void testSolvePnPGeneric_regression_16040() { Mat intrinsics = Mat.eye(3, 3, CvType.CV_64F); intrinsics.put(0, 0, 400); @@ -681,7 +418,7 @@ public class Calib3dTest extends OpenCVTestCase { Mat reprojectionError = new Mat(2, 1, CvType.CV_64FC1); - Calib3d.solvePnPGeneric(points3d, points2d, intrinsics, new MatOfDouble(), rvecs, tvecs, false, Calib3d.SOLVEPNP_IPPE, rvec, tvec, reprojectionError); + Cv3d.solvePnPGeneric(points3d, points2d, intrinsics, new MatOfDouble(), rvecs, tvecs, false, Cv3d.SOLVEPNP_IPPE, rvec, tvec, reprojectionError); Mat truth_rvec = new Mat(3, 1, CvType.CV_64F); truth_rvec.put(0, 0, 0, Math.PI / 2, 0); @@ -694,14 +431,14 @@ public class Calib3dTest extends OpenCVTestCase { } public void testGetDefaultNewCameraMatrixMat() { - Mat mtx = Calib3d.getDefaultNewCameraMatrix(gray0); + Mat mtx = Cv3d.getDefaultNewCameraMatrix(gray0); assertFalse(mtx.empty()); assertEquals(0, Core.countNonZero(mtx)); } public void testGetDefaultNewCameraMatrixMatSizeBoolean() { - Mat mtx = Calib3d.getDefaultNewCameraMatrix(gray0, size, true); + Mat mtx = Cv3d.getDefaultNewCameraMatrix(gray0, size, true); assertFalse(mtx.empty()); assertFalse(0 == Core.countNonZero(mtx)); @@ -723,7 +460,7 @@ public class Calib3dTest extends OpenCVTestCase { Mat map2 = new Mat(); // TODO: complete this test - Calib3d.initUndistortRectifyMap(cameraMatrix, distCoeffs, R, newCameraMatrix, size, CvType.CV_32F, map1, map2); + Cv3d.initUndistortRectifyMap(cameraMatrix, distCoeffs, R, newCameraMatrix, size, CvType.CV_32F, map1, map2); } public void testInitWideAngleProjMapMatMatSizeIntIntMatMat() { @@ -742,7 +479,7 @@ public class Calib3dTest extends OpenCVTestCase { truth.put(1, 0, 0, 0, 0); truth.put(2, 0, 0, 3, 0); // TODO: No documentation for this function - // Calib3d.initWideAngleProjMap(cameraMatrix, distCoeffs, imageSize, + // Cv3d.initWideAngleProjMap(cameraMatrix, distCoeffs, imageSize, // 5, m1type, truthput1, truthput2); } @@ -769,7 +506,7 @@ public class Calib3dTest extends OpenCVTestCase { } }; - Calib3d.undistort(src, dst, cameraMatrix, distCoeffs); + Cv3d.undistort(src, dst, cameraMatrix, distCoeffs); truth = new Mat(3, 3, CvType.CV_32F) { { @@ -797,7 +534,7 @@ public class Calib3dTest extends OpenCVTestCase { }; Mat newCameraMatrix = new Mat(3, 3, CvType.CV_32F, new Scalar(1)); - Calib3d.undistort(src, dst, cameraMatrix, distCoeffs, newCameraMatrix); + Cv3d.undistort(src, dst, cameraMatrix, distCoeffs, newCameraMatrix); truth = new Mat(3, 3, CvType.CV_32F, new Scalar(3)); assertMatEqual(truth, dst, EPS); @@ -810,7 +547,7 @@ public class Calib3dTest extends OpenCVTestCase { Mat cameraMatrix = Mat.eye(3, 3, CvType.CV_64FC1); Mat distCoeffs = new Mat(8, 1, CvType.CV_64FC1, new Scalar(0)); - Calib3d.undistortPoints(src, dst, cameraMatrix, distCoeffs); + Cv3d.undistortPoints(src, dst, cameraMatrix, distCoeffs); assertEquals(src.size(), dst.size()); for(int i=0; i src, List dst, Mat cameraMatrix, Mat distCoeffs) + func testUndistortPointsListOfPointListOfPointMatMat() { + let src = MatOfPoint2f(array: [Point2f(x: 1, y: 2), Point2f(x: 3, y: 4), Point2f(x: -1, y: -1)]) + let dst = MatOfPoint2f() + let cameraMatrix = Mat.eye(rows: 3, cols: 3, type: CvType.CV_64FC1) + let distCoeffs = Mat(rows: 8, cols: 1, type: CvType.CV_64FC1, scalar: Scalar(0)) + + Cv3d.undistortPoints(src: src, dst: dst, cameraMatrix: cameraMatrix, distCoeffs: distCoeffs) + + XCTAssertEqual(src.toArray(), dst.toArray()) + } +} diff --git a/modules/calib3d/misc/python/test/test_solvepnp.py b/modules/3d/misc/python/test/test_solvepnp.py old mode 100644 new mode 100755 similarity index 100% rename from modules/calib3d/misc/python/test/test_solvepnp.py rename to modules/3d/misc/python/test/test_solvepnp.py diff --git a/modules/calib3d/perf/perf_affine2d.cpp b/modules/3d/perf/perf_affine2d.cpp similarity index 100% rename from modules/calib3d/perf/perf_affine2d.cpp rename to modules/3d/perf/perf_affine2d.cpp diff --git a/modules/calib3d/perf/perf_main.cpp b/modules/3d/perf/perf_main.cpp similarity index 100% rename from modules/calib3d/perf/perf_main.cpp rename to modules/3d/perf/perf_main.cpp diff --git a/modules/calib3d/perf/perf_pnp.cpp b/modules/3d/perf/perf_pnp.cpp similarity index 100% rename from modules/calib3d/perf/perf_pnp.cpp rename to modules/3d/perf/perf_pnp.cpp diff --git a/modules/calib3d/perf/perf_precomp.hpp b/modules/3d/perf/perf_precomp.hpp similarity index 90% rename from modules/calib3d/perf/perf_precomp.hpp rename to modules/3d/perf/perf_precomp.hpp index 582d854458..0d91bd9605 100644 --- a/modules/calib3d/perf/perf_precomp.hpp +++ b/modules/3d/perf/perf_precomp.hpp @@ -5,6 +5,6 @@ #define __OPENCV_PERF_PRECOMP_HPP__ #include "opencv2/ts.hpp" -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" #endif diff --git a/modules/calib3d/perf/perf_undistort.cpp b/modules/3d/perf/perf_undistort.cpp similarity index 100% rename from modules/calib3d/perf/perf_undistort.cpp rename to modules/3d/perf/perf_undistort.cpp diff --git a/modules/calib3d/src/ap3p.cpp b/modules/3d/src/ap3p.cpp similarity index 99% rename from modules/calib3d/src/ap3p.cpp rename to modules/3d/src/ap3p.cpp index 386a4499ef..3aea8346d4 100644 --- a/modules/calib3d/src/ap3p.cpp +++ b/modules/3d/src/ap3p.cpp @@ -7,10 +7,11 @@ static inline double cbrt(double x) { return (double)cv::cubeRoot((float)x); }; #endif +namespace cv { + using namespace std; -namespace { -void solveQuartic(const double *factors, double *realRoots) { +static void solveQuartic(const double *factors, double *realRoots) { const double &a4 = factors[0]; const double &a3 = factors[1]; const double &a2 = factors[2]; @@ -63,7 +64,7 @@ void solveQuartic(const double *factors, double *realRoots) { realRoots[3] = B_4A - sqrt_2m_rh - sqrt2; } -void polishQuarticRoots(const double *coeffs, double *roots) { +static void polishQuarticRoots(const double *coeffs, double *roots) { const int iterations = 2; for (int i = 0; i < iterations; ++i) { for (int j = 0; j < 4; ++j) { @@ -123,9 +124,7 @@ inline void mat_mult(const double a[3][3], const double b[3][3], double result[3 result[2][1] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1]; result[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2]; } -} -namespace cv { void ap3p::init_inverse_parameters() { inv_fx = 1. / fx; inv_fy = 1. / fy; diff --git a/modules/calib3d/src/ap3p.h b/modules/3d/src/ap3p.h similarity index 100% rename from modules/calib3d/src/ap3p.h rename to modules/3d/src/ap3p.h diff --git a/modules/3d/src/calibration_base.cpp b/modules/3d/src/calibration_base.cpp new file mode 100644 index 0000000000..77a2f3cba1 --- /dev/null +++ b/modules/3d/src/calibration_base.cpp @@ -0,0 +1,1830 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "precomp.hpp" +#include "opencv2/imgproc/imgproc_c.h" +#include "distortion_model.hpp" +#include +#include + +using namespace cv; + +/* + This is straight-forward port v3 of Matlab calibration engine by Jean-Yves Bouguet + that is (in a large extent) based on the paper: + Z. Zhang. "A flexible new technique for camera calibration". + IEEE Transactions on Pattern Analysis and Machine Intelligence, 22(11):1330-1334, 2000. + The 1st initial port was done by Valery Mosyagin. +*/ + +// reimplementation of dAB.m +static void cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, CvMat* dABdB ) +{ + int i, j, M, N, L; + int bstep; + + CV_Assert( CV_IS_MAT(A) && CV_IS_MAT(B) ); + CV_Assert( CV_ARE_TYPES_EQ(A, B) && + (CV_MAT_TYPE(A->type) == CV_32F || CV_MAT_TYPE(A->type) == CV_64F) ); + CV_Assert( A->cols == B->rows ); + + M = A->rows; + L = A->cols; + N = B->cols; + bstep = B->step/CV_ELEM_SIZE(B->type); + + if( dABdA ) + { + CV_Assert( CV_ARE_TYPES_EQ(A, dABdA) && + dABdA->rows == A->rows*B->cols && dABdA->cols == A->rows*A->cols ); + } + + if( dABdB ) + { + CV_Assert( CV_ARE_TYPES_EQ(A, dABdB) && + dABdB->rows == A->rows*B->cols && dABdB->cols == B->rows*B->cols ); + } + + if( CV_MAT_TYPE(A->type) == CV_32F ) + { + for( i = 0; i < M*N; i++ ) + { + int i1 = i / N, i2 = i % N; + + if( dABdA ) + { + float* dcda = (float*)(dABdA->data.ptr + dABdA->step*i); + const float* b = (const float*)B->data.ptr + i2; + + for( j = 0; j < M*L; j++ ) + dcda[j] = 0; + for( j = 0; j < L; j++ ) + dcda[i1*L + j] = b[j*bstep]; + } + + if( dABdB ) + { + float* dcdb = (float*)(dABdB->data.ptr + dABdB->step*i); + const float* a = (const float*)(A->data.ptr + A->step*i1); + + for( j = 0; j < L*N; j++ ) + dcdb[j] = 0; + for( j = 0; j < L; j++ ) + dcdb[j*N + i2] = a[j]; + } + } + } + else + { + for( i = 0; i < M*N; i++ ) + { + int i1 = i / N, i2 = i % N; + + if( dABdA ) + { + double* dcda = (double*)(dABdA->data.ptr + dABdA->step*i); + const double* b = (const double*)B->data.ptr + i2; + + for( j = 0; j < M*L; j++ ) + dcda[j] = 0; + for( j = 0; j < L; j++ ) + dcda[i1*L + j] = b[j*bstep]; + } + + if( dABdB ) + { + double* dcdb = (double*)(dABdB->data.ptr + dABdB->step*i); + const double* a = (const double*)(A->data.ptr + A->step*i1); + + for( j = 0; j < L*N; j++ ) + dcdb[j] = 0; + for( j = 0; j < L; j++ ) + dcdb[j*N + i2] = a[j]; + } + } + } +} + +static int cvRodrigues2( const CvMat* src, CvMat* dst, CvMat* jacobian=0 ) +{ + double J[27] = {0}; + CvMat matJ = cvMat( 3, 9, CV_64F, J ); + + if( !CV_IS_MAT(src) ) + CV_Error( !src ? CV_StsNullPtr : CV_StsBadArg, "Input argument is not a valid matrix" ); + + if( !CV_IS_MAT(dst) ) + CV_Error( !dst ? CV_StsNullPtr : CV_StsBadArg, + "The first output argument is not a valid matrix" ); + + int depth = CV_MAT_DEPTH(src->type); + int elem_size = CV_ELEM_SIZE(depth); + + if( depth != CV_32F && depth != CV_64F ) + CV_Error( CV_StsUnsupportedFormat, "The matrices must have 32f or 64f data type" ); + + if( !CV_ARE_DEPTHS_EQ(src, dst) ) + CV_Error( CV_StsUnmatchedFormats, "All the matrices must have the same data type" ); + + if( jacobian ) + { + if( !CV_IS_MAT(jacobian) ) + CV_Error( CV_StsBadArg, "Jacobian is not a valid matrix" ); + + if( !CV_ARE_DEPTHS_EQ(src, jacobian) || CV_MAT_CN(jacobian->type) != 1 ) + CV_Error( CV_StsUnmatchedFormats, "Jacobian must have 32fC1 or 64fC1 datatype" ); + + if( (jacobian->rows != 9 || jacobian->cols != 3) && + (jacobian->rows != 3 || jacobian->cols != 9)) + CV_Error( CV_StsBadSize, "Jacobian must be 3x9 or 9x3" ); + } + + if( src->cols == 1 || src->rows == 1 ) + { + int step = src->rows > 1 ? src->step / elem_size : 1; + + if( src->rows + src->cols*CV_MAT_CN(src->type) - 1 != 3 ) + CV_Error( CV_StsBadSize, "Input matrix must be 1x3, 3x1 or 3x3" ); + + if( dst->rows != 3 || dst->cols != 3 || CV_MAT_CN(dst->type) != 1 ) + CV_Error( CV_StsBadSize, "Output matrix must be 3x3, single-channel floating point matrix" ); + + Point3d r; + if( depth == CV_32F ) + { + r.x = src->data.fl[0]; + r.y = src->data.fl[step]; + r.z = src->data.fl[step*2]; + } + else + { + r.x = src->data.db[0]; + r.y = src->data.db[step]; + r.z = src->data.db[step*2]; + } + + double theta = norm(r); + + if( theta < DBL_EPSILON ) + { + cvSetIdentity( dst ); + + if( jacobian ) + { + memset( J, 0, sizeof(J) ); + J[5] = J[15] = J[19] = -1; + J[7] = J[11] = J[21] = 1; + } + } + else + { + double c = cos(theta); + double s = sin(theta); + double c1 = 1. - c; + double itheta = theta ? 1./theta : 0.; + + r *= itheta; + + Matx33d rrt( r.x*r.x, r.x*r.y, r.x*r.z, r.x*r.y, r.y*r.y, r.y*r.z, r.x*r.z, r.y*r.z, r.z*r.z ); + Matx33d r_x( 0, -r.z, r.y, + r.z, 0, -r.x, + -r.y, r.x, 0 ); + + // R = cos(theta)*I + (1 - cos(theta))*r*rT + sin(theta)*[r_x] + Matx33d R = c*Matx33d::eye() + c1*rrt + s*r_x; + + Mat(R).convertTo(cvarrToMat(dst), dst->type); + + if( jacobian ) + { + const double I[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; + double drrt[] = { r.x+r.x, r.y, r.z, r.y, 0, 0, r.z, 0, 0, + 0, r.x, 0, r.x, r.y+r.y, r.z, 0, r.z, 0, + 0, 0, r.x, 0, 0, r.y, r.x, r.y, r.z+r.z }; + double d_r_x_[] = { 0, 0, 0, 0, 0, -1, 0, 1, 0, + 0, 0, 1, 0, 0, 0, -1, 0, 0, + 0, -1, 0, 1, 0, 0, 0, 0, 0 }; + for( int i = 0; i < 3; i++ ) + { + double ri = i == 0 ? r.x : i == 1 ? r.y : r.z; + double a0 = -s*ri, a1 = (s - 2*c1*itheta)*ri, a2 = c1*itheta; + double a3 = (c - s*itheta)*ri, a4 = s*itheta; + for( int k = 0; k < 9; k++ ) + J[i*9+k] = a0*I[k] + a1*rrt.val[k] + a2*drrt[i*9+k] + + a3*r_x.val[k] + a4*d_r_x_[i*9+k]; + } + } + } + } + else if( src->cols == 3 && src->rows == 3 ) + { + Matx33d U, Vt; + Vec3d W; + double theta, s, c; + int step = dst->rows > 1 ? dst->step / elem_size : 1; + + if( (dst->rows != 1 || dst->cols*CV_MAT_CN(dst->type) != 3) && + (dst->rows != 3 || dst->cols != 1 || CV_MAT_CN(dst->type) != 1)) + CV_Error( CV_StsBadSize, "Output matrix must be 1x3 or 3x1" ); + + Matx33d R = cvarrToMat(src); + + if( !checkRange(R, true, NULL, -100, 100) ) + { + cvZero(dst); + if( jacobian ) + cvZero(jacobian); + return 0; + } + + SVD::compute(R, W, U, Vt); + R = U*Vt; + + Point3d r(R(2, 1) - R(1, 2), R(0, 2) - R(2, 0), R(1, 0) - R(0, 1)); + + s = std::sqrt((r.x*r.x + r.y*r.y + r.z*r.z)*0.25); + c = (R(0, 0) + R(1, 1) + R(2, 2) - 1)*0.5; + c = c > 1. ? 1. : c < -1. ? -1. : c; + theta = acos(c); + + if( s < 1e-5 ) + { + double t; + + if( c > 0 ) + r = Point3d(0, 0, 0); + else + { + t = (R(0, 0) + 1)*0.5; + r.x = std::sqrt(MAX(t,0.)); + t = (R(1, 1) + 1)*0.5; + r.y = std::sqrt(MAX(t,0.))*(R(0, 1) < 0 ? -1. : 1.); + t = (R(2, 2) + 1)*0.5; + r.z = std::sqrt(MAX(t,0.))*(R(0, 2) < 0 ? -1. : 1.); + if( fabs(r.x) < fabs(r.y) && fabs(r.x) < fabs(r.z) && (R(1, 2) > 0) != (r.y*r.z > 0) ) + r.z = -r.z; + theta /= norm(r); + r *= theta; + } + + if( jacobian ) + { + memset( J, 0, sizeof(J) ); + if( c > 0 ) + { + J[5] = J[15] = J[19] = -0.5; + J[7] = J[11] = J[21] = 0.5; + } + } + } + else + { + double vth = 1/(2*s); + + if( jacobian ) + { + double t, dtheta_dtr = -1./s; + // var1 = [vth;theta] + // var = [om1;var1] = [om1;vth;theta] + double dvth_dtheta = -vth*c/s; + double d1 = 0.5*dvth_dtheta*dtheta_dtr; + double d2 = 0.5*dtheta_dtr; + // dvar1/dR = dvar1/dtheta*dtheta/dR = [dvth/dtheta; 1] * dtheta/dtr * dtr/dR + double dvardR[5*9] = + { + 0, 0, 0, 0, 0, 1, 0, -1, 0, + 0, 0, -1, 0, 0, 0, 1, 0, 0, + 0, 1, 0, -1, 0, 0, 0, 0, 0, + d1, 0, 0, 0, d1, 0, 0, 0, d1, + d2, 0, 0, 0, d2, 0, 0, 0, d2 + }; + // var2 = [om;theta] + double dvar2dvar[] = + { + vth, 0, 0, r.x, 0, + 0, vth, 0, r.y, 0, + 0, 0, vth, r.z, 0, + 0, 0, 0, 0, 1 + }; + double domegadvar2[] = + { + theta, 0, 0, r.x*vth, + 0, theta, 0, r.y*vth, + 0, 0, theta, r.z*vth + }; + + CvMat _dvardR = cvMat( 5, 9, CV_64FC1, dvardR ); + CvMat _dvar2dvar = cvMat( 4, 5, CV_64FC1, dvar2dvar ); + CvMat _domegadvar2 = cvMat( 3, 4, CV_64FC1, domegadvar2 ); + double t0[3*5]; + CvMat _t0 = cvMat( 3, 5, CV_64FC1, t0 ); + + cvMatMul( &_domegadvar2, &_dvar2dvar, &_t0 ); + cvMatMul( &_t0, &_dvardR, &matJ ); + + // transpose every row of matJ (treat the rows as 3x3 matrices) + CV_SWAP(J[1], J[3], t); CV_SWAP(J[2], J[6], t); CV_SWAP(J[5], J[7], t); + CV_SWAP(J[10], J[12], t); CV_SWAP(J[11], J[15], t); CV_SWAP(J[14], J[16], t); + CV_SWAP(J[19], J[21], t); CV_SWAP(J[20], J[24], t); CV_SWAP(J[23], J[25], t); + } + + vth *= theta; + r *= vth; + } + + if( depth == CV_32F ) + { + dst->data.fl[0] = (float)r.x; + dst->data.fl[step] = (float)r.y; + dst->data.fl[step*2] = (float)r.z; + } + else + { + dst->data.db[0] = r.x; + dst->data.db[step] = r.y; + dst->data.db[step*2] = r.z; + } + } + else + { + CV_Error(CV_StsBadSize, "Input matrix must be 1x3 or 3x1 for a rotation vector, or 3x3 for a rotation matrix"); + } + + if( jacobian ) + { + if( depth == CV_32F ) + { + if( jacobian->rows == matJ.rows ) + cvConvert( &matJ, jacobian ); + else + { + float Jf[3*9]; + CvMat _Jf = cvMat( matJ.rows, matJ.cols, CV_32FC1, Jf ); + cvConvert( &matJ, &_Jf ); + cvTranspose( &_Jf, jacobian ); + } + } + else if( jacobian->rows == matJ.rows ) + cvCopy( &matJ, jacobian ); + else + cvTranspose( &matJ, jacobian ); + } + + return 1; +} + +// reimplementation of compose_motion.m +static void cvComposeRT( const CvMat* _rvec1, const CvMat* _tvec1, + const CvMat* _rvec2, const CvMat* _tvec2, + CvMat* _rvec3, CvMat* _tvec3, + CvMat* dr3dr1, CvMat* dr3dt1, + CvMat* dr3dr2, CvMat* dr3dt2, + CvMat* dt3dr1, CvMat* dt3dt1, + CvMat* dt3dr2, CvMat* dt3dt2 ) +{ + double _r1[3], _r2[3]; + double _R1[9], _d1[9*3], _R2[9], _d2[9*3]; + CvMat r1 = cvMat(3,1,CV_64F,_r1), r2 = cvMat(3,1,CV_64F,_r2); + CvMat R1 = cvMat(3,3,CV_64F,_R1), R2 = cvMat(3,3,CV_64F,_R2); + CvMat dR1dr1 = cvMat(9,3,CV_64F,_d1), dR2dr2 = cvMat(9,3,CV_64F,_d2); + + CV_Assert( CV_IS_MAT(_rvec1) && CV_IS_MAT(_rvec2) ); + + CV_Assert( CV_MAT_TYPE(_rvec1->type) == CV_32F || + CV_MAT_TYPE(_rvec1->type) == CV_64F ); + + CV_Assert( _rvec1->rows == 3 && _rvec1->cols == 1 && CV_ARE_SIZES_EQ(_rvec1, _rvec2) ); + + cvConvert( _rvec1, &r1 ); + cvConvert( _rvec2, &r2 ); + + cvRodrigues2( &r1, &R1, &dR1dr1 ); + cvRodrigues2( &r2, &R2, &dR2dr2 ); + + if( _rvec3 || dr3dr1 || dr3dr2 ) + { + double _r3[3], _R3[9], _dR3dR1[9*9], _dR3dR2[9*9], _dr3dR3[9*3]; + double _W1[9*3], _W2[3*3]; + CvMat r3 = cvMat(3,1,CV_64F,_r3), R3 = cvMat(3,3,CV_64F,_R3); + CvMat dR3dR1 = cvMat(9,9,CV_64F,_dR3dR1), dR3dR2 = cvMat(9,9,CV_64F,_dR3dR2); + CvMat dr3dR3 = cvMat(3,9,CV_64F,_dr3dR3); + CvMat W1 = cvMat(3,9,CV_64F,_W1), W2 = cvMat(3,3,CV_64F,_W2); + + cvMatMul( &R2, &R1, &R3 ); + cvCalcMatMulDeriv( &R2, &R1, &dR3dR2, &dR3dR1 ); + + cvRodrigues2( &R3, &r3, &dr3dR3 ); + + if( _rvec3 ) + cvConvert( &r3, _rvec3 ); + + if( dr3dr1 ) + { + cvMatMul( &dr3dR3, &dR3dR1, &W1 ); + cvMatMul( &W1, &dR1dr1, &W2 ); + cvConvert( &W2, dr3dr1 ); + } + + if( dr3dr2 ) + { + cvMatMul( &dr3dR3, &dR3dR2, &W1 ); + cvMatMul( &W1, &dR2dr2, &W2 ); + cvConvert( &W2, dr3dr2 ); + } + } + + if( dr3dt1 ) + cvZero( dr3dt1 ); + if( dr3dt2 ) + cvZero( dr3dt2 ); + + if( _tvec3 || dt3dr2 || dt3dt1 ) + { + double _t1[3], _t2[3], _t3[3], _dxdR2[3*9], _dxdt1[3*3], _W3[3*3]; + CvMat t1 = cvMat(3,1,CV_64F,_t1), t2 = cvMat(3,1,CV_64F,_t2); + CvMat t3 = cvMat(3,1,CV_64F,_t3); + CvMat dxdR2 = cvMat(3, 9, CV_64F, _dxdR2); + CvMat dxdt1 = cvMat(3, 3, CV_64F, _dxdt1); + CvMat W3 = cvMat(3, 3, CV_64F, _W3); + + CV_Assert( CV_IS_MAT(_tvec1) && CV_IS_MAT(_tvec2) ); + CV_Assert( CV_ARE_SIZES_EQ(_tvec1, _tvec2) && CV_ARE_SIZES_EQ(_tvec1, _rvec1) ); + + cvConvert( _tvec1, &t1 ); + cvConvert( _tvec2, &t2 ); + cvMatMulAdd( &R2, &t1, &t2, &t3 ); + + if( _tvec3 ) + cvConvert( &t3, _tvec3 ); + + if( dt3dr2 || dt3dt1 ) + { + cvCalcMatMulDeriv( &R2, &t1, &dxdR2, &dxdt1 ); + if( dt3dr2 ) + { + cvMatMul( &dxdR2, &dR2dr2, &W3 ); + cvConvert( &W3, dt3dr2 ); + } + if( dt3dt1 ) + cvConvert( &dxdt1, dt3dt1 ); + } + } + + if( dt3dt2 ) + cvSetIdentity( dt3dt2 ); + if( dt3dr1 ) + cvZero( dt3dr1 ); +} + +static const char* cvDistCoeffErr = "Distortion coefficients must be 1x4, 4x1, 1x5, 5x1, 1x8, 8x1, 1x12, 12x1, 1x14 or 14x1 floating-point vector"; + +static void cvProjectPoints2Internal( const CvMat* objectPoints, + const CvMat* r_vec, + const CvMat* t_vec, + const CvMat* A, + const CvMat* distCoeffs, + CvMat* imagePoints, CvMat* dpdr CV_DEFAULT(NULL), + CvMat* dpdt CV_DEFAULT(NULL), CvMat* dpdf CV_DEFAULT(NULL), + CvMat* dpdc CV_DEFAULT(NULL), CvMat* dpdk CV_DEFAULT(NULL), + CvMat* dpdo CV_DEFAULT(NULL), + double aspectRatio CV_DEFAULT(0) ) +{ + Ptr matM, _m; + Ptr _dpdr, _dpdt, _dpdc, _dpdf, _dpdk; + Ptr _dpdo; + + int i, j, count; + int calc_derivatives; + const CvPoint3D64f* M; + CvPoint2D64f* m; + double r[3], R[9], dRdr[27], t[3], a[9], k[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, fx, fy, cx, cy; + Matx33d matTilt = Matx33d::eye(); + Matx33d dMatTiltdTauX(0,0,0,0,0,0,0,-1,0); + Matx33d dMatTiltdTauY(0,0,0,0,0,0,1,0,0); + CvMat _r, _t, _a = cvMat( 3, 3, CV_64F, a ), _k; + CvMat matR = cvMat( 3, 3, CV_64F, R ), _dRdr = cvMat( 3, 9, CV_64F, dRdr ); + double *dpdr_p = 0, *dpdt_p = 0, *dpdk_p = 0, *dpdf_p = 0, *dpdc_p = 0; + double* dpdo_p = 0; + int dpdr_step = 0, dpdt_step = 0, dpdk_step = 0, dpdf_step = 0, dpdc_step = 0; + int dpdo_step = 0; + bool fixedAspectRatio = aspectRatio > FLT_EPSILON; + + if( !CV_IS_MAT(objectPoints) || !CV_IS_MAT(r_vec) || + !CV_IS_MAT(t_vec) || !CV_IS_MAT(A) || + /*!CV_IS_MAT(distCoeffs) ||*/ !CV_IS_MAT(imagePoints) ) + CV_Error( CV_StsBadArg, "One of required arguments is not a valid matrix" ); + + int total = objectPoints->rows * objectPoints->cols * CV_MAT_CN(objectPoints->type); + if(total % 3 != 0) + { + //we have stopped support of homogeneous coordinates because it cause ambiguity in interpretation of the input data + CV_Error( CV_StsBadArg, "Homogeneous coordinates are not supported" ); + } + count = total / 3; + + if( CV_IS_CONT_MAT(objectPoints->type) && + (CV_MAT_DEPTH(objectPoints->type) == CV_32F || CV_MAT_DEPTH(objectPoints->type) == CV_64F)&& + ((objectPoints->rows == 1 && CV_MAT_CN(objectPoints->type) == 3) || + (objectPoints->rows == count && CV_MAT_CN(objectPoints->type)*objectPoints->cols == 3) || + (objectPoints->rows == 3 && CV_MAT_CN(objectPoints->type) == 1 && objectPoints->cols == count))) + { + matM.reset(cvCreateMat( objectPoints->rows, objectPoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(objectPoints->type)) )); + cvConvert(objectPoints, matM); + } + else + { +// matM = cvCreateMat( 1, count, CV_64FC3 ); +// cvConvertPointsHomogeneous( objectPoints, matM ); + CV_Error( CV_StsBadArg, "Homogeneous coordinates are not supported" ); + } + + if( CV_IS_CONT_MAT(imagePoints->type) && + (CV_MAT_DEPTH(imagePoints->type) == CV_32F || CV_MAT_DEPTH(imagePoints->type) == CV_64F) && + ((imagePoints->rows == 1 && CV_MAT_CN(imagePoints->type) == 2) || + (imagePoints->rows == count && CV_MAT_CN(imagePoints->type)*imagePoints->cols == 2) || + (imagePoints->rows == 2 && CV_MAT_CN(imagePoints->type) == 1 && imagePoints->cols == count))) + { + _m.reset(cvCreateMat( imagePoints->rows, imagePoints->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(imagePoints->type)) )); + cvConvert(imagePoints, _m); + } + else + { +// _m = cvCreateMat( 1, count, CV_64FC2 ); + CV_Error( CV_StsBadArg, "Homogeneous coordinates are not supported" ); + } + + M = (CvPoint3D64f*)matM->data.db; + m = (CvPoint2D64f*)_m->data.db; + + if( (CV_MAT_DEPTH(r_vec->type) != CV_64F && CV_MAT_DEPTH(r_vec->type) != CV_32F) || + (((r_vec->rows != 1 && r_vec->cols != 1) || + r_vec->rows*r_vec->cols*CV_MAT_CN(r_vec->type) != 3) && + ((r_vec->rows != 3 && r_vec->cols != 3) || CV_MAT_CN(r_vec->type) != 1))) + CV_Error( CV_StsBadArg, "Rotation must be represented by 1x3 or 3x1 " + "floating-point rotation vector, or 3x3 rotation matrix" ); + + if( r_vec->rows == 3 && r_vec->cols == 3 ) + { + _r = cvMat( 3, 1, CV_64FC1, r ); + cvRodrigues2( r_vec, &_r ); + cvRodrigues2( &_r, &matR, &_dRdr ); + cvCopy( r_vec, &matR ); + } + else + { + _r = cvMat( r_vec->rows, r_vec->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(r_vec->type)), r ); + cvConvert( r_vec, &_r ); + cvRodrigues2( &_r, &matR, &_dRdr ); + } + + if( (CV_MAT_DEPTH(t_vec->type) != CV_64F && CV_MAT_DEPTH(t_vec->type) != CV_32F) || + (t_vec->rows != 1 && t_vec->cols != 1) || + t_vec->rows*t_vec->cols*CV_MAT_CN(t_vec->type) != 3 ) + CV_Error( CV_StsBadArg, + "Translation vector must be 1x3 or 3x1 floating-point vector" ); + + _t = cvMat( t_vec->rows, t_vec->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(t_vec->type)), t ); + cvConvert( t_vec, &_t ); + + if( (CV_MAT_TYPE(A->type) != CV_64FC1 && CV_MAT_TYPE(A->type) != CV_32FC1) || + A->rows != 3 || A->cols != 3 ) + CV_Error( CV_StsBadArg, "Intrinsic parameters must be 3x3 floating-point matrix" ); + + cvConvert( A, &_a ); + fx = a[0]; fy = a[4]; + cx = a[2]; cy = a[5]; + + if( fixedAspectRatio ) + fx = fy*aspectRatio; + + if( distCoeffs ) + { + if( !CV_IS_MAT(distCoeffs) || + (CV_MAT_DEPTH(distCoeffs->type) != CV_64F && + CV_MAT_DEPTH(distCoeffs->type) != CV_32F) || + (distCoeffs->rows != 1 && distCoeffs->cols != 1) || + (distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 4 && + distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 5 && + distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 8 && + distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 12 && + distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) != 14) ) + CV_Error( CV_StsBadArg, cvDistCoeffErr ); + + _k = cvMat( distCoeffs->rows, distCoeffs->cols, + CV_MAKETYPE(CV_64F,CV_MAT_CN(distCoeffs->type)), k ); + cvConvert( distCoeffs, &_k ); + if(k[12] != 0 || k[13] != 0) + { + cv::computeTiltProjectionMatrix(k[12], k[13], + &matTilt, &dMatTiltdTauX, &dMatTiltdTauY); + } + } + + if( dpdr ) + { + if( !CV_IS_MAT(dpdr) || + (CV_MAT_TYPE(dpdr->type) != CV_32FC1 && + CV_MAT_TYPE(dpdr->type) != CV_64FC1) || + dpdr->rows != count*2 || dpdr->cols != 3 ) + CV_Error( CV_StsBadArg, "dp/drot must be 2Nx3 floating-point matrix" ); + + if( CV_MAT_TYPE(dpdr->type) == CV_64FC1 ) + { + _dpdr.reset(cvCloneMat(dpdr)); + } + else + _dpdr.reset(cvCreateMat( 2*count, 3, CV_64FC1 )); + dpdr_p = _dpdr->data.db; + dpdr_step = _dpdr->step/sizeof(dpdr_p[0]); + } + + if( dpdt ) + { + if( !CV_IS_MAT(dpdt) || + (CV_MAT_TYPE(dpdt->type) != CV_32FC1 && + CV_MAT_TYPE(dpdt->type) != CV_64FC1) || + dpdt->rows != count*2 || dpdt->cols != 3 ) + CV_Error( CV_StsBadArg, "dp/dT must be 2Nx3 floating-point matrix" ); + + if( CV_MAT_TYPE(dpdt->type) == CV_64FC1 ) + { + _dpdt.reset(cvCloneMat(dpdt)); + } + else + _dpdt.reset(cvCreateMat( 2*count, 3, CV_64FC1 )); + dpdt_p = _dpdt->data.db; + dpdt_step = _dpdt->step/sizeof(dpdt_p[0]); + } + + if( dpdf ) + { + if( !CV_IS_MAT(dpdf) || + (CV_MAT_TYPE(dpdf->type) != CV_32FC1 && CV_MAT_TYPE(dpdf->type) != CV_64FC1) || + dpdf->rows != count*2 || dpdf->cols != 2 ) + CV_Error( CV_StsBadArg, "dp/df must be 2Nx2 floating-point matrix" ); + + if( CV_MAT_TYPE(dpdf->type) == CV_64FC1 ) + { + _dpdf.reset(cvCloneMat(dpdf)); + } + else + _dpdf.reset(cvCreateMat( 2*count, 2, CV_64FC1 )); + dpdf_p = _dpdf->data.db; + dpdf_step = _dpdf->step/sizeof(dpdf_p[0]); + } + + if( dpdc ) + { + if( !CV_IS_MAT(dpdc) || + (CV_MAT_TYPE(dpdc->type) != CV_32FC1 && CV_MAT_TYPE(dpdc->type) != CV_64FC1) || + dpdc->rows != count*2 || dpdc->cols != 2 ) + CV_Error( CV_StsBadArg, "dp/dc must be 2Nx2 floating-point matrix" ); + + if( CV_MAT_TYPE(dpdc->type) == CV_64FC1 ) + { + _dpdc.reset(cvCloneMat(dpdc)); + } + else + _dpdc.reset(cvCreateMat( 2*count, 2, CV_64FC1 )); + dpdc_p = _dpdc->data.db; + dpdc_step = _dpdc->step/sizeof(dpdc_p[0]); + } + + if( dpdk ) + { + if( !CV_IS_MAT(dpdk) || + (CV_MAT_TYPE(dpdk->type) != CV_32FC1 && CV_MAT_TYPE(dpdk->type) != CV_64FC1) || + dpdk->rows != count*2 || (dpdk->cols != 14 && dpdk->cols != 12 && dpdk->cols != 8 && dpdk->cols != 5 && dpdk->cols != 4 && dpdk->cols != 2) ) + CV_Error( CV_StsBadArg, "dp/df must be 2Nx14, 2Nx12, 2Nx8, 2Nx5, 2Nx4 or 2Nx2 floating-point matrix" ); + + if( !distCoeffs ) + CV_Error( CV_StsNullPtr, "distCoeffs is NULL while dpdk is not" ); + + if( CV_MAT_TYPE(dpdk->type) == CV_64FC1 ) + { + _dpdk.reset(cvCloneMat(dpdk)); + } + else + _dpdk.reset(cvCreateMat( dpdk->rows, dpdk->cols, CV_64FC1 )); + dpdk_p = _dpdk->data.db; + dpdk_step = _dpdk->step/sizeof(dpdk_p[0]); + } + + if( dpdo ) + { + if( !CV_IS_MAT( dpdo ) || ( CV_MAT_TYPE( dpdo->type ) != CV_32FC1 + && CV_MAT_TYPE( dpdo->type ) != CV_64FC1 ) + || dpdo->rows != count * 2 || dpdo->cols != count * 3 ) + CV_Error( CV_StsBadArg, "dp/do must be 2Nx3N floating-point matrix" ); + + if( CV_MAT_TYPE( dpdo->type ) == CV_64FC1 ) + { + _dpdo.reset( cvCloneMat( dpdo ) ); + } + else + _dpdo.reset( cvCreateMat( 2 * count, 3 * count, CV_64FC1 ) ); + cvZero(_dpdo); + dpdo_p = _dpdo->data.db; + dpdo_step = _dpdo->step / sizeof( dpdo_p[0] ); + } + + calc_derivatives = dpdr || dpdt || dpdf || dpdc || dpdk || dpdo; + + for( i = 0; i < count; i++ ) + { + double X = M[i].x, Y = M[i].y, Z = M[i].z; + double x = R[0]*X + R[1]*Y + R[2]*Z + t[0]; + double y = R[3]*X + R[4]*Y + R[5]*Z + t[1]; + double z = R[6]*X + R[7]*Y + R[8]*Z + t[2]; + double r2, r4, r6, a1, a2, a3, cdist, icdist2; + double xd, yd, xd0, yd0, invProj; + Vec3d vecTilt; + Vec3d dVecTilt; + Matx22d dMatTilt; + Vec2d dXdYd; + + double z0 = z; + z = z ? 1./z : 1; + x *= z; y *= z; + + r2 = x*x + y*y; + r4 = r2*r2; + r6 = r4*r2; + a1 = 2*x*y; + a2 = r2 + 2*x*x; + a3 = r2 + 2*y*y; + cdist = 1 + k[0]*r2 + k[1]*r4 + k[4]*r6; + icdist2 = 1./(1 + k[5]*r2 + k[6]*r4 + k[7]*r6); + xd0 = x*cdist*icdist2 + k[2]*a1 + k[3]*a2 + k[8]*r2+k[9]*r4; + yd0 = y*cdist*icdist2 + k[2]*a3 + k[3]*a1 + k[10]*r2+k[11]*r4; + + // additional distortion by projecting onto a tilt plane + vecTilt = matTilt*Vec3d(xd0, yd0, 1); + invProj = vecTilt(2) ? 1./vecTilt(2) : 1; + xd = invProj * vecTilt(0); + yd = invProj * vecTilt(1); + + m[i].x = xd*fx + cx; + m[i].y = yd*fy + cy; + + if( calc_derivatives ) + { + if( dpdc_p ) + { + dpdc_p[0] = 1; dpdc_p[1] = 0; // dp_xdc_x; dp_xdc_y + dpdc_p[dpdc_step] = 0; + dpdc_p[dpdc_step+1] = 1; + dpdc_p += dpdc_step*2; + } + + if( dpdf_p ) + { + if( fixedAspectRatio ) + { + dpdf_p[0] = 0; dpdf_p[1] = xd*aspectRatio; // dp_xdf_x; dp_xdf_y + dpdf_p[dpdf_step] = 0; + dpdf_p[dpdf_step+1] = yd; + } + else + { + dpdf_p[0] = xd; dpdf_p[1] = 0; + dpdf_p[dpdf_step] = 0; + dpdf_p[dpdf_step+1] = yd; + } + dpdf_p += dpdf_step*2; + } + for (int row = 0; row < 2; ++row) + for (int col = 0; col < 2; ++col) + dMatTilt(row,col) = matTilt(row,col)*vecTilt(2) + - matTilt(2,col)*vecTilt(row); + double invProjSquare = (invProj*invProj); + dMatTilt *= invProjSquare; + if( dpdk_p ) + { + dXdYd = dMatTilt*Vec2d(x*icdist2*r2, y*icdist2*r2); + dpdk_p[0] = fx*dXdYd(0); + dpdk_p[dpdk_step] = fy*dXdYd(1); + dXdYd = dMatTilt*Vec2d(x*icdist2*r4, y*icdist2*r4); + dpdk_p[1] = fx*dXdYd(0); + dpdk_p[dpdk_step+1] = fy*dXdYd(1); + if( _dpdk->cols > 2 ) + { + dXdYd = dMatTilt*Vec2d(a1, a3); + dpdk_p[2] = fx*dXdYd(0); + dpdk_p[dpdk_step+2] = fy*dXdYd(1); + dXdYd = dMatTilt*Vec2d(a2, a1); + dpdk_p[3] = fx*dXdYd(0); + dpdk_p[dpdk_step+3] = fy*dXdYd(1); + if( _dpdk->cols > 4 ) + { + dXdYd = dMatTilt*Vec2d(x*icdist2*r6, y*icdist2*r6); + dpdk_p[4] = fx*dXdYd(0); + dpdk_p[dpdk_step+4] = fy*dXdYd(1); + + if( _dpdk->cols > 5 ) + { + dXdYd = dMatTilt*Vec2d( + x*cdist*(-icdist2)*icdist2*r2, y*cdist*(-icdist2)*icdist2*r2); + dpdk_p[5] = fx*dXdYd(0); + dpdk_p[dpdk_step+5] = fy*dXdYd(1); + dXdYd = dMatTilt*Vec2d( + x*cdist*(-icdist2)*icdist2*r4, y*cdist*(-icdist2)*icdist2*r4); + dpdk_p[6] = fx*dXdYd(0); + dpdk_p[dpdk_step+6] = fy*dXdYd(1); + dXdYd = dMatTilt*Vec2d( + x*cdist*(-icdist2)*icdist2*r6, y*cdist*(-icdist2)*icdist2*r6); + dpdk_p[7] = fx*dXdYd(0); + dpdk_p[dpdk_step+7] = fy*dXdYd(1); + if( _dpdk->cols > 8 ) + { + dXdYd = dMatTilt*Vec2d(r2, 0); + dpdk_p[8] = fx*dXdYd(0); //s1 + dpdk_p[dpdk_step+8] = fy*dXdYd(1); //s1 + dXdYd = dMatTilt*Vec2d(r4, 0); + dpdk_p[9] = fx*dXdYd(0); //s2 + dpdk_p[dpdk_step+9] = fy*dXdYd(1); //s2 + dXdYd = dMatTilt*Vec2d(0, r2); + dpdk_p[10] = fx*dXdYd(0);//s3 + dpdk_p[dpdk_step+10] = fy*dXdYd(1); //s3 + dXdYd = dMatTilt*Vec2d(0, r4); + dpdk_p[11] = fx*dXdYd(0);//s4 + dpdk_p[dpdk_step+11] = fy*dXdYd(1); //s4 + if( _dpdk->cols > 12 ) + { + dVecTilt = dMatTiltdTauX * Vec3d(xd0, yd0, 1); + dpdk_p[12] = fx * invProjSquare * ( + dVecTilt(0) * vecTilt(2) - dVecTilt(2) * vecTilt(0)); + dpdk_p[dpdk_step+12] = fy*invProjSquare * ( + dVecTilt(1) * vecTilt(2) - dVecTilt(2) * vecTilt(1)); + dVecTilt = dMatTiltdTauY * Vec3d(xd0, yd0, 1); + dpdk_p[13] = fx * invProjSquare * ( + dVecTilt(0) * vecTilt(2) - dVecTilt(2) * vecTilt(0)); + dpdk_p[dpdk_step+13] = fy * invProjSquare * ( + dVecTilt(1) * vecTilt(2) - dVecTilt(2) * vecTilt(1)); + } + } + } + } + } + dpdk_p += dpdk_step*2; + } + + if( dpdt_p ) + { + double dxdt[] = { z, 0, -x*z }, dydt[] = { 0, z, -y*z }; + for( j = 0; j < 3; j++ ) + { + double dr2dt = 2*x*dxdt[j] + 2*y*dydt[j]; + double dcdist_dt = k[0]*dr2dt + 2*k[1]*r2*dr2dt + 3*k[4]*r4*dr2dt; + double dicdist2_dt = -icdist2*icdist2*(k[5]*dr2dt + 2*k[6]*r2*dr2dt + 3*k[7]*r4*dr2dt); + double da1dt = 2*(x*dydt[j] + y*dxdt[j]); + double dmxdt = (dxdt[j]*cdist*icdist2 + x*dcdist_dt*icdist2 + x*cdist*dicdist2_dt + + k[2]*da1dt + k[3]*(dr2dt + 4*x*dxdt[j]) + k[8]*dr2dt + 2*r2*k[9]*dr2dt); + double dmydt = (dydt[j]*cdist*icdist2 + y*dcdist_dt*icdist2 + y*cdist*dicdist2_dt + + k[2]*(dr2dt + 4*y*dydt[j]) + k[3]*da1dt + k[10]*dr2dt + 2*r2*k[11]*dr2dt); + dXdYd = dMatTilt*Vec2d(dmxdt, dmydt); + dpdt_p[j] = fx*dXdYd(0); + dpdt_p[dpdt_step+j] = fy*dXdYd(1); + } + dpdt_p += dpdt_step*2; + } + + if( dpdr_p ) + { + double dx0dr[] = + { + X*dRdr[0] + Y*dRdr[1] + Z*dRdr[2], + X*dRdr[9] + Y*dRdr[10] + Z*dRdr[11], + X*dRdr[18] + Y*dRdr[19] + Z*dRdr[20] + }; + double dy0dr[] = + { + X*dRdr[3] + Y*dRdr[4] + Z*dRdr[5], + X*dRdr[12] + Y*dRdr[13] + Z*dRdr[14], + X*dRdr[21] + Y*dRdr[22] + Z*dRdr[23] + }; + double dz0dr[] = + { + X*dRdr[6] + Y*dRdr[7] + Z*dRdr[8], + X*dRdr[15] + Y*dRdr[16] + Z*dRdr[17], + X*dRdr[24] + Y*dRdr[25] + Z*dRdr[26] + }; + for( j = 0; j < 3; j++ ) + { + double dxdr = z*(dx0dr[j] - x*dz0dr[j]); + double dydr = z*(dy0dr[j] - y*dz0dr[j]); + double dr2dr = 2*x*dxdr + 2*y*dydr; + double dcdist_dr = (k[0] + 2*k[1]*r2 + 3*k[4]*r4)*dr2dr; + double dicdist2_dr = -icdist2*icdist2*(k[5] + 2*k[6]*r2 + 3*k[7]*r4)*dr2dr; + double da1dr = 2*(x*dydr + y*dxdr); + double dmxdr = (dxdr*cdist*icdist2 + x*dcdist_dr*icdist2 + x*cdist*dicdist2_dr + + k[2]*da1dr + k[3]*(dr2dr + 4*x*dxdr) + (k[8] + 2*r2*k[9])*dr2dr); + double dmydr = (dydr*cdist*icdist2 + y*dcdist_dr*icdist2 + y*cdist*dicdist2_dr + + k[2]*(dr2dr + 4*y*dydr) + k[3]*da1dr + (k[10] + 2*r2*k[11])*dr2dr); + dXdYd = dMatTilt*Vec2d(dmxdr, dmydr); + dpdr_p[j] = fx*dXdYd(0); + dpdr_p[dpdr_step+j] = fy*dXdYd(1); + } + dpdr_p += dpdr_step*2; + } + + if( dpdo_p ) + { + double dxdo[] = { z * ( R[0] - x * z * z0 * R[6] ), + z * ( R[1] - x * z * z0 * R[7] ), + z * ( R[2] - x * z * z0 * R[8] ) }; + double dydo[] = { z * ( R[3] - y * z * z0 * R[6] ), + z * ( R[4] - y * z * z0 * R[7] ), + z * ( R[5] - y * z * z0 * R[8] ) }; + for( j = 0; j < 3; j++ ) + { + double dr2do = 2 * x * dxdo[j] + 2 * y * dydo[j]; + double dr4do = 2 * r2 * dr2do; + double dr6do = 3 * r4 * dr2do; + double da1do = 2 * y * dxdo[j] + 2 * x * dydo[j]; + double da2do = dr2do + 4 * x * dxdo[j]; + double da3do = dr2do + 4 * y * dydo[j]; + double dcdist_do + = k[0] * dr2do + k[1] * dr4do + k[4] * dr6do; + double dicdist2_do = -icdist2 * icdist2 + * ( k[5] * dr2do + k[6] * dr4do + k[7] * dr6do ); + double dxd0_do = cdist * icdist2 * dxdo[j] + + x * icdist2 * dcdist_do + x * cdist * dicdist2_do + + k[2] * da1do + k[3] * da2do + k[8] * dr2do + + k[9] * dr4do; + double dyd0_do = cdist * icdist2 * dydo[j] + + y * icdist2 * dcdist_do + y * cdist * dicdist2_do + + k[2] * da3do + k[3] * da1do + k[10] * dr2do + + k[11] * dr4do; + dXdYd = dMatTilt * Vec2d( dxd0_do, dyd0_do ); + dpdo_p[i * 3 + j] = fx * dXdYd( 0 ); + dpdo_p[dpdo_step + i * 3 + j] = fy * dXdYd( 1 ); + } + dpdo_p += dpdo_step * 2; + } + } + } + + if( _m != imagePoints ) + cvConvert( _m, imagePoints ); + + if( _dpdr != dpdr ) + cvConvert( _dpdr, dpdr ); + + if( _dpdt != dpdt ) + cvConvert( _dpdt, dpdt ); + + if( _dpdf != dpdf ) + cvConvert( _dpdf, dpdf ); + + if( _dpdc != dpdc ) + cvConvert( _dpdc, dpdc ); + + if( _dpdk != dpdk ) + cvConvert( _dpdk, dpdk ); + + if( _dpdo != dpdo ) + cvConvert( _dpdo, dpdo ); +} + +static void cvProjectPoints2( const CvMat* objectPoints, + const CvMat* r_vec, + const CvMat* t_vec, + const CvMat* A, + const CvMat* distCoeffs, + CvMat* imagePoints, CvMat* dpdr, + CvMat* dpdt, CvMat* dpdf, + CvMat* dpdc, CvMat* dpdk, + double aspectRatio ) +{ + cvProjectPoints2Internal( objectPoints, r_vec, t_vec, A, distCoeffs, imagePoints, dpdr, dpdt, + dpdf, dpdc, dpdk, NULL, aspectRatio ); +} + +static void cvRQDecomp3x3( const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ, + CvMat *matrixQx, CvMat *matrixQy, CvMat *matrixQz, + CvPoint3D64f *eulerAngles) +{ + double matM[3][3], matR[3][3], matQ[3][3]; + CvMat M = cvMat(3, 3, CV_64F, matM); + CvMat R = cvMat(3, 3, CV_64F, matR); + CvMat Q = cvMat(3, 3, CV_64F, matQ); + double z, c, s; + + /* Validate parameters. */ + CV_Assert( CV_IS_MAT(matrixM) && CV_IS_MAT(matrixR) && CV_IS_MAT(matrixQ) && + matrixM->cols == 3 && matrixM->rows == 3 && + CV_ARE_SIZES_EQ(matrixM, matrixR) && CV_ARE_SIZES_EQ(matrixM, matrixQ)); + + cvConvert(matrixM, &M); + + /* Find Givens rotation Q_x for x axis (left multiplication). */ + /* + ( 1 0 0 ) + Qx = ( 0 c s ), c = m33/sqrt(m32^2 + m33^2), s = m32/sqrt(m32^2 + m33^2) + ( 0 -s c ) + */ + s = matM[2][1]; + c = matM[2][2]; + z = 1./std::sqrt(c * c + s * s + DBL_EPSILON); + c *= z; + s *= z; + + double _Qx[3][3] = { {1, 0, 0}, {0, c, s}, {0, -s, c} }; + CvMat Qx = cvMat(3, 3, CV_64F, _Qx); + + cvMatMul(&M, &Qx, &R); + assert(fabs(matR[2][1]) < FLT_EPSILON); + matR[2][1] = 0; + + /* Find Givens rotation for y axis. */ + /* + ( c 0 -s ) + Qy = ( 0 1 0 ), c = m33/sqrt(m31^2 + m33^2), s = -m31/sqrt(m31^2 + m33^2) + ( s 0 c ) + */ + s = -matR[2][0]; + c = matR[2][2]; + z = 1./std::sqrt(c * c + s * s + DBL_EPSILON); + c *= z; + s *= z; + + double _Qy[3][3] = { {c, 0, -s}, {0, 1, 0}, {s, 0, c} }; + CvMat Qy = cvMat(3, 3, CV_64F, _Qy); + cvMatMul(&R, &Qy, &M); + + assert(fabs(matM[2][0]) < FLT_EPSILON); + matM[2][0] = 0; + + /* Find Givens rotation for z axis. */ + /* + ( c s 0 ) + Qz = (-s c 0 ), c = m22/sqrt(m21^2 + m22^2), s = m21/sqrt(m21^2 + m22^2) + ( 0 0 1 ) + */ + + s = matM[1][0]; + c = matM[1][1]; + z = 1./std::sqrt(c * c + s * s + DBL_EPSILON); + c *= z; + s *= z; + + double _Qz[3][3] = { {c, s, 0}, {-s, c, 0}, {0, 0, 1} }; + CvMat Qz = cvMat(3, 3, CV_64F, _Qz); + + cvMatMul(&M, &Qz, &R); + assert(fabs(matR[1][0]) < FLT_EPSILON); + matR[1][0] = 0; + + // Solve the decomposition ambiguity. + // Diagonal entries of R, except the last one, shall be positive. + // Further rotate R by 180 degree if necessary + if( matR[0][0] < 0 ) + { + if( matR[1][1] < 0 ) + { + // rotate around z for 180 degree, i.e. a rotation matrix of + // [-1, 0, 0], + // [ 0, -1, 0], + // [ 0, 0, 1] + matR[0][0] *= -1; + matR[0][1] *= -1; + matR[1][1] *= -1; + + _Qz[0][0] *= -1; + _Qz[0][1] *= -1; + _Qz[1][0] *= -1; + _Qz[1][1] *= -1; + } + else + { + // rotate around y for 180 degree, i.e. a rotation matrix of + // [-1, 0, 0], + // [ 0, 1, 0], + // [ 0, 0, -1] + matR[0][0] *= -1; + matR[0][2] *= -1; + matR[1][2] *= -1; + matR[2][2] *= -1; + + cvTranspose( &Qz, &Qz ); + + _Qy[0][0] *= -1; + _Qy[0][2] *= -1; + _Qy[2][0] *= -1; + _Qy[2][2] *= -1; + } + } + else if( matR[1][1] < 0 ) + { + // ??? for some reason, we never get here ??? + + // rotate around x for 180 degree, i.e. a rotation matrix of + // [ 1, 0, 0], + // [ 0, -1, 0], + // [ 0, 0, -1] + matR[0][1] *= -1; + matR[0][2] *= -1; + matR[1][1] *= -1; + matR[1][2] *= -1; + matR[2][2] *= -1; + + cvTranspose( &Qz, &Qz ); + cvTranspose( &Qy, &Qy ); + + _Qx[1][1] *= -1; + _Qx[1][2] *= -1; + _Qx[2][1] *= -1; + _Qx[2][2] *= -1; + } + + // calculate the euler angle + if( eulerAngles ) + { + eulerAngles->x = acos(_Qx[1][1]) * (_Qx[1][2] >= 0 ? 1 : -1) * (180.0 / CV_PI); + eulerAngles->y = acos(_Qy[0][0]) * (_Qy[2][0] >= 0 ? 1 : -1) * (180.0 / CV_PI); + eulerAngles->z = acos(_Qz[0][0]) * (_Qz[0][1] >= 0 ? 1 : -1) * (180.0 / CV_PI); + } + + /* Calculate orthogonal matrix. */ + /* + Q = QzT * QyT * QxT + */ + cvGEMM( &Qz, &Qy, 1, 0, 0, &M, CV_GEMM_A_T + CV_GEMM_B_T ); + cvGEMM( &M, &Qx, 1, 0, 0, &Q, CV_GEMM_B_T ); + + /* Save R and Q matrices. */ + cvConvert( &R, matrixR ); + cvConvert( &Q, matrixQ ); + + if( matrixQx ) + cvConvert(&Qx, matrixQx); + if( matrixQy ) + cvConvert(&Qy, matrixQy); + if( matrixQz ) + cvConvert(&Qz, matrixQz); +} + + +static void +cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr, + CvMat *rotMatr, CvMat *posVect, + CvMat *rotMatrX, CvMat *rotMatrY, + CvMat *rotMatrZ, CvPoint3D64f *eulerAngles) +{ + double tmpProjMatrData[16], tmpMatrixDData[16], tmpMatrixVData[16]; + CvMat tmpProjMatr = cvMat(4, 4, CV_64F, tmpProjMatrData); + CvMat tmpMatrixD = cvMat(4, 4, CV_64F, tmpMatrixDData); + CvMat tmpMatrixV = cvMat(4, 4, CV_64F, tmpMatrixVData); + CvMat tmpMatrixM; + + /* Validate parameters. */ + if(projMatr == 0 || calibMatr == 0 || rotMatr == 0 || posVect == 0) + CV_Error(CV_StsNullPtr, "Some of parameters is a NULL pointer!"); + + if(!CV_IS_MAT(projMatr) || !CV_IS_MAT(calibMatr) || !CV_IS_MAT(rotMatr) || !CV_IS_MAT(posVect)) + CV_Error(CV_StsUnsupportedFormat, "Input parameters must be a matrices!"); + + if(projMatr->cols != 4 || projMatr->rows != 3) + CV_Error(CV_StsUnmatchedSizes, "Size of projection matrix must be 3x4!"); + + if(calibMatr->cols != 3 || calibMatr->rows != 3 || rotMatr->cols != 3 || rotMatr->rows != 3) + CV_Error(CV_StsUnmatchedSizes, "Size of calibration and rotation matrices must be 3x3!"); + + if(posVect->cols != 1 || posVect->rows != 4) + CV_Error(CV_StsUnmatchedSizes, "Size of position vector must be 4x1!"); + + /* Compute position vector. */ + cvSetZero(&tmpProjMatr); // Add zero row to make matrix square. + int i, k; + for(i = 0; i < 3; i++) + for(k = 0; k < 4; k++) + cvmSet(&tmpProjMatr, i, k, cvmGet(projMatr, i, k)); + + cvSVD(&tmpProjMatr, &tmpMatrixD, NULL, &tmpMatrixV, CV_SVD_MODIFY_A + CV_SVD_V_T); + + /* Save position vector. */ + for(i = 0; i < 4; i++) + cvmSet(posVect, i, 0, cvmGet(&tmpMatrixV, 3, i)); // Solution is last row of V. + + /* Compute calibration and rotation matrices via RQ decomposition. */ + cvGetCols(projMatr, &tmpMatrixM, 0, 3); // M is first square matrix of P. + + CV_Assert(cvDet(&tmpMatrixM) != 0.0); // So far only finite cameras could be decomposed, so M has to be nonsingular [det(M) != 0]. + + cvRQDecomp3x3(&tmpMatrixM, calibMatr, rotMatr, rotMatrX, rotMatrY, rotMatrZ, eulerAngles); +} + +class SolvePnPCallback CV_FINAL : public LMSolver::Callback +{ +public: + SolvePnPCallback(const Mat& _objpt, const Mat& _imgpt, + const Mat& _cameraMatrix, const Mat& _distCoeffs) + { + objpt = _objpt; + imgpt = _imgpt; + cameraMatrix = _cameraMatrix; + distCoeffs = _distCoeffs; + } + + bool compute(InputArray _param, OutputArray _err, OutputArray _Jac) const CV_OVERRIDE + { + Mat param = _param.getMat(); + CV_Assert((param.cols == 1 || param.rows == 1) && param.total() == 6 && param.type() == CV_64F); + double* pdata = param.ptr(); + Mat rvec(3, 1, CV_64F, pdata); + Mat tvec(3, 1, CV_64F, pdata + 3); + int count = objpt.rows + objpt.cols - 1; + _err.create(count*2, 1, CV_64F); + Mat err = _err.getMat(); + err = err.reshape(2, count); + if( _Jac.needed() ) + { + _Jac.create(count*2, 6, CV_64F); + Mat Jac = _Jac.getMat(); + Mat dpdr = Jac.colRange(0, 3); + Mat dpdt = Jac.colRange(3, 6); + CvMat objpt_c = cvMat(objpt); + CvMat err_c = cvMat(err); + CvMat rvec_c = cvMat(rvec); + CvMat tvec_c = cvMat(tvec); + CvMat A_c = cvMat(cameraMatrix); + CvMat dk_c = cvMat(distCoeffs); + CvMat dpdr_c = cvMat(dpdr); + CvMat dpdt_c = cvMat(dpdt); + cvProjectPoints2( &objpt_c, &rvec_c, &tvec_c, &A_c, + distCoeffs.empty() ? 0 : &dk_c, + &err_c, &dpdr_c, &dpdt_c, 0, 0, 0, 0 ); + } + else + { + projectPoints( objpt, rvec, tvec, cameraMatrix, distCoeffs, err); + } + err = err - imgpt; + err = err.reshape(1, 2*count); + return true; + } + + Mat objpt, imgpt, cameraMatrix, distCoeffs; +}; + + +void cv::findExtrinsicCameraParams2( const Mat& objectPoints, + const Mat& imagePoints, const Mat& A, + const Mat& distCoeffs, Mat& rvec, Mat& tvec, + int useExtrinsicGuess ) +{ + const int max_iter = 20; + Mat matM, _m, _mn; + + int i, count; + double a[9], ar[9]={1,0,0,0,1,0,0,0,1}, R[9]; + double MM[9] = { 0 }, U[9] = { 0 }, V[9] = { 0 }, W[3] = { 0 }; + double param[6] = { 0 }; + Mat matA( 3, 3, CV_64F, a ); + Mat _Ar( 3, 3, CV_64F, ar ); + Mat matR( 3, 3, CV_64F, R ); + Mat _r( 3, 1, CV_64F, param ); + Mat _t( 3, 1, CV_64F, param + 3 ); + Mat _MM( 3, 3, CV_64F, MM ); + Mat matU( 3, 3, CV_64F, U ); + Mat matV( 3, 3, CV_64F, V ); + Mat matW( 3, 1, CV_64F, W ); + Mat _param( 6, 1, CV_64F, param ); + Mat _dpdr, _dpdt; + + count = MAX(objectPoints.cols, objectPoints.rows); + if (objectPoints.checkVector(3) > 0) + objectPoints.convertTo(matM, CV_64F); + else + convertPointsFromHomogeneous(objectPoints, matM, CV_64F); + if (imagePoints.checkVector(2) > 0) + imagePoints.convertTo(_m, CV_64F); + else + convertPointsFromHomogeneous(imagePoints, _m, CV_64F); + A.convertTo(matA, CV_64F); + + CV_Assert((count >= 4) || (count == 3 && useExtrinsicGuess)); // it is unsafe to call LM optimisation without an extrinsic guess in the case of 3 points. This is because there is no guarantee that it will converge on the correct solution. + + // normalize image points + // (unapply the intrinsic matrix transformation and distortion) + undistortPoints(_m, _mn, matA, distCoeffs, Mat(), _Ar); + + if( useExtrinsicGuess ) + { + CV_Assert((rvec.rows == 1 || rvec.cols == 1) && rvec.total()*rvec.channels() == 3); + CV_Assert((tvec.rows == 1 || tvec.cols == 1) && tvec.total()*tvec.channels() == 3); + Mat _r_temp(rvec.rows, rvec.cols, CV_MAKETYPE(CV_64F,rvec.channels()), param); + Mat _t_temp(tvec.rows, tvec.cols, CV_MAKETYPE(CV_64F,tvec.channels()), param + 3); + rvec.convertTo(_r_temp, CV_64F); + tvec.convertTo(_t_temp, CV_64F); + } + else + { + Scalar Mc = mean(matM); + Mat _Mc( 1, 3, CV_64F, Mc.val ); + + matM = matM.reshape(1, count); + mulTransposed(matM, _MM, true, _Mc); + SVDecomp(_MM, matW, noArray(), matV, SVD::MODIFY_A); + CV_Assert(matW.ptr() == W); + CV_Assert(matV.ptr() == V); + + // initialize extrinsic parameters + if( W[2]/W[1] < 1e-3) + { + // a planar structure case (all M's lie in the same plane) + double tt[3]; + Mat R_transform = matV; + Mat T_transform( 3, 1, CV_64F, tt ); + + if( V[2]*V[2] + V[5]*V[5] < 1e-10 ) + R_transform = Mat::eye(3, 3, CV_64F); + + if( determinant(R_transform) < 0 ) + R_transform *= -1.; + + gemm( R_transform, _Mc, -1, Mat(), 0, T_transform, GEMM_2_T ); + + const double* Rp = R_transform.ptr(); + const double* Tp = T_transform.ptr(); + + Mat _Mxy(count, 1, CV_64FC2); + const double* src = (double*)matM.data; + double* dst = (double*)_Mxy.data; + + for( i = 0; i < count; i++, src += 3, dst += 2 ) + { + dst[0] = Rp[0]*src[0] + Rp[1]*src[1] + Rp[2]*src[2] + Tp[0]; + dst[1] = Rp[3]*src[0] + Rp[4]*src[1] + Rp[5]*src[2] + Tp[1]; + } + + Mat matH = findHomography(_Mxy, _mn); + + if( checkRange(matH, true)) + { + Mat _h1 = matH.col(0); + Mat _h2 = matH.col(1); + Mat _h3 = matH.col(2); + double* h = matH.ptr(); + CV_Assert(matH.isContinuous()); + double h1_norm = std::sqrt(h[0]*h[0] + h[3]*h[3] + h[6]*h[6]); + double h2_norm = std::sqrt(h[1]*h[1] + h[4]*h[4] + h[7]*h[7]); + + _h1 *= 1./MAX(h1_norm, DBL_EPSILON); + _h2 *= 1./MAX(h2_norm, DBL_EPSILON); + _t = _h3 * (2./MAX(h1_norm + h2_norm, DBL_EPSILON)); + _h1.cross(_h2).copyTo(_h3); + + Rodrigues( matH, _r ); + Rodrigues( _r, matH ); + _t += matH*T_transform; + matR = matH * R_transform; + } + else + { + setIdentity(matR); + _t.setTo(Scalar::all(0)); + } + + Rodrigues( matR, _r ); + } + else + { + // non-planar structure. Use DLT method + CV_CheckGE(count, 6, "DLT algorithm needs at least 6 points for pose estimation from 3D-2D point correspondences."); + double LL[12*12], LW[12], LV[12*12], sc; + Mat _LL( 12, 12, CV_64F, LL ); + Mat _LW( 12, 1, CV_64F, LW ); + Mat _LV( 12, 12, CV_64F, LV ); + Point3d* M = (Point3d*)matM.data; + Point2d* mn = (Point2d*)_mn.data; + + Mat matL(2*count, 12, CV_64F); + double* L = matL.ptr(); + + for( i = 0; i < count; i++, L += 24 ) + { + double x = -mn[i].x, y = -mn[i].y; + L[0] = L[16] = M[i].x; + L[1] = L[17] = M[i].y; + L[2] = L[18] = M[i].z; + L[3] = L[19] = 1.; + L[4] = L[5] = L[6] = L[7] = 0.; + L[12] = L[13] = L[14] = L[15] = 0.; + L[8] = x*M[i].x; + L[9] = x*M[i].y; + L[10] = x*M[i].z; + L[11] = x; + L[20] = y*M[i].x; + L[21] = y*M[i].y; + L[22] = y*M[i].z; + L[23] = y; + } + + mulTransposed( matL, _LL, true ); + SVDecomp( _LL, _LW, noArray(), _LV, SVD::MODIFY_A ); + Mat _RRt( 3, 4, CV_64F, LV + 11*12 ); + Mat _RR = _RRt.colRange(0, 3); + Mat _tt = _RRt.col(3); + if( determinant(_RR) < 0 ) + _RRt *= -1.0; + sc = norm(_RR, NORM_L2); + CV_Assert(fabs(sc) > DBL_EPSILON); + SVDecomp(_RR, matW, matU, matV, SVD::MODIFY_A); + matR = matU*matV; + _tt.convertTo(_t, CV_64F, norm(matR, NORM_L2)/sc); + Rodrigues(matR, _r); + } + } + + matM = matM.reshape(3, 1); + _mn = _mn.reshape(2, 1); + + // refine extrinsic parameters using iterative algorithm + Ptr callb = makePtr(matM, _m, matA, distCoeffs); + Ptr solver = LMSolver::create(callb, max_iter, (double)FLT_EPSILON); + solver->run(_param); + _param.rowRange(0, 3).copyTo(rvec); + _param.rowRange(3, 6).copyTo(tvec); +} + + +void cv::Rodrigues(InputArray _src, OutputArray _dst, OutputArray _jacobian) +{ + CV_INSTRUMENT_REGION(); + + Mat src = _src.getMat(); + const Size srcSz = src.size(); + CV_Check(srcSz, srcSz == Size(3, 1) || srcSz == Size(1, 3) || + (srcSz == Size(1, 1) && src.channels() == 3) || + srcSz == Size(3, 3), + "Input matrix must be 1x3 or 3x1 for a rotation vector, or 3x3 for a rotation matrix"); + + bool v2m = src.cols == 1 || src.rows == 1; + _dst.create(3, v2m ? 3 : 1, src.depth()); + Mat dst = _dst.getMat(); + CvMat _csrc = cvMat(src), _cdst = cvMat(dst), _cjacobian; + if( _jacobian.needed() ) + { + _jacobian.create(v2m ? Size(9, 3) : Size(3, 9), src.depth()); + _cjacobian = cvMat(_jacobian.getMat()); + } + bool ok = cvRodrigues2(&_csrc, &_cdst, _jacobian.needed() ? &_cjacobian : 0) > 0; + if( !ok ) + dst = Scalar(0); +} + +void cv::matMulDeriv( InputArray _Amat, InputArray _Bmat, + OutputArray _dABdA, OutputArray _dABdB ) +{ + CV_INSTRUMENT_REGION(); + + Mat A = _Amat.getMat(), B = _Bmat.getMat(); + _dABdA.create(A.rows*B.cols, A.rows*A.cols, A.type()); + _dABdB.create(A.rows*B.cols, B.rows*B.cols, A.type()); + Mat dABdA = _dABdA.getMat(), dABdB = _dABdB.getMat(); + CvMat matA = cvMat(A), matB = cvMat(B), c_dABdA = cvMat(dABdA), c_dABdB = cvMat(dABdB); + cvCalcMatMulDeriv(&matA, &matB, &c_dABdA, &c_dABdB); +} + + +void cv::composeRT( InputArray _rvec1, InputArray _tvec1, + InputArray _rvec2, InputArray _tvec2, + OutputArray _rvec3, OutputArray _tvec3, + OutputArray _dr3dr1, OutputArray _dr3dt1, + OutputArray _dr3dr2, OutputArray _dr3dt2, + OutputArray _dt3dr1, OutputArray _dt3dt1, + OutputArray _dt3dr2, OutputArray _dt3dt2 ) +{ + Mat rvec1 = _rvec1.getMat(), tvec1 = _tvec1.getMat(); + Mat rvec2 = _rvec2.getMat(), tvec2 = _tvec2.getMat(); + int rtype = rvec1.type(); + _rvec3.create(rvec1.size(), rtype); + _tvec3.create(tvec1.size(), rtype); + Mat rvec3 = _rvec3.getMat(), tvec3 = _tvec3.getMat(); + + CvMat c_rvec1 = cvMat(rvec1), c_tvec1 = cvMat(tvec1), c_rvec2 = cvMat(rvec2), + c_tvec2 = cvMat(tvec2), c_rvec3 = cvMat(rvec3), c_tvec3 = cvMat(tvec3); + CvMat c_dr3dr1, c_dr3dt1, c_dr3dr2, c_dr3dt2, c_dt3dr1, c_dt3dt1, c_dt3dr2, c_dt3dt2; + CvMat *p_dr3dr1=0, *p_dr3dt1=0, *p_dr3dr2=0, *p_dr3dt2=0, *p_dt3dr1=0, *p_dt3dt1=0, *p_dt3dr2=0, *p_dt3dt2=0; +#define CV_COMPOSE_RT_PARAM(name) \ + Mat name; \ + if (_ ## name.needed())\ + { \ + _ ## name.create(3, 3, rtype); \ + name = _ ## name.getMat(); \ + p_ ## name = &(c_ ## name = cvMat(name)); \ + } + + CV_COMPOSE_RT_PARAM(dr3dr1); CV_COMPOSE_RT_PARAM(dr3dt1); + CV_COMPOSE_RT_PARAM(dr3dr2); CV_COMPOSE_RT_PARAM(dr3dt2); + CV_COMPOSE_RT_PARAM(dt3dr1); CV_COMPOSE_RT_PARAM(dt3dt1); + CV_COMPOSE_RT_PARAM(dt3dr2); CV_COMPOSE_RT_PARAM(dt3dt2); +#undef CV_COMPOSE_RT_PARAM + + cvComposeRT(&c_rvec1, &c_tvec1, &c_rvec2, &c_tvec2, &c_rvec3, &c_tvec3, + p_dr3dr1, p_dr3dt1, p_dr3dr2, p_dr3dt2, + p_dt3dr1, p_dt3dt1, p_dt3dr2, p_dt3dt2); +} + + +void cv::projectPoints( InputArray _opoints, + InputArray _rvec, + InputArray _tvec, + InputArray _cameraMatrix, + InputArray _distCoeffs, + OutputArray _ipoints, + OutputArray _jacobian, + double aspectRatio ) +{ + Mat opoints = _opoints.getMat(); + int npoints = opoints.checkVector(3), depth = opoints.depth(); + if (npoints < 0) + opoints = opoints.t(); + npoints = opoints.checkVector(3); + CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_64F)); + + if (opoints.cols == 3) + opoints = opoints.reshape(3); + + CvMat dpdrot, dpdt, dpdf, dpdc, dpddist; + CvMat *pdpdrot=0, *pdpdt=0, *pdpdf=0, *pdpdc=0, *pdpddist=0; + + CV_Assert( _ipoints.needed() ); + + _ipoints.create(npoints, 1, CV_MAKETYPE(depth, 2), -1, true); + Mat imagePoints = _ipoints.getMat(); + CvMat c_imagePoints = cvMat(imagePoints); + CvMat c_objectPoints = cvMat(opoints); + Mat cameraMatrix = _cameraMatrix.getMat(); + + Mat rvec = _rvec.getMat(), tvec = _tvec.getMat(); + CvMat c_cameraMatrix = cvMat(cameraMatrix); + CvMat c_rvec = cvMat(rvec), c_tvec = cvMat(tvec); + + double dc0buf[5]={0}; + Mat dc0(5,1,CV_64F,dc0buf); + Mat distCoeffs = _distCoeffs.getMat(); + if( distCoeffs.empty() ) + distCoeffs = dc0; + CvMat c_distCoeffs = cvMat(distCoeffs); + int ndistCoeffs = distCoeffs.rows + distCoeffs.cols - 1; + + Mat jacobian; + if( _jacobian.needed() ) + { + _jacobian.create(npoints*2, 3+3+2+2+ndistCoeffs, CV_64F); + jacobian = _jacobian.getMat(); + pdpdrot = &(dpdrot = cvMat(jacobian.colRange(0, 3))); + pdpdt = &(dpdt = cvMat(jacobian.colRange(3, 6))); + pdpdf = &(dpdf = cvMat(jacobian.colRange(6, 8))); + pdpdc = &(dpdc = cvMat(jacobian.colRange(8, 10))); + pdpddist = &(dpddist = cvMat(jacobian.colRange(10, 10+ndistCoeffs))); + } + + cvProjectPoints2( &c_objectPoints, &c_rvec, &c_tvec, &c_cameraMatrix, &c_distCoeffs, + &c_imagePoints, pdpdrot, pdpdt, pdpdf, pdpdc, pdpddist, aspectRatio ); +} + +void cv::getUndistortRectangles(InputArray _cameraMatrix, InputArray _distCoeffs, + InputArray R, InputArray newCameraMatrix, Size imgSize, + Rect_& inner, Rect_& outer ) +{ + const int N = 9; + int x, y, k; + Mat _pts(1, N*N, CV_32FC2); + Point2f* pts = _pts.ptr(); + + for( y = k = 0; y < N; y++ ) + for( x = 0; x < N; x++ ) + pts[k++] = Point2f((float)x*imgSize.width/(N-1), (float)y*imgSize.height/(N-1)); + + undistortPoints(_pts, _pts, _cameraMatrix, _distCoeffs, R, newCameraMatrix); + + float iX0=-FLT_MAX, iX1=FLT_MAX, iY0=-FLT_MAX, iY1=FLT_MAX; + float oX0=FLT_MAX, oX1=-FLT_MAX, oY0=FLT_MAX, oY1=-FLT_MAX; + // find the inscribed rectangle. + // the code will likely not work with extreme rotation matrices (R) (>45%) + for( y = k = 0; y < N; y++ ) + for( x = 0; x < N; x++ ) + { + Point2f p = pts[k++]; + oX0 = MIN(oX0, p.x); + oX1 = MAX(oX1, p.x); + oY0 = MIN(oY0, p.y); + oY1 = MAX(oY1, p.y); + + if( x == 0 ) + iX0 = MAX(iX0, p.x); + if( x == N-1 ) + iX1 = MIN(iX1, p.x); + if( y == 0 ) + iY0 = MAX(iY0, p.y); + if( y == N-1 ) + iY1 = MIN(iY1, p.y); + } + inner = Rect_(iX0, iY0, iX1-iX0, iY1-iY0); + outer = Rect_(oX0, oY0, oX1-oX0, oY1-oY0); +} + +cv::Mat cv::getOptimalNewCameraMatrix( InputArray _cameraMatrix, InputArray _distCoeffs, + Size imgSize, double alpha, Size newImgSize, + Rect* validPixROI, bool centerPrincipalPoint ) +{ + Rect_ inner, outer; + newImgSize = newImgSize.width*newImgSize.height != 0 ? newImgSize : imgSize; + + Mat cameraMatrix = _cameraMatrix.getMat(), M; + cameraMatrix.convertTo(M, CV_64F); + CV_Assert(M.isContinuous()); + + if( centerPrincipalPoint ) + { + double cx0 = M.at(0, 2); + double cy0 = M.at(1, 2); + double cx = (newImgSize.width-1)*0.5; + double cy = (newImgSize.height-1)*0.5; + + getUndistortRectangles( _cameraMatrix, _distCoeffs, Mat(), cameraMatrix, imgSize, inner, outer ); + double s0 = std::max(std::max(std::max((double)cx/(cx0 - inner.x), (double)cy/(cy0 - inner.y)), + (double)cx/(inner.x + inner.width - cx0)), + (double)cy/(inner.y + inner.height - cy0)); + double s1 = std::min(std::min(std::min((double)cx/(cx0 - outer.x), (double)cy/(cy0 - outer.y)), + (double)cx/(outer.x + outer.width - cx0)), + (double)cy/(outer.y + outer.height - cy0)); + double s = s0*(1 - alpha) + s1*alpha; + + M.at(0, 0) *= s; + M.at(1, 1) *= s; + M.at(0, 2) = cx; + M.at(1, 2) = cy; + + if( validPixROI ) + { + inner = cv::Rect_((float)((inner.x - cx0)*s + cx), + (float)((inner.y - cy0)*s + cy), + (float)(inner.width*s), + (float)(inner.height*s)); + Rect r(cvCeil(inner.x), cvCeil(inner.y), cvFloor(inner.width), cvFloor(inner.height)); + r &= Rect(0, 0, newImgSize.width, newImgSize.height); + *validPixROI = r; + } + } + else + { + // Get inscribed and circumscribed rectangles in normalized + // (independent of camera matrix) coordinates + getUndistortRectangles( _cameraMatrix, _distCoeffs, Mat(), Mat(), imgSize, inner, outer ); + + // Projection mapping inner rectangle to viewport + double fx0 = (newImgSize.width - 1) / inner.width; + double fy0 = (newImgSize.height - 1) / inner.height; + double cx0 = -fx0 * inner.x; + double cy0 = -fy0 * inner.y; + + // Projection mapping outer rectangle to viewport + double fx1 = (newImgSize.width - 1) / outer.width; + double fy1 = (newImgSize.height - 1) / outer.height; + double cx1 = -fx1 * outer.x; + double cy1 = -fy1 * outer.y; + + // Interpolate between the two optimal projections + M.at(0, 0) = fx0*(1 - alpha) + fx1*alpha; + M.at(1, 1) = fy0*(1 - alpha) + fy1*alpha; + M.at(0, 2) = cx0*(1 - alpha) + cx1*alpha; + M.at(1, 2) = cy0*(1 - alpha) + cy1*alpha; + + if( validPixROI ) + { + getUndistortRectangles( _cameraMatrix, _distCoeffs, Mat(), M, imgSize, inner, outer ); + Rect r = inner; + r &= Rect(0, 0, newImgSize.width, newImgSize.height); + *validPixROI = r; + } + } + + return M; +} + +cv::Vec3d cv::RQDecomp3x3( InputArray _Mmat, + OutputArray _Rmat, + OutputArray _Qmat, + OutputArray _Qx, + OutputArray _Qy, + OutputArray _Qz ) +{ + CV_INSTRUMENT_REGION(); + + Mat M = _Mmat.getMat(); + _Rmat.create(3, 3, M.type()); + _Qmat.create(3, 3, M.type()); + Mat Rmat = _Rmat.getMat(); + Mat Qmat = _Qmat.getMat(); + Vec3d eulerAngles; + + CvMat matM = cvMat(M), matR = cvMat(Rmat), matQ = cvMat(Qmat); +#define CV_RQDecomp3x3_PARAM(name) \ + Mat name; \ + CvMat c_ ## name, *p ## name = NULL; \ + if( _ ## name.needed() ) \ + { \ + _ ## name.create(3, 3, M.type()); \ + name = _ ## name.getMat(); \ + c_ ## name = cvMat(name); p ## name = &c_ ## name; \ + } + + CV_RQDecomp3x3_PARAM(Qx); + CV_RQDecomp3x3_PARAM(Qy); + CV_RQDecomp3x3_PARAM(Qz); +#undef CV_RQDecomp3x3_PARAM + cvRQDecomp3x3(&matM, &matR, &matQ, pQx, pQy, pQz, (CvPoint3D64f*)&eulerAngles[0]); + return eulerAngles; +} + + +void cv::decomposeProjectionMatrix( InputArray _projMatrix, OutputArray _cameraMatrix, + OutputArray _rotMatrix, OutputArray _transVect, + OutputArray _rotMatrixX, OutputArray _rotMatrixY, + OutputArray _rotMatrixZ, OutputArray _eulerAngles ) +{ + CV_INSTRUMENT_REGION(); + + Mat projMatrix = _projMatrix.getMat(); + int type = projMatrix.type(); + _cameraMatrix.create(3, 3, type); + _rotMatrix.create(3, 3, type); + _transVect.create(4, 1, type); + Mat cameraMatrix = _cameraMatrix.getMat(); + Mat rotMatrix = _rotMatrix.getMat(); + Mat transVect = _transVect.getMat(); + CvMat c_projMatrix = cvMat(projMatrix), c_cameraMatrix = cvMat(cameraMatrix); + CvMat c_rotMatrix = cvMat(rotMatrix), c_transVect = cvMat(transVect); + CvPoint3D64f *p_eulerAngles = 0; + +#define CV_decomposeProjectionMatrix_PARAM(name) \ + Mat name; \ + CvMat c_ ## name, *p_ ## name = NULL; \ + if( _ ## name.needed() ) \ + { \ + _ ## name.create(3, 3, type); \ + name = _ ## name.getMat(); \ + c_ ## name = cvMat(name); p_ ## name = &c_ ## name; \ + } + + CV_decomposeProjectionMatrix_PARAM(rotMatrixX); + CV_decomposeProjectionMatrix_PARAM(rotMatrixY); + CV_decomposeProjectionMatrix_PARAM(rotMatrixZ); +#undef CV_decomposeProjectionMatrix_PARAM + + if( _eulerAngles.needed() ) + { + _eulerAngles.create(3, 1, CV_64F, -1, true); + p_eulerAngles = _eulerAngles.getMat().ptr(); + } + + cvDecomposeProjectionMatrix(&c_projMatrix, &c_cameraMatrix, &c_rotMatrix, + &c_transVect, p_rotMatrixX, p_rotMatrixY, + p_rotMatrixZ, p_eulerAngles); +} + +/* End of file. */ diff --git a/modules/calib3d/src/compat_ptsetreg.cpp b/modules/3d/src/compat_ptsetreg.cpp similarity index 63% rename from modules/calib3d/src/compat_ptsetreg.cpp rename to modules/3d/src/compat_ptsetreg.cpp index 05c71cc409..b87b5bac6d 100644 --- a/modules/calib3d/src/compat_ptsetreg.cpp +++ b/modules/3d/src/compat_ptsetreg.cpp @@ -42,13 +42,12 @@ #include "precomp.hpp" #include "opencv2/core/core_c.h" -#include "calib3d_c_api.h" /************************************************************************************\ Some backward compatibility stuff, to be moved to legacy or compat module \************************************************************************************/ -using cv::Ptr; +namespace cv { ////////////////// Levenberg-Marquardt engine (the old variant) //////////////////////// @@ -258,11 +257,12 @@ bool CvLevMarq::updateAlt( const CvMat*& _param, CvMat*& _JtJ, CvMat*& _JtErr, d return true; } -namespace { -static void subMatrix(const cv::Mat& src, cv::Mat& dst, const std::vector& cols, - const std::vector& rows) { - int nonzeros_cols = cv::countNonZero(cols); - cv::Mat tmp(src.rows, nonzeros_cols, CV_64FC1); +static void subMatrix(const Mat& src, Mat& dst, + const std::vector& cols, + const std::vector& rows) +{ + int nonzeros_cols = countNonZero(cols); + Mat tmp(src.rows, nonzeros_cols, CV_64FC1); for (int i = 0, j = 0; i < (int)cols.size(); i++) { @@ -283,9 +283,6 @@ static void subMatrix(const cv::Mat& src, cv::Mat& dst, const std::vector } } -} - - void CvLevMarq::step() { using namespace cv; @@ -322,150 +319,4 @@ void CvLevMarq::step() param->data.db[i] = prevParam->data.db[i] - (mask->data.ptr[i] ? nonzero_param(j++) : 0); } -CV_IMPL int cvRANSACUpdateNumIters( double p, double ep, int modelPoints, int maxIters ) -{ - return cv::RANSACUpdateNumIters(p, ep, modelPoints, maxIters); -} - - -CV_IMPL int cvFindHomography( const CvMat* _src, const CvMat* _dst, CvMat* __H, int method, - double ransacReprojThreshold, CvMat* _mask, int maxIters, - double confidence) -{ - cv::Mat src = cv::cvarrToMat(_src), dst = cv::cvarrToMat(_dst); - - if( src.channels() == 1 && (src.rows == 2 || src.rows == 3) && src.cols > 3 ) - cv::transpose(src, src); - if( dst.channels() == 1 && (dst.rows == 2 || dst.rows == 3) && dst.cols > 3 ) - cv::transpose(dst, dst); - - if ( maxIters < 0 ) - maxIters = 0; - if ( maxIters > 2000 ) - maxIters = 2000; - - if ( confidence < 0 ) - confidence = 0; - if ( confidence > 1 ) - confidence = 1; - - const cv::Mat H = cv::cvarrToMat(__H), mask = cv::cvarrToMat(_mask); - cv::Mat H0 = cv::findHomography(src, dst, method, ransacReprojThreshold, - _mask ? cv::_OutputArray(mask) : cv::_OutputArray(), maxIters, - confidence); - - if( H0.empty() ) - { - cv::Mat Hz = cv::cvarrToMat(__H); - Hz.setTo(cv::Scalar::all(0)); - return 0; - } - H0.convertTo(H, H.type()); - return 1; -} - - -CV_IMPL int cvFindFundamentalMat( const CvMat* points1, const CvMat* points2, - CvMat* fmatrix, int method, - double param1, double param2, CvMat* _mask ) -{ - cv::Mat m1 = cv::cvarrToMat(points1), m2 = cv::cvarrToMat(points2); - - if( m1.channels() == 1 && (m1.rows == 2 || m1.rows == 3) && m1.cols > 3 ) - cv::transpose(m1, m1); - if( m2.channels() == 1 && (m2.rows == 2 || m2.rows == 3) && m2.cols > 3 ) - cv::transpose(m2, m2); - - const cv::Mat FM = cv::cvarrToMat(fmatrix), mask = cv::cvarrToMat(_mask); - cv::Mat FM0 = cv::findFundamentalMat(m1, m2, method, param1, param2, - _mask ? cv::_OutputArray(mask) : cv::_OutputArray()); - - if( FM0.empty() ) - { - cv::Mat FM0z = cv::cvarrToMat(fmatrix); - FM0z.setTo(cv::Scalar::all(0)); - return 0; - } - - CV_Assert( FM0.cols == 3 && FM0.rows % 3 == 0 && FM.cols == 3 && FM.rows % 3 == 0 && FM.channels() == 1 ); - cv::Mat FM1 = FM.rowRange(0, MIN(FM0.rows, FM.rows)); - FM0.rowRange(0, FM1.rows).convertTo(FM1, FM1.type()); - return FM1.rows / 3; -} - - -CV_IMPL void cvComputeCorrespondEpilines( const CvMat* points, int pointImageID, - const CvMat* fmatrix, CvMat* _lines ) -{ - cv::Mat pt = cv::cvarrToMat(points), fm = cv::cvarrToMat(fmatrix); - cv::Mat lines = cv::cvarrToMat(_lines); - const cv::Mat lines0 = lines; - - if( pt.channels() == 1 && (pt.rows == 2 || pt.rows == 3) && pt.cols > 3 ) - cv::transpose(pt, pt); - - cv::computeCorrespondEpilines(pt, pointImageID, fm, lines); - - bool tflag = lines0.channels() == 1 && lines0.rows == 3 && lines0.cols > 3; - lines = lines.reshape(lines0.channels(), (tflag ? lines0.cols : lines0.rows)); - - if( tflag ) - { - CV_Assert( lines.rows == lines0.cols && lines.cols == lines0.rows ); - if( lines0.type() == lines.type() ) - transpose( lines, lines0 ); - else - { - transpose( lines, lines ); - lines.convertTo( lines0, lines0.type() ); - } - } - else - { - CV_Assert( lines.size() == lines0.size() ); - if( lines.data != lines0.data ) - lines.convertTo(lines0, lines0.type()); - } -} - - -CV_IMPL void cvConvertPointsHomogeneous( const CvMat* _src, CvMat* _dst ) -{ - cv::Mat src = cv::cvarrToMat(_src), dst = cv::cvarrToMat(_dst); - const cv::Mat dst0 = dst; - - int d0 = src.channels() > 1 ? src.channels() : MIN(src.cols, src.rows); - - if( src.channels() == 1 && src.cols > d0 ) - cv::transpose(src, src); - - int d1 = dst.channels() > 1 ? dst.channels() : MIN(dst.cols, dst.rows); - - if( d0 == d1 ) - src.copyTo(dst); - else if( d0 < d1 ) - cv::convertPointsToHomogeneous(src, dst); - else - cv::convertPointsFromHomogeneous(src, dst); - - bool tflag = dst0.channels() == 1 && dst0.cols > d1; - dst = dst.reshape(dst0.channels(), (tflag ? dst0.cols : dst0.rows)); - - if( tflag ) - { - CV_Assert( dst.rows == dst0.cols && dst.cols == dst0.rows ); - if( dst0.type() == dst.type() ) - transpose( dst, dst0 ); - else - { - transpose( dst, dst ); - dst.convertTo( dst0, dst0.type() ); - } - } - else - { - CV_Assert( dst.size() == dst0.size() ); - if( dst.data != dst0.data ) - dst.convertTo(dst0, dst0.type()); - } } diff --git a/modules/calib3d/src/distortion_model.hpp b/modules/3d/src/distortion_model.hpp similarity index 98% rename from modules/calib3d/src/distortion_model.hpp rename to modules/3d/src/distortion_model.hpp index a9c3ddec8a..9280c98c56 100644 --- a/modules/calib3d/src/distortion_model.hpp +++ b/modules/3d/src/distortion_model.hpp @@ -45,7 +45,7 @@ //! @cond IGNORED -namespace cv { namespace detail { +namespace cv { /** Computes the matrix for the projection onto a tilted image sensor \param tauX angular parameter rotation around x-axis @@ -115,7 +115,7 @@ void computeTiltProjectionMatrix(FLOAT tauX, *invMatTilt = matRotXY.t()*invMatProjZ; } } -}} // namespace detail, cv +} // namespace detail, _3d, cv //! @endcond diff --git a/modules/calib3d/src/dls.cpp b/modules/3d/src/dls.cpp similarity index 92% rename from modules/calib3d/src/dls.cpp rename to modules/3d/src/dls.cpp index a0ff0c3e1e..67b2cd8132 100644 --- a/modules/calib3d/src/dls.cpp +++ b/modules/3d/src/dls.cpp @@ -21,15 +21,15 @@ # include "opencv2/core/eigen.hpp" #endif -using namespace std; +namespace cv { -dls::dls(const cv::Mat& opoints, const cv::Mat& ipoints) +dls::dls(const Mat& opoints, const Mat& ipoints) { N = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F)); - p = cv::Mat(3, N, CV_64F); - z = cv::Mat(3, N, CV_64F); - mn = cv::Mat::zeros(3, 1, CV_64F); + p = Mat(3, N, CV_64F); + z = Mat(3, N, CV_64F); + mn = Mat::zeros(3, 1, CV_64F); cost__ = 9999; @@ -40,14 +40,14 @@ dls::dls(const cv::Mat& opoints, const cv::Mat& ipoints) if (opoints.depth() == ipoints.depth()) { if (opoints.depth() == CV_32F) - init_points(opoints, ipoints); + init_points(opoints, ipoints); else - init_points(opoints, ipoints); + init_points(opoints, ipoints); } else if (opoints.depth() == CV_32F) - init_points(opoints, ipoints); + init_points(opoints, ipoints); else - init_points(opoints, ipoints); + init_points(opoints, ipoints); } dls::~dls() @@ -55,10 +55,10 @@ dls::~dls() // TODO Auto-generated destructor stub } -bool dls::compute_pose(cv::Mat& R, cv::Mat& t) +bool dls::compute_pose(Mat& R, Mat& t) { - std::vector R_; + std::vector R_; R_.push_back(rotx(CV_PI/2)); R_.push_back(roty(CV_PI/2)); R_.push_back(rotz(CV_PI/2)); @@ -67,7 +67,7 @@ bool dls::compute_pose(cv::Mat& R, cv::Mat& t) for (int i = 0; i < 3; ++i) { // Make a random rotation - cv::Mat pp = R_[i] * ( p - cv::repeat(mn, 1, p.cols) ); + Mat pp = R_[i] * ( p - repeat(mn, 1, p.cols) ); // clear for new data C_est_.clear(); @@ -99,13 +99,13 @@ bool dls::compute_pose(cv::Mat& R, cv::Mat& t) return false; } -void dls::run_kernel(const cv::Mat& pp) +void dls::run_kernel(const Mat& pp) { - cv::Mat Mtilde(27, 27, CV_64F); - cv::Mat D = cv::Mat::zeros(9, 9, CV_64F); + Mat Mtilde(27, 27, CV_64F); + Mat D = Mat::zeros(9, 9, CV_64F); build_coeff_matrix(pp, Mtilde, D); - cv::Mat eigenval_r, eigenval_i, eigenvec_r, eigenvec_i; + Mat eigenval_r, eigenval_i, eigenvec_r, eigenvec_i; compute_eigenvec(Mtilde, eigenval_r, eigenval_i, eigenvec_r, eigenvec_i); /* @@ -115,16 +115,16 @@ void dls::run_kernel(const cv::Mat& pp) // extract the optimal solutions from the eigen decomposition of the // Multiplication matrix - cv::Mat sols = cv::Mat::zeros(3, 27, CV_64F); + Mat sols = Mat::zeros(3, 27, CV_64F); std::vector cost; int count = 0; for (int k = 0; k < 27; ++k) { // V(:,k) = V(:,k)/V(1,k); - cv::Mat V_kA = eigenvec_r.col(k); // 27x1 - cv::Mat V_kB = cv::Mat(1, 1, z.depth(), V_kA.at(0)); // 1x1 - cv::Mat V_k; cv::solve(V_kB.t(), V_kA.t(), V_k); // A/B = B'\A' - cv::Mat( V_k.t()).copyTo( eigenvec_r.col(k) ); + Mat V_kA = eigenvec_r.col(k); // 27x1 + Mat V_kB = Mat(1, 1, z.depth(), V_kA.at(0)); // 1x1 + Mat V_k; solve(V_kB.t(), V_kA.t(), V_k); // A/B = B'\A' + Mat( V_k.t()).copyTo( eigenvec_r.col(k) ); //if (imag(V(2,k)) == 0) #ifdef HAVE_EIGEN @@ -138,24 +138,24 @@ void dls::run_kernel(const cv::Mat& pp) stmp[1] = eigenvec_r.at(3, k); stmp[2] = eigenvec_r.at(1, k); - cv::Mat H = Hessian(stmp); + Mat H = Hessian(stmp); - cv::Mat eigenvalues, eigenvectors; - cv::eigen(H, eigenvalues, eigenvectors); + Mat eigenvalues, eigenvectors; + eigen(H, eigenvalues, eigenvectors); if(positive_eigenvalues(&eigenvalues)) { // sols(:,i) = stmp; - cv::Mat stmp_mat(3, 1, CV_64F, &stmp); + Mat stmp_mat(3, 1, CV_64F, &stmp); stmp_mat.copyTo( sols.col(count) ); - cv::Mat Cbar = cayley2rotbar(stmp_mat); - cv::Mat Cbarvec = Cbar.reshape(1,1).t(); + Mat Cbar = cayley2rotbar(stmp_mat); + Mat Cbarvec = Cbar.reshape(1,1).t(); // cost(i) = CbarVec' * D * CbarVec; - cv::Mat cost_mat = Cbarvec.t() * D * Cbarvec; + Mat cost_mat = Cbarvec.t() * D * Cbarvec; cost.push_back( cost_mat.at(0) ); count++; @@ -166,30 +166,30 @@ void dls::run_kernel(const cv::Mat& pp) // extract solutions sols = sols.clone().colRange(0, count); - std::vector C_est, t_est; + std::vector C_est, t_est; for (int j = 0; j < sols.cols; ++j) { // recover the optimal orientation // C_est(:,:,j) = 1/(1 + sols(:,j)' * sols(:,j)) * cayley2rotbar(sols(:,j)); - cv::Mat sols_j = sols.col(j); - double sols_mult = 1./(1.+cv::Mat( sols_j.t() * sols_j ).at(0)); - cv::Mat C_est_j = cayley2rotbar(sols_j).mul(sols_mult); + Mat sols_j = sols.col(j); + double sols_mult = 1./(1.+Mat( sols_j.t() * sols_j ).at(0)); + Mat C_est_j = cayley2rotbar(sols_j).mul(sols_mult); C_est.push_back( C_est_j ); - cv::Mat A2 = cv::Mat::zeros(3, 3, CV_64F); - cv::Mat b2 = cv::Mat::zeros(3, 1, CV_64F); + Mat A2 = Mat::zeros(3, 3, CV_64F); + Mat b2 = Mat::zeros(3, 1, CV_64F); for (int i = 0; i < N; ++i) { - cv::Mat eye = cv::Mat::eye(3, 3, CV_64F); - cv::Mat z_mul = z.col(i)*z.col(i).t(); + Mat eye = Mat::eye(3, 3, CV_64F); + Mat z_mul = z.col(i)*z.col(i).t(); A2 += eye - z_mul; b2 += (z_mul - eye) * C_est_j * pp.col(i); } // recover the optimal translation - cv::Mat X2; cv::solve(A2, b2, X2); // A\B + Mat X2; solve(A2, b2, X2); // A\B t_est.push_back(X2); } @@ -197,12 +197,12 @@ void dls::run_kernel(const cv::Mat& pp) // check that the points are infront of the center of perspectivity for (int k = 0; k < sols.cols; ++k) { - cv::Mat cam_points = C_est[k] * pp + cv::repeat(t_est[k], 1, pp.cols); - cv::Mat cam_points_k = cam_points.row(2); + Mat cam_points = C_est[k] * pp + repeat(t_est[k], 1, pp.cols); + Mat cam_points_k = cam_points.row(2); if(is_empty(&cam_points_k)) { - cv::Mat C_valid = C_est[k], t_valid = t_est[k]; + Mat C_valid = C_est[k], t_valid = t_est[k]; double cost_valid = cost[k]; C_est_.push_back(C_valid); @@ -213,20 +213,20 @@ void dls::run_kernel(const cv::Mat& pp) } -void dls::build_coeff_matrix(const cv::Mat& pp, cv::Mat& Mtilde, cv::Mat& D) +void dls::build_coeff_matrix(const Mat& pp, Mat& Mtilde, Mat& D) { CV_Assert(!pp.empty() && N > 0); - cv::Mat eye = cv::Mat::eye(3, 3, CV_64F); + Mat eye = Mat::eye(3, 3, CV_64F); // build coeff matrix // An intermediate matrix, the inverse of what is called "H" in the paper // (see eq. 25) - cv::Mat H = cv::Mat::zeros(3, 3, CV_64F); - cv::Mat A = cv::Mat::zeros(3, 9, CV_64F); - cv::Mat pp_i(3, 1, CV_64F); + Mat H = Mat::zeros(3, 3, CV_64F); + Mat A = Mat::zeros(3, 9, CV_64F); + Mat pp_i(3, 1, CV_64F); - cv::Mat z_i(3, 1, CV_64F); + Mat z_i(3, 1, CV_64F); for (int i = 0; i < N; ++i) { z.col(i).copyTo(z_i); @@ -236,10 +236,10 @@ void dls::build_coeff_matrix(const cv::Mat& pp, cv::Mat& Mtilde, cv::Mat& D) H = eye.mul(N) - z * z.t(); // A\B - cv::solve(H, A, A, cv::DECOMP_NORMAL); + solve(H, A, A, DECOMP_NORMAL); H.release(); - cv::Mat ppi_A(3, 1, CV_64F); + Mat ppi_A(3, 1, CV_64F); for (int i = 0; i < N; ++i) { z.col(i).copyTo(z_i); @@ -253,18 +253,18 @@ void dls::build_coeff_matrix(const cv::Mat& pp, cv::Mat& Mtilde, cv::Mat& D) // generate random samples std::vector u(5); - cv::randn(u, 0, 200); + randn(u, 0, 200); - cv::Mat M2 = cayley_LS_M(f1coeff, f2coeff, f3coeff, u); + Mat M2 = cayley_LS_M(f1coeff, f2coeff, f3coeff, u); - cv::Mat M2_1 = M2(cv::Range(0,27), cv::Range(0,27)); - cv::Mat M2_2 = M2(cv::Range(0,27), cv::Range(27,120)); - cv::Mat M2_3 = M2(cv::Range(27,120), cv::Range(27,120)); - cv::Mat M2_4 = M2(cv::Range(27,120), cv::Range(0,27)); + Mat M2_1 = M2(Range(0,27), Range(0,27)); + Mat M2_2 = M2(Range(0,27), Range(27,120)); + Mat M2_3 = M2(Range(27,120), Range(27,120)); + Mat M2_4 = M2(Range(27,120), Range(0,27)); M2.release(); // A/B = B'\A' - cv::Mat M2_5; cv::solve(M2_3.t(), M2_2.t(), M2_5); + Mat M2_5; solve(M2_3.t(), M2_2.t(), M2_5); M2_2.release(); M2_3.release(); // construct the multiplication matrix via schur compliment of the Macaulay @@ -273,13 +273,13 @@ void dls::build_coeff_matrix(const cv::Mat& pp, cv::Mat& Mtilde, cv::Mat& D) } -void dls::compute_eigenvec(const cv::Mat& Mtilde, cv::Mat& eigenval_real, cv::Mat& eigenval_imag, - cv::Mat& eigenvec_real, cv::Mat& eigenvec_imag) +void dls::compute_eigenvec(const Mat& Mtilde, Mat& eigenval_real, Mat& eigenval_imag, + Mat& eigenvec_real, Mat& eigenvec_imag) { #ifdef HAVE_EIGEN Eigen::MatrixXd Mtilde_eig, zeros_eig; - cv::cv2eigen(Mtilde, Mtilde_eig); - cv::cv2eigen(cv::Mat::zeros(27, 27, CV_64F), zeros_eig); + cv2eigen(Mtilde, Mtilde_eig); + cv2eigen(Mat::zeros(27, 27, CV_64F), zeros_eig); Eigen::MatrixXcd Mtilde_eig_cmplx(27, 27); Mtilde_eig_cmplx.real() = Mtilde_eig; @@ -293,20 +293,20 @@ void dls::compute_eigenvec(const cv::Mat& Mtilde, cv::Mat& eigenval_real, cv::Ma Eigen::MatrixXd eigvec_real = ces.eigenvectors().real(); Eigen::MatrixXd eigvec_imag = ces.eigenvectors().imag(); - cv::eigen2cv(eigval_real, eigenval_real); - cv::eigen2cv(eigval_imag, eigenval_imag); - cv::eigen2cv(eigvec_real, eigenvec_real); - cv::eigen2cv(eigvec_imag, eigenvec_imag); + eigen2cv(eigval_real, eigenval_real); + eigen2cv(eigval_imag, eigenval_imag); + eigen2cv(eigvec_real, eigenvec_real); + eigen2cv(eigvec_imag, eigenvec_imag); #else EigenvalueDecomposition es(Mtilde); eigenval_real = es.eigenvalues(); eigenvec_real = es.eigenvectors(); - eigenval_imag = eigenvec_imag = cv::Mat(); + eigenval_imag = eigenvec_imag = Mat(); #endif } -void dls::fill_coeff(const cv::Mat * D_mat) +void dls::fill_coeff(const Mat * D_mat) { // TODO: shift D and coefficients one position to left @@ -394,9 +394,9 @@ void dls::fill_coeff(const cv::Mat * D_mat) } -cv::Mat dls::LeftMultVec(const cv::Mat& v) +Mat dls::LeftMultVec(const Mat& v) { - cv::Mat mat_ = cv::Mat::zeros(3, 9, CV_64F); + Mat mat_ = Mat::zeros(3, 9, CV_64F); for (int i = 0; i < 3; ++i) { @@ -407,12 +407,12 @@ cv::Mat dls::LeftMultVec(const cv::Mat& v) return mat_; } -cv::Mat dls::cayley_LS_M(const std::vector& a, const std::vector& b, const std::vector& c, const std::vector& u) +Mat dls::cayley_LS_M(const std::vector& a, const std::vector& b, const std::vector& c, const std::vector& u) { // TODO: input matrix pointer // TODO: shift coefficients one position to left - cv::Mat M = cv::Mat::zeros(120, 120, CV_64F); + Mat M = Mat::zeros(120, 120, CV_64F); M.at(0,0)=u[1]; M.at(0,35)=a[1]; M.at(0,83)=b[1]; M.at(0,118)=c[1]; M.at(1,0)=u[4]; M.at(1,1)=u[1]; M.at(1,34)=a[1]; M.at(1,35)=a[10]; M.at(1,54)=b[1]; M.at(1,83)=b[10]; M.at(1,99)=c[1]; M.at(1,118)=c[10]; @@ -538,7 +538,7 @@ cv::Mat dls::cayley_LS_M(const std::vector& a, const std::vector return M.t(); } -cv::Mat dls::Hessian(const double s[]) +Mat dls::Hessian(const double s[]) { // the vector of monomials is // m = [ const ; s1^2 * s2 ; s1 * s2 ; s1 * s3 ; s2 * s3 ; s2^2 * s3 ; s2^3 ; ... @@ -577,73 +577,73 @@ cv::Mat dls::Hessian(const double s[]) Hs3[14]=0; Hs3[15]=3*s[2]*s[2]; Hs3[16]=s[0]*s[1]; Hs3[17]=0; Hs3[18]=s[0]*s[0]; Hs3[19]=0; // fill Hessian matrix - cv::Mat H(3, 3, CV_64F); - H.at(0,0) = cv::Mat(cv::Mat(f1coeff).rowRange(1,21).t()*cv::Mat(20, 1, CV_64F, &Hs1)).at(0,0); - H.at(0,1) = cv::Mat(cv::Mat(f1coeff).rowRange(1,21).t()*cv::Mat(20, 1, CV_64F, &Hs2)).at(0,0); - H.at(0,2) = cv::Mat(cv::Mat(f1coeff).rowRange(1,21).t()*cv::Mat(20, 1, CV_64F, &Hs3)).at(0,0); + Mat H(3, 3, CV_64F); + H.at(0,0) = Mat(Mat(f1coeff).rowRange(1,21).t()*Mat(20, 1, CV_64F, &Hs1)).at(0,0); + H.at(0,1) = Mat(Mat(f1coeff).rowRange(1,21).t()*Mat(20, 1, CV_64F, &Hs2)).at(0,0); + H.at(0,2) = Mat(Mat(f1coeff).rowRange(1,21).t()*Mat(20, 1, CV_64F, &Hs3)).at(0,0); - H.at(1,0) = cv::Mat(cv::Mat(f2coeff).rowRange(1,21).t()*cv::Mat(20, 1, CV_64F, &Hs1)).at(0,0); - H.at(1,1) = cv::Mat(cv::Mat(f2coeff).rowRange(1,21).t()*cv::Mat(20, 1, CV_64F, &Hs2)).at(0,0); - H.at(1,2) = cv::Mat(cv::Mat(f2coeff).rowRange(1,21).t()*cv::Mat(20, 1, CV_64F, &Hs3)).at(0,0); + H.at(1,0) = Mat(Mat(f2coeff).rowRange(1,21).t()*Mat(20, 1, CV_64F, &Hs1)).at(0,0); + H.at(1,1) = Mat(Mat(f2coeff).rowRange(1,21).t()*Mat(20, 1, CV_64F, &Hs2)).at(0,0); + H.at(1,2) = Mat(Mat(f2coeff).rowRange(1,21).t()*Mat(20, 1, CV_64F, &Hs3)).at(0,0); - H.at(2,0) = cv::Mat(cv::Mat(f3coeff).rowRange(1,21).t()*cv::Mat(20, 1, CV_64F, &Hs1)).at(0,0); - H.at(2,1) = cv::Mat(cv::Mat(f3coeff).rowRange(1,21).t()*cv::Mat(20, 1, CV_64F, &Hs2)).at(0,0); - H.at(2,2) = cv::Mat(cv::Mat(f3coeff).rowRange(1,21).t()*cv::Mat(20, 1, CV_64F, &Hs3)).at(0,0); + H.at(2,0) = Mat(Mat(f3coeff).rowRange(1,21).t()*Mat(20, 1, CV_64F, &Hs1)).at(0,0); + H.at(2,1) = Mat(Mat(f3coeff).rowRange(1,21).t()*Mat(20, 1, CV_64F, &Hs2)).at(0,0); + H.at(2,2) = Mat(Mat(f3coeff).rowRange(1,21).t()*Mat(20, 1, CV_64F, &Hs3)).at(0,0); return H; } -cv::Mat dls::cayley2rotbar(const cv::Mat& s) +Mat dls::cayley2rotbar(const Mat& s) { - double s_mul1 = cv::Mat(s.t()*s).at(0,0); - cv::Mat s_mul2 = s*s.t(); - cv::Mat eye = cv::Mat::eye(3, 3, CV_64F); + double s_mul1 = Mat(s.t()*s).at(0,0); + Mat s_mul2 = s*s.t(); + Mat eye = Mat::eye(3, 3, CV_64F); - return cv::Mat( eye.mul(1.-s_mul1) + skewsymm(&s).mul(2.) + s_mul2.mul(2.) ).t(); + return Mat( eye.mul(1.-s_mul1) + skewsymm(&s).mul(2.) + s_mul2.mul(2.) ).t(); } -cv::Mat dls::skewsymm(const cv::Mat * X1) +Mat dls::skewsymm(const Mat * X1) { - cv::MatConstIterator_ it = X1->begin(); - return (cv::Mat_(3,3) << 0, -*(it+2), *(it+1), + MatConstIterator_ it = X1->begin(); + return (Mat_(3,3) << 0, -*(it+2), *(it+1), *(it+2), 0, -*(it+0), -*(it+1), *(it+0), 0); } -cv::Mat dls::rotx(const double t) +Mat dls::rotx(const double t) { // rotx: rotation about y-axis double ct = cos(t); double st = sin(t); - return (cv::Mat_(3,3) << 1, 0, 0, 0, ct, -st, 0, st, ct); + return (Mat_(3,3) << 1, 0, 0, 0, ct, -st, 0, st, ct); } -cv::Mat dls::roty(const double t) +Mat dls::roty(const double t) { // roty: rotation about y-axis double ct = cos(t); double st = sin(t); - return (cv::Mat_(3,3) << ct, 0, st, 0, 1, 0, -st, 0, ct); + return (Mat_(3,3) << ct, 0, st, 0, 1, 0, -st, 0, ct); } -cv::Mat dls::rotz(const double t) +Mat dls::rotz(const double t) { // rotz: rotation about y-axis double ct = cos(t); double st = sin(t); - return (cv::Mat_(3,3) << ct, -st, 0, st, ct, 0, 0, 0, 1); + return (Mat_(3,3) << ct, -st, 0, st, ct, 0, 0, 0, 1); } -cv::Mat dls::mean(const cv::Mat& M) +Mat dls::mean(const Mat& M) { - cv::Mat m = cv::Mat::zeros(3, 1, CV_64F); + Mat m = Mat::zeros(3, 1, CV_64F); for (int i = 0; i < M.cols; ++i) m += M.col(i); return m.mul(1./(double)M.cols); } -bool dls::is_empty(const cv::Mat * M) +bool dls::is_empty(const Mat * M) { - cv::MatConstIterator_ it = M->begin(), it_end = M->end(); + MatConstIterator_ it = M->begin(), it_end = M->end(); for(; it != it_end; ++it) { if(*it < 0) return false; @@ -651,9 +651,11 @@ bool dls::is_empty(const cv::Mat * M) return true; } -bool dls::positive_eigenvalues(const cv::Mat * eigenvalues) +bool dls::positive_eigenvalues(const Mat * eigenvalues) { CV_Assert(eigenvalues && !eigenvalues->empty()); - cv::MatConstIterator_ it = eigenvalues->begin(); + MatConstIterator_ it = eigenvalues->begin(); return *(it) > 0 && *(it+1) > 0 && *(it+2) > 0; } + +} diff --git a/modules/calib3d/src/dls.h b/modules/3d/src/dls.h similarity index 99% rename from modules/calib3d/src/dls.h rename to modules/3d/src/dls.h index f03bee49d7..8c385709b2 100644 --- a/modules/calib3d/src/dls.h +++ b/modules/3d/src/dls.h @@ -2,11 +2,9 @@ #define DLS_H_ #include "precomp.hpp" - #include -using namespace std; -using namespace cv; +namespace cv { class dls { @@ -770,4 +768,6 @@ public: Mat eigenvectors() { return _eigenvectors; } }; +} + #endif // DLS_H diff --git a/modules/calib3d/src/epnp.cpp b/modules/3d/src/epnp.cpp similarity index 98% rename from modules/calib3d/src/epnp.cpp rename to modules/3d/src/epnp.cpp index 9a887c8067..c66506d23a 100644 --- a/modules/calib3d/src/epnp.cpp +++ b/modules/3d/src/epnp.cpp @@ -1,9 +1,12 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + #include #include "precomp.hpp" #include "epnp.h" -namespace cv -{ +namespace cv { epnp::epnp(const Mat& cameraMatrix, const Mat& opoints, const Mat& ipoints) { diff --git a/modules/calib3d/src/epnp.h b/modules/3d/src/epnp.h similarity index 93% rename from modules/calib3d/src/epnp.h rename to modules/3d/src/epnp.h index a66596b368..a6db4b7078 100644 --- a/modules/calib3d/src/epnp.h +++ b/modules/3d/src/epnp.h @@ -1,11 +1,14 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + #ifndef epnp_h #define epnp_h #include "precomp.hpp" #include "opencv2/core/core_c.h" -namespace cv -{ +namespace cv { class epnp { public: diff --git a/modules/calib3d/src/five-point.cpp b/modules/3d/src/five-point.cpp similarity index 99% rename from modules/calib3d/src/five-point.cpp rename to modules/3d/src/five-point.cpp index f35b7bb4b2..c7339d8f7c 100644 --- a/modules/calib3d/src/five-point.cpp +++ b/modules/3d/src/five-point.cpp @@ -30,11 +30,9 @@ */ #include "precomp.hpp" - #include "usac.hpp" -namespace cv -{ +namespace cv { class EMEstimatorCallback CV_FINAL : public PointSetRegistrator::Callback { @@ -128,7 +126,7 @@ public: } Mat Bz(3, 3, CV_64F, bz); - cv::Mat xy1; + Mat xy1; SVD::solveZ(Bz, xy1); if (fabs(xy1.at(2)) < 1e-10) continue; @@ -136,7 +134,7 @@ public: ys.push_back(xy1.at(1) / xy1.at(2)); zs.push_back(z1); - cv::Mat Evec = EE.col(0) * xs.back() + EE.col(1) * ys.back() + EE.col(2) * zs.back() + EE.col(3); + Mat Evec = EE.col(0) * xs.back() + EE.col(1) * ys.back() + EE.col(2) * zs.back() + EE.col(3); Evec /= norm(Evec); memcpy(e + count * 9, Evec.ptr(), 9 * sizeof(double)); @@ -401,10 +399,8 @@ protected: } }; -} - // Input should be a vector of n 2D points or a Nx2 matrix -cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix, +Mat findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix, int method, double prob, double threshold, OutputArray _mask) { CV_INSTRUMENT_REGION(); @@ -455,16 +451,16 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArr return E; } -cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp, +Mat findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp, int method, double prob, double threshold, OutputArray _mask) { CV_INSTRUMENT_REGION(); Mat cameraMatrix = (Mat_(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1); - return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, _mask); + return findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, _mask); } -cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, +Mat findEssentialMat( InputArray _points1, InputArray _points2, InputArray cameraMatrix1, InputArray distCoeffs1, InputArray cameraMatrix2, InputArray distCoeffs2, int method, double prob, double threshold, OutputArray _mask) @@ -493,7 +489,7 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, return findEssentialMat(_pointsUntistorted1, _pointsUntistorted2, cm0, method, prob, threshold, _mask); } -cv::Mat cv::findEssentialMat( InputArray points1, InputArray points2, +Mat findEssentialMat( InputArray points1, InputArray points2, InputArray cameraMatrix1, InputArray cameraMatrix2, InputArray dist_coeff1, InputArray dist_coeff2, OutputArray mask, const UsacParams ¶ms) { Ptr model; @@ -507,7 +503,7 @@ cv::Mat cv::findEssentialMat( InputArray points1, InputArray points2, } -int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2, +int recoverPose( InputArray E, InputArray _points1, InputArray _points2, InputArray _cameraMatrix, OutputArray _R, OutputArray _t, double distanceThresh, InputOutputArray _mask, OutputArray triangulatedPoints) { @@ -677,20 +673,20 @@ int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2, } } -int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2, InputArray _cameraMatrix, +int recoverPose( InputArray E, InputArray _points1, InputArray _points2, InputArray _cameraMatrix, OutputArray _R, OutputArray _t, InputOutputArray _mask) { - return cv::recoverPose(E, _points1, _points2, _cameraMatrix, _R, _t, 50, _mask); + return recoverPose(E, _points1, _points2, _cameraMatrix, _R, _t, 50, _mask); } -int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2, OutputArray _R, +int recoverPose( InputArray E, InputArray _points1, InputArray _points2, OutputArray _R, OutputArray _t, double focal, Point2d pp, InputOutputArray _mask) { Mat cameraMatrix = (Mat_(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1); - return cv::recoverPose(E, _points1, _points2, cameraMatrix, _R, _t, _mask); + return recoverPose(E, _points1, _points2, cameraMatrix, _R, _t, _mask); } -void cv::decomposeEssentialMat( InputArray _E, OutputArray _R1, OutputArray _R2, OutputArray _t ) +void decomposeEssentialMat( InputArray _E, OutputArray _R1, OutputArray _R2, OutputArray _t ) { CV_INSTRUMENT_REGION(); @@ -715,3 +711,5 @@ void cv::decomposeEssentialMat( InputArray _E, OutputArray _R1, OutputArray _R2, R2.copyTo(_R2); t.copyTo(_t); } + +} diff --git a/modules/calib3d/src/fundam.cpp b/modules/3d/src/fundam.cpp similarity index 82% rename from modules/calib3d/src/fundam.cpp rename to modules/3d/src/fundam.cpp index 2ddcabba06..853c304c81 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/3d/src/fundam.cpp @@ -46,8 +46,7 @@ #include "usac.hpp" -namespace cv -{ +namespace cv { /** * This class estimates a homography \f$H\in \mathbb{R}^{3\times 3}\f$ @@ -269,9 +268,7 @@ public: Mat src, dst; }; -} // end namesapce cv -namespace cv{ static bool createAndRunRHORegistrator(double confidence, int maxIters, double ransacReprojThreshold, @@ -346,10 +343,8 @@ static bool createAndRunRHORegistrator(double confidence, return result; } -} - -cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, +Mat findHomography( InputArray _points1, InputArray _points2, int method, double ransacReprojThreshold, OutputArray _mask, const int maxIters, const double confidence) { @@ -441,14 +436,14 @@ cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, return H; } -cv::Mat cv::findHomography( InputArray _points1, InputArray _points2, +Mat findHomography( InputArray _points1, InputArray _points2, OutputArray _mask, int method, double ransacReprojThreshold ) { - return cv::findHomography(_points1, _points2, method, ransacReprojThreshold, _mask); + return findHomography(_points1, _points2, method, ransacReprojThreshold, _mask); } -cv::Mat cv::findHomography(InputArray srcPoints, InputArray dstPoints, OutputArray mask, +Mat findHomography(InputArray srcPoints, InputArray dstPoints, OutputArray mask, const UsacParams ¶ms) { Ptr model; usac::setParameters(model, usac::EstimationMethod::Homography, params, mask.needed()); @@ -470,9 +465,6 @@ cv::Mat cv::findHomography(InputArray srcPoints, InputArray dstPoints, OutputArr that can be found at http://www-sop.inria.fr/robotvis/personnel/zzhang/zzhang-eng.html */ /************************************** 7-point algorithm *******************************/ -namespace cv -{ - /** * Compute the fundamental matrix using the 7-point algorithm. * @@ -826,9 +818,7 @@ public: } }; -} - -cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, +Mat findFundamentalMat( InputArray _points1, InputArray _points2, int method, double ransacReprojThreshold, double confidence, int maxIters, OutputArray _mask ) { @@ -897,20 +887,20 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, return F; } -cv::Mat cv::findFundamentalMat( cv::InputArray points1, cv::InputArray points2, +Mat findFundamentalMat( InputArray points1, InputArray points2, int method, double ransacReprojThreshold, double confidence, - cv::OutputArray mask ) + OutputArray mask ) { - return cv::findFundamentalMat(points1, points2, method, ransacReprojThreshold, confidence, 1000, mask); + return findFundamentalMat(points1, points2, method, ransacReprojThreshold, confidence, 1000, mask); } -cv::Mat cv::findFundamentalMat( cv::InputArray points1, cv::InputArray points2, cv::OutputArray mask, +Mat findFundamentalMat( InputArray points1, InputArray points2, OutputArray mask, int method, double ransacReprojThreshold, double confidence ) { - return cv::findFundamentalMat(points1, points2, method, ransacReprojThreshold, confidence, 1000, mask); + return findFundamentalMat(points1, points2, method, ransacReprojThreshold, confidence, 1000, mask); } -cv::Mat cv::findFundamentalMat( InputArray points1, InputArray points2, +Mat findFundamentalMat( InputArray points1, InputArray points2, OutputArray mask, const UsacParams ¶ms) { Ptr model; setParameters(model, usac::EstimationMethod::Fundamental, params, mask.needed()); @@ -926,7 +916,7 @@ cv::Mat cv::findFundamentalMat( InputArray points1, InputArray points2, -void cv::computeCorrespondEpilines( InputArray _points, int whichImage, +void computeCorrespondEpilines( InputArray _points, int whichImage, InputArray _Fmat, OutputArray _lines ) { CV_INSTRUMENT_REGION(); @@ -1010,7 +1000,7 @@ static inline float scaleFor(float x){ } -void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) +void convertPointsFromHomogeneous( InputArray _src, OutputArray _dst, int dtype ) { CV_INSTRUMENT_REGION(); @@ -1026,7 +1016,14 @@ void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) } CV_Assert( npoints >= 0 && (depth == CV_32S || depth == CV_32F || depth == CV_64F)); - int dtype = CV_MAKETYPE(depth <= CV_32F ? CV_32F : CV_64F, cn-1); + int ddepth; + if (dtype < 0) + ddepth = depth <= CV_32F ? CV_32F : CV_64F; + else + ddepth = CV_MAT_DEPTH(dtype); + CV_Assert(ddepth == CV_32F || ddepth == CV_64F); + dtype = CV_MAKETYPE(ddepth, cn-1); + _dst.create(npoints, 1, dtype); Mat dst = _dst.getMat(); if( !dst.isContinuous() ) @@ -1042,22 +1039,38 @@ void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) if( cn == 3 ) { const Point3i* sptr = src.ptr(); - Point2f* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - { - float scale = sptr[i].z != 0 ? 1.f/sptr[i].z : 1.f; - dptr[i] = Point2f(sptr[i].x*scale, sptr[i].y*scale); - } + Point2f* fdptr = (Point2f*)dst.data; + Point2d* ddptr = (Point2d*)dst.data; + if (ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + { + float scale = sptr[i].z != 0 ? 1.f/sptr[i].z : 1.f; + fdptr[i] = Point2f(sptr[i].x*scale, sptr[i].y*scale); + } + else + for( i = 0; i < npoints; i++ ) + { + double scale = sptr[i].z != 0 ? 1./sptr[i].z : 1.; + ddptr[i] = Point2d(sptr[i].x*scale, sptr[i].y*scale); + } } else { const Vec4i* sptr = src.ptr(); - Point3f* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - { - float scale = sptr[i][3] != 0 ? 1.f/sptr[i][3] : 1.f; - dptr[i] = Point3f(sptr[i][0]*scale, sptr[i][1]*scale, sptr[i][2]*scale); - } + Point3f* fdptr = (Point3f*)dst.data; + Point3d* ddptr = (Point3d*)dst.data; + if (ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + { + float scale = sptr[i][3] != 0 ? 1.f/sptr[i][3] : 1.f; + fdptr[i] = Point3f(sptr[i][0]*scale, sptr[i][1]*scale, sptr[i][2]*scale); + } + else + for( i = 0; i < npoints; i++ ) + { + double scale = sptr[i][3] != 0 ? 1./sptr[i][3] : 1.; + ddptr[i] = Point3d(sptr[i][0]*scale, sptr[i][1]*scale, sptr[i][2]*scale); + } } } else if( depth == CV_32F ) @@ -1065,22 +1078,38 @@ void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) if( cn == 3 ) { const Point3f* sptr = src.ptr(); - Point2f* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - { - float scale = scaleFor(sptr[i].z); - dptr[i] = Point2f(sptr[i].x*scale, sptr[i].y*scale); - } + Point2f* fdptr = (Point2f*)dst.data; + Point2d* ddptr = (Point2d*)dst.data; + if (ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + { + float scale = scaleFor(sptr[i].z); + fdptr[i] = Point2f(sptr[i].x*scale, sptr[i].y*scale); + } + else + for( i = 0; i < npoints; i++ ) + { + double scale = scaleFor((double)sptr[i].z); + ddptr[i] = Point2d(sptr[i].x*scale, sptr[i].y*scale); + } } else { const Vec4f* sptr = src.ptr(); - Point3f* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - { - float scale = scaleFor(sptr[i][3]); - dptr[i] = Point3f(sptr[i][0]*scale, sptr[i][1]*scale, sptr[i][2]*scale); - } + Point3f* fdptr = (Point3f*)dst.data; + Point3d* ddptr = (Point3d*)dst.data; + if (ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + { + float scale = scaleFor(sptr[i][3]); + fdptr[i] = Point3f(sptr[i][0]*scale, sptr[i][1]*scale, sptr[i][2]*scale); + } + else + for( i = 0; i < npoints; i++ ) + { + double scale = scaleFor((double)sptr[i][3]); + ddptr[i] = Point3d(sptr[i][0]*scale, sptr[i][1]*scale, sptr[i][2]*scale); + } } } else if( depth == CV_64F ) @@ -1088,22 +1117,38 @@ void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) if( cn == 3 ) { const Point3d* sptr = src.ptr(); - Point2d* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - { - double scale = scaleFor(sptr[i].z); - dptr[i] = Point2d(sptr[i].x*scale, sptr[i].y*scale); - } + Point2f* fdptr = (Point2f*)dst.data; + Point2d* ddptr = (Point2d*)dst.data; + if (ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + { + double scale = scaleFor(sptr[i].z); + fdptr[i] = Point2f((float)(sptr[i].x*scale), (float)(sptr[i].y*scale)); + } + else + for( i = 0; i < npoints; i++ ) + { + double scale = scaleFor(sptr[i].z); + ddptr[i] = Point2d(sptr[i].x*scale, sptr[i].y*scale); + } } else { const Vec4d* sptr = src.ptr(); - Point3d* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - { - double scale = scaleFor(sptr[i][3]); - dptr[i] = Point3d(sptr[i][0]*scale, sptr[i][1]*scale, sptr[i][2]*scale); - } + Point3f* fdptr = (Point3f*)dst.data; + Point3d* ddptr = (Point3d*)dst.data; + if (ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + { + double scale = scaleFor(sptr[i][3]); + fdptr[i] = Point3f((float)(sptr[i][0]*scale), (float)(sptr[i][1]*scale), (float)(sptr[i][2]*scale)); + } + else + for( i = 0; i < npoints; i++ ) + { + double scale = scaleFor(sptr[i][3]); + ddptr[i] = Point3d(sptr[i][0]*scale, sptr[i][1]*scale, sptr[i][2]*scale); + } } } else @@ -1111,7 +1156,7 @@ void cv::convertPointsFromHomogeneous( InputArray _src, OutputArray _dst ) } -void cv::convertPointsToHomogeneous( InputArray _src, OutputArray _dst ) +void convertPointsToHomogeneous( InputArray _src, OutputArray _dst, int dtype ) { CV_INSTRUMENT_REGION(); @@ -1127,7 +1172,15 @@ void cv::convertPointsToHomogeneous( InputArray _src, OutputArray _dst ) } CV_Assert( npoints >= 0 && (depth == CV_32S || depth == CV_32F || depth == CV_64F)); - int dtype = CV_MAKETYPE(depth, cn+1); + int ddepth; + if (dtype < 0) + ddepth = depth; + else + { + ddepth = CV_MAT_DEPTH(dtype); + CV_Assert(ddepth == CV_32F || ddepth == CV_64F || (ddepth == depth)); + } + dtype = CV_MAKETYPE(ddepth, cn+1); _dst.create(npoints, 1, dtype); Mat dst = _dst.getMat(); if( !dst.isContinuous() ) @@ -1138,63 +1191,91 @@ void cv::convertPointsToHomogeneous( InputArray _src, OutputArray _dst ) } CV_Assert( dst.isContinuous() ); - if( depth == CV_32S ) + if( cn == 2 ) { - if( cn == 2 ) + Point3i* idptr = (Point3i*)dst.data; + Point3f* fdptr = (Point3f*)dst.data; + Point3d* ddptr = (Point3d*)dst.data; + + if( depth == CV_32S ) { const Point2i* sptr = src.ptr(); - Point3i* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - dptr[i] = Point3i(sptr[i].x, sptr[i].y, 1); + + if (ddepth == CV_32S) + for( i = 0; i < npoints; i++ ) + idptr[i] = Point3i(sptr[i].x, sptr[i].y, 1); + else if(ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + fdptr[i] = Point3f((float)sptr[i].x, (float)sptr[i].y, 1.f); + else + for( i = 0; i < npoints; i++ ) + ddptr[i] = Point3d(sptr[i].x, sptr[i].y, 1.); } - else - { - const Point3i* sptr = src.ptr(); - Vec4i* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - dptr[i] = Vec4i(sptr[i].x, sptr[i].y, sptr[i].z, 1); - } - } - else if( depth == CV_32F ) - { - if( cn == 2 ) + else if( depth == CV_32F ) { const Point2f* sptr = src.ptr(); - Point3f* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - dptr[i] = Point3f(sptr[i].x, sptr[i].y, 1.f); + if(ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + fdptr[i] = Point3f((float)sptr[i].x, (float)sptr[i].y, 1.f); + else + for( i = 0; i < npoints; i++ ) + ddptr[i] = Point3d(sptr[i].x, sptr[i].y, 1.); } else { - const Point3f* sptr = src.ptr(); - Vec4f* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - dptr[i] = Vec4f(sptr[i].x, sptr[i].y, sptr[i].z, 1.f); + const Point2d* sptr = src.ptr(); + if(ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + fdptr[i] = Point3f((float)sptr[i].x, (float)sptr[i].y, 1.f); + else + for( i = 0; i < npoints; i++ ) + ddptr[i] = Point3d(sptr[i].x, sptr[i].y, 1.); } } - else if( depth == CV_64F ) + else { - if( cn == 2 ) + Vec4i* idptr = (Vec4i*)dst.data; + Vec4f* fdptr = (Vec4f*)dst.data; + Vec4d* ddptr = (Vec4d*)dst.data; + + if (depth == CV_32S) { - const Point2d* sptr = src.ptr(); - Point3d* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - dptr[i] = Point3d(sptr[i].x, sptr[i].y, 1.); + const Point3i* sptr = src.ptr(); + if (ddepth == CV_32S) + for( i = 0; i < npoints; i++ ) + idptr[i] = Vec4i(sptr[i].x, sptr[i].y, sptr[i].z, 1); + else if (ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + fdptr[i] = Vec4f((float)sptr[i].x, (float)sptr[i].y, (float)sptr[i].z, 1.f); + else + for( i = 0; i < npoints; i++ ) + ddptr[i] = Vec4d(sptr[i].x, sptr[i].y, sptr[i].z, 1.); + } + else if (depth == CV_32F) + { + const Point3f* sptr = src.ptr(); + if (ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + fdptr[i] = Vec4f(sptr[i].x, sptr[i].y, sptr[i].z, 1.f); + else + for( i = 0; i < npoints; i++ ) + ddptr[i] = Vec4d(sptr[i].x, sptr[i].y, sptr[i].z, 1.); } else { const Point3d* sptr = src.ptr(); - Vec4d* dptr = dst.ptr(); - for( i = 0; i < npoints; i++ ) - dptr[i] = Vec4d(sptr[i].x, sptr[i].y, sptr[i].z, 1.); + if (ddepth == CV_32F) + for( i = 0; i < npoints; i++ ) + fdptr[i] = Vec4f((float)sptr[i].x, (float)sptr[i].y, (float)sptr[i].z, 1.f); + else + for( i = 0; i < npoints; i++ ) + ddptr[i] = Vec4d(sptr[i].x, sptr[i].y, sptr[i].z, 1.); } } - else - CV_Error(Error::StsUnsupportedFormat, ""); } -void cv::convertPointsHomogeneous( InputArray _src, OutputArray _dst ) +void convertPointsHomogeneous( InputArray _src, OutputArray _dst ) { CV_INSTRUMENT_REGION(); @@ -1207,7 +1288,7 @@ void cv::convertPointsHomogeneous( InputArray _src, OutputArray _dst ) convertPointsToHomogeneous(_src, _dst); } -double cv::sampsonDistance(InputArray _pt1, InputArray _pt2, InputArray _F) +double sampsonDistance(InputArray _pt1, InputArray _pt2, InputArray _F) { CV_INSTRUMENT_REGION(); @@ -1230,4 +1311,6 @@ double cv::sampsonDistance(InputArray _pt1, InputArray _pt2, InputArray _F) return v*v / (F_pt1[0] + F_pt1[1] + Ft_pt2[0] + Ft_pt2[1]); } +} + /* End of file. */ diff --git a/modules/calib3d/src/homography_decomp.cpp b/modules/3d/src/homography_decomp.cpp similarity index 99% rename from modules/calib3d/src/homography_decomp.cpp rename to modules/3d/src/homography_decomp.cpp index 3bfb62ec2c..e9153a686d 100644 --- a/modules/calib3d/src/homography_decomp.cpp +++ b/modules/3d/src/homography_decomp.cpp @@ -50,8 +50,7 @@ #include "precomp.hpp" #include -namespace cv -{ +namespace cv { namespace HomographyDecomposition { diff --git a/modules/calib3d/src/ippe.cpp b/modules/3d/src/ippe.cpp similarity index 99% rename from modules/calib3d/src/ippe.cpp rename to modules/3d/src/ippe.cpp index ec6089596c..ccfda42c55 100644 --- a/modules/calib3d/src/ippe.cpp +++ b/modules/3d/src/ippe.cpp @@ -1097,4 +1097,4 @@ void homographyHO(InputArray _srcPoints, InputArray _targPoints, Matx33d& H) H = H * h22_inv; } } -} //namespace cv +} //namespace cv::_3d diff --git a/modules/calib3d/src/ippe.hpp b/modules/3d/src/ippe.hpp similarity index 99% rename from modules/calib3d/src/ippe.hpp rename to modules/3d/src/ippe.hpp index 986210b187..bcd3e58aef 100644 --- a/modules/calib3d/src/ippe.hpp +++ b/modules/3d/src/ippe.hpp @@ -255,5 +255,5 @@ void homographyHO(InputArray srcPoints, InputArray targPoints, Matx33d& H); void normalizeDataIsotropic(InputArray Data, OutputArray DataN, OutputArray T, OutputArray Ti); } -} //namespace cv +} //namespace cv::_3d #endif diff --git a/modules/calib3d/src/levmarq.cpp b/modules/3d/src/levmarq.cpp similarity index 99% rename from modules/calib3d/src/levmarq.cpp rename to modules/3d/src/levmarq.cpp index 623cc202b9..0dfca5dd3b 100644 --- a/modules/calib3d/src/levmarq.cpp +++ b/modules/3d/src/levmarq.cpp @@ -74,8 +74,7 @@ POSSIBILITY OF SUCH DAMAGE. */ -namespace cv -{ +namespace cv { class LMSolverImpl CV_FINAL : public LMSolver { diff --git a/modules/calib3d/src/main.cpp b/modules/3d/src/main.cpp similarity index 100% rename from modules/calib3d/src/main.cpp rename to modules/3d/src/main.cpp diff --git a/modules/calib3d/src/opencl/stereobm.cl b/modules/3d/src/opencl/stereobm.cl similarity index 100% rename from modules/calib3d/src/opencl/stereobm.cl rename to modules/3d/src/opencl/stereobm.cl diff --git a/modules/calib3d/src/p3p.cpp b/modules/3d/src/p3p.cpp similarity index 98% rename from modules/calib3d/src/p3p.cpp rename to modules/3d/src/p3p.cpp index 01b1734db8..9d9cd3787c 100644 --- a/modules/calib3d/src/p3p.cpp +++ b/modules/3d/src/p3p.cpp @@ -1,3 +1,7 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + #include #include #include @@ -5,6 +9,8 @@ #include "polynom_solver.h" #include "p3p.h" +namespace cv { + void p3p::init_inverse_parameters() { inv_fx = 1. / fx; @@ -464,3 +470,5 @@ bool p3p::jacobi_4x4(double * A, double * D, double * U) return false; } + +} diff --git a/modules/calib3d/src/p3p.h b/modules/3d/src/p3p.h similarity index 92% rename from modules/calib3d/src/p3p.h rename to modules/3d/src/p3p.h index 93e867d479..edffe3d6f1 100644 --- a/modules/calib3d/src/p3p.h +++ b/modules/3d/src/p3p.h @@ -1,9 +1,14 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + #ifndef P3P_H #define P3P_H - #include "precomp.hpp" +namespace cv { + class p3p { public: @@ -68,4 +73,6 @@ class p3p double inv_fx, inv_fy, cx_fx, cy_fy; }; +} + #endif // P3P_H diff --git a/modules/calib3d/src/polynom_solver.cpp b/modules/3d/src/polynom_solver.cpp similarity index 94% rename from modules/calib3d/src/polynom_solver.cpp rename to modules/3d/src/polynom_solver.cpp index beb91cafc0..5eb04b7bf4 100644 --- a/modules/calib3d/src/polynom_solver.cpp +++ b/modules/3d/src/polynom_solver.cpp @@ -1,9 +1,15 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + #include "precomp.hpp" #include "polynom_solver.h" #include #include +namespace cv { + int solve_deg2(double a, double b, double c, double & x1, double & x2) { double delta = b * b - 4 * a * c; @@ -168,3 +174,5 @@ int solve_deg4(double a, double b, double c, double d, double e, return nb_real_roots; } + +} diff --git a/modules/calib3d/src/polynom_solver.h b/modules/3d/src/polynom_solver.h similarity index 65% rename from modules/calib3d/src/polynom_solver.h rename to modules/3d/src/polynom_solver.h index 713bcf3fbd..b3f753c5cb 100644 --- a/modules/calib3d/src/polynom_solver.h +++ b/modules/3d/src/polynom_solver.h @@ -1,6 +1,12 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + #ifndef POLYNOM_SOLVER_H #define POLYNOM_SOLVER_H +namespace cv { + int solve_deg2(double a, double b, double c, double & x1, double & x2); int solve_deg3(double a, double b, double c, double d, @@ -9,4 +15,6 @@ int solve_deg3(double a, double b, double c, double d, int solve_deg4(double a, double b, double c, double d, double e, double & x0, double & x1, double & x2, double & x3); +} + #endif // POLYNOM_SOLVER_H diff --git a/modules/3d/src/precomp.hpp b/modules/3d/src/precomp.hpp new file mode 100644 index 0000000000..52cd86f3f5 --- /dev/null +++ b/modules/3d/src/precomp.hpp @@ -0,0 +1,143 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ +#ifndef __OPENCV_PRECOMP_H__ +#define __OPENCV_PRECOMP_H__ + +#include "opencv2/core/utility.hpp" + +#include "opencv2/core/private.hpp" + +#include "opencv2/3d.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/features2d.hpp" + +#include "opencv2/core/ocl.hpp" + +#define GET_OPTIMIZED(func) (func) + + +namespace cv { + +/** + * Compute the number of iterations given the confidence, outlier ratio, number + * of model points and the maximum iteration number. + * + * @param p confidence value + * @param ep outlier ratio + * @param modelPoints number of model points required for estimation + * @param maxIters maximum number of iterations + * @return + * \f[ + * \frac{\ln(1-p)}{\ln\left(1-(1-ep)^\mathrm{modelPoints}\right)} + * \f] + * + * If the computed number of iterations is larger than maxIters, then maxIters is returned. + */ +int RANSACUpdateNumIters( double p, double ep, int modelPoints, int maxIters ); + +class CV_EXPORTS PointSetRegistrator : public Algorithm +{ +public: + class CV_EXPORTS Callback + { + public: + virtual ~Callback() {} + virtual int runKernel(InputArray m1, InputArray m2, OutputArray model) const = 0; + virtual void computeError(InputArray m1, InputArray m2, InputArray model, OutputArray err) const = 0; + virtual bool checkSubset(InputArray, InputArray, int) const { return true; } + }; + + virtual void setCallback(const Ptr& cb) = 0; + virtual bool run(InputArray m1, InputArray m2, OutputArray model, OutputArray mask) const = 0; +}; + +CV_EXPORTS Ptr createRANSACPointSetRegistrator(const Ptr& cb, + int modelPoints, double threshold, + double confidence=0.99, int maxIters=1000 ); + +CV_EXPORTS Ptr createLMeDSPointSetRegistrator(const Ptr& cb, + int modelPoints, double confidence=0.99, int maxIters=1000 ); + +template inline int compressElems( T* ptr, const uchar* mask, int mstep, int count ) +{ + int i, j; + for( i = j = 0; i < count; i++ ) + if( mask[i*mstep] ) + { + if( i > j ) + ptr[j] = ptr[i]; + j++; + } + return j; +} + +static inline bool haveCollinearPoints( const Mat& m, int count ) +{ + int j, k, i = count-1; + const Point2f* ptr = m.ptr(); + + // check that the i-th selected point does not belong + // to a line connecting some previously selected points + // also checks that points are not too close to each other + for( j = 0; j < i; j++ ) + { + double dx1 = ptr[j].x - ptr[i].x; + double dy1 = ptr[j].y - ptr[i].y; + for( k = 0; k < j; k++ ) + { + double dx2 = ptr[k].x - ptr[i].x; + double dy2 = ptr[k].y - ptr[i].y; + if( fabs(dx2*dy1 - dy2*dx1) <= FLT_EPSILON*(fabs(dx1) + fabs(dy1) + fabs(dx2) + fabs(dy2))) + return true; + } + } + return false; +} + +void findExtrinsicCameraParams2( const Mat& objectPoints, + const Mat& imagePoints, const Mat& A, + const Mat& distCoeffs, Mat& rvec, Mat& tvec, + int useExtrinsicGuess ); + +} // namespace cv + +#endif diff --git a/modules/calib3d/src/ptsetreg.cpp b/modules/3d/src/ptsetreg.cpp similarity index 99% rename from modules/calib3d/src/ptsetreg.cpp rename to modules/3d/src/ptsetreg.cpp index 6bd3b16c32..04f665fdab 100644 --- a/modules/calib3d/src/ptsetreg.cpp +++ b/modules/3d/src/ptsetreg.cpp @@ -49,8 +49,7 @@ #include "usac.hpp" -namespace cv -{ +namespace cv { int RANSACUpdateNumIters( double p, double ep, int modelPoints, int maxIters ) { @@ -931,7 +930,7 @@ Mat estimateAffine2D(InputArray _from, InputArray _to, OutputArray _inliers, { if (method >= USAC_DEFAULT && method <= USAC_MAGSAC) - return cv::usac::estimateAffine2D(_from, _to, _inliers, method, + return usac::estimateAffine2D(_from, _to, _inliers, method, ransacReprojThreshold, (int)maxIters, confidence, (int)refineIters); Mat from = _from.getMat(), to = _to.getMat(); diff --git a/modules/calib3d/src/rho.cpp b/modules/3d/src/rho.cpp similarity index 99% rename from modules/calib3d/src/rho.cpp rename to modules/3d/src/rho.cpp index 341b6b9063..d7b3cb6854 100644 --- a/modules/calib3d/src/rho.cpp +++ b/modules/3d/src/rho.cpp @@ -57,12 +57,8 @@ #include "rho.h" #include "opencv2/core/utils/buffer_area.private.hpp" - - - /* For the sake of cv:: namespace ONLY: */ -namespace cv{/* For C support, replace with extern "C" { */ - +namespace cv { /* Constants */ const size_t HSIZE = (3*3*sizeof(float)); diff --git a/modules/calib3d/src/rho.h b/modules/3d/src/rho.h similarity index 99% rename from modules/calib3d/src/rho.h rename to modules/3d/src/rho.h index a8211161af..f1ba2f67a4 100644 --- a/modules/calib3d/src/rho.h +++ b/modules/3d/src/rho.h @@ -47,18 +47,11 @@ #ifndef __OPENCV_RHO_H__ #define __OPENCV_RHO_H__ - - /* Includes */ #include - - - - /* Defines */ - /* Flags */ #ifndef RHO_FLAG_NONE #define RHO_FLAG_NONE (0U<<0) @@ -73,10 +66,8 @@ #define RHO_FLAG_ENABLE_FINAL_REFINEMENT (1U<<2) #endif - - /* Namespace cv */ -namespace cv{ +namespace cv { /* Data structures */ @@ -255,13 +246,7 @@ unsigned rhoHest(Ptr p, /* Homography estimation context. */ const float* guessH, /* Extrinsic guess, NULL if none provided */ float* finalH); /* Final result. */ - - - /* End Namespace cv */ } - - - #endif diff --git a/modules/calib3d/src/solvepnp.cpp b/modules/3d/src/solvepnp.cpp similarity index 98% rename from modules/calib3d/src/solvepnp.cpp rename to modules/3d/src/solvepnp.cpp index 0f12333eb9..01e8e9ac57 100644 --- a/modules/calib3d/src/solvepnp.cpp +++ b/modules/3d/src/solvepnp.cpp @@ -48,14 +48,14 @@ #include "ap3p.h" #include "ippe.hpp" #include "sqpnp.hpp" -#include "calib3d_c_api.h" - #include "usac.hpp" #include -namespace cv -{ +namespace cv { + +using namespace std; + #if defined _DEBUG || defined CV_STATIC_ANALYSIS static bool isPlanarObjectPoints(InputArray _objectPoints, double threshold) { @@ -790,7 +790,7 @@ void solvePnPRefineVVS(InputArray _objectPoints, InputArray _imagePoints, int solvePnPGeneric( InputArray _opoints, InputArray _ipoints, InputArray _cameraMatrix, InputArray _distCoeffs, OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, - bool useExtrinsicGuess, SolvePnPMethod flags, + bool useExtrinsicGuess, int flags, InputArray _rvec, InputArray _tvec, OutputArray reprojectionError) { CV_INSTRUMENT_REGION(); @@ -869,13 +869,8 @@ int solvePnPGeneric( InputArray _opoints, InputArray _ipoints, tvec.create(3, 1, CV_64FC1); } - CvMat c_objectPoints = cvMat(opoints), c_imagePoints = cvMat(ipoints); - CvMat c_cameraMatrix = cvMat(cameraMatrix), c_distCoeffs = cvMat(distCoeffs); - CvMat c_rvec = cvMat(rvec), c_tvec = cvMat(tvec); - cvFindExtrinsicCameraParams2(&c_objectPoints, &c_imagePoints, &c_cameraMatrix, - (c_distCoeffs.rows && c_distCoeffs.cols) ? &c_distCoeffs : 0, - &c_rvec, &c_tvec, useExtrinsicGuess ); - + findExtrinsicCameraParams2(opoints, ipoints, cameraMatrix, distCoeffs, + rvec, tvec, useExtrinsicGuess ); vec_rvecs.push_back(rvec); vec_tvecs.push_back(tvec); } diff --git a/modules/calib3d/src/sqpnp.cpp b/modules/3d/src/sqpnp.cpp similarity index 99% rename from modules/calib3d/src/sqpnp.cpp rename to modules/3d/src/sqpnp.cpp index 7117e61c96..1ce99ff954 100644 --- a/modules/calib3d/src/sqpnp.cpp +++ b/modules/3d/src/sqpnp.cpp @@ -39,8 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "precomp.hpp" #include "sqpnp.hpp" -#include - namespace cv { namespace sqpnp { diff --git a/modules/calib3d/src/sqpnp.hpp b/modules/3d/src/sqpnp.hpp similarity index 100% rename from modules/calib3d/src/sqpnp.hpp rename to modules/3d/src/sqpnp.hpp diff --git a/modules/calib3d/src/triangulate.cpp b/modules/3d/src/triangulate.cpp similarity index 99% rename from modules/calib3d/src/triangulate.cpp rename to modules/3d/src/triangulate.cpp index cded42232a..ee8d1217e6 100644 --- a/modules/calib3d/src/triangulate.cpp +++ b/modules/3d/src/triangulate.cpp @@ -42,6 +42,8 @@ #include "precomp.hpp" #include "opencv2/core/core_c.h" +namespace cv { + // cvCorrectMatches function is Copyright (C) 2009, Jostein Austvik Jacobsen. // cvTriangulatePoints function is derived from icvReconstructPointsFor3View, originally by Valery Mosyagin. @@ -343,7 +345,7 @@ icvCorrectMatches(CvMat *F_, CvMat *points1_, CvMat *points2_, CvMat *new_points cvConvert( points2, new_points2 ); } -void cv::triangulatePoints( InputArray _projMatr1, InputArray _projMatr2, +void triangulatePoints( InputArray _projMatr1, InputArray _projMatr2, InputArray _projPoints1, InputArray _projPoints2, OutputArray _points4D ) { @@ -368,7 +370,7 @@ void cv::triangulatePoints( InputArray _projMatr1, InputArray _projMatr2, icvTriangulatePoints(&cvMatr1, &cvMatr2, &cvPoints1, &cvPoints2, &cvPoints4D); } -void cv::correctMatches( InputArray _F, InputArray _points1, InputArray _points2, +void correctMatches( InputArray _F, InputArray _points1, InputArray _points2, OutputArray _newPoints1, OutputArray _newPoints2 ) { CV_INSTRUMENT_REGION(); @@ -386,3 +388,5 @@ void cv::correctMatches( InputArray _F, InputArray _points1, InputArray _points2 icvCorrectMatches(&cvF, &cvPoints1, &cvPoints2, &cvNewPoints1, &cvNewPoints2); } + +} diff --git a/modules/calib3d/src/undistort.dispatch.cpp b/modules/3d/src/undistort.dispatch.cpp similarity index 75% rename from modules/calib3d/src/undistort.dispatch.cpp rename to modules/3d/src/undistort.dispatch.cpp index 2dd52037a9..72681483ca 100644 --- a/modules/calib3d/src/undistort.dispatch.cpp +++ b/modules/3d/src/undistort.dispatch.cpp @@ -43,13 +43,10 @@ #include "precomp.hpp" #include "distortion_model.hpp" -#include "calib3d_c_api.h" - #include "undistort.simd.hpp" #include "undistort.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content -namespace cv -{ +namespace cv { Mat getDefaultNewCameraMatrix( InputArray _cameraMatrix, Size imgsize, bool centerPrincipalPoint ) @@ -68,8 +65,7 @@ Mat getDefaultNewCameraMatrix( InputArray _cameraMatrix, Size imgsize, return newCameraMatrix; } -namespace { -Ptr getInitUndistortRectifyMapComputer(Size _size, Mat &_map1, Mat &_map2, int _m1type, +static Ptr getInitUndistortRectifyMapComputer(Size _size, Mat &_map1, Mat &_map2, int _m1type, const double* _ir, Matx33d &_matTilt, double _u0, double _v0, double _fx, double _fy, double _k1, double _k2, double _p1, double _p2, @@ -81,7 +77,6 @@ Ptr getInitUndistortRectifyMapComputer(Size _size, Mat &_map1, CV_CPU_DISPATCH(getInitUndistortRectifyMapComputer, (_size, _map1, _map2, _m1type, _ir, _matTilt, _u0, _v0, _fx, _fy, _k1, _k2, _p1, _p2, _k3, _k4, _k5, _k6, _s1, _s2, _s3, _s4), CV_CPU_DISPATCH_MODES_ALL); } -} void initUndistortRectifyMap( InputArray _cameraMatrix, InputArray _distCoeffs, InputArray _matR, InputArray _newCameraMatrix, @@ -157,7 +152,7 @@ void initUndistortRectifyMap( InputArray _cameraMatrix, InputArray _distCoeffs, // Matrix for trapezoidal distortion of tilted image sensor Matx33d matTilt = Matx33d::eye(); - detail::computeTiltProjectionMatrix(tauX, tauY, &matTilt); + computeTiltProjectionMatrix(tauX, tauY, &matTilt); parallel_for_(Range(0, size.height), *getInitUndistortRectifyMapComputer( size, map1, map2, m1type, ir, matTilt, u0, v0, @@ -212,126 +207,74 @@ void undistort( InputArray _src, OutputArray _dst, InputArray _cameraMatrix, } } -} - -CV_IMPL void -cvUndistort2( const CvArr* srcarr, CvArr* dstarr, const CvMat* Aarr, const CvMat* dist_coeffs, const CvMat* newAarr ) -{ - cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr), dst0 = dst; - cv::Mat A = cv::cvarrToMat(Aarr), distCoeffs = cv::cvarrToMat(dist_coeffs), newA; - if( newAarr ) - newA = cv::cvarrToMat(newAarr); - - CV_Assert( src.size() == dst.size() && src.type() == dst.type() ); - cv::undistort( src, dst, A, distCoeffs, newA ); -} - - -CV_IMPL void cvInitUndistortMap( const CvMat* Aarr, const CvMat* dist_coeffs, - CvArr* mapxarr, CvArr* mapyarr ) -{ - cv::Mat A = cv::cvarrToMat(Aarr), distCoeffs = cv::cvarrToMat(dist_coeffs); - cv::Mat mapx = cv::cvarrToMat(mapxarr), mapy, mapx0 = mapx, mapy0; - - if( mapyarr ) - mapy0 = mapy = cv::cvarrToMat(mapyarr); - - cv::initUndistortRectifyMap( A, distCoeffs, cv::Mat(), A, - mapx.size(), mapx.type(), mapx, mapy ); - CV_Assert( mapx0.data == mapx.data && mapy0.data == mapy.data ); -} - -void -cvInitUndistortRectifyMap( const CvMat* Aarr, const CvMat* dist_coeffs, - const CvMat *Rarr, const CvMat* ArArr, CvArr* mapxarr, CvArr* mapyarr ) -{ - cv::Mat A = cv::cvarrToMat(Aarr), distCoeffs, R, Ar; - cv::Mat mapx = cv::cvarrToMat(mapxarr), mapy, mapx0 = mapx, mapy0; - - if( mapyarr ) - mapy0 = mapy = cv::cvarrToMat(mapyarr); - - if( dist_coeffs ) - distCoeffs = cv::cvarrToMat(dist_coeffs); - if( Rarr ) - R = cv::cvarrToMat(Rarr); - if( ArArr ) - Ar = cv::cvarrToMat(ArArr); - - cv::initUndistortRectifyMap( A, distCoeffs, R, Ar, mapx.size(), mapx.type(), mapx, mapy ); - CV_Assert( mapx0.data == mapx.data && mapy0.data == mapy.data ); -} - -static void cvUndistortPointsInternal( const CvMat* _src, CvMat* _dst, const CvMat* _cameraMatrix, - const CvMat* _distCoeffs, - const CvMat* matR, const CvMat* matP, cv::TermCriteria criteria) +static void undistortPointsInternal( const Mat& _src, Mat& _dst, const Mat& _cameraMatrix, + const Mat& _distCoeffs, const Mat& matR, const Mat& matP, TermCriteria criteria) { CV_Assert(criteria.isValid()); double A[3][3], RR[3][3], k[14]={0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - CvMat matA=cvMat(3, 3, CV_64F, A), _Dk; - CvMat _RR=cvMat(3, 3, CV_64F, RR); + Mat matA(3, 3, CV_64F, A), _Dk; + Mat _RR(3, 3, CV_64F, RR); cv::Matx33d invMatTilt = cv::Matx33d::eye(); cv::Matx33d matTilt = cv::Matx33d::eye(); + bool haveDistCoeffs = !_distCoeffs.empty(); - CV_Assert( CV_IS_MAT(_src) && CV_IS_MAT(_dst) && - (_src->rows == 1 || _src->cols == 1) && - (_dst->rows == 1 || _dst->cols == 1) && - _src->cols + _src->rows - 1 == _dst->rows + _dst->cols - 1 && - (CV_MAT_TYPE(_src->type) == CV_32FC2 || CV_MAT_TYPE(_src->type) == CV_64FC2) && - (CV_MAT_TYPE(_dst->type) == CV_32FC2 || CV_MAT_TYPE(_dst->type) == CV_64FC2)); + CV_Assert( (_src.rows == 1 || _src.cols == 1) && + (_dst.rows == 1 || _dst.cols == 1) && + _src.cols + _src.rows - 1 == _dst.rows + _dst.cols - 1 && + (_src.type() == CV_32FC2 || _src.type() == CV_64FC2) && + (_dst.type() == CV_32FC2 || _dst.type() == CV_64FC2)); - CV_Assert( CV_IS_MAT(_cameraMatrix) && - _cameraMatrix->rows == 3 && _cameraMatrix->cols == 3 ); + CV_Assert( _cameraMatrix.rows == 3 && _cameraMatrix.cols == 3 && _cameraMatrix.channels() == 1 ); + _cameraMatrix.convertTo(matA, CV_64F); - cvConvert( _cameraMatrix, &matA ); - - - if( _distCoeffs ) + if( haveDistCoeffs ) { - CV_Assert( CV_IS_MAT(_distCoeffs) && - (_distCoeffs->rows == 1 || _distCoeffs->cols == 1) && - (_distCoeffs->rows*_distCoeffs->cols == 4 || - _distCoeffs->rows*_distCoeffs->cols == 5 || - _distCoeffs->rows*_distCoeffs->cols == 8 || - _distCoeffs->rows*_distCoeffs->cols == 12 || - _distCoeffs->rows*_distCoeffs->cols == 14)); + CV_Assert( + (_distCoeffs.rows == 1 || _distCoeffs.cols == 1) && + (_distCoeffs.rows*_distCoeffs.cols == 4 || + _distCoeffs.rows*_distCoeffs.cols == 5 || + _distCoeffs.rows*_distCoeffs.cols == 8 || + _distCoeffs.rows*_distCoeffs.cols == 12 || + _distCoeffs.rows*_distCoeffs.cols == 14)); - _Dk = cvMat( _distCoeffs->rows, _distCoeffs->cols, - CV_MAKETYPE(CV_64F,CV_MAT_CN(_distCoeffs->type)), k); - - cvConvert( _distCoeffs, &_Dk ); + _Dk = Mat( _distCoeffs.rows, _distCoeffs.cols, + CV_MAKETYPE(CV_64F,_distCoeffs.channels()), k); + _distCoeffs.convertTo(_Dk, CV_64F); + CV_Assert(_Dk.ptr() == k); if (k[12] != 0 || k[13] != 0) { - cv::detail::computeTiltProjectionMatrix(k[12], k[13], NULL, NULL, NULL, &invMatTilt); - cv::detail::computeTiltProjectionMatrix(k[12], k[13], &matTilt, NULL, NULL); + computeTiltProjectionMatrix(k[12], k[13], NULL, NULL, NULL, &invMatTilt); + computeTiltProjectionMatrix(k[12], k[13], &matTilt, NULL, NULL); } } - if( matR ) + if( !matR.empty() ) { - CV_Assert( CV_IS_MAT(matR) && matR->rows == 3 && matR->cols == 3 ); - cvConvert( matR, &_RR ); + CV_Assert( matR.rows == 3 && matR.cols == 3 && matR.channels() == 1 ); + matR.convertTo(_RR, CV_64F); + CV_Assert(_RR.ptr() == &RR[0][0]); } else - cvSetIdentity(&_RR); + setIdentity(_RR); - if( matP ) + if( !matP.empty() ) { double PP[3][3]; - CvMat _P3x3, _PP=cvMat(3, 3, CV_64F, PP); - CV_Assert( CV_IS_MAT(matP) && matP->rows == 3 && (matP->cols == 3 || matP->cols == 4)); - cvConvert( cvGetCols(matP, &_P3x3, 0, 3), &_PP ); - cvMatMul( &_PP, &_RR, &_RR ); + Mat _PP(3, 3, CV_64F, PP); + CV_Assert( matP.rows == 3 && (matP.cols == 3 || matP.cols == 4)); + matP.colRange(0, 3).convertTo(_PP, CV_64F); + CV_Assert(_PP.ptr() == &PP[0][0]); + _RR = _PP*_RR; } - const CvPoint2D32f* srcf = (const CvPoint2D32f*)_src->data.ptr; - const CvPoint2D64f* srcd = (const CvPoint2D64f*)_src->data.ptr; - CvPoint2D32f* dstf = (CvPoint2D32f*)_dst->data.ptr; - CvPoint2D64f* dstd = (CvPoint2D64f*)_dst->data.ptr; - int stype = CV_MAT_TYPE(_src->type); - int dtype = CV_MAT_TYPE(_dst->type); - int sstep = _src->rows == 1 ? 1 : _src->step/CV_ELEM_SIZE(stype); - int dstep = _dst->rows == 1 ? 1 : _dst->step/CV_ELEM_SIZE(dtype); + const Point2f* srcf = (const Point2f*)_src.data; + const Point2d* srcd = (const Point2d*)_src.data; + Point2f* dstf = (Point2f*)_dst.data; + Point2d* dstd = (Point2d*)_dst.data; + int stype = _src.type(); + int dtype = _dst.type(); + int sstep = _src.rows == 1 ? 1 : (int)(_src.step/_src.elemSize()); + int dstep = _dst.rows == 1 ? 1 : (int)(_dst.step/_dst.elemSize()); double fx = A[0][0]; double fy = A[1][1]; @@ -340,7 +283,7 @@ static void cvUndistortPointsInternal( const CvMat* _src, CvMat* _dst, const CvM double cx = A[0][2]; double cy = A[1][2]; - int n = _src->rows + _src->cols - 1; + int n = _src.rows + _src.cols - 1; for( int i = 0; i < n; i++ ) { double x, y, x0 = 0, y0 = 0, u, v; @@ -358,7 +301,7 @@ static void cvUndistortPointsInternal( const CvMat* _src, CvMat* _dst, const CvM x = (x - cx)*ifx; y = (y - cy)*ify; - if( _distCoeffs ) { + if( haveDistCoeffs ) { // compensate tilt distortion cv::Vec3d vecUntilt = invMatTilt * cv::Vec3d(x, y, 1); double invProj = vecUntilt(2) ? 1./vecUntilt(2) : 1; @@ -370,9 +313,9 @@ static void cvUndistortPointsInternal( const CvMat* _src, CvMat* _dst, const CvM for( int j = 0; ; j++ ) { - if ((criteria.type & cv::TermCriteria::COUNT) && j >= criteria.maxCount) + if ((criteria.type & TermCriteria::COUNT) && j >= criteria.maxCount) break; - if ((criteria.type & cv::TermCriteria::EPS) && error < criteria.epsilon) + if ((criteria.type & TermCriteria::EPS) && error < criteria.epsilon) break; double r2 = x*x + y*y; double icdist = (1 + ((k[7]*r2 + k[6])*r2 + k[5])*r2)/(1 + ((k[4]*r2 + k[1])*r2 + k[0])*r2); @@ -387,11 +330,11 @@ static void cvUndistortPointsInternal( const CvMat* _src, CvMat* _dst, const CvM x = (x0 - deltaX)*icdist; y = (y0 - deltaY)*icdist; - if(criteria.type & cv::TermCriteria::EPS) + if(criteria.type & TermCriteria::EPS) { double r4, r6, a1, a2, a3, cdist, icdist2; double xd, yd, xd0, yd0; - cv::Vec3d vecTilt; + Vec3d vecTilt; r2 = x*x + y*y; r4 = r2*r2; @@ -436,25 +379,6 @@ static void cvUndistortPointsInternal( const CvMat* _src, CvMat* _dst, const CvM } } -void cvUndistortPoints(const CvMat* _src, CvMat* _dst, const CvMat* _cameraMatrix, - const CvMat* _distCoeffs, - const CvMat* matR, const CvMat* matP) -{ - cvUndistortPointsInternal(_src, _dst, _cameraMatrix, _distCoeffs, matR, matP, - cv::TermCriteria(cv::TermCriteria::COUNT, 5, 0.01)); -} - -namespace cv { - -void undistortPoints(InputArray _src, OutputArray _dst, - InputArray _cameraMatrix, - InputArray _distCoeffs, - InputArray _Rmat, - InputArray _Pmat) -{ - undistortPoints(_src, _dst, _cameraMatrix, _distCoeffs, _Rmat, _Pmat, TermCriteria(TermCriteria::MAX_ITER, 5, 0.01)); -} - void undistortPoints(InputArray _src, OutputArray _dst, InputArray _cameraMatrix, InputArray _distCoeffs, @@ -477,15 +401,7 @@ void undistortPoints(InputArray _src, OutputArray _dst, _dst.create(npoints, 1, CV_MAKETYPE(depth, 2), -1, true); Mat dst = _dst.getMat(); - CvMat _csrc = cvMat(src), _cdst = cvMat(dst), _ccameraMatrix = cvMat(cameraMatrix); - CvMat matR, matP, _cdistCoeffs, *pR=0, *pP=0, *pD=0; - if( !R.empty() ) - pR = &(matR = cvMat(R)); - if( !P.empty() ) - pP = &(matP = cvMat(P)); - if( !distCoeffs.empty() ) - pD = &(_cdistCoeffs = cvMat(distCoeffs)); - cvUndistortPointsInternal(&_csrc, &_cdst, &_ccameraMatrix, pD, pR, pP, criteria); + undistortPointsInternal(src, dst, cameraMatrix, distCoeffs, R, P, criteria); } static Point2f mapPointSpherical(const Point2f& p, float alpha, Vec4d* J, enum UndistortTypes projType) @@ -599,8 +515,8 @@ float initWideAngleProjMap(InputArray _cameraMatrix0, InputArray _distCoeffs0, Mat mapxy(dsize, CV_32FC2); double k1 = k[0], k2 = k[1], k3 = k[2], p1 = k[3], p2 = k[4], k4 = k[5], k5 = k[6], k6 = k[7], s1 = k[8], s2 = k[9], s3 = k[10], s4 = k[11]; double fx = cameraMatrix.at(0,0), fy = cameraMatrix.at(1,1), cx = scenter.x, cy = scenter.y; - cv::Matx33d matTilt; - cv::detail::computeTiltProjectionMatrix(k[12], k[13], &matTilt); + Matx33d matTilt; + computeTiltProjectionMatrix(k[12], k[13], &matTilt); for( int y = 0; y < dsize.height; y++ ) { @@ -641,5 +557,5 @@ float initWideAngleProjMap(InputArray _cameraMatrix0, InputArray _distCoeffs0, return scale; } -} // namespace +} /* End of file */ diff --git a/modules/calib3d/src/undistort.simd.hpp b/modules/3d/src/undistort.simd.hpp similarity index 100% rename from modules/calib3d/src/undistort.simd.hpp rename to modules/3d/src/undistort.simd.hpp diff --git a/modules/calib3d/src/usac.hpp b/modules/3d/src/usac.hpp similarity index 100% rename from modules/calib3d/src/usac.hpp rename to modules/3d/src/usac.hpp diff --git a/modules/calib3d/src/usac/degeneracy.cpp b/modules/3d/src/usac/degeneracy.cpp similarity index 100% rename from modules/calib3d/src/usac/degeneracy.cpp rename to modules/3d/src/usac/degeneracy.cpp diff --git a/modules/calib3d/src/usac/dls_solver.cpp b/modules/3d/src/usac/dls_solver.cpp similarity index 100% rename from modules/calib3d/src/usac/dls_solver.cpp rename to modules/3d/src/usac/dls_solver.cpp diff --git a/modules/calib3d/src/usac/essential_solver.cpp b/modules/3d/src/usac/essential_solver.cpp similarity index 99% rename from modules/calib3d/src/usac/essential_solver.cpp rename to modules/3d/src/usac/essential_solver.cpp index 0adca0966f..2e41246506 100644 --- a/modules/calib3d/src/usac/essential_solver.cpp +++ b/modules/3d/src/usac/essential_solver.cpp @@ -337,4 +337,4 @@ public: Ptr EssentialNonMinimalSolver::create (const Mat &points_) { return makePtr(points_); } -}} \ No newline at end of file +}} diff --git a/modules/calib3d/src/usac/estimator.cpp b/modules/3d/src/usac/estimator.cpp similarity index 100% rename from modules/calib3d/src/usac/estimator.cpp rename to modules/3d/src/usac/estimator.cpp diff --git a/modules/calib3d/src/usac/fundamental_solver.cpp b/modules/3d/src/usac/fundamental_solver.cpp similarity index 100% rename from modules/calib3d/src/usac/fundamental_solver.cpp rename to modules/3d/src/usac/fundamental_solver.cpp diff --git a/modules/calib3d/src/usac/gamma_values.cpp b/modules/3d/src/usac/gamma_values.cpp similarity index 100% rename from modules/calib3d/src/usac/gamma_values.cpp rename to modules/3d/src/usac/gamma_values.cpp diff --git a/modules/calib3d/src/usac/homography_solver.cpp b/modules/3d/src/usac/homography_solver.cpp similarity index 99% rename from modules/calib3d/src/usac/homography_solver.cpp rename to modules/3d/src/usac/homography_solver.cpp index b60e39781a..3af13134c0 100644 --- a/modules/calib3d/src/usac/homography_solver.cpp +++ b/modules/3d/src/usac/homography_solver.cpp @@ -335,4 +335,4 @@ public: Ptr AffineNonMinimalSolver::create(const Mat &points_) { return makePtr(points_); } -}} \ No newline at end of file +}} diff --git a/modules/calib3d/src/usac/local_optimization.cpp b/modules/3d/src/usac/local_optimization.cpp similarity index 100% rename from modules/calib3d/src/usac/local_optimization.cpp rename to modules/3d/src/usac/local_optimization.cpp diff --git a/modules/calib3d/src/usac/pnp_solver.cpp b/modules/3d/src/usac/pnp_solver.cpp similarity index 99% rename from modules/calib3d/src/usac/pnp_solver.cpp rename to modules/3d/src/usac/pnp_solver.cpp index e095eeff7c..ce62d2892e 100644 --- a/modules/calib3d/src/usac/pnp_solver.cpp +++ b/modules/3d/src/usac/pnp_solver.cpp @@ -377,4 +377,4 @@ public: Ptr P3PSolver::create(const Mat &points_, const Mat &calib_norm_pts, const Mat &K) { return makePtr(points_, calib_norm_pts, K); } -}} \ No newline at end of file +}} diff --git a/modules/calib3d/src/usac/quality.cpp b/modules/3d/src/usac/quality.cpp similarity index 99% rename from modules/calib3d/src/usac/quality.cpp rename to modules/3d/src/usac/quality.cpp index 856dbb5c95..f29a5cfbb6 100644 --- a/modules/calib3d/src/usac/quality.cpp +++ b/modules/3d/src/usac/quality.cpp @@ -584,4 +584,4 @@ Ptr SPRT::create (int state, const Ptr &err_, int points_size_, return makePtr(state, err_, points_size_, inlier_threshold_, prob_pt_of_good_model, prob_pt_of_bad_model, time_sample, avg_num_models, score_type_); } -}} \ No newline at end of file +}} diff --git a/modules/calib3d/src/usac/ransac_solvers.cpp b/modules/3d/src/usac/ransac_solvers.cpp similarity index 100% rename from modules/calib3d/src/usac/ransac_solvers.cpp rename to modules/3d/src/usac/ransac_solvers.cpp diff --git a/modules/calib3d/src/usac/sampler.cpp b/modules/3d/src/usac/sampler.cpp similarity index 100% rename from modules/calib3d/src/usac/sampler.cpp rename to modules/3d/src/usac/sampler.cpp diff --git a/modules/calib3d/src/usac/termination.cpp b/modules/3d/src/usac/termination.cpp similarity index 100% rename from modules/calib3d/src/usac/termination.cpp rename to modules/3d/src/usac/termination.cpp diff --git a/modules/calib3d/src/usac/utils.cpp b/modules/3d/src/usac/utils.cpp similarity index 99% rename from modules/calib3d/src/usac/utils.cpp rename to modules/3d/src/usac/utils.cpp index 1c781a7d82..9c4d2b91af 100644 --- a/modules/calib3d/src/usac/utils.cpp +++ b/modules/3d/src/usac/utils.cpp @@ -530,4 +530,4 @@ Ptr GridNeighborhoodGraph::create(const Mat &points, return makePtr(points, points_size, cell_size_x_img1_, cell_size_y_img1_, cell_size_x_img2_, cell_size_y_img2_, max_neighbors); } -}} \ No newline at end of file +}} diff --git a/modules/calib3d/test/test_affine2d_estimator.cpp b/modules/3d/test/test_affine2d_estimator.cpp similarity index 100% rename from modules/calib3d/test/test_affine2d_estimator.cpp rename to modules/3d/test/test_affine2d_estimator.cpp diff --git a/modules/calib3d/test/test_affine3.cpp b/modules/3d/test/test_affine3.cpp similarity index 100% rename from modules/calib3d/test/test_affine3.cpp rename to modules/3d/test/test_affine3.cpp diff --git a/modules/calib3d/test/test_affine3d_estimator.cpp b/modules/3d/test/test_affine3d_estimator.cpp similarity index 100% rename from modules/calib3d/test/test_affine3d_estimator.cpp rename to modules/3d/test/test_affine3d_estimator.cpp diff --git a/modules/calib3d/test/test_affine_partial2d_estimator.cpp b/modules/3d/test/test_affine_partial2d_estimator.cpp similarity index 100% rename from modules/calib3d/test/test_affine_partial2d_estimator.cpp rename to modules/3d/test/test_affine_partial2d_estimator.cpp diff --git a/modules/calib3d/test/test_compose_rt.cpp b/modules/3d/test/test_compose_rt.cpp similarity index 100% rename from modules/calib3d/test/test_compose_rt.cpp rename to modules/3d/test/test_compose_rt.cpp diff --git a/modules/calib3d/test/test_decompose_projection.cpp b/modules/3d/test/test_decompose_projection.cpp similarity index 100% rename from modules/calib3d/test/test_decompose_projection.cpp rename to modules/3d/test/test_decompose_projection.cpp diff --git a/modules/calib3d/test/test_filter_homography_decomp.cpp b/modules/3d/test/test_filter_homography_decomp.cpp similarity index 99% rename from modules/calib3d/test/test_filter_homography_decomp.cpp rename to modules/3d/test/test_filter_homography_decomp.cpp index 533d9ddf56..633d43ad8e 100644 --- a/modules/calib3d/test/test_filter_homography_decomp.cpp +++ b/modules/3d/test/test_filter_homography_decomp.cpp @@ -41,7 +41,7 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" namespace opencv_test { namespace { diff --git a/modules/calib3d/test/test_fundam.cpp b/modules/3d/test/test_fundam.cpp similarity index 99% rename from modules/calib3d/test/test_fundam.cpp rename to modules/3d/test/test_fundam.cpp index 874e8912d7..92d383f1a2 100644 --- a/modules/calib3d/test/test_fundam.cpp +++ b/modules/3d/test/test_fundam.cpp @@ -41,7 +41,6 @@ #include "test_precomp.hpp" #include "opencv2/core/core_c.h" -#include "opencv2/calib3d/calib3d_c.h" namespace cvtest { @@ -826,13 +825,13 @@ void CV_FundamentalMatTest::get_test_array_types_and_sizes( int /*test_case_idx* dims = cvtest::randInt(rng) % 2 + 2; method = 1 << (cvtest::randInt(rng) % 4); - if( method == CV_FM_7POINT ) + if( method == FM_7POINT ) pt_count = 7; else { - pt_count = MAX( pt_count, 8 + (method == CV_FM_8POINT) ); + pt_count = MAX( pt_count, 8 + (method == FM_8POINT) ); if( pt_count >= 8 && cvtest::randInt(rng) % 2 ) - method |= CV_FM_8POINT; + method |= FM_8POINT; } types[INPUT][0] = CV_MAKETYPE(pt_depth, 1); @@ -1012,7 +1011,7 @@ void CV_FundamentalMatTest::prepare_to_validation( int test_case_idx ) cvtest::convert(Fsrc, F, F.type()); - if( method <= CV_FM_8POINT ) + if( method <= FM_8POINT ) memset( status, 1, pt_count ); for( i = 0; i < pt_count; i++ ) @@ -1125,7 +1124,7 @@ void CV_EssentialMatTest::get_test_array_types_and_sizes( int /*test_case_idx*/, dims = cvtest::randInt(rng) % 2 + 2; dims = 2; - method = CV_LMEDS << (cvtest::randInt(rng) % 2); + method = LMEDS << (cvtest::randInt(rng) % 2); types[INPUT][0] = CV_MAKETYPE(pt_depth, 1); @@ -1389,7 +1388,7 @@ void CV_EssentialMatTest::prepare_to_validation( int test_case_idx ) pose_prop1[0] = 0; // No check for CV_LMeDS on translation. Since it // involves with some degraded problem, when data is exact inliers. - pose_prop2[0] = method == CV_LMEDS || pt_count == 5 ? 0 : MIN(terr1, terr2); + pose_prop2[0] = method == LMEDS || pt_count == 5 ? 0 : MIN(terr1, terr2); // int inliers_count = countNonZero(test_mat[TEMP][1]); diff --git a/modules/calib3d/test/test_homography.cpp b/modules/3d/test/test_homography.cpp similarity index 99% rename from modules/calib3d/test/test_homography.cpp rename to modules/3d/test/test_homography.cpp index 09478dae03..0fd5735a18 100644 --- a/modules/calib3d/test/test_homography.cpp +++ b/modules/3d/test/test_homography.cpp @@ -42,6 +42,7 @@ //M*/ #include "test_precomp.hpp" +#include namespace opencv_test { namespace { diff --git a/modules/calib3d/test/test_homography_decomp.cpp b/modules/3d/test/test_homography_decomp.cpp similarity index 100% rename from modules/calib3d/test/test_homography_decomp.cpp rename to modules/3d/test/test_homography_decomp.cpp diff --git a/modules/calib3d/test/test_main.cpp b/modules/3d/test/test_main.cpp similarity index 100% rename from modules/calib3d/test/test_main.cpp rename to modules/3d/test/test_main.cpp diff --git a/modules/calib3d/test/test_modelest.cpp b/modules/3d/test/test_modelest.cpp similarity index 100% rename from modules/calib3d/test/test_modelest.cpp rename to modules/3d/test/test_modelest.cpp diff --git a/modules/calib3d/test/test_precomp.hpp b/modules/3d/test/test_precomp.hpp similarity index 94% rename from modules/calib3d/test/test_precomp.hpp rename to modules/3d/test/test_precomp.hpp index 0a4f7c208b..b60e846160 100644 --- a/modules/calib3d/test/test_precomp.hpp +++ b/modules/3d/test/test_precomp.hpp @@ -8,7 +8,7 @@ #include #include "opencv2/ts.hpp" -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" namespace cvtest { diff --git a/modules/calib3d/test/test_solvepnp_ransac.cpp b/modules/3d/test/test_solvepnp_ransac.cpp similarity index 100% rename from modules/calib3d/test/test_solvepnp_ransac.cpp rename to modules/3d/test/test_solvepnp_ransac.cpp diff --git a/modules/calib3d/test/test_translation3d_estimator.cpp b/modules/3d/test/test_translation3d_estimator.cpp similarity index 100% rename from modules/calib3d/test/test_translation3d_estimator.cpp rename to modules/3d/test/test_translation3d_estimator.cpp diff --git a/modules/calib3d/test/test_undistort.cpp b/modules/3d/test/test_undistort.cpp similarity index 99% rename from modules/calib3d/test/test_undistort.cpp rename to modules/3d/test/test_undistort.cpp index c1ec2063ee..c6b6fb95f9 100644 --- a/modules/calib3d/test/test_undistort.cpp +++ b/modules/3d/test/test_undistort.cpp @@ -711,7 +711,7 @@ void CV_InitUndistortRectifyMapTest::run_func() cv::Mat R = zero_R ? cv::Mat() : test_mat[INPUT][2]; cv::Mat new_cam = zero_new_cam ? cv::Mat() : test_mat[INPUT][3]; cv::Mat& mapx = test_mat[OUTPUT][0], &mapy = test_mat[OUTPUT][1]; - cv::initUndistortRectifyMap(camera_mat,dist,R,new_cam,img_size,map_type,mapx,mapy); + initUndistortRectifyMap(camera_mat,dist,R,new_cam,img_size,map_type,mapx,mapy); } double CV_InitUndistortRectifyMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) diff --git a/modules/calib3d/test/test_undistort_badarg.cpp b/modules/3d/test/test_undistort_badarg.cpp similarity index 100% rename from modules/calib3d/test/test_undistort_badarg.cpp rename to modules/3d/test/test_undistort_badarg.cpp diff --git a/modules/calib3d/test/test_undistort_points.cpp b/modules/3d/test/test_undistort_points.cpp similarity index 100% rename from modules/calib3d/test/test_undistort_points.cpp rename to modules/3d/test/test_undistort_points.cpp diff --git a/modules/calib3d/test/test_usac.cpp b/modules/3d/test/test_usac.cpp similarity index 100% rename from modules/calib3d/test/test_usac.cpp rename to modules/3d/test/test_usac.cpp diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 6a8004036b..10b72f8880 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -20,7 +20,7 @@ foreach(mod ${OPENCV_MODULES_BUILD} ${OPENCV_MODULES_DISABLED_USER} ${OPENCV_MOD endforeach() ocv_list_sort(OPENCV_MODULES_MAIN) ocv_list_sort(OPENCV_MODULES_EXTRA) -set(FIXED_ORDER_MODULES core imgproc imgcodecs videoio highgui video calib3d features2d objdetect dnn ml flann photo stitching) +set(FIXED_ORDER_MODULES core imgproc imgcodecs videoio highgui video 3d stereo features2d calib objdetect dnn ml flann photo stitching) list(REMOVE_ITEM OPENCV_MODULES_MAIN ${FIXED_ORDER_MODULES}) set(OPENCV_MODULES_MAIN ${FIXED_ORDER_MODULES} ${OPENCV_MODULES_MAIN}) diff --git a/modules/calib/CMakeLists.txt b/modules/calib/CMakeLists.txt new file mode 100644 index 0000000000..7773da95a2 --- /dev/null +++ b/modules/calib/CMakeLists.txt @@ -0,0 +1,9 @@ +set(the_description "Camera Calibration and 3D Reconstruction") + +set(debug_modules "") +if(DEBUG_opencv_calib) + list(APPEND debug_modules opencv_highgui) +endif() +ocv_define_module(calib opencv_imgproc opencv_features2d opencv_flann opencv_3d opencv_stereo ${debug_modules} + WRAP java objc python js +) diff --git a/modules/calib/doc/calib.bib b/modules/calib/doc/calib.bib new file mode 100644 index 0000000000..9646154e5d --- /dev/null +++ b/modules/calib/doc/calib.bib @@ -0,0 +1,12 @@ +@inproceedings{strobl2011iccv, + title={More accurate pinhole camera calibration with imperfect planar target}, + author={Strobl, Klaus H. and Hirzinger, Gerd}, + booktitle={2011 IEEE International Conference on Computer Vision (ICCV)}, + pages={1068-1075}, + month={Nov}, + year={2011}, + address={Barcelona, Spain}, + publisher={IEEE}, + url={https://elib.dlr.de/71888/1/strobl_2011iccv.pdf}, + doi={10.1109/ICCVW.2011.6130369} +} diff --git a/modules/calib3d/doc/pics/checkerboard_radon.png b/modules/calib/doc/pics/checkerboard_radon.png similarity index 100% rename from modules/calib3d/doc/pics/checkerboard_radon.png rename to modules/calib/doc/pics/checkerboard_radon.png diff --git a/modules/calib3d/doc/pics/distortion_examples.png b/modules/calib/doc/pics/distortion_examples.png similarity index 100% rename from modules/calib3d/doc/pics/distortion_examples.png rename to modules/calib/doc/pics/distortion_examples.png diff --git a/modules/calib3d/doc/pics/distortion_examples2.png b/modules/calib/doc/pics/distortion_examples2.png similarity index 100% rename from modules/calib3d/doc/pics/distortion_examples2.png rename to modules/calib/doc/pics/distortion_examples2.png diff --git a/modules/calib3d/doc/pics/fisheye_undistorted.jpg b/modules/calib/doc/pics/fisheye_undistorted.jpg similarity index 100% rename from modules/calib3d/doc/pics/fisheye_undistorted.jpg rename to modules/calib/doc/pics/fisheye_undistorted.jpg diff --git a/modules/calib3d/doc/pics/hand-eye_figure.png b/modules/calib/doc/pics/hand-eye_figure.png similarity index 100% rename from modules/calib3d/doc/pics/hand-eye_figure.png rename to modules/calib/doc/pics/hand-eye_figure.png diff --git a/modules/calib3d/doc/pics/pinhole_camera_model.png b/modules/calib/doc/pics/pinhole_camera_model.png similarity index 100% rename from modules/calib3d/doc/pics/pinhole_camera_model.png rename to modules/calib/doc/pics/pinhole_camera_model.png diff --git a/modules/calib3d/doc/pics/robot-world_hand-eye_figure.png b/modules/calib/doc/pics/robot-world_hand-eye_figure.png similarity index 100% rename from modules/calib3d/doc/pics/robot-world_hand-eye_figure.png rename to modules/calib/doc/pics/robot-world_hand-eye_figure.png diff --git a/modules/calib3d/doc/pics/stereo_undistort.jpg b/modules/calib/doc/pics/stereo_undistort.jpg similarity index 100% rename from modules/calib3d/doc/pics/stereo_undistort.jpg rename to modules/calib/doc/pics/stereo_undistort.jpg diff --git a/modules/calib/include/opencv2/calib.hpp b/modules/calib/include/opencv2/calib.hpp new file mode 100644 index 0000000000..945db3e87b --- /dev/null +++ b/modules/calib/include/opencv2/calib.hpp @@ -0,0 +1,1647 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#ifndef OPENCV_CALIB_HPP +#define OPENCV_CALIB_HPP + +#include "opencv2/core.hpp" +#include "opencv2/features2d.hpp" +#include "opencv2/core/affine.hpp" + +/** + @defgroup calib Camera Calibration + +The functions in this section use a so-called pinhole camera model. The view of a scene +is obtained by projecting a scene's 3D point \f$P_w\f$ into the image plane using a perspective +transformation which forms the corresponding pixel \f$p\f$. Both \f$P_w\f$ and \f$p\f$ are +represented in homogeneous coordinates, i.e. as 3D and 2D homogeneous vector respectively. You will +find a brief introduction to projective geometry, homogeneous vectors and homogeneous +transformations at the end of this section's introduction. For more succinct notation, we often drop +the 'homogeneous' and say vector instead of homogeneous vector. + +The distortion-free projective transformation given by a pinhole camera model is shown below. + +\f[s \; p = A \begin{bmatrix} R|t \end{bmatrix} P_w,\f] + +where \f$P_w\f$ is a 3D point expressed with respect to the world coordinate system, +\f$p\f$ is a 2D pixel in the image plane, \f$A\f$ is the camera intrinsic matrix, +\f$R\f$ and \f$t\f$ are the rotation and translation that describe the change of coordinates from +world to camera coordinate systems (or camera frame) and \f$s\f$ is the projective transformation's +arbitrary scaling and not part of the camera model. + +The camera intrinsic matrix \f$A\f$ (notation used as in @cite Zhang2000 and also generally notated +as \f$K\f$) projects 3D points given in the camera coordinate system to 2D pixel coordinates, i.e. + +\f[p = A P_c.\f] + +The camera intrinsic matrix \f$A\f$ is composed of the focal lengths \f$f_x\f$ and \f$f_y\f$, which are +expressed in pixel units, and the principal point \f$(c_x, c_y)\f$, that is usually close to the +image center: + +\f[A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1},\f] + +and thus + +\f[s \vecthree{u}{v}{1} = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1} \vecthree{X_c}{Y_c}{Z_c}.\f] + +The matrix of intrinsic parameters does not depend on the scene viewed. So, once estimated, it can +be re-used as long as the focal length is fixed (in case of a zoom lens). Thus, if an image from the +camera is scaled by a factor, all of these parameters need to be scaled (multiplied/divided, +respectively) by the same factor. + +The joint rotation-translation matrix \f$[R|t]\f$ is the matrix product of a projective +transformation and a homogeneous transformation. The 3-by-4 projective transformation maps 3D points +represented in camera coordinates to 2D poins in the image plane and represented in normalized +camera coordinates \f$x' = X_c / Z_c\f$ and \f$y' = Y_c / Z_c\f$: + +\f[Z_c \begin{bmatrix} +x' \\ +y' \\ +1 +\end{bmatrix} = \begin{bmatrix} +1 & 0 & 0 & 0 \\ +0 & 1 & 0 & 0 \\ +0 & 0 & 1 & 0 +\end{bmatrix} +\begin{bmatrix} +X_c \\ +Y_c \\ +Z_c \\ +1 +\end{bmatrix}.\f] + +The homogeneous transformation is encoded by the extrinsic parameters \f$R\f$ and \f$t\f$ and +represents the change of basis from world coordinate system \f$w\f$ to the camera coordinate sytem +\f$c\f$. Thus, given the representation of the point \f$P\f$ in world coordinates, \f$P_w\f$, we +obtain \f$P\f$'s representation in the camera coordinate system, \f$P_c\f$, by + +\f[P_c = \begin{bmatrix} +R & t \\ +0 & 1 +\end{bmatrix} P_w,\f] + +This homogeneous transformation is composed out of \f$R\f$, a 3-by-3 rotation matrix, and \f$t\f$, a +3-by-1 translation vector: + +\f[\begin{bmatrix} +R & t \\ +0 & 1 +\end{bmatrix} = \begin{bmatrix} +r_{11} & r_{12} & r_{13} & t_x \\ +r_{21} & r_{22} & r_{23} & t_y \\ +r_{31} & r_{32} & r_{33} & t_z \\ +0 & 0 & 0 & 1 +\end{bmatrix}, +\f] + +and therefore + +\f[\begin{bmatrix} +X_c \\ +Y_c \\ +Z_c \\ +1 +\end{bmatrix} = \begin{bmatrix} +r_{11} & r_{12} & r_{13} & t_x \\ +r_{21} & r_{22} & r_{23} & t_y \\ +r_{31} & r_{32} & r_{33} & t_z \\ +0 & 0 & 0 & 1 +\end{bmatrix} +\begin{bmatrix} +X_w \\ +Y_w \\ +Z_w \\ +1 +\end{bmatrix}.\f] + +Combining the projective transformation and the homogeneous transformation, we obtain the projective +transformation that maps 3D points in world coordinates into 2D points in the image plane and in +normalized camera coordinates: + +\f[Z_c \begin{bmatrix} +x' \\ +y' \\ +1 +\end{bmatrix} = \begin{bmatrix} R|t \end{bmatrix} \begin{bmatrix} +X_w \\ +Y_w \\ +Z_w \\ +1 +\end{bmatrix} = \begin{bmatrix} +r_{11} & r_{12} & r_{13} & t_x \\ +r_{21} & r_{22} & r_{23} & t_y \\ +r_{31} & r_{32} & r_{33} & t_z +\end{bmatrix} +\begin{bmatrix} +X_w \\ +Y_w \\ +Z_w \\ +1 +\end{bmatrix},\f] + +with \f$x' = X_c / Z_c\f$ and \f$y' = Y_c / Z_c\f$. Putting the equations for instrincs and extrinsics together, we can write out +\f$s \; p = A \begin{bmatrix} R|t \end{bmatrix} P_w\f$ as + +\f[s \vecthree{u}{v}{1} = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1} +\begin{bmatrix} +r_{11} & r_{12} & r_{13} & t_x \\ +r_{21} & r_{22} & r_{23} & t_y \\ +r_{31} & r_{32} & r_{33} & t_z +\end{bmatrix} +\begin{bmatrix} +X_w \\ +Y_w \\ +Z_w \\ +1 +\end{bmatrix}.\f] + +If \f$Z_c \ne 0\f$, the transformation above is equivalent to the following, + +\f[\begin{bmatrix} +u \\ +v +\end{bmatrix} = \begin{bmatrix} +f_x X_c/Z_c + c_x \\ +f_y Y_c/Z_c + c_y +\end{bmatrix}\f] + +with + +\f[\vecthree{X_c}{Y_c}{Z_c} = \begin{bmatrix} +R|t +\end{bmatrix} \begin{bmatrix} +X_w \\ +Y_w \\ +Z_w \\ +1 +\end{bmatrix}.\f] + +The following figure illustrates the pinhole camera model. + +![Pinhole camera model](pics/pinhole_camera_model.png) + +Real lenses usually have some distortion, mostly radial distortion, and slight tangential distortion. +So, the above model is extended as: + +\f[\begin{bmatrix} +u \\ +v +\end{bmatrix} = \begin{bmatrix} +f_x x'' + c_x \\ +f_y y'' + c_y +\end{bmatrix}\f] + +where + +\f[\begin{bmatrix} +x'' \\ +y'' +\end{bmatrix} = \begin{bmatrix} +x' \frac{1 + k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} + 2 p_1 x' y' + p_2(r^2 + 2 x'^2) + s_1 r^2 + s_2 r^4 \\ +y' \frac{1 + k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} + p_1 (r^2 + 2 y'^2) + 2 p_2 x' y' + s_3 r^2 + s_4 r^4 \\ +\end{bmatrix}\f] + +with + +\f[r^2 = x'^2 + y'^2\f] + +and + +\f[\begin{bmatrix} +x'\\ +y' +\end{bmatrix} = \begin{bmatrix} +X_c/Z_c \\ +Y_c/Z_c +\end{bmatrix},\f] + +if \f$Z_c \ne 0\f$. + +The distortion parameters are the radial coefficients \f$k_1\f$, \f$k_2\f$, \f$k_3\f$, \f$k_4\f$, \f$k_5\f$, and \f$k_6\f$ +,\f$p_1\f$ and \f$p_2\f$ are the tangential distortion coefficients, and \f$s_1\f$, \f$s_2\f$, \f$s_3\f$, and \f$s_4\f$, +are the thin prism distortion coefficients. Higher-order coefficients are not considered in OpenCV. + +The next figures show two common types of radial distortion: barrel distortion +(\f$ 1 + k_1 r^2 + k_2 r^4 + k_3 r^6 \f$ monotonically decreasing) +and pincushion distortion (\f$ 1 + k_1 r^2 + k_2 r^4 + k_3 r^6 \f$ monotonically increasing). +Radial distortion is always monotonic for real lenses, +and if the estimator produces a non-monotonic result, +this should be considered a calibration failure. +More generally, radial distortion must be monotonic and the distortion function must be bijective. +A failed estimation result may look deceptively good near the image center +but will work poorly in e.g. AR/SFM applications. +The optimization method used in OpenCV camera calibration does not include these constraints as +the framework does not support the required integer programming and polynomial inequalities. +See [issue #15992](https://github.com/opencv/opencv/issues/15992) for additional information. + +![](pics/distortion_examples.png) +![](pics/distortion_examples2.png) + +In some cases, the image sensor may be tilted in order to focus an oblique plane in front of the +camera (Scheimpflug principle). This can be useful for particle image velocimetry (PIV) or +triangulation with a laser fan. The tilt causes a perspective distortion of \f$x''\f$ and +\f$y''\f$. This distortion can be modeled in the following way, see e.g. @cite Louhichi07. + +\f[\begin{bmatrix} +u \\ +v +\end{bmatrix} = \begin{bmatrix} +f_x x''' + c_x \\ +f_y y''' + c_y +\end{bmatrix},\f] + +where + +\f[s\vecthree{x'''}{y'''}{1} = +\vecthreethree{R_{33}(\tau_x, \tau_y)}{0}{-R_{13}(\tau_x, \tau_y)} +{0}{R_{33}(\tau_x, \tau_y)}{-R_{23}(\tau_x, \tau_y)} +{0}{0}{1} R(\tau_x, \tau_y) \vecthree{x''}{y''}{1}\f] + +and the matrix \f$R(\tau_x, \tau_y)\f$ is defined by two rotations with angular parameter +\f$\tau_x\f$ and \f$\tau_y\f$, respectively, + +\f[ +R(\tau_x, \tau_y) = +\vecthreethree{\cos(\tau_y)}{0}{-\sin(\tau_y)}{0}{1}{0}{\sin(\tau_y)}{0}{\cos(\tau_y)} +\vecthreethree{1}{0}{0}{0}{\cos(\tau_x)}{\sin(\tau_x)}{0}{-\sin(\tau_x)}{\cos(\tau_x)} = +\vecthreethree{\cos(\tau_y)}{\sin(\tau_y)\sin(\tau_x)}{-\sin(\tau_y)\cos(\tau_x)} +{0}{\cos(\tau_x)}{\sin(\tau_x)} +{\sin(\tau_y)}{-\cos(\tau_y)\sin(\tau_x)}{\cos(\tau_y)\cos(\tau_x)}. +\f] + +In the functions below the coefficients are passed or returned as + +\f[(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \tau_x, \tau_y]]]])\f] + +vector. That is, if the vector contains four elements, it means that \f$k_3=0\f$ . The distortion +coefficients do not depend on the scene viewed. Thus, they also belong to the intrinsic camera +parameters. And they remain the same regardless of the captured image resolution. If, for example, a +camera has been calibrated on images of 320 x 240 resolution, absolutely the same distortion +coefficients can be used for 640 x 480 images from the same camera while \f$f_x\f$, \f$f_y\f$, +\f$c_x\f$, and \f$c_y\f$ need to be scaled appropriately. + +The functions below use the above model to do the following: + +- Project 3D points to the image plane given intrinsic and extrinsic parameters. +- Compute extrinsic parameters given intrinsic parameters, a few 3D points, and their +projections. +- Estimate intrinsic and extrinsic camera parameters from several views of a known calibration +pattern (every view is described by several 3D-2D point correspondences). +- Estimate the relative position and orientation of the stereo camera "heads" and compute the +*rectification* transformation that makes the camera optical axes parallel. + + Homogeneous Coordinates
+Homogeneous Coordinates are a system of coordinates that are used in projective geometry. Their use +allows to represent points at infinity by finite coordinates and simplifies formulas when compared +to the cartesian counterparts, e.g. they have the advantage that affine transformations can be +expressed as linear homogeneous transformation. + +One obtains the homogeneous vector \f$P_h\f$ by appending a 1 along an n-dimensional cartesian +vector \f$P\f$ e.g. for a 3D cartesian vector the mapping \f$P \rightarrow P_h\f$ is: + +\f[\begin{bmatrix} +X \\ +Y \\ +Z +\end{bmatrix} \rightarrow \begin{bmatrix} +X \\ +Y \\ +Z \\ +1 +\end{bmatrix}.\f] + +For the inverse mapping \f$P_h \rightarrow P\f$, one divides all elements of the homogeneous vector +by its last element, e.g. for a 3D homogeneous vector one gets its 2D cartesian counterpart by: + +\f[\begin{bmatrix} +X \\ +Y \\ +W +\end{bmatrix} \rightarrow \begin{bmatrix} +X / W \\ +Y / W +\end{bmatrix},\f] + +if \f$W \ne 0\f$. + +Due to this mapping, all multiples \f$k P_h\f$, for \f$k \ne 0\f$, of a homogeneous point represent +the same point \f$P_h\f$. An intuitive understanding of this property is that under a projective +transformation, all multiples of \f$P_h\f$ are mapped to the same point. This is the physical +observation one does for pinhole cameras, as all points along a ray through the camera's pinhole are +projected to the same image point, e.g. all points along the red ray in the image of the pinhole +camera model above would be mapped to the same image coordinate. This property is also the source +for the scale ambiguity s in the equation of the pinhole camera model. + +As mentioned, by using homogeneous coordinates we can express any change of basis parameterized by +\f$R\f$ and \f$t\f$ as a linear transformation, e.g. for the change of basis from coordinate system +0 to coordinate system 1 becomes: + +\f[P_1 = R P_0 + t \rightarrow P_{h_1} = \begin{bmatrix} +R & t \\ +0 & 1 +\end{bmatrix} P_{h_0}.\f] + +@note + - Many functions in this module take a camera intrinsic matrix as an input parameter. Although all + functions assume the same structure of this parameter, they may name it differently. The + parameter's description, however, will be clear in that a camera intrinsic matrix with the structure + shown above is required. + - A calibration sample for 3 cameras in a horizontal position can be found at + opencv_source_code/samples/cpp/3calibration.cpp + - A calibration sample based on a sequence of images can be found at + opencv_source_code/samples/cpp/calibration.cpp + - A calibration sample in order to do 3D reconstruction can be found at + opencv_source_code/samples/cpp/build3dmodel.cpp + - A calibration example on stereo calibration can be found at + opencv_source_code/samples/cpp/stereo_calib.cpp + - A calibration example on stereo matching can be found at + opencv_source_code/samples/cpp/stereo_match.cpp + - (Python) A camera calibration sample can be found at + opencv_source_code/samples/python/calibrate.py + + @{ + @defgroup calib3d_fisheye Fisheye camera model + + Definitions: Let P be a point in 3D of coordinates X in the world reference frame (stored in the + matrix X) The coordinate vector of P in the camera reference frame is: + + \f[Xc = R X + T\f] + + where R is the rotation matrix corresponding to the rotation vector om: R = rodrigues(om); call x, y + and z the 3 coordinates of Xc: + + \f[x = Xc_1 \\ y = Xc_2 \\ z = Xc_3\f] + + The pinhole projection coordinates of P is [a; b] where + + \f[a = x / z \ and \ b = y / z \\ r^2 = a^2 + b^2 \\ \theta = atan(r)\f] + + Fisheye distortion: + + \f[\theta_d = \theta (1 + k_1 \theta^2 + k_2 \theta^4 + k_3 \theta^6 + k_4 \theta^8)\f] + + The distorted point coordinates are [x'; y'] where + + \f[x' = (\theta_d / r) a \\ y' = (\theta_d / r) b \f] + + Finally, conversion into pixel coordinates: The final pixel coordinates vector [u; v] where: + + \f[u = f_x (x' + \alpha y') + c_x \\ + v = f_y y' + c_y\f] + + @defgroup calib3d_c C API + + @} + */ + +namespace cv { + +//! @addtogroup calib +//! @{ + +enum { CALIB_CB_ADAPTIVE_THRESH = 1, + CALIB_CB_NORMALIZE_IMAGE = 2, + CALIB_CB_FILTER_QUADS = 4, + CALIB_CB_FAST_CHECK = 8, + CALIB_CB_EXHAUSTIVE = 16, + CALIB_CB_ACCURACY = 32, + CALIB_CB_LARGER = 64, + CALIB_CB_MARKER = 128 + }; + +enum { CALIB_CB_SYMMETRIC_GRID = 1, + CALIB_CB_ASYMMETRIC_GRID = 2, + CALIB_CB_CLUSTERING = 4 + }; + +enum { CALIB_NINTRINSIC = 18, + CALIB_USE_INTRINSIC_GUESS = 0x00001, + CALIB_FIX_ASPECT_RATIO = 0x00002, + CALIB_FIX_PRINCIPAL_POINT = 0x00004, + CALIB_ZERO_TANGENT_DIST = 0x00008, + CALIB_FIX_FOCAL_LENGTH = 0x00010, + CALIB_FIX_K1 = 0x00020, + CALIB_FIX_K2 = 0x00040, + CALIB_FIX_K3 = 0x00080, + CALIB_FIX_K4 = 0x00800, + CALIB_FIX_K5 = 0x01000, + CALIB_FIX_K6 = 0x02000, + CALIB_RATIONAL_MODEL = 0x04000, + CALIB_THIN_PRISM_MODEL = 0x08000, + CALIB_FIX_S1_S2_S3_S4 = 0x10000, + CALIB_TILTED_MODEL = 0x40000, + CALIB_FIX_TAUX_TAUY = 0x80000, + CALIB_USE_QR = 0x100000, //!< use QR instead of SVD decomposition for solving. Faster but potentially less precise + CALIB_FIX_TANGENT_DIST = 0x200000, + // only for stereo + CALIB_FIX_INTRINSIC = 0x00100, + CALIB_SAME_FOCAL_LENGTH = 0x00200, + // for stereo rectification + CALIB_ZERO_DISPARITY = 0x00400, + CALIB_USE_LU = (1 << 17), //!< use LU instead of SVD decomposition for solving. much faster but potentially less precise + CALIB_USE_EXTRINSIC_GUESS = (1 << 22) //!< for stereoCalibrate + }; + +enum HandEyeCalibrationMethod +{ + CALIB_HAND_EYE_TSAI = 0, //!< A New Technique for Fully Autonomous and Efficient 3D Robotics Hand/Eye Calibration @cite Tsai89 + CALIB_HAND_EYE_PARK = 1, //!< Robot Sensor Calibration: Solving AX = XB on the Euclidean Group @cite Park94 + CALIB_HAND_EYE_HORAUD = 2, //!< Hand-eye Calibration @cite Horaud95 + CALIB_HAND_EYE_ANDREFF = 3, //!< On-line Hand-Eye Calibration @cite Andreff99 + CALIB_HAND_EYE_DANIILIDIS = 4 //!< Hand-Eye Calibration Using Dual Quaternions @cite Daniilidis98 +}; + +enum RobotWorldHandEyeCalibrationMethod +{ + CALIB_ROBOT_WORLD_HAND_EYE_SHAH = 0, //!< Solving the robot-world/hand-eye calibration problem using the kronecker product @cite Shah2013SolvingTR + CALIB_ROBOT_WORLD_HAND_EYE_LI = 1 //!< Simultaneous robot-world and hand-eye calibration using dual-quaternions and kronecker product @cite Li2010SimultaneousRA +}; + +/** @brief Finds an initial camera intrinsic matrix from 3D-2D point correspondences. + +@param objectPoints Vector of vectors of the calibration pattern points in the calibration pattern +coordinate space. In the old interface all the per-view vectors are concatenated. See +calibrateCamera for details. +@param imagePoints Vector of vectors of the projections of the calibration pattern points. In the +old interface all the per-view vectors are concatenated. +@param imageSize Image size in pixels used to initialize the principal point. +@param aspectRatio If it is zero or negative, both \f$f_x\f$ and \f$f_y\f$ are estimated independently. +Otherwise, \f$f_x = f_y * \texttt{aspectRatio}\f$ . + +The function estimates and returns an initial camera intrinsic matrix for the camera calibration process. +Currently, the function only supports planar calibration patterns, which are patterns where each +object point has z-coordinate =0. + */ +CV_EXPORTS_W Mat initCameraMatrix2D( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, + Size imageSize, double aspectRatio = 1.0 ); + +/** @brief Finds the positions of internal corners of the chessboard. + +@param image Source chessboard view. It must be an 8-bit grayscale or color image. +@param patternSize Number of inner corners per a chessboard row and column +( patternSize = cv::Size(points_per_row,points_per_colum) = cv::Size(columns,rows) ). +@param corners Output array of detected corners. +@param flags Various operation flags that can be zero or a combination of the following values: +- **CALIB_CB_ADAPTIVE_THRESH** Use adaptive thresholding to convert the image to black +and white, rather than a fixed threshold level (computed from the average image brightness). +- **CALIB_CB_NORMALIZE_IMAGE** Normalize the image gamma with equalizeHist before +applying fixed or adaptive thresholding. +- **CALIB_CB_FILTER_QUADS** Use additional criteria (like contour area, perimeter, +square-like shape) to filter out false quads extracted at the contour retrieval stage. +- **CALIB_CB_FAST_CHECK** Run a fast check on the image that looks for chessboard corners, +and shortcut the call if none is found. This can drastically speed up the call in the +degenerate condition when no chessboard is observed. + +The function attempts to determine whether the input image is a view of the chessboard pattern and +locate the internal chessboard corners. The function returns a non-zero value if all of the corners +are found and they are placed in a certain order (row by row, left to right in every row). +Otherwise, if the function fails to find all the corners or reorder them, it returns 0. For example, +a regular chessboard has 8 x 8 squares and 7 x 7 internal corners, that is, points where the black +squares touch each other. The detected coordinates are approximate, and to determine their positions +more accurately, the function calls cornerSubPix. You also may use the function cornerSubPix with +different parameters if returned coordinates are not accurate enough. + +Sample usage of detecting and drawing chessboard corners: : +@code + Size patternsize(8,6); //interior number of corners + Mat gray = ....; //source image + vector corners; //this will be filled by the detected corners + + //CALIB_CB_FAST_CHECK saves a lot of time on images + //that do not contain any chessboard corners + bool patternfound = findChessboardCorners(gray, patternsize, corners, + CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + + CALIB_CB_FAST_CHECK); + + if(patternfound) + cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1), + TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1)); + + drawChessboardCorners(img, patternsize, Mat(corners), patternfound); +@endcode +@note The function requires white space (like a square-thick border, the wider the better) around +the board to make the detection more robust in various environments. Otherwise, if there is no +border and the background is dark, the outer black squares cannot be segmented properly and so the +square grouping and ordering algorithm fails. + */ +CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, + int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE ); + +/* + Checks whether the image contains chessboard of the specific size or not. + If yes, nonzero value is returned. +*/ +CV_EXPORTS_W bool checkChessboard(InputArray img, Size size); + +/** @brief Finds the positions of internal corners of the chessboard using a sector based approach. + +@param image Source chessboard view. It must be an 8-bit grayscale or color image. +@param patternSize Number of inner corners per a chessboard row and column +( patternSize = cv::Size(points_per_row,points_per_colum) = cv::Size(columns,rows) ). +@param corners Output array of detected corners. +@param flags Various operation flags that can be zero or a combination of the following values: +- **CALIB_CB_NORMALIZE_IMAGE** Normalize the image gamma with equalizeHist before detection. +- **CALIB_CB_EXHAUSTIVE** Run an exhaustive search to improve detection rate. +- **CALIB_CB_ACCURACY** Up sample input image to improve sub-pixel accuracy due to aliasing effects. +- **CALIB_CB_LARGER** The detected pattern is allowed to be larger than patternSize (see description). +- **CALIB_CB_MARKER** The detected pattern must have a marker (see description). +This should be used if an accurate camera calibration is required. +@param meta Optional output arrray of detected corners (CV_8UC1 and size = cv::Size(columns,rows)). +Each entry stands for one corner of the pattern and can have one of the following values: +- 0 = no meta data attached +- 1 = left-top corner of a black cell +- 2 = left-top corner of a white cell +- 3 = left-top corner of a black cell with a white marker dot +- 4 = left-top corner of a white cell with a black marker dot (pattern origin in case of markers otherwise first corner) + +The function is analog to findchessboardCorners but uses a localized radon +transformation approximated by box filters being more robust to all sort of +noise, faster on larger images and is able to directly return the sub-pixel +position of the internal chessboard corners. The Method is based on the paper +@cite duda2018 "Accurate Detection and Localization of Checkerboard Corners for +Calibration" demonstrating that the returned sub-pixel positions are more +accurate than the one returned by cornerSubPix allowing a precise camera +calibration for demanding applications. + +In the case, the flags **CALIB_CB_LARGER** or **CALIB_CB_MARKER** are given, +the result can be recovered from the optional meta array. Both flags are +helpful to use calibration patterns exceeding the field of view of the camera. +These oversized patterns allow more accurate calibrations as corners can be +utilized, which are as close as possible to the image borders. For a +consistent coordinate system across all images, the optional marker (see image +below) can be used to move the origin of the board to the location where the +black circle is located. + +@note The function requires a white boarder with roughly the same width as one +of the checkerboard fields around the whole board to improve the detection in +various environments. In addition, because of the localized radon +transformation it is beneficial to use round corners for the field corners +which are located on the outside of the board. The following figure illustrates +a sample checkerboard optimized for the detection. However, any other checkerboard +can be used as well. +![Checkerboard](pics/checkerboard_radon.png) + */ +CV_EXPORTS_AS(findChessboardCornersSBWithMeta) +bool findChessboardCornersSB(InputArray image,Size patternSize, OutputArray corners, + int flags,OutputArray meta); +/** @overload */ +CV_EXPORTS_W inline +bool findChessboardCornersSB(InputArray image, Size patternSize, OutputArray corners, + int flags = 0) +{ + return findChessboardCornersSB(image, patternSize, corners, flags, noArray()); +} + +/** @brief Estimates the sharpness of a detected chessboard. + +Image sharpness, as well as brightness, are a critical parameter for accuracte +camera calibration. For accessing these parameters for filtering out +problematic calibraiton images, this method calculates edge profiles by traveling from +black to white chessboard cell centers. Based on this, the number of pixels is +calculated required to transit from black to white. This width of the +transition area is a good indication of how sharp the chessboard is imaged +and should be below ~3.0 pixels. + +@param image Gray image used to find chessboard corners +@param patternSize Size of a found chessboard pattern +@param corners Corners found by findChessboardCorners(SB) +@param rise_distance Rise distance 0.8 means 10% ... 90% of the final signal strength +@param vertical By default edge responses for horizontal lines are calculated +@param sharpness Optional output array with a sharpness value for calculated edge responses (see description) + +The optional sharpness array is of type CV_32FC1 and has for each calculated +profile one row with the following five entries: +* 0 = x coordinate of the underlying edge in the image +* 1 = y coordinate of the underlying edge in the image +* 2 = width of the transition area (sharpness) +* 3 = signal strength in the black cell (min brightness) +* 4 = signal strength in the white cell (max brightness) + +@return Scalar(average sharpness, average min brightness, average max brightness,0) +*/ +CV_EXPORTS_W Scalar estimateChessboardSharpness(InputArray image, Size patternSize, InputArray corners, + float rise_distance=0.8F,bool vertical=false, + OutputArray sharpness=noArray()); + + +//! finds subpixel-accurate positions of the chessboard corners +CV_EXPORTS_W bool find4QuadCornerSubpix( InputArray img, InputOutputArray corners, Size region_size ); + +/** @brief Renders the detected chessboard corners. + +@param image Destination image. It must be an 8-bit color image. +@param patternSize Number of inner corners per a chessboard row and column +(patternSize = cv::Size(points_per_row,points_per_column)). +@param corners Array of detected corners, the output of findChessboardCorners. +@param patternWasFound Parameter indicating whether the complete board was found or not. The +return value of findChessboardCorners should be passed here. + +The function draws individual chessboard corners detected either as red circles if the board was not +found, or as colored corners connected with lines if the board was found. + */ +CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize, + InputArray corners, bool patternWasFound ); + +struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters +{ + CV_WRAP CirclesGridFinderParameters(); + CV_PROP_RW cv::Size2f densityNeighborhoodSize; + CV_PROP_RW float minDensity; + CV_PROP_RW int kmeansAttempts; + CV_PROP_RW int minDistanceToAddKeypoint; + CV_PROP_RW int keypointScale; + CV_PROP_RW float minGraphConfidence; + CV_PROP_RW float vertexGain; + CV_PROP_RW float vertexPenalty; + CV_PROP_RW float existingVertexGain; + CV_PROP_RW float edgeGain; + CV_PROP_RW float edgePenalty; + CV_PROP_RW float convexHullFactor; + CV_PROP_RW float minRNGEdgeSwitchDist; + + enum GridType + { + SYMMETRIC_GRID, ASYMMETRIC_GRID + }; + GridType gridType; + + CV_PROP_RW float squareSize; //!< Distance between two adjacent points. Used by CALIB_CB_CLUSTERING. + CV_PROP_RW float maxRectifiedDistance; //!< Max deviation from prediction. Used by CALIB_CB_CLUSTERING. +}; + +#ifndef DISABLE_OPENCV_3_COMPATIBILITY +typedef CirclesGridFinderParameters CirclesGridFinderParameters2; +#endif + +/** @brief Finds centers in the grid of circles. + +@param image grid view of input circles; it must be an 8-bit grayscale or color image. +@param patternSize number of circles per row and column +( patternSize = Size(points_per_row, points_per_colum) ). +@param centers output array of detected centers. +@param flags various operation flags that can be one of the following values: +- **CALIB_CB_SYMMETRIC_GRID** uses symmetric pattern of circles. +- **CALIB_CB_ASYMMETRIC_GRID** uses asymmetric pattern of circles. +- **CALIB_CB_CLUSTERING** uses a special algorithm for grid detection. It is more robust to +perspective distortions but much more sensitive to background clutter. +@param blobDetector feature detector that finds blobs like dark circles on light background. +@param parameters struct for finding circles in a grid pattern. + +The function attempts to determine whether the input image contains a grid of circles. If it is, the +function locates centers of the circles. The function returns a non-zero value if all of the centers +have been found and they have been placed in a certain order (row by row, left to right in every +row). Otherwise, if the function fails to find all the corners or reorder them, it returns 0. + +Sample usage of detecting and drawing the centers of circles: : +@code + Size patternsize(7,7); //number of centers + Mat gray = ....; //source image + vector centers; //this will be filled by the detected centers + + bool patternfound = findCirclesGrid(gray, patternsize, centers); + + drawChessboardCorners(img, patternsize, Mat(centers), patternfound); +@endcode +@note The function requires white space (like a square-thick border, the wider the better) around +the board to make the detection more robust in various environments. + */ +CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, + OutputArray centers, int flags, + const Ptr &blobDetector, + const CirclesGridFinderParameters& parameters); + +/** @overload */ +CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, + OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID, + const Ptr &blobDetector = SimpleBlobDetector::create()); + +/** @brief Finds the camera intrinsic and extrinsic parameters from several views of a calibration +pattern. + +@param objectPoints In the new interface it is a vector of vectors of calibration pattern points in +the calibration pattern coordinate space (e.g. std::vector>). The outer +vector contains as many elements as the number of pattern views. If the same calibration pattern +is shown in each view and it is fully visible, all the vectors will be the same. Although, it is +possible to use partially occluded patterns or even different patterns in different views. Then, +the vectors will be different. Although the points are 3D, they all lie in the calibration pattern's +XY coordinate plane (thus 0 in the Z-coordinate), if the used calibration pattern is a planar rig. +In the old interface all the vectors of object points from different views are concatenated +together. +@param imagePoints In the new interface it is a vector of vectors of the projections of calibration +pattern points (e.g. std::vector>). imagePoints.size() and +objectPoints.size(), and imagePoints[i].size() and objectPoints[i].size() for each i, must be equal, +respectively. In the old interface all the vectors of object points from different views are +concatenated together. +@param imageSize Size of the image used only to initialize the camera intrinsic matrix. +@param cameraMatrix Input/output 3x3 floating-point camera intrinsic matrix +\f$\cameramatrix{A}\f$ . If CV\_CALIB\_USE\_INTRINSIC\_GUESS +and/or CALIB_FIX_ASPECT_RATIO are specified, some or all of fx, fy, cx, cy must be +initialized before calling the function. +@param distCoeffs Input/output vector of distortion coefficients +\f$\distcoeffs\f$. +@param rvecs Output vector of rotation vectors (@ref Rodrigues ) estimated for each pattern view +(e.g. std::vector>). That is, each i-th rotation vector together with the corresponding +i-th translation vector (see the next output parameter description) brings the calibration pattern +from the object coordinate space (in which object points are specified) to the camera coordinate +space. In more technical terms, the tuple of the i-th rotation and translation vector performs +a change of basis from object coordinate space to camera coordinate space. Due to its duality, this +tuple is equivalent to the position of the calibration pattern with respect to the camera coordinate +space. +@param tvecs Output vector of translation vectors estimated for each pattern view, see parameter +describtion above. +@param stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic +parameters. Order of deviations values: +\f$(f_x, f_y, c_x, c_y, k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6 , s_1, s_2, s_3, + s_4, \tau_x, \tau_y)\f$ If one of parameters is not estimated, it's deviation is equals to zero. +@param stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic +parameters. Order of deviations values: \f$(R_0, T_0, \dotsc , R_{M - 1}, T_{M - 1})\f$ where M is +the number of pattern views. \f$R_i, T_i\f$ are concatenated 1x3 vectors. + @param perViewErrors Output vector of the RMS re-projection error estimated for each pattern view. +@param flags Different flags that may be zero or a combination of the following values: +- **CALIB_USE_INTRINSIC_GUESS** cameraMatrix contains valid initial values of +fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image +center ( imageSize is used), and focal distances are computed in a least-squares fashion. +Note, that if intrinsic parameters are known, there is no need to use this function just to +estimate extrinsic parameters. Use solvePnP instead. +- **CALIB_FIX_PRINCIPAL_POINT** The principal point is not changed during the global +optimization. It stays at the center or at a different location specified when +CALIB_USE_INTRINSIC_GUESS is set too. +- **CALIB_FIX_ASPECT_RATIO** The functions consider only fy as a free parameter. The +ratio fx/fy stays the same as in the input cameraMatrix . When +CALIB_USE_INTRINSIC_GUESS is not set, the actual input values of fx and fy are +ignored, only their ratio is computed and used further. +- **CALIB_ZERO_TANGENT_DIST** Tangential distortion coefficients \f$(p_1, p_2)\f$ are set +to zeros and stay zero. +- **CALIB_FIX_K1,...,CALIB_FIX_K6** The corresponding radial distortion +coefficient is not changed during the optimization. If CALIB_USE_INTRINSIC_GUESS is +set, the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to 0. +- **CALIB_RATIONAL_MODEL** Coefficients k4, k5, and k6 are enabled. To provide the +backward compatibility, this extra flag should be explicitly specified to make the +calibration function use the rational model and return 8 coefficients. If the flag is not +set, the function computes and returns only 5 distortion coefficients. +- **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the +backward compatibility, this extra flag should be explicitly specified to make the +calibration function use the thin prism model and return 12 coefficients. If the flag is not +set, the function computes and returns only 5 distortion coefficients. +- **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during +the optimization. If CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the +supplied distCoeffs matrix is used. Otherwise, it is set to 0. +- **CALIB_TILTED_MODEL** Coefficients tauX and tauY are enabled. To provide the +backward compatibility, this extra flag should be explicitly specified to make the +calibration function use the tilted sensor model and return 14 coefficients. If the flag is not +set, the function computes and returns only 5 distortion coefficients. +- **CALIB_FIX_TAUX_TAUY** The coefficients of the tilted sensor model are not changed during +the optimization. If CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the +supplied distCoeffs matrix is used. Otherwise, it is set to 0. +@param criteria Termination criteria for the iterative optimization algorithm. + +@return the overall RMS re-projection error. + +The function estimates the intrinsic camera parameters and extrinsic parameters for each of the +views. The algorithm is based on @cite Zhang2000 and @cite BouguetMCT . The coordinates of 3D object +points and their corresponding 2D projections in each view must be specified. That may be achieved +by using an object with known geometry and easily detectable feature points. Such an object is +called a calibration rig or calibration pattern, and OpenCV has built-in support for a chessboard as +a calibration rig (see @ref findChessboardCorners). Currently, initialization of intrinsic +parameters (when CALIB_USE_INTRINSIC_GUESS is not set) is only implemented for planar calibration +patterns (where Z-coordinates of the object points must be all zeros). 3D calibration rigs can also +be used as long as initial cameraMatrix is provided. + +The algorithm performs the following steps: + +- Compute the initial intrinsic parameters (the option only available for planar calibration + patterns) or read them from the input parameters. The distortion coefficients are all set to + zeros initially unless some of CALIB_FIX_K? are specified. + +- Estimate the initial camera pose as if the intrinsic parameters have been already known. This is + done using solvePnP . + +- Run the global Levenberg-Marquardt optimization algorithm to minimize the reprojection error, + that is, the total sum of squared distances between the observed feature points imagePoints and + the projected (using the current estimates for camera parameters and the poses) object points + objectPoints. See projectPoints for details. + +@note + If you use a non-square (i.e. non-N-by-N) grid and @ref findChessboardCorners for calibration, + and @ref calibrateCamera returns bad values (zero distortion coefficients, \f$c_x\f$ and + \f$c_y\f$ very far from the image center, and/or large differences between \f$f_x\f$ and + \f$f_y\f$ (ratios of 10:1 or more)), then you are probably using patternSize=cvSize(rows,cols) + instead of using patternSize=cvSize(cols,rows) in @ref findChessboardCorners. + +@sa + calibrateCameraRO, findChessboardCorners, solvePnP, initCameraMatrix2D, stereoCalibrate, + undistort + */ +CV_EXPORTS_AS(calibrateCameraExtended) double calibrateCamera( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, Size imageSize, + InputOutputArray cameraMatrix, InputOutputArray distCoeffs, + OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, + OutputArray stdDeviationsIntrinsics, + OutputArray stdDeviationsExtrinsics, + OutputArray perViewErrors, + int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); + +/** @overload */ +CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, Size imageSize, + InputOutputArray cameraMatrix, InputOutputArray distCoeffs, + OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, + int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); + +/** @brief Finds the camera intrinsic and extrinsic parameters from several views of a calibration pattern. + +This function is an extension of calibrateCamera() with the method of releasing object which was +proposed in @cite strobl2011iccv. In many common cases with inaccurate, unmeasured, roughly planar +targets (calibration plates), this method can dramatically improve the precision of the estimated +camera parameters. Both the object-releasing method and standard method are supported by this +function. Use the parameter **iFixedPoint** for method selection. In the internal implementation, +calibrateCamera() is a wrapper for this function. + +@param objectPoints Vector of vectors of calibration pattern points in the calibration pattern +coordinate space. See calibrateCamera() for details. If the method of releasing object to be used, +the identical calibration board must be used in each view and it must be fully visible, and all +objectPoints[i] must be the same and all points should be roughly close to a plane. **The calibration +target has to be rigid, or at least static if the camera (rather than the calibration target) is +shifted for grabbing images.** +@param imagePoints Vector of vectors of the projections of calibration pattern points. See +calibrateCamera() for details. +@param imageSize Size of the image used only to initialize the intrinsic camera matrix. +@param iFixedPoint The index of the 3D object point in objectPoints[0] to be fixed. It also acts as +a switch for calibration method selection. If object-releasing method to be used, pass in the +parameter in the range of [1, objectPoints[0].size()-2], otherwise a value out of this range will +make standard calibration method selected. Usually the top-right corner point of the calibration +board grid is recommended to be fixed when object-releasing method being utilized. According to +\cite strobl2011iccv, two other points are also fixed. In this implementation, objectPoints[0].front +and objectPoints[0].back.z are used. With object-releasing method, accurate rvecs, tvecs and +newObjPoints are only possible if coordinates of these three fixed points are accurate enough. +@param cameraMatrix Output 3x3 floating-point camera matrix. See calibrateCamera() for details. +@param distCoeffs Output vector of distortion coefficients. See calibrateCamera() for details. +@param rvecs Output vector of rotation vectors estimated for each pattern view. See calibrateCamera() +for details. +@param tvecs Output vector of translation vectors estimated for each pattern view. +@param newObjPoints The updated output vector of calibration pattern points. The coordinates might +be scaled based on three fixed points. The returned coordinates are accurate only if the above +mentioned three fixed points are accurate. If not needed, noArray() can be passed in. This parameter +is ignored with standard calibration method. +@param stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic parameters. +See calibrateCamera() for details. +@param stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic parameters. +See calibrateCamera() for details. +@param stdDeviationsObjPoints Output vector of standard deviations estimated for refined coordinates +of calibration pattern points. It has the same size and order as objectPoints[0] vector. This +parameter is ignored with standard calibration method. + @param perViewErrors Output vector of the RMS re-projection error estimated for each pattern view. +@param flags Different flags that may be zero or a combination of some predefined values. See +calibrateCamera() for details. If the method of releasing object is used, the calibration time may +be much longer. CALIB_USE_QR or CALIB_USE_LU could be used for faster calibration with potentially +less precise and less stable in some rare cases. +@param criteria Termination criteria for the iterative optimization algorithm. + +@return the overall RMS re-projection error. + +The function estimates the intrinsic camera parameters and extrinsic parameters for each of the +views. The algorithm is based on @cite Zhang2000, @cite BouguetMCT and @cite strobl2011iccv. See +calibrateCamera() for other detailed explanations. +@sa + calibrateCamera, findChessboardCorners, solvePnP, initCameraMatrix2D, stereoCalibrate, undistort + */ +CV_EXPORTS_AS(calibrateCameraROExtended) double calibrateCameraRO( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, Size imageSize, int iFixedPoint, + InputOutputArray cameraMatrix, InputOutputArray distCoeffs, + OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, + OutputArray newObjPoints, + OutputArray stdDeviationsIntrinsics, + OutputArray stdDeviationsExtrinsics, + OutputArray stdDeviationsObjPoints, + OutputArray perViewErrors, + int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); + +/** @overload */ +CV_EXPORTS_W double calibrateCameraRO( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, Size imageSize, int iFixedPoint, + InputOutputArray cameraMatrix, InputOutputArray distCoeffs, + OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, + OutputArray newObjPoints, + int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); + +/** @brief Computes useful camera characteristics from the camera intrinsic matrix. + +@param cameraMatrix Input camera intrinsic matrix that can be estimated by calibrateCamera or +stereoCalibrate . +@param imageSize Input image size in pixels. +@param apertureWidth Physical width in mm of the sensor. +@param apertureHeight Physical height in mm of the sensor. +@param fovx Output field of view in degrees along the horizontal sensor axis. +@param fovy Output field of view in degrees along the vertical sensor axis. +@param focalLength Focal length of the lens in mm. +@param principalPoint Principal point in mm. +@param aspectRatio \f$f_y/f_x\f$ + +The function computes various useful camera characteristics from the previously estimated camera +matrix. + +@note + Do keep in mind that the unity measure 'mm' stands for whatever unit of measure one chooses for + the chessboard pitch (it can thus be any value). + */ +CV_EXPORTS_W void calibrationMatrixValues( InputArray cameraMatrix, Size imageSize, + double apertureWidth, double apertureHeight, + CV_OUT double& fovx, CV_OUT double& fovy, + CV_OUT double& focalLength, CV_OUT Point2d& principalPoint, + CV_OUT double& aspectRatio ); + +/** @brief Calibrates a stereo camera set up. This function finds the intrinsic parameters +for each of the two cameras and the extrinsic parameters between the two cameras. + +@param objectPoints Vector of vectors of the calibration pattern points. The same structure as +in @ref calibrateCamera. For each pattern view, both cameras need to see the same object +points. Therefore, objectPoints.size(), imagePoints1.size(), and imagePoints2.size() need to be +equal as well as objectPoints[i].size(), imagePoints1[i].size(), and imagePoints2[i].size() need to +be equal for each i. +@param imagePoints1 Vector of vectors of the projections of the calibration pattern points, +observed by the first camera. The same structure as in @ref calibrateCamera. +@param imagePoints2 Vector of vectors of the projections of the calibration pattern points, +observed by the second camera. The same structure as in @ref calibrateCamera. +@param cameraMatrix1 Input/output camera intrinsic matrix for the first camera, the same as in +@ref calibrateCamera. Furthermore, for the stereo case, additional flags may be used, see below. +@param distCoeffs1 Input/output vector of distortion coefficients, the same as in +@ref calibrateCamera. +@param cameraMatrix2 Input/output second camera intrinsic matrix for the second camera. See description for +cameraMatrix1. +@param distCoeffs2 Input/output lens distortion coefficients for the second camera. See +description for distCoeffs1. +@param imageSize Size of the image used only to initialize the camera intrinsic matrices. +@param R Output rotation matrix. Together with the translation vector T, this matrix brings +points given in the first camera's coordinate system to points in the second camera's +coordinate system. In more technical terms, the tuple of R and T performs a change of basis +from the first camera's coordinate system to the second camera's coordinate system. Due to its +duality, this tuple is equivalent to the position of the first camera with respect to the +second camera coordinate system. +@param T Output translation vector, see description above. +@param E Output essential matrix. +@param F Output fundamental matrix. +@param perViewErrors Output vector of the RMS re-projection error estimated for each pattern view. +@param flags Different flags that may be zero or a combination of the following values: +- **CALIB_FIX_INTRINSIC** Fix cameraMatrix? and distCoeffs? so that only R, T, E, and F +matrices are estimated. +- **CALIB_USE_INTRINSIC_GUESS** Optimize some or all of the intrinsic parameters +according to the specified flags. Initial values are provided by the user. +- **CALIB_USE_EXTRINSIC_GUESS** R and T contain valid initial values that are optimized further. +Otherwise R and T are initialized to the median value of the pattern views (each dimension separately). +- **CALIB_FIX_PRINCIPAL_POINT** Fix the principal points during the optimization. +- **CALIB_FIX_FOCAL_LENGTH** Fix \f$f^{(j)}_x\f$ and \f$f^{(j)}_y\f$ . +- **CALIB_FIX_ASPECT_RATIO** Optimize \f$f^{(j)}_y\f$ . Fix the ratio \f$f^{(j)}_x/f^{(j)}_y\f$ +. +- **CALIB_SAME_FOCAL_LENGTH** Enforce \f$f^{(0)}_x=f^{(1)}_x\f$ and \f$f^{(0)}_y=f^{(1)}_y\f$ . +- **CALIB_ZERO_TANGENT_DIST** Set tangential distortion coefficients for each camera to +zeros and fix there. +- **CALIB_FIX_K1,...,CALIB_FIX_K6** Do not change the corresponding radial +distortion coefficient during the optimization. If CALIB_USE_INTRINSIC_GUESS is set, +the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to 0. +- **CALIB_RATIONAL_MODEL** Enable coefficients k4, k5, and k6. To provide the backward +compatibility, this extra flag should be explicitly specified to make the calibration +function use the rational model and return 8 coefficients. If the flag is not set, the +function computes and returns only 5 distortion coefficients. +- **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the +backward compatibility, this extra flag should be explicitly specified to make the +calibration function use the thin prism model and return 12 coefficients. If the flag is not +set, the function computes and returns only 5 distortion coefficients. +- **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during +the optimization. If CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the +supplied distCoeffs matrix is used. Otherwise, it is set to 0. +- **CALIB_TILTED_MODEL** Coefficients tauX and tauY are enabled. To provide the +backward compatibility, this extra flag should be explicitly specified to make the +calibration function use the tilted sensor model and return 14 coefficients. If the flag is not +set, the function computes and returns only 5 distortion coefficients. +- **CALIB_FIX_TAUX_TAUY** The coefficients of the tilted sensor model are not changed during +the optimization. If CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the +supplied distCoeffs matrix is used. Otherwise, it is set to 0. +@param criteria Termination criteria for the iterative optimization algorithm. + +The function estimates the transformation between two cameras making a stereo pair. If one computes +the poses of an object relative to the first camera and to the second camera, +( \f$R_1\f$,\f$T_1\f$ ) and (\f$R_2\f$,\f$T_2\f$), respectively, for a stereo camera where the +relative position and orientation between the two cameras are fixed, then those poses definitely +relate to each other. This means, if the relative position and orientation (\f$R\f$,\f$T\f$) of the +two cameras is known, it is possible to compute (\f$R_2\f$,\f$T_2\f$) when (\f$R_1\f$,\f$T_1\f$) is +given. This is what the described function does. It computes (\f$R\f$,\f$T\f$) such that: + +\f[R_2=R R_1\f] +\f[T_2=R T_1 + T.\f] + +Therefore, one can compute the coordinate representation of a 3D point for the second camera's +coordinate system when given the point's coordinate representation in the first camera's coordinate +system: + +\f[\begin{bmatrix} +X_2 \\ +Y_2 \\ +Z_2 \\ +1 +\end{bmatrix} = \begin{bmatrix} +R & T \\ +0 & 1 +\end{bmatrix} \begin{bmatrix} +X_1 \\ +Y_1 \\ +Z_1 \\ +1 +\end{bmatrix}.\f] + + +Optionally, it computes the essential matrix E: + +\f[E= \vecthreethree{0}{-T_2}{T_1}{T_2}{0}{-T_0}{-T_1}{T_0}{0} R\f] + +where \f$T_i\f$ are components of the translation vector \f$T\f$ : \f$T=[T_0, T_1, T_2]^T\f$ . +And the function can also compute the fundamental matrix F: + +\f[F = cameraMatrix2^{-T}\cdot E \cdot cameraMatrix1^{-1}\f] + +Besides the stereo-related information, the function can also perform a full calibration of each of +the two cameras. However, due to the high dimensionality of the parameter space and noise in the +input data, the function can diverge from the correct solution. If the intrinsic parameters can be +estimated with high accuracy for each of the cameras individually (for example, using +calibrateCamera ), you are recommended to do so and then pass CALIB_FIX_INTRINSIC flag to the +function along with the computed intrinsic parameters. Otherwise, if all the parameters are +estimated at once, it makes sense to restrict some parameters, for example, pass +CALIB_SAME_FOCAL_LENGTH and CALIB_ZERO_TANGENT_DIST flags, which is usually a +reasonable assumption. + +Similarly to calibrateCamera, the function minimizes the total re-projection error for all the +points in all the available views from both cameras. The function returns the final value of the +re-projection error. + */ +CV_EXPORTS_AS(stereoCalibrateExtended) double stereoCalibrate( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1, + InputOutputArray cameraMatrix2, InputOutputArray distCoeffs2, + Size imageSize, InputOutputArray R,InputOutputArray T, OutputArray E, OutputArray F, + OutputArray perViewErrors, int flags = CALIB_FIX_INTRINSIC, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6) ); + +/// @overload +CV_EXPORTS_W double stereoCalibrate( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1, + InputOutputArray cameraMatrix2, InputOutputArray distCoeffs2, + Size imageSize, OutputArray R,OutputArray T, OutputArray E, OutputArray F, + int flags = CALIB_FIX_INTRINSIC, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6) ); + + +/** @brief Computes Hand-Eye calibration: \f$_{}^{g}\textrm{T}_c\f$ + +@param[in] R_gripper2base Rotation part extracted from the homogeneous matrix that transforms a point +expressed in the gripper frame to the robot base frame (\f$_{}^{b}\textrm{T}_g\f$). +This is a vector (`vector`) that contains the rotation, `(3x3)` rotation matrices or `(3x1)` rotation vectors, +for all the transformations from gripper frame to robot base frame. +@param[in] t_gripper2base Translation part extracted from the homogeneous matrix that transforms a point +expressed in the gripper frame to the robot base frame (\f$_{}^{b}\textrm{T}_g\f$). +This is a vector (`vector`) that contains the `(3x1)` translation vectors for all the transformations +from gripper frame to robot base frame. +@param[in] R_target2cam Rotation part extracted from the homogeneous matrix that transforms a point +expressed in the target frame to the camera frame (\f$_{}^{c}\textrm{T}_t\f$). +This is a vector (`vector`) that contains the rotation, `(3x3)` rotation matrices or `(3x1)` rotation vectors, +for all the transformations from calibration target frame to camera frame. +@param[in] t_target2cam Rotation part extracted from the homogeneous matrix that transforms a point +expressed in the target frame to the camera frame (\f$_{}^{c}\textrm{T}_t\f$). +This is a vector (`vector`) that contains the `(3x1)` translation vectors for all the transformations +from calibration target frame to camera frame. +@param[out] R_cam2gripper Estimated `(3x3)` rotation part extracted from the homogeneous matrix that transforms a point +expressed in the camera frame to the gripper frame (\f$_{}^{g}\textrm{T}_c\f$). +@param[out] t_cam2gripper Estimated `(3x1)` translation part extracted from the homogeneous matrix that transforms a point +expressed in the camera frame to the gripper frame (\f$_{}^{g}\textrm{T}_c\f$). +@param[in] method One of the implemented Hand-Eye calibration method, see cv::HandEyeCalibrationMethod + +The function performs the Hand-Eye calibration using various methods. One approach consists in estimating the +rotation then the translation (separable solutions) and the following methods are implemented: + - R. Tsai, R. Lenz A New Technique for Fully Autonomous and Efficient 3D Robotics Hand/EyeCalibration \cite Tsai89 + - F. Park, B. Martin Robot Sensor Calibration: Solving AX = XB on the Euclidean Group \cite Park94 + - R. Horaud, F. Dornaika Hand-Eye Calibration \cite Horaud95 + +Another approach consists in estimating simultaneously the rotation and the translation (simultaneous solutions), +with the following implemented methods: + - N. Andreff, R. Horaud, B. Espiau On-line Hand-Eye Calibration \cite Andreff99 + - K. Daniilidis Hand-Eye Calibration Using Dual Quaternions \cite Daniilidis98 + +The following picture describes the Hand-Eye calibration problem where the transformation between a camera ("eye") +mounted on a robot gripper ("hand") has to be estimated. This configuration is called eye-in-hand. + +The eye-to-hand configuration consists in a static camera observing a calibration pattern mounted on the robot +end-effector. The transformation from the camera to the robot base frame can then be estimated by inputting +the suitable transformations to the function, see below. + +![](pics/hand-eye_figure.png) + +The calibration procedure is the following: + - a static calibration pattern is used to estimate the transformation between the target frame + and the camera frame + - the robot gripper is moved in order to acquire several poses + - for each pose, the homogeneous transformation between the gripper frame and the robot base frame is recorded using for + instance the robot kinematics +\f[ + \begin{bmatrix} + X_b\\ + Y_b\\ + Z_b\\ + 1 + \end{bmatrix} + = + \begin{bmatrix} + _{}^{b}\textrm{R}_g & _{}^{b}\textrm{t}_g \\ + 0_{1 \times 3} & 1 + \end{bmatrix} + \begin{bmatrix} + X_g\\ + Y_g\\ + Z_g\\ + 1 + \end{bmatrix} +\f] + - for each pose, the homogeneous transformation between the calibration target frame and the camera frame is recorded using + for instance a pose estimation method (PnP) from 2D-3D point correspondences +\f[ + \begin{bmatrix} + X_c\\ + Y_c\\ + Z_c\\ + 1 + \end{bmatrix} + = + \begin{bmatrix} + _{}^{c}\textrm{R}_t & _{}^{c}\textrm{t}_t \\ + 0_{1 \times 3} & 1 + \end{bmatrix} + \begin{bmatrix} + X_t\\ + Y_t\\ + Z_t\\ + 1 + \end{bmatrix} +\f] + +The Hand-Eye calibration procedure returns the following homogeneous transformation +\f[ + \begin{bmatrix} + X_g\\ + Y_g\\ + Z_g\\ + 1 + \end{bmatrix} + = + \begin{bmatrix} + _{}^{g}\textrm{R}_c & _{}^{g}\textrm{t}_c \\ + 0_{1 \times 3} & 1 + \end{bmatrix} + \begin{bmatrix} + X_c\\ + Y_c\\ + Z_c\\ + 1 + \end{bmatrix} +\f] + +This problem is also known as solving the \f$\mathbf{A}\mathbf{X}=\mathbf{X}\mathbf{B}\f$ equation: + - for an eye-in-hand configuration +\f[ + \begin{align*} + ^{b}{\textrm{T}_g}^{(1)} \hspace{0.2em} ^{g}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(1)} &= + \hspace{0.1em} ^{b}{\textrm{T}_g}^{(2)} \hspace{0.2em} ^{g}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} \\ + + (^{b}{\textrm{T}_g}^{(2)})^{-1} \hspace{0.2em} ^{b}{\textrm{T}_g}^{(1)} \hspace{0.2em} ^{g}\textrm{T}_c &= + \hspace{0.1em} ^{g}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} (^{c}{\textrm{T}_t}^{(1)})^{-1} \\ + + \textrm{A}_i \textrm{X} &= \textrm{X} \textrm{B}_i \\ + \end{align*} +\f] + + - for an eye-to-hand configuration +\f[ + \begin{align*} + ^{g}{\textrm{T}_b}^{(1)} \hspace{0.2em} ^{b}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(1)} &= + \hspace{0.1em} ^{g}{\textrm{T}_b}^{(2)} \hspace{0.2em} ^{b}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} \\ + + (^{g}{\textrm{T}_b}^{(2)})^{-1} \hspace{0.2em} ^{g}{\textrm{T}_b}^{(1)} \hspace{0.2em} ^{b}\textrm{T}_c &= + \hspace{0.1em} ^{b}\textrm{T}_c \hspace{0.2em} ^{c}{\textrm{T}_t}^{(2)} (^{c}{\textrm{T}_t}^{(1)})^{-1} \\ + + \textrm{A}_i \textrm{X} &= \textrm{X} \textrm{B}_i \\ + \end{align*} +\f] + +\note +Additional information can be found on this [website](http://campar.in.tum.de/Chair/HandEyeCalibration). +\note +A minimum of 2 motions with non parallel rotation axes are necessary to determine the hand-eye transformation. +So at least 3 different poses are required, but it is strongly recommended to use many more poses. + + */ +CV_EXPORTS void calibrateHandEye( InputArrayOfArrays R_gripper2base, InputArrayOfArrays t_gripper2base, + InputArrayOfArrays R_target2cam, InputArrayOfArrays t_target2cam, + OutputArray R_cam2gripper, OutputArray t_cam2gripper, + HandEyeCalibrationMethod method=CALIB_HAND_EYE_TSAI ); + +/** @brief Computes Robot-World/Hand-Eye calibration: \f$_{}^{w}\textrm{T}_b\f$ and \f$_{}^{c}\textrm{T}_g\f$ + +@param[in] R_world2cam Rotation part extracted from the homogeneous matrix that transforms a point +expressed in the world frame to the camera frame (\f$_{}^{c}\textrm{T}_w\f$). +This is a vector (`vector`) that contains the rotation, `(3x3)` rotation matrices or `(3x1)` rotation vectors, +for all the transformations from world frame to the camera frame. +@param[in] t_world2cam Translation part extracted from the homogeneous matrix that transforms a point +expressed in the world frame to the camera frame (\f$_{}^{c}\textrm{T}_w\f$). +This is a vector (`vector`) that contains the `(3x1)` translation vectors for all the transformations +from world frame to the camera frame. +@param[in] R_base2gripper Rotation part extracted from the homogeneous matrix that transforms a point +expressed in the robot base frame to the gripper frame (\f$_{}^{g}\textrm{T}_b\f$). +This is a vector (`vector`) that contains the rotation, `(3x3)` rotation matrices or `(3x1)` rotation vectors, +for all the transformations from robot base frame to the gripper frame. +@param[in] t_base2gripper Rotation part extracted from the homogeneous matrix that transforms a point +expressed in the robot base frame to the gripper frame (\f$_{}^{g}\textrm{T}_b\f$). +This is a vector (`vector`) that contains the `(3x1)` translation vectors for all the transformations +from robot base frame to the gripper frame. +@param[out] R_base2world Estimated `(3x3)` rotation part extracted from the homogeneous matrix that transforms a point +expressed in the robot base frame to the world frame (\f$_{}^{w}\textrm{T}_b\f$). +@param[out] t_base2world Estimated `(3x1)` translation part extracted from the homogeneous matrix that transforms a point +expressed in the robot base frame to the world frame (\f$_{}^{w}\textrm{T}_b\f$). +@param[out] R_gripper2cam Estimated `(3x3)` rotation part extracted from the homogeneous matrix that transforms a point +expressed in the gripper frame to the camera frame (\f$_{}^{c}\textrm{T}_g\f$). +@param[out] t_gripper2cam Estimated `(3x1)` translation part extracted from the homogeneous matrix that transforms a point +expressed in the gripper frame to the camera frame (\f$_{}^{c}\textrm{T}_g\f$). +@param[in] method One of the implemented Robot-World/Hand-Eye calibration method, see cv::RobotWorldHandEyeCalibrationMethod + +The function performs the Robot-World/Hand-Eye calibration using various methods. One approach consists in estimating the +rotation then the translation (separable solutions): + - M. Shah, Solving the robot-world/hand-eye calibration problem using the kronecker product \cite Shah2013SolvingTR + +Another approach consists in estimating simultaneously the rotation and the translation (simultaneous solutions), +with the following implemented method: + - A. Li, L. Wang, and D. Wu, Simultaneous robot-world and hand-eye calibration using dual-quaternions and kronecker product \cite Li2010SimultaneousRA + +The following picture describes the Robot-World/Hand-Eye calibration problem where the transformations between a robot and a world frame +and between a robot gripper ("hand") and a camera ("eye") mounted at the robot end-effector have to be estimated. + +![](pics/robot-world_hand-eye_figure.png) + +The calibration procedure is the following: + - a static calibration pattern is used to estimate the transformation between the target frame + and the camera frame + - the robot gripper is moved in order to acquire several poses + - for each pose, the homogeneous transformation between the gripper frame and the robot base frame is recorded using for + instance the robot kinematics +\f[ + \begin{bmatrix} + X_g\\ + Y_g\\ + Z_g\\ + 1 + \end{bmatrix} + = + \begin{bmatrix} + _{}^{g}\textrm{R}_b & _{}^{g}\textrm{t}_b \\ + 0_{1 \times 3} & 1 + \end{bmatrix} + \begin{bmatrix} + X_b\\ + Y_b\\ + Z_b\\ + 1 + \end{bmatrix} +\f] + - for each pose, the homogeneous transformation between the calibration target frame (the world frame) and the camera frame is recorded using + for instance a pose estimation method (PnP) from 2D-3D point correspondences +\f[ + \begin{bmatrix} + X_c\\ + Y_c\\ + Z_c\\ + 1 + \end{bmatrix} + = + \begin{bmatrix} + _{}^{c}\textrm{R}_w & _{}^{c}\textrm{t}_w \\ + 0_{1 \times 3} & 1 + \end{bmatrix} + \begin{bmatrix} + X_w\\ + Y_w\\ + Z_w\\ + 1 + \end{bmatrix} +\f] + +The Robot-World/Hand-Eye calibration procedure returns the following homogeneous transformations +\f[ + \begin{bmatrix} + X_w\\ + Y_w\\ + Z_w\\ + 1 + \end{bmatrix} + = + \begin{bmatrix} + _{}^{w}\textrm{R}_b & _{}^{w}\textrm{t}_b \\ + 0_{1 \times 3} & 1 + \end{bmatrix} + \begin{bmatrix} + X_b\\ + Y_b\\ + Z_b\\ + 1 + \end{bmatrix} +\f] +\f[ + \begin{bmatrix} + X_c\\ + Y_c\\ + Z_c\\ + 1 + \end{bmatrix} + = + \begin{bmatrix} + _{}^{c}\textrm{R}_g & _{}^{c}\textrm{t}_g \\ + 0_{1 \times 3} & 1 + \end{bmatrix} + \begin{bmatrix} + X_g\\ + Y_g\\ + Z_g\\ + 1 + \end{bmatrix} +\f] + +This problem is also known as solving the \f$\mathbf{A}\mathbf{X}=\mathbf{Z}\mathbf{B}\f$ equation, with: + - \f$\mathbf{A} \Leftrightarrow \hspace{0.1em} _{}^{c}\textrm{T}_w\f$ + - \f$\mathbf{X} \Leftrightarrow \hspace{0.1em} _{}^{w}\textrm{T}_b\f$ + - \f$\mathbf{Z} \Leftrightarrow \hspace{0.1em} _{}^{c}\textrm{T}_g\f$ + - \f$\mathbf{B} \Leftrightarrow \hspace{0.1em} _{}^{g}\textrm{T}_b\f$ + +\note +At least 3 measurements are required (input vectors size must be greater or equal to 3). + + */ +CV_EXPORTS void calibrateRobotWorldHandEye( InputArrayOfArrays R_world2cam, InputArrayOfArrays t_world2cam, + InputArrayOfArrays R_base2gripper, InputArrayOfArrays t_base2gripper, + OutputArray R_base2world, OutputArray t_base2world, + OutputArray R_gripper2cam, OutputArray t_gripper2cam, + RobotWorldHandEyeCalibrationMethod method=CALIB_ROBOT_WORLD_HAND_EYE_SHAH ); + +/** @brief The methods in this namespace use a so-called fisheye camera model. + @ingroup calib3d_fisheye +*/ +namespace fisheye +{ +//! @addtogroup calib3d_fisheye +//! @{ + +enum{ + CALIB_USE_INTRINSIC_GUESS = 1 << 0, + CALIB_RECOMPUTE_EXTRINSIC = 1 << 1, + CALIB_CHECK_COND = 1 << 2, + CALIB_FIX_SKEW = 1 << 3, + CALIB_FIX_K1 = 1 << 4, + CALIB_FIX_K2 = 1 << 5, + CALIB_FIX_K3 = 1 << 6, + CALIB_FIX_K4 = 1 << 7, + CALIB_FIX_INTRINSIC = 1 << 8, + CALIB_FIX_PRINCIPAL_POINT = 1 << 9 +}; + +/** @brief Projects points using fisheye model + +@param objectPoints Array of object points, 1xN/Nx1 3-channel (or vector\ ), where N is +the number of points in the view. +@param imagePoints Output array of image points, 2xN/Nx2 1-channel or 1xN/Nx1 2-channel, or +vector\. +@param affine +@param K Camera intrinsic matrix \f$cameramatrix{K}\f$. +@param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. +@param alpha The skew coefficient. +@param jacobian Optional output 2Nx15 jacobian matrix of derivatives of image points with respect +to components of the focal lengths, coordinates of the principal point, distortion coefficients, +rotation vector, translation vector, and the skew. In the old interface different components of +the jacobian are returned via different output parameters. + +The function computes projections of 3D points to the image plane given intrinsic and extrinsic +camera parameters. Optionally, the function computes Jacobians - matrices of partial derivatives of +image points coordinates (as functions of all the input parameters) with respect to the particular +parameters, intrinsic and/or extrinsic. + */ +CV_EXPORTS void projectPoints(InputArray objectPoints, OutputArray imagePoints, const Affine3d& affine, + InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray()); + +/** @overload */ +CV_EXPORTS_W void projectPoints(InputArray objectPoints, OutputArray imagePoints, InputArray rvec, InputArray tvec, + InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray()); + +/** @brief Distorts 2D points using fisheye model. + +@param undistorted Array of object points, 1xN/Nx1 2-channel (or vector\ ), where N is +the number of points in the view. +@param K Camera intrinsic matrix \f$cameramatrix{K}\f$. +@param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. +@param alpha The skew coefficient. +@param distorted Output array of image points, 1xN/Nx1 2-channel, or vector\ . + +Note that the function assumes the camera intrinsic matrix of the undistorted points to be identity. +This means if you want to transform back points undistorted with undistortPoints() you have to +multiply them with \f$P^{-1}\f$. + */ +CV_EXPORTS_W void distortPoints(InputArray undistorted, OutputArray distorted, InputArray K, InputArray D, double alpha = 0); + +/** @brief Undistorts 2D points using fisheye model + +@param distorted Array of object points, 1xN/Nx1 2-channel (or vector\ ), where N is the +number of points in the view. +@param K Camera intrinsic matrix \f$cameramatrix{K}\f$. +@param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. +@param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 +1-channel or 1x1 3-channel +@param P New camera intrinsic matrix (3x3) or new projection matrix (3x4) +@param undistorted Output array of image points, 1xN/Nx1 2-channel, or vector\ . + */ +CV_EXPORTS_W void undistortPoints(InputArray distorted, OutputArray undistorted, + InputArray K, InputArray D, InputArray R = noArray(), InputArray P = noArray()); + +/** @brief Computes undistortion and rectification maps for image transform by cv::remap(). If D is empty zero +distortion is used, if R or P is empty identity matrixes are used. + +@param K Camera intrinsic matrix \f$cameramatrix{K}\f$. +@param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. +@param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 +1-channel or 1x1 3-channel +@param P New camera intrinsic matrix (3x3) or new projection matrix (3x4) +@param size Undistorted image size. +@param m1type Type of the first output map that can be CV_32FC1 or CV_16SC2 . See convertMaps() +for details. +@param map1 The first output map. +@param map2 The second output map. + */ +CV_EXPORTS_W void initUndistortRectifyMap(InputArray K, InputArray D, InputArray R, InputArray P, + const cv::Size& size, int m1type, OutputArray map1, OutputArray map2); + +/** @brief Transforms an image to compensate for fisheye lens distortion. + +@param distorted image with fisheye lens distortion. +@param undistorted Output image with compensated fisheye lens distortion. +@param K Camera intrinsic matrix \f$cameramatrix{K}\f$. +@param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. +@param Knew Camera intrinsic matrix of the distorted image. By default, it is the identity matrix but you +may additionally scale and shift the result by using a different matrix. +@param new_size the new size + +The function transforms an image to compensate radial and tangential lens distortion. + +The function is simply a combination of fisheye::initUndistortRectifyMap (with unity R ) and remap +(with bilinear interpolation). See the former function for details of the transformation being +performed. + +See below the results of undistortImage. + - a\) result of undistort of perspective camera model (all possible coefficients (k_1, k_2, k_3, + k_4, k_5, k_6) of distortion were optimized under calibration) + - b\) result of fisheye::undistortImage of fisheye camera model (all possible coefficients (k_1, k_2, + k_3, k_4) of fisheye distortion were optimized under calibration) + - c\) original image was captured with fisheye lens + +Pictures a) and b) almost the same. But if we consider points of image located far from the center +of image, we can notice that on image a) these points are distorted. + +![image](pics/fisheye_undistorted.jpg) + */ +CV_EXPORTS_W void undistortImage(InputArray distorted, OutputArray undistorted, + InputArray K, InputArray D, InputArray Knew = cv::noArray(), const Size& new_size = Size()); + +/** @brief Estimates new camera intrinsic matrix for undistortion or rectification. + +@param K Camera intrinsic matrix \f$cameramatrix{K}\f$. +@param image_size Size of the image +@param D Input vector of distortion coefficients \f$\distcoeffsfisheye\f$. +@param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 +1-channel or 1x1 3-channel +@param P New camera intrinsic matrix (3x3) or new projection matrix (3x4) +@param balance Sets the new focal length in range between the min focal length and the max focal +length. Balance is in range of [0, 1]. +@param new_size the new size +@param fov_scale Divisor for new focal length. + */ +CV_EXPORTS_W void estimateNewCameraMatrixForUndistortRectify(InputArray K, InputArray D, const Size &image_size, InputArray R, + OutputArray P, double balance = 0.0, const Size& new_size = Size(), double fov_scale = 1.0); + +/** @brief Performs camera calibaration + +@param objectPoints vector of vectors of calibration pattern points in the calibration pattern +coordinate space. +@param imagePoints vector of vectors of the projections of calibration pattern points. +imagePoints.size() and objectPoints.size() and imagePoints[i].size() must be equal to +objectPoints[i].size() for each i. +@param image_size Size of the image used only to initialize the camera intrinsic matrix. +@param K Output 3x3 floating-point camera intrinsic matrix +\f$\cameramatrix{A}\f$ . If +fisheye::CALIB_USE_INTRINSIC_GUESS/ is specified, some or all of fx, fy, cx, cy must be +initialized before calling the function. +@param D Output vector of distortion coefficients \f$\distcoeffsfisheye\f$. +@param rvecs Output vector of rotation vectors (see Rodrigues ) estimated for each pattern view. +That is, each k-th rotation vector together with the corresponding k-th translation vector (see +the next output parameter description) brings the calibration pattern from the model coordinate +space (in which object points are specified) to the world coordinate space, that is, a real +position of the calibration pattern in the k-th pattern view (k=0.. *M* -1). +@param tvecs Output vector of translation vectors estimated for each pattern view. +@param flags Different flags that may be zero or a combination of the following values: +- **fisheye::CALIB_USE_INTRINSIC_GUESS** cameraMatrix contains valid initial values of +fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image +center ( imageSize is used), and focal distances are computed in a least-squares fashion. +- **fisheye::CALIB_RECOMPUTE_EXTRINSIC** Extrinsic will be recomputed after each iteration +of intrinsic optimization. +- **fisheye::CALIB_CHECK_COND** The functions will check validity of condition number. +- **fisheye::CALIB_FIX_SKEW** Skew coefficient (alpha) is set to zero and stay zero. +- **fisheye::CALIB_FIX_K1..fisheye::CALIB_FIX_K4** Selected distortion coefficients +are set to zeros and stay zero. +- **fisheye::CALIB_FIX_PRINCIPAL_POINT** The principal point is not changed during the global +optimization. It stays at the center or at a different location specified when CALIB_USE_INTRINSIC_GUESS is set too. +@param criteria Termination criteria for the iterative optimization algorithm. + */ +CV_EXPORTS_W double calibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, const Size& image_size, + InputOutputArray K, InputOutputArray D, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags = 0, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); + +/** @brief Stereo rectification for fisheye camera model + +@param K1 First camera intrinsic matrix. +@param D1 First camera distortion parameters. +@param K2 Second camera intrinsic matrix. +@param D2 Second camera distortion parameters. +@param imageSize Size of the image used for stereo calibration. +@param R Rotation matrix between the coordinate systems of the first and the second +cameras. +@param tvec Translation vector between coordinate systems of the cameras. +@param R1 Output 3x3 rectification transform (rotation matrix) for the first camera. +@param R2 Output 3x3 rectification transform (rotation matrix) for the second camera. +@param P1 Output 3x4 projection matrix in the new (rectified) coordinate systems for the first +camera. +@param P2 Output 3x4 projection matrix in the new (rectified) coordinate systems for the second +camera. +@param Q Output \f$4 \times 4\f$ disparity-to-depth mapping matrix (see reprojectImageTo3D ). +@param flags Operation flags that may be zero or CALIB_ZERO_DISPARITY . If the flag is set, +the function makes the principal points of each camera have the same pixel coordinates in the +rectified views. And if the flag is not set, the function may still shift the images in the +horizontal or vertical direction (depending on the orientation of epipolar lines) to maximize the +useful image area. +@param newImageSize New image resolution after rectification. The same size should be passed to +initUndistortRectifyMap (see the stereo_calib.cpp sample in OpenCV samples directory). When (0,0) +is passed (default), it is set to the original imageSize . Setting it to larger value can help you +preserve details in the original image, especially when there is a big radial distortion. +@param balance Sets the new focal length in range between the min focal length and the max focal +length. Balance is in range of [0, 1]. +@param fov_scale Divisor for new focal length. + */ +CV_EXPORTS_W void stereoRectify(InputArray K1, InputArray D1, InputArray K2, InputArray D2, const Size &imageSize, InputArray R, InputArray tvec, + OutputArray R1, OutputArray R2, OutputArray P1, OutputArray P2, OutputArray Q, int flags, const Size &newImageSize = Size(), + double balance = 0.0, double fov_scale = 1.0); + +/** @brief Performs stereo calibration + +@param objectPoints Vector of vectors of the calibration pattern points. +@param imagePoints1 Vector of vectors of the projections of the calibration pattern points, +observed by the first camera. +@param imagePoints2 Vector of vectors of the projections of the calibration pattern points, +observed by the second camera. +@param K1 Input/output first camera intrinsic matrix: +\f$\vecthreethree{f_x^{(j)}}{0}{c_x^{(j)}}{0}{f_y^{(j)}}{c_y^{(j)}}{0}{0}{1}\f$ , \f$j = 0,\, 1\f$ . If +any of fisheye::CALIB_USE_INTRINSIC_GUESS , fisheye::CALIB_FIX_INTRINSIC are specified, +some or all of the matrix components must be initialized. +@param D1 Input/output vector of distortion coefficients \f$\distcoeffsfisheye\f$ of 4 elements. +@param K2 Input/output second camera intrinsic matrix. The parameter is similar to K1 . +@param D2 Input/output lens distortion coefficients for the second camera. The parameter is +similar to D1 . +@param imageSize Size of the image used only to initialize camera intrinsic matrix. +@param R Output rotation matrix between the 1st and the 2nd camera coordinate systems. +@param T Output translation vector between the coordinate systems of the cameras. +@param flags Different flags that may be zero or a combination of the following values: +- **fisheye::CALIB_FIX_INTRINSIC** Fix K1, K2? and D1, D2? so that only R, T matrices +are estimated. +- **fisheye::CALIB_USE_INTRINSIC_GUESS** K1, K2 contains valid initial values of +fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image +center (imageSize is used), and focal distances are computed in a least-squares fashion. +- **fisheye::CALIB_RECOMPUTE_EXTRINSIC** Extrinsic will be recomputed after each iteration +of intrinsic optimization. +- **fisheye::CALIB_CHECK_COND** The functions will check validity of condition number. +- **fisheye::CALIB_FIX_SKEW** Skew coefficient (alpha) is set to zero and stay zero. +- **fisheye::CALIB_FIX_K1..4** Selected distortion coefficients are set to zeros and stay +zero. +@param criteria Termination criteria for the iterative optimization algorithm. + */ +CV_EXPORTS_W double stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + InputOutputArray K1, InputOutputArray D1, InputOutputArray K2, InputOutputArray D2, Size imageSize, + OutputArray R, OutputArray T, int flags = fisheye::CALIB_FIX_INTRINSIC, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); + +//! @} calib3d_fisheye +} //end namespace fisheye +} //end namespace cv + +#endif diff --git a/modules/calib/include/opencv2/calib3d.hpp b/modules/calib/include/opencv2/calib3d.hpp new file mode 100644 index 0000000000..60eb96c356 --- /dev/null +++ b/modules/calib/include/opencv2/calib3d.hpp @@ -0,0 +1,14 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +// this is the header for backward compatibility with OpenCV 4.x and earlier versions + +#ifndef OPENCV_CALIB3D_HPP +#define OPENCV_CALIB3D_HPP + +#include "opencv2/3d.hpp" +#include "opencv2/stereo.hpp" +#include "opencv2/calib.hpp" + +#endif diff --git a/modules/calib/include/opencv2/calib3d/calib3d.hpp b/modules/calib/include/opencv2/calib3d/calib3d.hpp new file mode 100644 index 0000000000..d68ea192f6 --- /dev/null +++ b/modules/calib/include/opencv2/calib3d/calib3d.hpp @@ -0,0 +1,12 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +// this is the header for backward compatibility with OpenCV 4.x and earlier versions + +#ifndef OPENCV_CALIB3D_CALIB3D_HPP +#define OPENCV_CALIB3D_CALIB3D_HPP + +#include "opencv2/calib3d.hpp" + +#endif diff --git a/modules/calib/misc/java/gen_dict.json b/modules/calib/misc/java/gen_dict.json new file mode 100644 index 0000000000..e7e2e50970 --- /dev/null +++ b/modules/calib/misc/java/gen_dict.json @@ -0,0 +1,14 @@ +{ + "class_ignore_list": [ + "CirclesGridFinderParameters" + ], + "namespaces_dict": { + "cv.fisheye": "fisheye" + }, + "func_arg_fix" : { + "initCameraMatrix2D" : { "objectPoints" : {"ctype" : "vector_vector_Point3f"}, + "imagePoints" : {"ctype" : "vector_vector_Point2f"} }, + "findChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} }, + "drawChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} } + } +} diff --git a/modules/calib/misc/java/test/CalibTest.java b/modules/calib/misc/java/test/CalibTest.java new file mode 100644 index 0000000000..6f73d13d09 --- /dev/null +++ b/modules/calib/misc/java/test/CalibTest.java @@ -0,0 +1,155 @@ +package org.opencv.test.calib; + +import java.util.ArrayList; + +import org.opencv.cv3d.Cv3d; +import org.opencv.calib.Calib; +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDouble; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.MatOfPoint3f; +import org.opencv.core.Point; +import org.opencv.core.Scalar; +import org.opencv.core.Size; +import org.opencv.test.OpenCVTestCase; +import org.opencv.imgproc.Imgproc; + +public class CalibTest extends OpenCVTestCase { + + Size size; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + size = new Size(3, 3); + } + + public void testFindChessboardCornersMatSizeMat() { + Size patternSize = new Size(9, 6); + MatOfPoint2f corners = new MatOfPoint2f(); + Calib.findChessboardCorners(grayChess, patternSize, corners); + assertFalse(corners.empty()); + } + + public void testFindChessboardCornersMatSizeMatInt() { + Size patternSize = new Size(9, 6); + MatOfPoint2f corners = new MatOfPoint2f(); + Calib.findChessboardCorners(grayChess, patternSize, corners, Calib.CALIB_CB_ADAPTIVE_THRESH + Calib.CALIB_CB_NORMALIZE_IMAGE + + Calib.CALIB_CB_FAST_CHECK); + assertFalse(corners.empty()); + } + + public void testFind4QuadCornerSubpix() { + Size patternSize = new Size(9, 6); + MatOfPoint2f corners = new MatOfPoint2f(); + Size region_size = new Size(5, 5); + Calib.findChessboardCorners(grayChess, patternSize, corners); + Calib.find4QuadCornerSubpix(grayChess, corners, region_size); + assertFalse(corners.empty()); + } + + public void testFindCirclesGridMatSizeMat() { + int size = 300; + Mat img = new Mat(size, size, CvType.CV_8U); + img.setTo(new Scalar(255)); + Mat centers = new Mat(); + + assertFalse(Calib.findCirclesGrid(img, new Size(5, 5), centers)); + + for (int i = 0; i < 5; i++) + for (int j = 0; j < 5; j++) { + Point pt = new Point(size * (2 * i + 1) / 10, size * (2 * j + 1) / 10); + Imgproc.circle(img, pt, 10, new Scalar(0), -1); + } + + assertTrue(Calib.findCirclesGrid(img, new Size(5, 5), centers)); + + assertEquals(25, centers.rows()); + assertEquals(1, centers.cols()); + assertEquals(CvType.CV_32FC2, centers.type()); + } + + public void testFindCirclesGridMatSizeMatInt() { + int size = 300; + Mat img = new Mat(size, size, CvType.CV_8U); + img.setTo(new Scalar(255)); + Mat centers = new Mat(); + + assertFalse(Calib.findCirclesGrid(img, new Size(3, 5), centers, Calib.CALIB_CB_CLUSTERING + | Calib.CALIB_CB_ASYMMETRIC_GRID)); + + int step = size * 2 / 15; + int offsetx = size / 6; + int offsety = (size - 4 * step) / 2; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 5; j++) { + Point pt = new Point(offsetx + (2 * i + j % 2) * step, offsety + step * j); + Imgproc.circle(img, pt, 10, new Scalar(0), -1); + } + + assertTrue(Calib.findCirclesGrid(img, new Size(3, 5), centers, Calib.CALIB_CB_CLUSTERING + | Calib.CALIB_CB_ASYMMETRIC_GRID)); + + assertEquals(15, centers.rows()); + assertEquals(1, centers.cols()); + assertEquals(CvType.CV_32FC2, centers.type()); + } + + public void testConstants() + { + // calib3d.hpp: some constants have conflict with constants from 'fisheye' namespace + assertEquals(1, Calib.CALIB_USE_INTRINSIC_GUESS); + assertEquals(2, Calib.CALIB_FIX_ASPECT_RATIO); + assertEquals(4, Calib.CALIB_FIX_PRINCIPAL_POINT); + assertEquals(8, Calib.CALIB_ZERO_TANGENT_DIST); + assertEquals(16, Calib.CALIB_FIX_FOCAL_LENGTH); + assertEquals(32, Calib.CALIB_FIX_K1); + assertEquals(64, Calib.CALIB_FIX_K2); + assertEquals(128, Calib.CALIB_FIX_K3); + assertEquals(0x0800, Calib.CALIB_FIX_K4); + assertEquals(0x1000, Calib.CALIB_FIX_K5); + assertEquals(0x2000, Calib.CALIB_FIX_K6); + assertEquals(0x4000, Calib.CALIB_RATIONAL_MODEL); + assertEquals(0x8000, Calib.CALIB_THIN_PRISM_MODEL); + assertEquals(0x10000, Calib.CALIB_FIX_S1_S2_S3_S4); + assertEquals(0x40000, Calib.CALIB_TILTED_MODEL); + assertEquals(0x80000, Calib.CALIB_FIX_TAUX_TAUY); + assertEquals(0x100000, Calib.CALIB_USE_QR); + assertEquals(0x200000, Calib.CALIB_FIX_TANGENT_DIST); + assertEquals(0x100, Calib.CALIB_FIX_INTRINSIC); + assertEquals(0x200, Calib.CALIB_SAME_FOCAL_LENGTH); + assertEquals(0x400, Calib.CALIB_ZERO_DISPARITY); + assertEquals((1 << 17), Calib.CALIB_USE_LU); + assertEquals((1 << 22), Calib.CALIB_USE_EXTRINSIC_GUESS); + } + + /*public void testEstimateNewCameraMatrixForUndistortRectify() { + Mat K = new Mat().eye(3, 3, CvType.CV_64FC1); + Mat K_new = new Mat().eye(3, 3, CvType.CV_64FC1); + Mat K_new_truth = new Mat().eye(3, 3, CvType.CV_64FC1); + Mat D = new Mat().zeros(4, 1, CvType.CV_64FC1); + + K.put(0,0,600.4447738238429); + K.put(1,1,578.9929805505851); + K.put(0,2,992.0642578801213); + K.put(1,2,549.2682624212172); + + D.put(0,0,-0.05090103223466704); + D.put(1,0,0.030944413642173308); + D.put(2,0,-0.021509225493198905); + D.put(3,0,0.0043378096628297145); + + K_new_truth.put(0,0, 387.4809086880343); + K_new_truth.put(0,2, 1036.669802754649); + K_new_truth.put(1,1, 373.6375700303157); + K_new_truth.put(1,2, 538.8373261247601); + + Calib.fisheye_estimateNewCameraMatrixForUndistortRectify(K,D,new Size(1920,1080), + new Mat().eye(3, 3, CvType.CV_64F), K_new, 0.0, new Size(1920,1080)); + + assertMatEqual(K_new, K_new_truth, EPS); + }*/ +} diff --git a/modules/calib3d/misc/objc/gen_dict.json b/modules/calib/misc/objc/gen_dict.json similarity index 86% rename from modules/calib3d/misc/objc/gen_dict.json rename to modules/calib/misc/objc/gen_dict.json index bace946846..a7b4984c21 100644 --- a/modules/calib3d/misc/objc/gen_dict.json +++ b/modules/calib/misc/objc/gen_dict.json @@ -1,6 +1,6 @@ { "func_arg_fix" : { - "Calib3d" : { + "Calib" : { "findCirclesGrid" : { "blobDetector" : {"defval" : "cv::SimpleBlobDetector::create()"} } } } diff --git a/modules/calib/misc/objc/test/CalibTest.swift b/modules/calib/misc/objc/test/CalibTest.swift new file mode 100644 index 0000000000..c8f249d7ad --- /dev/null +++ b/modules/calib/misc/objc/test/CalibTest.swift @@ -0,0 +1,123 @@ +// +// Calib3dTest.swift +// +// Created by Giles Payne on 2020/05/26. +// + +import XCTest +import OpenCV + +class CalibTest: OpenCVTestCase { + + var size = Size() + + override func setUp() { + super.setUp() + size = Size(width: 3, height: 3) + } + + override func tearDown() { + super.tearDown() + } + + func testFindChessboardCornersMatSizeMat() { + let patternSize = Size(width: 9, height: 6) + let corners = MatOfPoint2f() + Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners) + XCTAssertFalse(corners.empty()) + } + + func testFindChessboardCornersMatSizeMatInt() { + let patternSize = Size(width: 9, height: 6) + let corners = MatOfPoint2f() + Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners, flags: Calib.CALIB_CB_ADAPTIVE_THRESH + Calib.CALIB_CB_NORMALIZE_IMAGE + Calib.CALIB_CB_FAST_CHECK) + XCTAssertFalse(corners.empty()) + } + + func testFind4QuadCornerSubpix() { + let patternSize = Size(width: 9, height: 6) + let corners = MatOfPoint2f() + let region_size = Size(width: 5, height: 5) + Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners) + Calib.find4QuadCornerSubpix(img: grayChess, corners: corners, region_size: region_size) + XCTAssertFalse(corners.empty()) + } + + func testFindCirclesGridMatSizeMat() { + let size = 300 + let img = Mat(rows:Int32(size), cols:Int32(size), type:CvType.CV_8U) + img.setTo(scalar: Scalar(255)) + let centers = Mat() + + XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 5, height: 5), centers: centers)) + + for i in 0..<5 { + for j in 0..<5 { + let x = Int32(size * (2 * i + 1) / 10) + let y = Int32(size * (2 * j + 1) / 10) + let pt = Point(x: x, y: y) + Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1) + } + } + + XCTAssert(Calib.findCirclesGrid(image: img, patternSize:Size(width:5, height:5), centers:centers)) + + XCTAssertEqual(25, centers.rows()) + XCTAssertEqual(1, centers.cols()) + XCTAssertEqual(CvType.CV_32FC2, centers.type()) + } + + func testFindCirclesGridMatSizeMatInt() { + let size:Int32 = 300 + let img = Mat(rows:size, cols: size, type: CvType.CV_8U) + img.setTo(scalar: Scalar(255)) + let centers = Mat() + + XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID)) + + let step = size * 2 / 15 + let offsetx = size / 6 + let offsety = (size - 4 * step) / 2 + for i:Int32 in 0...2 { + for j:Int32 in 0...4 { + let pt = Point(x: offsetx + (2 * i + j % 2) * step, y: offsety + step * j) + Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1) + } + } + + XCTAssert(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID)) + + XCTAssertEqual(15, centers.rows()) + XCTAssertEqual(1, centers.cols()) + XCTAssertEqual(CvType.CV_32FC2, centers.type()) + } + + func testConstants() + { + // calib3d.hpp: some constants have conflict with constants from 'fisheye' namespace + XCTAssertEqual(1, Calib.CALIB_USE_INTRINSIC_GUESS) + XCTAssertEqual(2, Calib.CALIB_FIX_ASPECT_RATIO) + XCTAssertEqual(4, Calib.CALIB_FIX_PRINCIPAL_POINT) + XCTAssertEqual(8, Calib.CALIB_ZERO_TANGENT_DIST) + XCTAssertEqual(16, Calib.CALIB_FIX_FOCAL_LENGTH) + XCTAssertEqual(32, Calib.CALIB_FIX_K1) + XCTAssertEqual(64, Calib.CALIB_FIX_K2) + XCTAssertEqual(128, Calib.CALIB_FIX_K3) + XCTAssertEqual(0x0800, Calib.CALIB_FIX_K4) + XCTAssertEqual(0x1000, Calib.CALIB_FIX_K5) + XCTAssertEqual(0x2000, Calib.CALIB_FIX_K6) + XCTAssertEqual(0x4000, Calib.CALIB_RATIONAL_MODEL) + XCTAssertEqual(0x8000, Calib.CALIB_THIN_PRISM_MODEL) + XCTAssertEqual(0x10000, Calib.CALIB_FIX_S1_S2_S3_S4) + XCTAssertEqual(0x40000, Calib.CALIB_TILTED_MODEL) + XCTAssertEqual(0x80000, Calib.CALIB_FIX_TAUX_TAUY) + XCTAssertEqual(0x100000, Calib.CALIB_USE_QR) + XCTAssertEqual(0x200000, Calib.CALIB_FIX_TANGENT_DIST) + XCTAssertEqual(0x100, Calib.CALIB_FIX_INTRINSIC) + XCTAssertEqual(0x200, Calib.CALIB_SAME_FOCAL_LENGTH) + XCTAssertEqual(0x400, Calib.CALIB_ZERO_DISPARITY) + XCTAssertEqual((1 << 17), Calib.CALIB_USE_LU) + XCTAssertEqual((1 << 22), Calib.CALIB_USE_EXTRINSIC_GUESS) + } + +} diff --git a/modules/calib3d/misc/python/test/test_calibration.py b/modules/calib/misc/python/test/test_calibration.py old mode 100644 new mode 100755 similarity index 100% rename from modules/calib3d/misc/python/test/test_calibration.py rename to modules/calib/misc/python/test/test_calibration.py diff --git a/modules/calib3d/perf/perf_cicrlesGrid.cpp b/modules/calib/perf/perf_cicrlesGrid.cpp similarity index 100% rename from modules/calib3d/perf/perf_cicrlesGrid.cpp rename to modules/calib/perf/perf_cicrlesGrid.cpp diff --git a/modules/calib/perf/perf_main.cpp b/modules/calib/perf/perf_main.cpp new file mode 100644 index 0000000000..54c334da13 --- /dev/null +++ b/modules/calib/perf/perf_main.cpp @@ -0,0 +1,7 @@ +#include "perf_precomp.hpp" + +#if defined(HAVE_HPX) + #include +#endif + +CV_PERF_TEST_MAIN(calib3d) diff --git a/modules/calib/perf/perf_precomp.hpp b/modules/calib/perf/perf_precomp.hpp new file mode 100644 index 0000000000..0872e8667a --- /dev/null +++ b/modules/calib/perf/perf_precomp.hpp @@ -0,0 +1,10 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html +#ifndef __OPENCV_PERF_PRECOMP_HPP__ +#define __OPENCV_PERF_PRECOMP_HPP__ + +#include "opencv2/ts.hpp" +#include "opencv2/calib.hpp" + +#endif diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib/src/calibinit.cpp similarity index 96% rename from modules/calib3d/src/calibinit.cpp rename to modules/calib/src/calibinit.cpp index d763013038..b776a1b617 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib/src/calibinit.cpp @@ -71,6 +71,7 @@ #include "precomp.hpp" #include "circlesgrid.hpp" +#include "opencv2/imgproc/imgproc_c.h" #include @@ -88,7 +89,7 @@ #ifdef DEBUG_CHESSBOARD #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" -#define DPRINTF(...) CV_LOG_INFO(NULL, cv::format("calib3d: " __VA_ARGS__)) +#define DPRINTF(...) CV_LOG_INFO(NULL, format("calib: " __VA_ARGS__)) #else #define DPRINTF(...) #endif @@ -101,7 +102,7 @@ namespace cv { #define MAX_CONTOUR_APPROX 7 -#define USE_CV_FINDCONTOURS // switch between cv::findContours() and legacy C API +#define USE_CV_FINDCONTOURS // switch between findContours() and legacy C API #ifdef USE_CV_FINDCONTOURS struct QuadCountour { Point pt[4]; @@ -114,11 +115,6 @@ struct QuadCountour { } }; #else - -} // namespace -#include "opencv2/imgproc/imgproc_c.h" -namespace cv { - struct CvContourEx { CV_CONTOUR_FIELDS() @@ -126,16 +122,15 @@ struct CvContourEx }; #endif - /** This structure stores information about the chessboard corner.*/ struct ChessBoardCorner { - cv::Point2f pt; // Coordinates of the corner + Point2f pt; // Coordinates of the corner int row; // Board row index int count; // Number of neighbor corners struct ChessBoardCorner* neighbors[4]; // Neighbor corners - ChessBoardCorner(const cv::Point2f& pt_ = cv::Point2f()) : + ChessBoardCorner(const Point2f& pt_ = Point2f()) : pt(pt_), row(0), count(0) { neighbors[0] = neighbors[1] = neighbors[2] = neighbors[3] = NULL; @@ -225,11 +220,11 @@ static void SHOW_QUADS(const std::string & name, const Mat & img_, ChessBoardQua class ChessBoardDetector { public: - cv::Mat binarized_image; + Mat binarized_image; Size pattern_size; - cv::AutoBuffer all_quads; - cv::AutoBuffer all_corners; + AutoBuffer all_quads; + AutoBuffer all_corners; int all_quads_count; @@ -246,9 +241,9 @@ public: all_quads_count = 0; } - void generateQuads(const cv::Mat& image_, int flags); + void generateQuads(const Mat& image_, int flags); - bool processQuads(std::vector& out_corners, int &prev_sqr_size); + bool processQuads(std::vector& out_corners, int &prev_sqr_size); void findQuadNeighbors(); @@ -271,7 +266,7 @@ public: void removeQuadFromGroup(std::vector& quads, ChessBoardQuad& q0); - bool checkBoardMonotony(const std::vector& corners); + bool checkBoardMonotony(const std::vector& corners); }; /***************************************************************************************************/ @@ -349,16 +344,16 @@ static void icvBinarizationHistogramBased(Mat & img) int iMaxPix1 = iMaxPix/100; const int iNumBins = 256; const int iMaxPos = 20; - cv::AutoBuffer piHistIntensity(iNumBins); - cv::AutoBuffer piHistSmooth(iNumBins); - cv::AutoBuffer piHistGrad(iNumBins); - cv::AutoBuffer piMaxPos(iMaxPos); + AutoBuffer piHistIntensity(iNumBins); + AutoBuffer piHistSmooth(iNumBins); + AutoBuffer piHistGrad(iNumBins); + AutoBuffer piMaxPos(iMaxPos); icvGetIntensityHistogram256(img, piHistIntensity); #if 0 // get accumulated sum starting from bright - cv::AutoBuffer piAccumSum(iNumBins); + AutoBuffer piAccumSum(iNumBins); piAccumSum[iNumBins-1] = piHistIntensity[iNumBins-1]; for (int i = iNumBins - 2; i >= 0; --i) { @@ -508,7 +503,7 @@ bool findChessboardCorners(InputArray image_, Size pattern_size, if (!corners_.needed()) CV_Error(Error::StsNullPtr, "Null pointer to corners"); - std::vector out_corners; + std::vector out_corners; if (img.channels() != 1) { @@ -588,8 +583,8 @@ bool findChessboardCorners(InputArray image_, Size pattern_size, { // empiric threshold level // thresholding performed here and not inside the cycle to save processing time - double mean = cv::mean(img).val[0]; - int thresh_level = std::max(cvRound(mean - 10), 10); + double meanval = mean(img).val[0]; + int thresh_level = std::max(cvRound(meanval - 10), 10); threshold(img, thresh_img, thresh_level, 255, THRESH_BINARY); } //if flag CALIB_CB_ADAPTIVE_THRESH is not set it doesn't make sense to iterate over k @@ -680,8 +675,8 @@ bool findChessboardCorners(InputArray image_, Size pattern_size, } } } - cv::cornerSubPix(img, out_corners, Size(2, 2), Size(-1,-1), - cv::TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 15, 0.1)); + cornerSubPix(img, out_corners, Size(2, 2), Size(-1,-1), + TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 15, 0.1)); } Mat(out_corners).copyTo(corners_); @@ -699,7 +694,7 @@ bool findChessboardCorners(InputArray image_, Size pattern_size, // This function has been created as temporary workaround for the bug in current implementation // of cvFindChessboardCornes that produces absolutely unordered sets of corners. // -bool ChessBoardDetector::checkBoardMonotony(const std::vector& corners) +bool ChessBoardDetector::checkBoardMonotony(const std::vector& corners) { for (int k = 0; k < 2; ++k) { @@ -707,8 +702,8 @@ bool ChessBoardDetector::checkBoardMonotony(const std::vector& corn int max_j = (k == 0 ? pattern_size.width: pattern_size.height) - 1; for (int i = 0; i < max_i; ++i) { - cv::Point2f a = k == 0 ? corners[i*pattern_size.width] : corners[i]; - cv::Point2f b = k == 0 ? corners[(i+1)*pattern_size.width-1] + Point2f a = k == 0 ? corners[i*pattern_size.width] : corners[i]; + Point2f b = k == 0 ? corners[(i+1)*pattern_size.width-1] : corners[(pattern_size.height-1)*pattern_size.width + i]; float dx0 = b.x - a.x, dy0 = b.y - a.y; if (fabs(dx0) + fabs(dy0) < FLT_EPSILON) @@ -716,7 +711,7 @@ bool ChessBoardDetector::checkBoardMonotony(const std::vector& corn float prevt = 0; for (int j = 1; j < max_j; ++j) { - cv::Point2f c = k == 0 ? corners[i*pattern_size.width + j] + Point2f c = k == 0 ? corners[i*pattern_size.width + j] : corners[j*pattern_size.width + i]; float t = ((c.x - a.x)*dx0 + (c.y - a.y)*dy0)/(dx0*dx0 + dy0*dy0); if (t < prevt || t > 1) @@ -1008,11 +1003,11 @@ int ChessBoardDetector::addOuterQuad(ChessBoardQuad& quad, std::vectorpt - quad.corners[j]->pt; + const Point2f pt_offset = quad.corners[i]->pt - quad.corners[j]->pt; for (int k = 0; k < 4; k++) { ChessBoardCorner& corner = (ChessBoardCorner&)all_corners[q_index * 4 + k]; - const cv::Point2f& pt = quad.corners[k]->pt; + const Point2f& pt = quad.corners[k]->pt; corner = ChessBoardCorner(pt); q.corners[k] = &corner; corner.pt += pt_offset; @@ -1215,14 +1210,14 @@ int ChessBoardDetector::cleanFoundConnectedQuads(std::vector& q CV_DbgAssert(quad_count > 0); // create an array of quadrangle centers - cv::AutoBuffer centers(quad_count); + AutoBuffer centers(quad_count); - cv::Point2f center; + Point2f center; for (int i = 0; i < quad_count; ++i) { ChessBoardQuad* q = quad_group[i]; - const cv::Point2f ci = ( + const Point2f ci = ( q->corners[0]->pt + q->corners[1]->pt + q->corners[2]->pt + @@ -1250,11 +1245,11 @@ int ChessBoardDetector::cleanFoundConnectedQuads(std::vector& q for (int skip = 0; skip < quad_count; ++skip) { // get bounding rectangle - cv::Point2f temp = centers[skip]; // temporarily make index 'skip' the same as + Point2f temp = centers[skip]; // temporarily make index 'skip' the same as centers[skip] = center; // pattern center (so it is not counted for convex hull) std::vector hull; Mat points(1, quad_count, CV_32FC2, ¢ers[0]); - cv::convexHull(points, hull, true); + convexHull(points, hull, true); centers[skip] = temp; double hull_area = contourArea(hull, true); @@ -1572,7 +1567,7 @@ int ChessBoardDetector::checkQuadGroup(std::vector& quad_group, // check if we need to revert the order in each row { - cv::Point2f p0 = out_corners[0]->pt, + Point2f p0 = out_corners[0]->pt, p1 = out_corners[pattern_size.width-1]->pt, p2 = out_corners[pattern_size.width]->pt; if( (p1.x - p0.x)*(p2.y - p1.y) - (p1.y - p0.y)*(p2.x - p1.x) < 0 ) @@ -1637,7 +1632,7 @@ void ChessBoardDetector::findQuadNeighbors() int closest_corner_idx = -1; ChessBoardQuad *closest_quad = 0; - cv::Point2f pt = cur_quad.corners[i]->pt; + Point2f pt = cur_quad.corners[i]->pt; // find the closest corner in all other quadrangles for (int k = 0; k < all_quads_count; k++) @@ -1750,7 +1745,7 @@ void ChessBoardDetector::findQuadNeighbors() // returns corners in clockwise order // corners don't necessarily start at same position on quad (e.g., // top left corner) -void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags) +void ChessBoardDetector::generateQuads(const Mat& image_, int flags) { binarized_image = image_; // save for debug purposes @@ -1763,16 +1758,16 @@ void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags) int min_size = 25; //cvRound( image->cols * image->rows * .03 * 0.01 * 0.92 ); bool filterQuads = (flags & CALIB_CB_FILTER_QUADS) != 0; -#ifdef USE_CV_FINDCONTOURS // use cv::findContours +#ifdef USE_CV_FINDCONTOURS // use findContours std::vector > contours; std::vector hierarchy; - cv::findContours(image_, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); + findContours(image_, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); if (contours.empty()) { - CV_LOG_DEBUG(NULL, "calib3d(chessboard): cv::findContours() returns no contours"); + CV_LOG_DEBUG(NULL, "calib(chessboard): findContours() returns no contours"); return; } @@ -1813,18 +1808,18 @@ void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags) // reject non-quadrangles if (approx_contour.size() != 4) continue; - if (!cv::isContourConvex(approx_contour)) + if (!isContourConvex(approx_contour)) continue; - cv::Point pt[4]; + Point pt[4]; for (int i = 0; i < 4; ++i) pt[i] = approx_contour[i]; CV_LOG_VERBOSE(NULL, 9, "... contours(" << contour_quads.size() << " added):" << pt[0] << " " << pt[1] << " " << pt[2] << " " << pt[3]); if (filterQuads) { - double p = cv::arcLength(approx_contour, true); - double area = cv::contourArea(approx_contour, false); + double p = arcLength(approx_contour, true); + double area = contourArea(approx_contour, false); double d1 = sqrt(normL2Sqr(pt[0] - pt[2])); double d2 = sqrt(normL2Sqr(pt[1] - pt[3])); @@ -1885,7 +1880,7 @@ void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags) CvContourEx* board = 0; // create temporary storage for contours and the sequence of pointers to found quadrangles - cv::Ptr temp_storage(cvCreateMemStorage(0)); + Ptr temp_storage(cvCreateMemStorage(0)); CvSeq *root = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvSeq*), temp_storage); // initialize contour retrieving routine @@ -1922,7 +1917,7 @@ void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags) // reject non-quadrangles if( dst_contour->total == 4 && cvCheckContourConvexity(dst_contour) ) { - cv::Point2i pt[4]; + Point2i pt[4]; double p = cvContourPerimeter(dst_contour); double area = fabs(cvContourArea(dst_contour, CV_WHOLE_SEQ)); @@ -2001,7 +1996,7 @@ void ChessBoardDetector::generateQuads(const cv::Mat& image_, int flags) CV_LOG_VERBOSE(NULL, 3, "filtered quad_count=" << quad_count); } -bool ChessBoardDetector::processQuads(std::vector& out_corners, int &prev_sqr_size) +bool ChessBoardDetector::processQuads(std::vector& out_corners, int &prev_sqr_size) { out_corners.resize(0); if (all_quads_count <= 0) @@ -2127,7 +2122,7 @@ void drawChessboardCorners( InputOutputArray image, Size patternSize, for (int i = 0; i < nelems; i++ ) { - cv::Point2i pt( + Point2i pt( cvRound(corners_data[i].x*(1 << shift)), cvRound(corners_data[i].y*(1 << shift)) ); @@ -2150,7 +2145,7 @@ void drawChessboardCorners( InputOutputArray image, Size patternSize, {255,0,255,0} }; - cv::Point2i prev_pt; + Point2i prev_pt; for (int y = 0, i = 0; y < patternSize.height; y++) { const int* line_color = &line_colors[y % line_max][0]; @@ -2161,7 +2156,7 @@ void drawChessboardCorners( InputOutputArray image, Size patternSize, for (int x = 0; x < patternSize.width; x++, i++) { - cv::Point2i pt( + Point2i pt( cvRound(corners_data[i].x*(1 << shift)), cvRound(corners_data[i].y*(1 << shift)) ); @@ -2238,7 +2233,7 @@ bool findCirclesGrid( InputArray _image, Size patternSize, { isFound = boxFinder.findHoles(); } - catch (const cv::Exception &) + catch (const Exception &) { } @@ -2284,7 +2279,7 @@ bool findCirclesGrid( InputArray _image, Size patternSize, bool findCirclesGrid(InputArray _image, Size patternSize, OutputArray _centers, int flags, const Ptr &blobDetector) { - return cv::findCirclesGrid(_image, patternSize, _centers, flags, blobDetector, CirclesGridFinderParameters()); + return findCirclesGrid(_image, patternSize, _centers, flags, blobDetector, CirclesGridFinderParameters()); } } // namespace diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib/src/calibration.cpp similarity index 66% rename from modules/calib3d/src/calibration.cpp rename to modules/calib/src/calibration.cpp index a84e49b785..f4db51d324 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib/src/calibration.cpp @@ -43,7 +43,6 @@ #include "precomp.hpp" #include "opencv2/imgproc/imgproc_c.h" #include "distortion_model.hpp" -#include "calib3d_c_api.h" #include #include @@ -55,10 +54,10 @@ The 1st initial port was done by Valery Mosyagin. */ -using namespace cv; +namespace cv { // reimplementation of dAB.m -CV_IMPL void cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, CvMat* dABdB ) +static void cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, CvMat* dABdB ) { int i, j, M, N, L; int bstep; @@ -145,110 +144,7 @@ CV_IMPL void cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, Cv } } -// reimplementation of compose_motion.m -CV_IMPL void cvComposeRT( const CvMat* _rvec1, const CvMat* _tvec1, - const CvMat* _rvec2, const CvMat* _tvec2, - CvMat* _rvec3, CvMat* _tvec3, - CvMat* dr3dr1, CvMat* dr3dt1, - CvMat* dr3dr2, CvMat* dr3dt2, - CvMat* dt3dr1, CvMat* dt3dt1, - CvMat* dt3dr2, CvMat* dt3dt2 ) -{ - double _r1[3], _r2[3]; - double _R1[9], _d1[9*3], _R2[9], _d2[9*3]; - CvMat r1 = cvMat(3,1,CV_64F,_r1), r2 = cvMat(3,1,CV_64F,_r2); - CvMat R1 = cvMat(3,3,CV_64F,_R1), R2 = cvMat(3,3,CV_64F,_R2); - CvMat dR1dr1 = cvMat(9,3,CV_64F,_d1), dR2dr2 = cvMat(9,3,CV_64F,_d2); - - CV_Assert( CV_IS_MAT(_rvec1) && CV_IS_MAT(_rvec2) ); - - CV_Assert( CV_MAT_TYPE(_rvec1->type) == CV_32F || - CV_MAT_TYPE(_rvec1->type) == CV_64F ); - - CV_Assert( _rvec1->rows == 3 && _rvec1->cols == 1 && CV_ARE_SIZES_EQ(_rvec1, _rvec2) ); - - cvConvert( _rvec1, &r1 ); - cvConvert( _rvec2, &r2 ); - - cvRodrigues2( &r1, &R1, &dR1dr1 ); - cvRodrigues2( &r2, &R2, &dR2dr2 ); - - if( _rvec3 || dr3dr1 || dr3dr2 ) - { - double _r3[3], _R3[9], _dR3dR1[9*9], _dR3dR2[9*9], _dr3dR3[9*3]; - double _W1[9*3], _W2[3*3]; - CvMat r3 = cvMat(3,1,CV_64F,_r3), R3 = cvMat(3,3,CV_64F,_R3); - CvMat dR3dR1 = cvMat(9,9,CV_64F,_dR3dR1), dR3dR2 = cvMat(9,9,CV_64F,_dR3dR2); - CvMat dr3dR3 = cvMat(3,9,CV_64F,_dr3dR3); - CvMat W1 = cvMat(3,9,CV_64F,_W1), W2 = cvMat(3,3,CV_64F,_W2); - - cvMatMul( &R2, &R1, &R3 ); - cvCalcMatMulDeriv( &R2, &R1, &dR3dR2, &dR3dR1 ); - - cvRodrigues2( &R3, &r3, &dr3dR3 ); - - if( _rvec3 ) - cvConvert( &r3, _rvec3 ); - - if( dr3dr1 ) - { - cvMatMul( &dr3dR3, &dR3dR1, &W1 ); - cvMatMul( &W1, &dR1dr1, &W2 ); - cvConvert( &W2, dr3dr1 ); - } - - if( dr3dr2 ) - { - cvMatMul( &dr3dR3, &dR3dR2, &W1 ); - cvMatMul( &W1, &dR2dr2, &W2 ); - cvConvert( &W2, dr3dr2 ); - } - } - - if( dr3dt1 ) - cvZero( dr3dt1 ); - if( dr3dt2 ) - cvZero( dr3dt2 ); - - if( _tvec3 || dt3dr2 || dt3dt1 ) - { - double _t1[3], _t2[3], _t3[3], _dxdR2[3*9], _dxdt1[3*3], _W3[3*3]; - CvMat t1 = cvMat(3,1,CV_64F,_t1), t2 = cvMat(3,1,CV_64F,_t2); - CvMat t3 = cvMat(3,1,CV_64F,_t3); - CvMat dxdR2 = cvMat(3, 9, CV_64F, _dxdR2); - CvMat dxdt1 = cvMat(3, 3, CV_64F, _dxdt1); - CvMat W3 = cvMat(3, 3, CV_64F, _W3); - - CV_Assert( CV_IS_MAT(_tvec1) && CV_IS_MAT(_tvec2) ); - CV_Assert( CV_ARE_SIZES_EQ(_tvec1, _tvec2) && CV_ARE_SIZES_EQ(_tvec1, _rvec1) ); - - cvConvert( _tvec1, &t1 ); - cvConvert( _tvec2, &t2 ); - cvMatMulAdd( &R2, &t1, &t2, &t3 ); - - if( _tvec3 ) - cvConvert( &t3, _tvec3 ); - - if( dt3dr2 || dt3dt1 ) - { - cvCalcMatMulDeriv( &R2, &t1, &dxdR2, &dxdt1 ); - if( dt3dr2 ) - { - cvMatMul( &dxdR2, &dR2dr2, &W3 ); - cvConvert( &W3, dt3dr2 ); - } - if( dt3dt1 ) - cvConvert( &dxdt1, dt3dt1 ); - } - } - - if( dt3dt2 ) - cvSetIdentity( dt3dt2 ); - if( dt3dr1 ) - cvZero( dt3dr1 ); -} - -CV_IMPL int cvRodrigues2( const CvMat* src, CvMat* dst, CvMat* jacobian ) +static int cvRodrigues2( const CvMat* src, CvMat* dst, CvMat* jacobian=0 ) { double J[27] = {0}; CvMat matJ = cvMat( 3, 9, CV_64F, J ); @@ -516,6 +412,108 @@ CV_IMPL int cvRodrigues2( const CvMat* src, CvMat* dst, CvMat* jacobian ) return 1; } +// reimplementation of compose_motion.m +static void cvComposeRT( const CvMat* _rvec1, const CvMat* _tvec1, + const CvMat* _rvec2, const CvMat* _tvec2, + CvMat* _rvec3, CvMat* _tvec3, + CvMat* dr3dr1=0, CvMat* dr3dt1=0, + CvMat* dr3dr2=0, CvMat* dr3dt2=0, + CvMat* dt3dr1=0, CvMat* dt3dt1=0, + CvMat* dt3dr2=0, CvMat* dt3dt2=0 ) +{ + double _r1[3], _r2[3]; + double _R1[9], _d1[9*3], _R2[9], _d2[9*3]; + CvMat r1 = cvMat(3,1,CV_64F,_r1), r2 = cvMat(3,1,CV_64F,_r2); + CvMat R1 = cvMat(3,3,CV_64F,_R1), R2 = cvMat(3,3,CV_64F,_R2); + CvMat dR1dr1 = cvMat(9,3,CV_64F,_d1), dR2dr2 = cvMat(9,3,CV_64F,_d2); + + CV_Assert( CV_IS_MAT(_rvec1) && CV_IS_MAT(_rvec2) ); + + CV_Assert( CV_MAT_TYPE(_rvec1->type) == CV_32F || + CV_MAT_TYPE(_rvec1->type) == CV_64F ); + + CV_Assert( _rvec1->rows == 3 && _rvec1->cols == 1 && CV_ARE_SIZES_EQ(_rvec1, _rvec2) ); + + cvConvert( _rvec1, &r1 ); + cvConvert( _rvec2, &r2 ); + + cvRodrigues2( &r1, &R1, &dR1dr1 ); + cvRodrigues2( &r2, &R2, &dR2dr2 ); + + if( _rvec3 || dr3dr1 || dr3dr2 ) + { + double _r3[3], _R3[9], _dR3dR1[9*9], _dR3dR2[9*9], _dr3dR3[9*3]; + double _W1[9*3], _W2[3*3]; + CvMat r3 = cvMat(3,1,CV_64F,_r3), R3 = cvMat(3,3,CV_64F,_R3); + CvMat dR3dR1 = cvMat(9,9,CV_64F,_dR3dR1), dR3dR2 = cvMat(9,9,CV_64F,_dR3dR2); + CvMat dr3dR3 = cvMat(3,9,CV_64F,_dr3dR3); + CvMat W1 = cvMat(3,9,CV_64F,_W1), W2 = cvMat(3,3,CV_64F,_W2); + + cvMatMul( &R2, &R1, &R3 ); + cvCalcMatMulDeriv( &R2, &R1, &dR3dR2, &dR3dR1 ); + + cvRodrigues2( &R3, &r3, &dr3dR3 ); + + if( _rvec3 ) + cvConvert( &r3, _rvec3 ); + + if( dr3dr1 ) + { + cvMatMul( &dr3dR3, &dR3dR1, &W1 ); + cvMatMul( &W1, &dR1dr1, &W2 ); + cvConvert( &W2, dr3dr1 ); + } + + if( dr3dr2 ) + { + cvMatMul( &dr3dR3, &dR3dR2, &W1 ); + cvMatMul( &W1, &dR2dr2, &W2 ); + cvConvert( &W2, dr3dr2 ); + } + } + + if( dr3dt1 ) + cvZero( dr3dt1 ); + if( dr3dt2 ) + cvZero( dr3dt2 ); + + if( _tvec3 || dt3dr2 || dt3dt1 ) + { + double _t1[3], _t2[3], _t3[3], _dxdR2[3*9], _dxdt1[3*3], _W3[3*3]; + CvMat t1 = cvMat(3,1,CV_64F,_t1), t2 = cvMat(3,1,CV_64F,_t2); + CvMat t3 = cvMat(3,1,CV_64F,_t3); + CvMat dxdR2 = cvMat(3, 9, CV_64F, _dxdR2); + CvMat dxdt1 = cvMat(3, 3, CV_64F, _dxdt1); + CvMat W3 = cvMat(3, 3, CV_64F, _W3); + + CV_Assert( CV_IS_MAT(_tvec1) && CV_IS_MAT(_tvec2) ); + CV_Assert( CV_ARE_SIZES_EQ(_tvec1, _tvec2) && CV_ARE_SIZES_EQ(_tvec1, _rvec1) ); + + cvConvert( _tvec1, &t1 ); + cvConvert( _tvec2, &t2 ); + cvMatMulAdd( &R2, &t1, &t2, &t3 ); + + if( _tvec3 ) + cvConvert( &t3, _tvec3 ); + + if( dt3dr2 || dt3dt1 ) + { + cvCalcMatMulDeriv( &R2, &t1, &dxdR2, &dxdt1 ); + if( dt3dr2 ) + { + cvMatMul( &dxdR2, &dR2dr2, &W3 ); + cvConvert( &W3, dt3dr2 ); + } + if( dt3dt1 ) + cvConvert( &dxdt1, dt3dt1 ); + } + } + + if( dt3dt2 ) + cvSetIdentity( dt3dt2 ); + if( dt3dr1 ) + cvZero( dt3dr1 ); +} static const char* cvDistCoeffErr = "Distortion coefficients must be 1x4, 4x1, 1x5, 5x1, 1x8, 8x1, 1x12, 12x1, 1x14 or 14x1 floating-point vector"; @@ -656,8 +654,7 @@ static void cvProjectPoints2Internal( const CvMat* objectPoints, cvConvert( distCoeffs, &_k ); if(k[12] != 0 || k[13] != 0) { - detail::computeTiltProjectionMatrix(k[12], k[13], - &matTilt, &dMatTiltdTauX, &dMatTiltdTauY); + computeTiltProjectionMatrix(k[12], k[13], &matTilt, &dMatTiltdTauX, &dMatTiltdTauY); } } @@ -1028,290 +1025,79 @@ static void cvProjectPoints2Internal( const CvMat* objectPoints, cvConvert( _dpdo, dpdo ); } -CV_IMPL void cvProjectPoints2( const CvMat* objectPoints, +static void cvProjectPoints2( const CvMat* objectPoints, const CvMat* r_vec, const CvMat* t_vec, const CvMat* A, const CvMat* distCoeffs, - CvMat* imagePoints, CvMat* dpdr, - CvMat* dpdt, CvMat* dpdf, - CvMat* dpdc, CvMat* dpdk, - double aspectRatio ) + CvMat* imagePoints, CvMat* dpdr=0, + CvMat* dpdt=0, CvMat* dpdf=0, + CvMat* dpdc=0, CvMat* dpdk=0, + double aspectRatio=0 ) { cvProjectPoints2Internal( objectPoints, r_vec, t_vec, A, distCoeffs, imagePoints, dpdr, dpdt, dpdf, dpdc, dpdk, NULL, aspectRatio ); } -CV_IMPL void cvFindExtrinsicCameraParams2( const CvMat* objectPoints, +static void cvFindExtrinsicCameraParams2( const CvMat* objectPoints, const CvMat* imagePoints, const CvMat* A, const CvMat* distCoeffs, CvMat* rvec, CvMat* tvec, int useExtrinsicGuess ) { - const int max_iter = 20; - Ptr matM, _Mxy, _m, _mn, matL; - - int i, count; - double a[9], ar[9]={1,0,0,0,1,0,0,0,1}, R[9]; - double MM[9] = { 0 }, U[9] = { 0 }, V[9] = { 0 }, W[3] = { 0 }; - cv::Scalar Mc; - double param[6] = { 0 }; - CvMat matA = cvMat( 3, 3, CV_64F, a ); - CvMat _Ar = cvMat( 3, 3, CV_64F, ar ); - CvMat matR = cvMat( 3, 3, CV_64F, R ); - CvMat _r = cvMat( 3, 1, CV_64F, param ); - CvMat _t = cvMat( 3, 1, CV_64F, param + 3 ); - CvMat _Mc = cvMat( 1, 3, CV_64F, Mc.val ); - CvMat _MM = cvMat( 3, 3, CV_64F, MM ); - CvMat matU = cvMat( 3, 3, CV_64F, U ); - CvMat matV = cvMat( 3, 3, CV_64F, V ); - CvMat matW = cvMat( 3, 1, CV_64F, W ); - CvMat _param = cvMat( 6, 1, CV_64F, param ); - CvMat _dpdr, _dpdt; - - CV_Assert( CV_IS_MAT(objectPoints) && CV_IS_MAT(imagePoints) && - CV_IS_MAT(A) && CV_IS_MAT(rvec) && CV_IS_MAT(tvec) ); - - count = MAX(objectPoints->cols, objectPoints->rows); - matM.reset(cvCreateMat( 1, count, CV_64FC3 )); - _m.reset(cvCreateMat( 1, count, CV_64FC2 )); - - cvConvertPointsHomogeneous( objectPoints, matM ); - cvConvertPointsHomogeneous( imagePoints, _m ); - cvConvert( A, &matA ); - - CV_Assert( (CV_MAT_DEPTH(rvec->type) == CV_64F || CV_MAT_DEPTH(rvec->type) == CV_32F) && - (rvec->rows == 1 || rvec->cols == 1) && rvec->rows*rvec->cols*CV_MAT_CN(rvec->type) == 3 ); - - CV_Assert( (CV_MAT_DEPTH(tvec->type) == CV_64F || CV_MAT_DEPTH(tvec->type) == CV_32F) && - (tvec->rows == 1 || tvec->cols == 1) && tvec->rows*tvec->cols*CV_MAT_CN(tvec->type) == 3 ); - - CV_Assert((count >= 4) || (count == 3 && useExtrinsicGuess)); // it is unsafe to call LM optimisation without an extrinsic guess in the case of 3 points. This is because there is no guarantee that it will converge on the correct solution. - - _mn.reset(cvCreateMat( 1, count, CV_64FC2 )); - _Mxy.reset(cvCreateMat( 1, count, CV_64FC2 )); - - // normalize image points - // (unapply the intrinsic matrix transformation and distortion) - cvUndistortPoints( _m, _mn, &matA, distCoeffs, 0, &_Ar ); - - if( useExtrinsicGuess ) - { - CvMat _r_temp = cvMat(rvec->rows, rvec->cols, - CV_MAKETYPE(CV_64F,CV_MAT_CN(rvec->type)), param ); - CvMat _t_temp = cvMat(tvec->rows, tvec->cols, - CV_MAKETYPE(CV_64F,CV_MAT_CN(tvec->type)), param + 3); - cvConvert( rvec, &_r_temp ); - cvConvert( tvec, &_t_temp ); - } - else - { - Mc = cvAvg(matM); - cvReshape( matM, matM, 1, count ); - cvMulTransposed( matM, &_MM, 1, &_Mc ); - cvSVD( &_MM, &matW, 0, &matV, CV_SVD_MODIFY_A + CV_SVD_V_T ); - - // initialize extrinsic parameters - if( W[2]/W[1] < 1e-3) - { - // a planar structure case (all M's lie in the same plane) - double tt[3], h[9], h1_norm, h2_norm; - CvMat* R_transform = &matV; - CvMat T_transform = cvMat( 3, 1, CV_64F, tt ); - CvMat matH = cvMat( 3, 3, CV_64F, h ); - CvMat _h1, _h2, _h3; - - if( V[2]*V[2] + V[5]*V[5] < 1e-10 ) - cvSetIdentity( R_transform ); - - if( cvDet(R_transform) < 0 ) - cvScale( R_transform, R_transform, -1 ); - - cvGEMM( R_transform, &_Mc, -1, 0, 0, &T_transform, CV_GEMM_B_T ); - - for( i = 0; i < count; i++ ) - { - const double* Rp = R_transform->data.db; - const double* Tp = T_transform.data.db; - const double* src = matM->data.db + i*3; - double* dst = _Mxy->data.db + i*2; - - dst[0] = Rp[0]*src[0] + Rp[1]*src[1] + Rp[2]*src[2] + Tp[0]; - dst[1] = Rp[3]*src[0] + Rp[4]*src[1] + Rp[5]*src[2] + Tp[1]; - } - - cvFindHomography( _Mxy, _mn, &matH ); - - if( cvCheckArr(&matH, CV_CHECK_QUIET) ) - { - cvGetCol( &matH, &_h1, 0 ); - _h2 = _h1; _h2.data.db++; - _h3 = _h2; _h3.data.db++; - h1_norm = std::sqrt(h[0]*h[0] + h[3]*h[3] + h[6]*h[6]); - h2_norm = std::sqrt(h[1]*h[1] + h[4]*h[4] + h[7]*h[7]); - - cvScale( &_h1, &_h1, 1./MAX(h1_norm, DBL_EPSILON) ); - cvScale( &_h2, &_h2, 1./MAX(h2_norm, DBL_EPSILON) ); - cvScale( &_h3, &_t, 2./MAX(h1_norm + h2_norm, DBL_EPSILON)); - cvCrossProduct( &_h1, &_h2, &_h3 ); - - cvRodrigues2( &matH, &_r ); - cvRodrigues2( &_r, &matH ); - cvMatMulAdd( &matH, &T_transform, &_t, &_t ); - cvMatMul( &matH, R_transform, &matR ); - } - else - { - cvSetIdentity( &matR ); - cvZero( &_t ); - } - - cvRodrigues2( &matR, &_r ); - } - else - { - // non-planar structure. Use DLT method - CV_CheckGE(count, 6, "DLT algorithm needs at least 6 points for pose estimation from 3D-2D point correspondences."); - double* L; - double LL[12*12], LW[12], LV[12*12], sc; - CvMat _LL = cvMat( 12, 12, CV_64F, LL ); - CvMat _LW = cvMat( 12, 1, CV_64F, LW ); - CvMat _LV = cvMat( 12, 12, CV_64F, LV ); - CvMat _RRt, _RR, _tt; - CvPoint3D64f* M = (CvPoint3D64f*)matM->data.db; - CvPoint2D64f* mn = (CvPoint2D64f*)_mn->data.db; - - matL.reset(cvCreateMat( 2*count, 12, CV_64F )); - L = matL->data.db; - - for( i = 0; i < count; i++, L += 24 ) - { - double x = -mn[i].x, y = -mn[i].y; - L[0] = L[16] = M[i].x; - L[1] = L[17] = M[i].y; - L[2] = L[18] = M[i].z; - L[3] = L[19] = 1.; - L[4] = L[5] = L[6] = L[7] = 0.; - L[12] = L[13] = L[14] = L[15] = 0.; - L[8] = x*M[i].x; - L[9] = x*M[i].y; - L[10] = x*M[i].z; - L[11] = x; - L[20] = y*M[i].x; - L[21] = y*M[i].y; - L[22] = y*M[i].z; - L[23] = y; - } - - cvMulTransposed( matL, &_LL, 1 ); - cvSVD( &_LL, &_LW, 0, &_LV, CV_SVD_MODIFY_A + CV_SVD_V_T ); - _RRt = cvMat( 3, 4, CV_64F, LV + 11*12 ); - cvGetCols( &_RRt, &_RR, 0, 3 ); - cvGetCol( &_RRt, &_tt, 3 ); - if( cvDet(&_RR) < 0 ) - cvScale( &_RRt, &_RRt, -1 ); - sc = cvNorm(&_RR); - CV_Assert(fabs(sc) > DBL_EPSILON); - cvSVD( &_RR, &matW, &matU, &matV, CV_SVD_MODIFY_A + CV_SVD_U_T + CV_SVD_V_T ); - cvGEMM( &matU, &matV, 1, 0, 0, &matR, CV_GEMM_A_T ); - cvScale( &_tt, &_t, cvNorm(&matR)/sc ); - cvRodrigues2( &matR, &_r ); - } - } - - cvReshape( matM, matM, 3, 1 ); - cvReshape( _mn, _mn, 2, 1 ); - - // refine extrinsic parameters using iterative algorithm - CvLevMarq solver( 6, count*2, cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,max_iter,FLT_EPSILON), true); - cvCopy( &_param, solver.param ); - - for(;;) - { - CvMat *matJ = 0, *_err = 0; - const CvMat *__param = 0; - bool proceed = solver.update( __param, matJ, _err ); - cvCopy( __param, &_param ); - if( !proceed || !_err ) - break; - cvReshape( _err, _err, 2, 1 ); - if( matJ ) - { - cvGetCols( matJ, &_dpdr, 0, 3 ); - cvGetCols( matJ, &_dpdt, 3, 6 ); - cvProjectPoints2( matM, &_r, &_t, &matA, distCoeffs, - _err, &_dpdr, &_dpdt, 0, 0, 0 ); - } - else - { - cvProjectPoints2( matM, &_r, &_t, &matA, distCoeffs, - _err, 0, 0, 0, 0, 0 ); - } - cvSub(_err, _m, _err); - cvReshape( _err, _err, 1, 2*count ); - } - cvCopy( solver.param, &_param ); - - _r = cvMat( rvec->rows, rvec->cols, - CV_MAKETYPE(CV_64F,CV_MAT_CN(rvec->type)), param ); - _t = cvMat( tvec->rows, tvec->cols, - CV_MAKETYPE(CV_64F,CV_MAT_CN(tvec->type)), param + 3 ); - - cvConvert( &_r, rvec ); - cvConvert( &_t, tvec ); + cv::Mat objpt = cvarrToMat(objectPoints), imgpt = cvarrToMat(imagePoints); + cv::Mat cameraMatrix = cvarrToMat(A), dk, rv0=cvarrToMat(rvec), tv0=cvarrToMat(tvec), rv, tv; + if (distCoeffs) + dk = cvarrToMat(distCoeffs); + solvePnP(objpt, imgpt, cameraMatrix, dk, rv, tv, useExtrinsicGuess != 0, SOLVEPNP_ITERATIVE ); + CV_Assert(rv.size() == rv0.size() && tv.size() == tv0.size()); + rv.convertTo(rv0, rv0.type()); + tv.convertTo(tv0, tv0.type()); } -CV_IMPL void cvInitIntrinsicParams2D( const CvMat* objectPoints, - const CvMat* imagePoints, const CvMat* npoints, - CvSize imageSize, CvMat* cameraMatrix, +static void initIntrinsicParams2D( const Mat& objectPoints, + const Mat& imagePoints, const Mat& npoints, + Size imageSize, OutputArray cameraMatrix, double aspectRatio ) { - Ptr matA, _b, _allH; - - int i, j, pos, nimages, ni = 0; + int i, j, pos; double a[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 }; double H[9] = {0}, f[2] = {0}; - CvMat _a = cvMat( 3, 3, CV_64F, a ); - CvMat matH = cvMat( 3, 3, CV_64F, H ); - CvMat _f = cvMat( 2, 1, CV_64F, f ); + Mat _a( 3, 3, CV_64F, a ); + Mat matH( 3, 3, CV_64F, H ); + Mat _f( 2, 1, CV_64F, f ); - CV_Assert(npoints); - CV_Assert(CV_MAT_TYPE(npoints->type) == CV_32SC1); - CV_Assert(CV_IS_MAT_CONT(npoints->type)); - nimages = npoints->rows + npoints->cols - 1; + CV_Assert(npoints.type() == CV_32SC1 && (npoints.rows == 1 || npoints.cols == 1) && npoints.isContinuous()); + int nimages = npoints.rows + npoints.cols - 1; - if( (CV_MAT_TYPE(objectPoints->type) != CV_32FC3 && - CV_MAT_TYPE(objectPoints->type) != CV_64FC3) || - (CV_MAT_TYPE(imagePoints->type) != CV_32FC2 && - CV_MAT_TYPE(imagePoints->type) != CV_64FC2) ) - CV_Error( CV_StsUnsupportedFormat, "Both object points and image points must be 2D" ); + CV_Assert( objectPoints.type() == CV_32FC3 || + objectPoints.type() == CV_64FC3 ); + CV_Assert( imagePoints.type() == CV_32FC2 || + imagePoints.type() == CV_64FC2 ); - if( objectPoints->rows != 1 || imagePoints->rows != 1 ) + if( objectPoints.rows != 1 || imagePoints.rows != 1 ) CV_Error( CV_StsBadSize, "object points and image points must be a single-row matrices" ); - matA.reset(cvCreateMat( 2*nimages, 2, CV_64F )); - _b.reset(cvCreateMat( 2*nimages, 1, CV_64F )); + Mat matA( 2*nimages, 2, CV_64F ); + Mat _b( 2*nimages, 1, CV_64F ); a[2] = (!imageSize.width) ? 0.5 : (imageSize.width - 1)*0.5; a[5] = (!imageSize.height) ? 0.5 : (imageSize.height - 1)*0.5; - _allH.reset(cvCreateMat( nimages, 9, CV_64F )); + Mat _allH( nimages, 9, CV_64F ); // extract vanishing points in order to obtain initial value for the focal length - for( i = 0, pos = 0; i < nimages; i++, pos += ni ) + for( i = 0, pos = 0; i < nimages; i++ ) { - CV_DbgAssert(npoints->data.i); - CV_DbgAssert(matA && matA->data.db); - CV_DbgAssert(_b && _b->data.db); - double* Ap = matA->data.db + i*4; - double* bp = _b->data.db + i*2; - ni = npoints->data.i[i]; + double* Ap = (double*)matA.data + i*4; + double* bp = (double*)_b.data + i*2; + int ni = npoints.at(i); double h[3], v[3], d1[3], d2[3]; double n[4] = {0,0,0,0}; - CvMat _m, matM; - cvGetCols( objectPoints, &matM, pos, pos + ni ); - cvGetCols( imagePoints, &_m, pos, pos + ni ); + Mat matM = objectPoints.colRange(pos, pos + ni); + Mat _m = imagePoints.colRange(pos, pos + ni); + pos += ni; - cvFindHomography( &matM, &_m, &matH ); - CV_DbgAssert(_allH && _allH->data.db); - memcpy( _allH->data.db + i*9, H, sizeof(H) ); + Mat matH0 = findHomography(matM, _m); + CV_Assert(matH0.size() == Size(3, 3)); + matH0.convertTo(matH, CV_64F); H[0] -= H[6]*a[2]; H[1] -= H[7]*a[2]; H[2] -= H[8]*a[2]; H[3] -= H[6]*a[5]; H[4] -= H[7]*a[5]; H[5] -= H[8]*a[5]; @@ -1340,7 +1126,8 @@ CV_IMPL void cvInitIntrinsicParams2D( const CvMat* objectPoints, bp[0] = -h[2]*v[2]; bp[1] = -d1[2]*d2[2]; } - cvSolve( matA, _b, &_f, CV_NORMAL + CV_SVD ); + solve(matA, _b, _f, DECOMP_NORMAL + DECOMP_SVD); + CV_Assert((double*)_f.data == f); a[0] = std::sqrt(fabs(1./f[0])); a[4] = std::sqrt(fabs(1./f[1])); if( aspectRatio != 0 ) @@ -1349,14 +1136,13 @@ CV_IMPL void cvInitIntrinsicParams2D( const CvMat* objectPoints, a[0] = aspectRatio*tf; a[4] = tf; } - - cvConvert( &_a, cameraMatrix ); + _a.copyTo(cameraMatrix); } -static void subMatrix(const cv::Mat& src, cv::Mat& dst, const std::vector& cols, +static void subMatrix(const Mat& src, Mat& dst, const std::vector& cols, const std::vector& rows) { - int nonzeros_cols = cv::countNonZero(cols); - cv::Mat tmp(src.rows, nonzeros_cols, CV_64FC1); + int nonzeros_cols = countNonZero(cols); + Mat tmp(src.rows, nonzeros_cols, CV_64FC1); for (int i = 0, j = 0; i < (int)cols.size(); i++) { @@ -1366,7 +1152,7 @@ static void subMatrix(const cv::Mat& src, cv::Mat& dst, const std::vector } } - int nonzeros_rows = cv::countNonZero(rows); + int nonzeros_rows = countNonZero(rows); dst.create(nonzeros_rows, nonzeros_cols, CV_64FC1); for (int i = 0, j = 0; i < (int)rows.size(); i++) { @@ -1383,7 +1169,7 @@ static double cvCalibrateCamera2Internal( const CvMat* objectPoints, CvMat* rvecs, CvMat* tvecs, CvMat* newObjPoints, CvMat* stdDevs, CvMat* perViewErrors, int flags, CvTermCriteria termCrit ) { - const int NINTRINSIC = CV_CALIB_NINTRINSIC; + const int NINTRINSIC = CALIB_NINTRINSIC; double reprojErr = 0; Matx33d A; @@ -1516,13 +1302,13 @@ static double cvCalibrateCamera2Internal( const CvMat* objectPoints, if(CV_MAT_CN(objectPoints->type) == 3) { cvarrToMat(objectPoints).convertTo(matM, CV_64F); } else { - convertPointsHomogeneous(cvarrToMat(objectPoints), matM); + convertPointsToHomogeneous(cvarrToMat(objectPoints), matM, CV_64F); } if(CV_MAT_CN(imagePoints->type) == 2) { cvarrToMat(imagePoints).convertTo(_m, CV_64F); } else { - convertPointsHomogeneous(cvarrToMat(imagePoints), _m); + convertPointsFromHomogeneous(cvarrToMat(imagePoints), _m, CV_64F); } nparams = NINTRINSIC + nimages*6; @@ -1585,8 +1371,8 @@ static double cvCalibrateCamera2Internal( const CvMat* objectPoints, CV_Error( CV_StsOutOfRange, "The specified aspect ratio (= cameraMatrix[0][0] / cameraMatrix[1][1]) is incorrect" ); } - CvMat _matM = cvMat(matM), m = cvMat(_m); - cvInitIntrinsicParams2D( &_matM, &m, npoints, imageSize, &matA, aspectRatio ); + Mat _npoints = cvarrToMat(npoints); + initIntrinsicParams2D( matM, _m, _npoints, imageSize, A, aspectRatio ); } CvLevMarq solver( nparams, 0, termCrit ); @@ -1682,7 +1468,7 @@ static double cvCalibrateCamera2Internal( const CvMat* objectPoints, CvMat _Mi = cvMat(matM.colRange(pos, pos + ni)); CvMat _mi = cvMat(_m.colRange(pos, pos + ni)); - cvFindExtrinsicCameraParams2( &_Mi, &_mi, &matA, &_k, &_ri, &_ti ); + cvFindExtrinsicCameraParams2( &_Mi, &_mi, &matA, &_k, &_ri, &_ti, 0 ); } // 3. run the optimization @@ -1750,7 +1536,7 @@ static double cvCalibrateCamera2Internal( const CvMat* objectPoints, (flags & CALIB_FIX_ASPECT_RATIO) ? aspectRatio : 0); } else - cvProjectPoints2( &_Mi, &_ri, &_ti, &matA, &_k, &_mp ); + cvProjectPoints2Internal( &_Mi, &_ri, &_ti, &matA, &_k, &_mp, 0, 0, 0, 0, 0, 0 ); cvSub( &_mp, &_mi, &_mp ); if (perViewErrors || stdDevs) @@ -1871,16 +1657,18 @@ static double cvCalibrateCamera2Internal( const CvMat* objectPoints, /* finds intrinsic and extrinsic camera parameters from a few views of known calibration pattern */ -CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, +static double cvCalibrateCamera2( const CvMat* objectPoints, const CvMat* imagePoints, const CvMat* npoints, CvSize imageSize, CvMat* cameraMatrix, CvMat* distCoeffs, - CvMat* rvecs, CvMat* tvecs, int flags, CvTermCriteria termCrit ) + CvMat* rvecs, CvMat* tvecs, int flags, CvTermCriteria termCrit= + cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 30, DBL_EPSILON)) { return cvCalibrateCamera2Internal(objectPoints, imagePoints, npoints, imageSize, -1, cameraMatrix, distCoeffs, rvecs, tvecs, NULL, NULL, NULL, flags, termCrit); } -CV_IMPL double cvCalibrateCamera4( const CvMat* objectPoints, +#if 0 +static double cvCalibrateCamera4( const CvMat* objectPoints, const CvMat* imagePoints, const CvMat* npoints, CvSize imageSize, int iFixedPoint, CvMat* cameraMatrix, CvMat* distCoeffs, CvMat* rvecs, CvMat* tvecs, CvMat* newObjPoints, int flags, CvTermCriteria termCrit ) @@ -1905,7 +1693,7 @@ CV_IMPL double cvCalibrateCamera4( const CvMat* objectPoints, if(CV_MAT_CN(objectPoints->type) == 3) { matM = cvarrToMat(objectPoints); } else { - convertPointsHomogeneous(cvarrToMat(objectPoints), matM); + convertPointsToHomogeneous(cvarrToMat(objectPoints), matM, CV_64F); } matM = matM.reshape(3, 1); @@ -1932,7 +1720,7 @@ CV_IMPL double cvCalibrateCamera4( const CvMat* objectPoints, NULL, flags, termCrit); } -void cvCalibrationMatrixValues( const CvMat *calibMatr, CvSize imgSize, +static void cvCalibrationMatrixValues( const CvMat *calibMatr, CvSize imgSize, double apertureWidth, double apertureHeight, double *fovx, double *fovy, double *focalLength, CvPoint2D64f *principalPoint, double *pasp ) { @@ -1945,7 +1733,7 @@ void cvCalibrationMatrixValues( const CvMat *calibMatr, CvSize imgSize, double dummy = .0; Point2d pp; - cv::calibrationMatrixValues(cvarrToMat(calibMatr), imgSize, apertureWidth, apertureHeight, + calibrationMatrixValues(cvarrToMat(calibMatr), imgSize, apertureWidth, apertureHeight, fovx ? *fovx : dummy, fovy ? *fovy : dummy, focalLength ? *focalLength : dummy, @@ -1955,7 +1743,7 @@ void cvCalibrationMatrixValues( const CvMat *calibMatr, CvSize imgSize, if(principalPoint) *principalPoint = cvPoint2D64f(pp.x, pp.y); } - +#endif //////////////////////////////// Stereo Calibration /////////////////////////////////// @@ -2152,7 +1940,7 @@ static double cvStereoCalibrateImpl( const CvMat* _objectPoints, const CvMat* _i R[k] = cvMat(3, 3, CV_64F, r[k]); T[k] = cvMat(3, 1, CV_64F, t[k]); - cvFindExtrinsicCameraParams2( &objpt_i, &imgpt_i[k], &K[k], &Dist[k], &om[k], &T[k] ); + cvFindExtrinsicCameraParams2( &objpt_i, &imgpt_i[k], &K[k], &Dist[k], &om[k], &T[k], 0 ); cvRodrigues2( &om[k], &R[k] ); if( k == 0 ) { @@ -2442,7 +2230,9 @@ static double cvStereoCalibrateImpl( const CvMat* _objectPoints, const CvMat* _i return std::sqrt(reprojErr/(pointsTotal*2)); } -double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1, + +#if 0 +static double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1, const CvMat* _imagePoints2, const CvMat* _npoints, CvMat* _cameraMatrix1, CvMat* _distCoeffs1, CvMat* _cameraMatrix2, CvMat* _distCoeffs2, @@ -2457,656 +2247,6 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1 } static void -icvGetRectangles( const CvMat* cameraMatrix, const CvMat* distCoeffs, - const CvMat* R, const CvMat* newCameraMatrix, CvSize imgSize, - cv::Rect_& inner, cv::Rect_& outer ) -{ - const int N = 9; - int x, y, k; - cv::Ptr _pts(cvCreateMat(1, N*N, CV_32FC2)); - CvPoint2D32f* pts = (CvPoint2D32f*)(_pts->data.ptr); - - for( y = k = 0; y < N; y++ ) - for( x = 0; x < N; x++ ) - pts[k++] = cvPoint2D32f((float)x*imgSize.width/(N-1), - (float)y*imgSize.height/(N-1)); - - cvUndistortPoints(_pts, _pts, cameraMatrix, distCoeffs, R, newCameraMatrix); - - float iX0=-FLT_MAX, iX1=FLT_MAX, iY0=-FLT_MAX, iY1=FLT_MAX; - float oX0=FLT_MAX, oX1=-FLT_MAX, oY0=FLT_MAX, oY1=-FLT_MAX; - // find the inscribed rectangle. - // the code will likely not work with extreme rotation matrices (R) (>45%) - for( y = k = 0; y < N; y++ ) - for( x = 0; x < N; x++ ) - { - CvPoint2D32f p = pts[k++]; - oX0 = MIN(oX0, p.x); - oX1 = MAX(oX1, p.x); - oY0 = MIN(oY0, p.y); - oY1 = MAX(oY1, p.y); - - if( x == 0 ) - iX0 = MAX(iX0, p.x); - if( x == N-1 ) - iX1 = MIN(iX1, p.x); - if( y == 0 ) - iY0 = MAX(iY0, p.y); - if( y == N-1 ) - iY1 = MIN(iY1, p.y); - } - inner = cv::Rect_(iX0, iY0, iX1-iX0, iY1-iY0); - outer = cv::Rect_(oX0, oY0, oX1-oX0, oY1-oY0); -} - - -void cvStereoRectify( const CvMat* _cameraMatrix1, const CvMat* _cameraMatrix2, - const CvMat* _distCoeffs1, const CvMat* _distCoeffs2, - CvSize imageSize, const CvMat* matR, const CvMat* matT, - CvMat* _R1, CvMat* _R2, CvMat* _P1, CvMat* _P2, - CvMat* matQ, int flags, double alpha, CvSize newImgSize, - CvRect* roi1, CvRect* roi2 ) -{ - double _om[3], _t[3] = {0}, _uu[3]={0,0,0}, _r_r[3][3], _pp[3][4]; - double _ww[3], _wr[3][3], _z[3] = {0,0,0}, _ri[3][3]; - cv::Rect_ inner1, inner2, outer1, outer2; - - CvMat om = cvMat(3, 1, CV_64F, _om); - CvMat t = cvMat(3, 1, CV_64F, _t); - CvMat uu = cvMat(3, 1, CV_64F, _uu); - CvMat r_r = cvMat(3, 3, CV_64F, _r_r); - CvMat pp = cvMat(3, 4, CV_64F, _pp); - CvMat ww = cvMat(3, 1, CV_64F, _ww); // temps - CvMat wR = cvMat(3, 3, CV_64F, _wr); - CvMat Z = cvMat(3, 1, CV_64F, _z); - CvMat Ri = cvMat(3, 3, CV_64F, _ri); - double nx = imageSize.width, ny = imageSize.height; - int i, k; - - if( matR->rows == 3 && matR->cols == 3 ) - cvRodrigues2(matR, &om); // get vector rotation - else - cvConvert(matR, &om); // it's already a rotation vector - cvConvertScale(&om, &om, -0.5); // get average rotation - cvRodrigues2(&om, &r_r); // rotate cameras to same orientation by averaging - cvMatMul(&r_r, matT, &t); - - int idx = fabs(_t[0]) > fabs(_t[1]) ? 0 : 1; - double c = _t[idx], nt = cvNorm(&t, 0, CV_L2); - _uu[idx] = c > 0 ? 1 : -1; - - CV_Assert(nt > 0.0); - - // calculate global Z rotation - cvCrossProduct(&t,&uu,&ww); - double nw = cvNorm(&ww, 0, CV_L2); - if (nw > 0.0) - cvConvertScale(&ww, &ww, acos(fabs(c)/nt)/nw); - cvRodrigues2(&ww, &wR); - - // apply to both views - cvGEMM(&wR, &r_r, 1, 0, 0, &Ri, CV_GEMM_B_T); - cvConvert( &Ri, _R1 ); - cvGEMM(&wR, &r_r, 1, 0, 0, &Ri, 0); - cvConvert( &Ri, _R2 ); - cvMatMul(&Ri, matT, &t); - - // calculate projection/camera matrices - // these contain the relevant rectified image internal params (fx, fy=fx, cx, cy) - double fc_new = DBL_MAX; - CvPoint2D64f cc_new[2] = {}; - - newImgSize = newImgSize.width * newImgSize.height != 0 ? newImgSize : imageSize; - const double ratio_x = (double)newImgSize.width / imageSize.width / 2; - const double ratio_y = (double)newImgSize.height / imageSize.height / 2; - const double ratio = idx == 1 ? ratio_x : ratio_y; - fc_new = (cvmGet(_cameraMatrix1, idx ^ 1, idx ^ 1) + cvmGet(_cameraMatrix2, idx ^ 1, idx ^ 1)) * ratio; - - for( k = 0; k < 2; k++ ) - { - const CvMat* A = k == 0 ? _cameraMatrix1 : _cameraMatrix2; - const CvMat* Dk = k == 0 ? _distCoeffs1 : _distCoeffs2; - CvPoint2D32f _pts[4] = {}; - CvPoint3D32f _pts_3[4] = {}; - CvMat pts = cvMat(1, 4, CV_32FC2, _pts); - CvMat pts_3 = cvMat(1, 4, CV_32FC3, _pts_3); - - for( i = 0; i < 4; i++ ) - { - int j = (i<2) ? 0 : 1; - _pts[i].x = (float)((i % 2)*(nx-1)); - _pts[i].y = (float)(j*(ny-1)); - } - cvUndistortPoints( &pts, &pts, A, Dk, 0, 0 ); - cvConvertPointsHomogeneous( &pts, &pts_3 ); - - //Change camera matrix to have cc=[0,0] and fc = fc_new - double _a_tmp[3][3]; - CvMat A_tmp = cvMat(3, 3, CV_64F, _a_tmp); - _a_tmp[0][0]=fc_new; - _a_tmp[1][1]=fc_new; - _a_tmp[0][2]=0.0; - _a_tmp[1][2]=0.0; - cvProjectPoints2( &pts_3, k == 0 ? _R1 : _R2, &Z, &A_tmp, 0, &pts ); - CvScalar avg = cvAvg(&pts); - cc_new[k].x = (nx-1)/2 - avg.val[0]; - cc_new[k].y = (ny-1)/2 - avg.val[1]; - } - - // vertical focal length must be the same for both images to keep the epipolar constraint - // (for horizontal epipolar lines -- TBD: check for vertical epipolar lines) - // use fy for fx also, for simplicity - - // For simplicity, set the principal points for both cameras to be the average - // of the two principal points (either one of or both x- and y- coordinates) - if( flags & CALIB_ZERO_DISPARITY ) - { - cc_new[0].x = cc_new[1].x = (cc_new[0].x + cc_new[1].x)*0.5; - cc_new[0].y = cc_new[1].y = (cc_new[0].y + cc_new[1].y)*0.5; - } - else if( idx == 0 ) // horizontal stereo - cc_new[0].y = cc_new[1].y = (cc_new[0].y + cc_new[1].y)*0.5; - else // vertical stereo - cc_new[0].x = cc_new[1].x = (cc_new[0].x + cc_new[1].x)*0.5; - - cvZero( &pp ); - _pp[0][0] = _pp[1][1] = fc_new; - _pp[0][2] = cc_new[0].x; - _pp[1][2] = cc_new[0].y; - _pp[2][2] = 1; - cvConvert(&pp, _P1); - - _pp[0][2] = cc_new[1].x; - _pp[1][2] = cc_new[1].y; - _pp[idx][3] = _t[idx]*fc_new; // baseline * focal length - cvConvert(&pp, _P2); - - alpha = MIN(alpha, 1.); - - icvGetRectangles( _cameraMatrix1, _distCoeffs1, _R1, _P1, imageSize, inner1, outer1 ); - icvGetRectangles( _cameraMatrix2, _distCoeffs2, _R2, _P2, imageSize, inner2, outer2 ); - - { - newImgSize = newImgSize.width*newImgSize.height != 0 ? newImgSize : imageSize; - double cx1_0 = cc_new[0].x; - double cy1_0 = cc_new[0].y; - double cx2_0 = cc_new[1].x; - double cy2_0 = cc_new[1].y; - double cx1 = newImgSize.width*cx1_0/imageSize.width; - double cy1 = newImgSize.height*cy1_0/imageSize.height; - double cx2 = newImgSize.width*cx2_0/imageSize.width; - double cy2 = newImgSize.height*cy2_0/imageSize.height; - double s = 1.; - - if( alpha >= 0 ) - { - double s0 = std::max(std::max(std::max((double)cx1/(cx1_0 - inner1.x), (double)cy1/(cy1_0 - inner1.y)), - (double)(newImgSize.width - cx1)/(inner1.x + inner1.width - cx1_0)), - (double)(newImgSize.height - cy1)/(inner1.y + inner1.height - cy1_0)); - s0 = std::max(std::max(std::max(std::max((double)cx2/(cx2_0 - inner2.x), (double)cy2/(cy2_0 - inner2.y)), - (double)(newImgSize.width - cx2)/(inner2.x + inner2.width - cx2_0)), - (double)(newImgSize.height - cy2)/(inner2.y + inner2.height - cy2_0)), - s0); - - double s1 = std::min(std::min(std::min((double)cx1/(cx1_0 - outer1.x), (double)cy1/(cy1_0 - outer1.y)), - (double)(newImgSize.width - cx1)/(outer1.x + outer1.width - cx1_0)), - (double)(newImgSize.height - cy1)/(outer1.y + outer1.height - cy1_0)); - s1 = std::min(std::min(std::min(std::min((double)cx2/(cx2_0 - outer2.x), (double)cy2/(cy2_0 - outer2.y)), - (double)(newImgSize.width - cx2)/(outer2.x + outer2.width - cx2_0)), - (double)(newImgSize.height - cy2)/(outer2.y + outer2.height - cy2_0)), - s1); - - s = s0*(1 - alpha) + s1*alpha; - } - - fc_new *= s; - cc_new[0] = cvPoint2D64f(cx1, cy1); - cc_new[1] = cvPoint2D64f(cx2, cy2); - - cvmSet(_P1, 0, 0, fc_new); - cvmSet(_P1, 1, 1, fc_new); - cvmSet(_P1, 0, 2, cx1); - cvmSet(_P1, 1, 2, cy1); - - cvmSet(_P2, 0, 0, fc_new); - cvmSet(_P2, 1, 1, fc_new); - cvmSet(_P2, 0, 2, cx2); - cvmSet(_P2, 1, 2, cy2); - cvmSet(_P2, idx, 3, s*cvmGet(_P2, idx, 3)); - - if(roi1) - { - *roi1 = cvRect( - cv::Rect(cvCeil((inner1.x - cx1_0)*s + cx1), - cvCeil((inner1.y - cy1_0)*s + cy1), - cvFloor(inner1.width*s), cvFloor(inner1.height*s)) - & cv::Rect(0, 0, newImgSize.width, newImgSize.height) - ); - } - - if(roi2) - { - *roi2 = cvRect( - cv::Rect(cvCeil((inner2.x - cx2_0)*s + cx2), - cvCeil((inner2.y - cy2_0)*s + cy2), - cvFloor(inner2.width*s), cvFloor(inner2.height*s)) - & cv::Rect(0, 0, newImgSize.width, newImgSize.height) - ); - } - } - - if( matQ ) - { - double q[] = - { - 1, 0, 0, -cc_new[0].x, - 0, 1, 0, -cc_new[0].y, - 0, 0, 0, fc_new, - 0, 0, -1./_t[idx], - (idx == 0 ? cc_new[0].x - cc_new[1].x : cc_new[0].y - cc_new[1].y)/_t[idx] - }; - CvMat Q = cvMat(4, 4, CV_64F, q); - cvConvert( &Q, matQ ); - } -} - - -void cvGetOptimalNewCameraMatrix( const CvMat* cameraMatrix, const CvMat* distCoeffs, - CvSize imgSize, double alpha, - CvMat* newCameraMatrix, CvSize newImgSize, - CvRect* validPixROI, int centerPrincipalPoint ) -{ - cv::Rect_ inner, outer; - newImgSize = newImgSize.width*newImgSize.height != 0 ? newImgSize : imgSize; - - double M[3][3]; - CvMat matM = cvMat(3, 3, CV_64F, M); - cvConvert(cameraMatrix, &matM); - - if( centerPrincipalPoint ) - { - double cx0 = M[0][2]; - double cy0 = M[1][2]; - double cx = (newImgSize.width-1)*0.5; - double cy = (newImgSize.height-1)*0.5; - - icvGetRectangles( cameraMatrix, distCoeffs, 0, cameraMatrix, imgSize, inner, outer ); - double s0 = std::max(std::max(std::max((double)cx/(cx0 - inner.x), (double)cy/(cy0 - inner.y)), - (double)cx/(inner.x + inner.width - cx0)), - (double)cy/(inner.y + inner.height - cy0)); - double s1 = std::min(std::min(std::min((double)cx/(cx0 - outer.x), (double)cy/(cy0 - outer.y)), - (double)cx/(outer.x + outer.width - cx0)), - (double)cy/(outer.y + outer.height - cy0)); - double s = s0*(1 - alpha) + s1*alpha; - - M[0][0] *= s; - M[1][1] *= s; - M[0][2] = cx; - M[1][2] = cy; - - if( validPixROI ) - { - inner = cv::Rect_((float)((inner.x - cx0)*s + cx), - (float)((inner.y - cy0)*s + cy), - (float)(inner.width*s), - (float)(inner.height*s)); - cv::Rect r(cvCeil(inner.x), cvCeil(inner.y), cvFloor(inner.width), cvFloor(inner.height)); - r &= cv::Rect(0, 0, newImgSize.width, newImgSize.height); - *validPixROI = cvRect(r); - } - } - else - { - // Get inscribed and circumscribed rectangles in normalized - // (independent of camera matrix) coordinates - icvGetRectangles( cameraMatrix, distCoeffs, 0, 0, imgSize, inner, outer ); - - // Projection mapping inner rectangle to viewport - double fx0 = (newImgSize.width - 1) / inner.width; - double fy0 = (newImgSize.height - 1) / inner.height; - double cx0 = -fx0 * inner.x; - double cy0 = -fy0 * inner.y; - - // Projection mapping outer rectangle to viewport - double fx1 = (newImgSize.width - 1) / outer.width; - double fy1 = (newImgSize.height - 1) / outer.height; - double cx1 = -fx1 * outer.x; - double cy1 = -fy1 * outer.y; - - // Interpolate between the two optimal projections - M[0][0] = fx0*(1 - alpha) + fx1*alpha; - M[1][1] = fy0*(1 - alpha) + fy1*alpha; - M[0][2] = cx0*(1 - alpha) + cx1*alpha; - M[1][2] = cy0*(1 - alpha) + cy1*alpha; - - if( validPixROI ) - { - icvGetRectangles( cameraMatrix, distCoeffs, 0, &matM, imgSize, inner, outer ); - cv::Rect r = inner; - r &= cv::Rect(0, 0, newImgSize.width, newImgSize.height); - *validPixROI = cvRect(r); - } - } - - cvConvert(&matM, newCameraMatrix); -} - - -CV_IMPL int cvStereoRectifyUncalibrated( - const CvMat* _points1, const CvMat* _points2, - const CvMat* F0, CvSize imgSize, - CvMat* _H1, CvMat* _H2, double threshold ) -{ - Ptr _m1, _m2, _lines1, _lines2; - - int i, j, npoints; - double cx, cy; - double u[9], v[9], w[9], f[9], h1[9], h2[9], h0[9], e2[3] = {0}; - CvMat E2 = cvMat( 3, 1, CV_64F, e2 ); - CvMat U = cvMat( 3, 3, CV_64F, u ); - CvMat V = cvMat( 3, 3, CV_64F, v ); - CvMat W = cvMat( 3, 3, CV_64F, w ); - CvMat F = cvMat( 3, 3, CV_64F, f ); - CvMat H1 = cvMat( 3, 3, CV_64F, h1 ); - CvMat H2 = cvMat( 3, 3, CV_64F, h2 ); - CvMat H0 = cvMat( 3, 3, CV_64F, h0 ); - - CvPoint2D64f* m1; - CvPoint2D64f* m2; - CvPoint3D64f* lines1; - CvPoint3D64f* lines2; - - CV_Assert( CV_IS_MAT(_points1) && CV_IS_MAT(_points2) && - CV_ARE_SIZES_EQ(_points1, _points2) ); - - npoints = _points1->rows * _points1->cols * CV_MAT_CN(_points1->type) / 2; - - _m1.reset(cvCreateMat( _points1->rows, _points1->cols, CV_64FC(CV_MAT_CN(_points1->type)) )); - _m2.reset(cvCreateMat( _points2->rows, _points2->cols, CV_64FC(CV_MAT_CN(_points2->type)) )); - _lines1.reset(cvCreateMat( 1, npoints, CV_64FC3 )); - _lines2.reset(cvCreateMat( 1, npoints, CV_64FC3 )); - - cvConvert( F0, &F ); - - cvSVD( (CvMat*)&F, &W, &U, &V, CV_SVD_U_T + CV_SVD_V_T ); - W.data.db[8] = 0.; - cvGEMM( &U, &W, 1, 0, 0, &W, CV_GEMM_A_T ); - cvMatMul( &W, &V, &F ); - - cx = cvRound( (imgSize.width-1)*0.5 ); - cy = cvRound( (imgSize.height-1)*0.5 ); - - cvZero( _H1 ); - cvZero( _H2 ); - - cvConvert( _points1, _m1 ); - cvConvert( _points2, _m2 ); - cvReshape( _m1, _m1, 2, 1 ); - cvReshape( _m2, _m2, 2, 1 ); - - m1 = (CvPoint2D64f*)_m1->data.ptr; - m2 = (CvPoint2D64f*)_m2->data.ptr; - lines1 = (CvPoint3D64f*)_lines1->data.ptr; - lines2 = (CvPoint3D64f*)_lines2->data.ptr; - - if( threshold > 0 ) - { - cvComputeCorrespondEpilines( _m1, 1, &F, _lines1 ); - cvComputeCorrespondEpilines( _m2, 2, &F, _lines2 ); - - // measure distance from points to the corresponding epilines, mark outliers - for( i = j = 0; i < npoints; i++ ) - { - if( fabs(m1[i].x*lines2[i].x + - m1[i].y*lines2[i].y + - lines2[i].z) <= threshold && - fabs(m2[i].x*lines1[i].x + - m2[i].y*lines1[i].y + - lines1[i].z) <= threshold ) - { - if( j < i ) - { - m1[j] = m1[i]; - m2[j] = m2[i]; - } - j++; - } - } - - npoints = j; - if( npoints == 0 ) - return 0; - } - - _m1->cols = _m2->cols = npoints; - memcpy( E2.data.db, U.data.db + 6, sizeof(e2)); - cvScale( &E2, &E2, e2[2] > 0 ? 1 : -1 ); - - double t[] = - { - 1, 0, -cx, - 0, 1, -cy, - 0, 0, 1 - }; - CvMat T = cvMat(3, 3, CV_64F, t); - cvMatMul( &T, &E2, &E2 ); - - int mirror = e2[0] < 0; - double d = MAX(std::sqrt(e2[0]*e2[0] + e2[1]*e2[1]),DBL_EPSILON); - double alpha = e2[0]/d; - double beta = e2[1]/d; - double r[] = - { - alpha, beta, 0, - -beta, alpha, 0, - 0, 0, 1 - }; - CvMat R = cvMat(3, 3, CV_64F, r); - cvMatMul( &R, &T, &T ); - cvMatMul( &R, &E2, &E2 ); - double invf = fabs(e2[2]) < 1e-6*fabs(e2[0]) ? 0 : -e2[2]/e2[0]; - double k[] = - { - 1, 0, 0, - 0, 1, 0, - invf, 0, 1 - }; - CvMat K = cvMat(3, 3, CV_64F, k); - cvMatMul( &K, &T, &H2 ); - cvMatMul( &K, &E2, &E2 ); - - double it[] = - { - 1, 0, cx, - 0, 1, cy, - 0, 0, 1 - }; - CvMat iT = cvMat( 3, 3, CV_64F, it ); - cvMatMul( &iT, &H2, &H2 ); - - memcpy( E2.data.db, U.data.db + 6, sizeof(e2)); - cvScale( &E2, &E2, e2[2] > 0 ? 1 : -1 ); - - double e2_x[] = - { - 0, -e2[2], e2[1], - e2[2], 0, -e2[0], - -e2[1], e2[0], 0 - }; - double e2_111[] = - { - e2[0], e2[0], e2[0], - e2[1], e2[1], e2[1], - e2[2], e2[2], e2[2], - }; - CvMat E2_x = cvMat(3, 3, CV_64F, e2_x); - CvMat E2_111 = cvMat(3, 3, CV_64F, e2_111); - cvMatMulAdd(&E2_x, &F, &E2_111, &H0 ); - cvMatMul(&H2, &H0, &H0); - CvMat E1=cvMat(3, 1, CV_64F, V.data.db+6); - cvMatMul(&H0, &E1, &E1); - - cvPerspectiveTransform( _m1, _m1, &H0 ); - cvPerspectiveTransform( _m2, _m2, &H2 ); - CvMat A = cvMat( 1, npoints, CV_64FC3, lines1 ), BxBy, B; - double x[3] = {0}; - CvMat X = cvMat( 3, 1, CV_64F, x ); - cvConvertPointsHomogeneous( _m1, &A ); - cvReshape( &A, &A, 1, npoints ); - cvReshape( _m2, &BxBy, 1, npoints ); - cvGetCol( &BxBy, &B, 0 ); - cvSolve( &A, &B, &X, CV_SVD ); - - double ha[] = - { - x[0], x[1], x[2], - 0, 1, 0, - 0, 0, 1 - }; - CvMat Ha = cvMat(3, 3, CV_64F, ha); - cvMatMul( &Ha, &H0, &H1 ); - cvPerspectiveTransform( _m1, _m1, &Ha ); - - if( mirror ) - { - double mm[] = { -1, 0, cx*2, 0, -1, cy*2, 0, 0, 1 }; - CvMat MM = cvMat(3, 3, CV_64F, mm); - cvMatMul( &MM, &H1, &H1 ); - cvMatMul( &MM, &H2, &H2 ); - } - - cvConvert( &H1, _H1 ); - cvConvert( &H2, _H2 ); - - return 1; -} - - -void cv::reprojectImageTo3D( InputArray _disparity, - OutputArray __3dImage, InputArray _Qmat, - bool handleMissingValues, int dtype ) -{ - CV_INSTRUMENT_REGION(); - - Mat disparity = _disparity.getMat(), Q = _Qmat.getMat(); - int stype = disparity.type(); - - CV_Assert( stype == CV_8UC1 || stype == CV_16SC1 || - stype == CV_32SC1 || stype == CV_32FC1 ); - CV_Assert( Q.size() == Size(4,4) ); - - if( dtype >= 0 ) - dtype = CV_MAKETYPE(CV_MAT_DEPTH(dtype), 3); - - if( __3dImage.fixedType() ) - { - int dtype_ = __3dImage.type(); - CV_Assert( dtype == -1 || dtype == dtype_ ); - dtype = dtype_; - } - - if( dtype < 0 ) - dtype = CV_32FC3; - else - CV_Assert( dtype == CV_16SC3 || dtype == CV_32SC3 || dtype == CV_32FC3 ); - - __3dImage.create(disparity.size(), dtype); - Mat _3dImage = __3dImage.getMat(); - - const float bigZ = 10000.f; - Matx44d _Q; - Q.convertTo(_Q, CV_64F); - - int x, cols = disparity.cols; - CV_Assert( cols >= 0 ); - - std::vector _sbuf(cols); - std::vector _dbuf(cols); - float* sbuf = &_sbuf[0]; - Vec3f* dbuf = &_dbuf[0]; - double minDisparity = FLT_MAX; - - // NOTE: here we quietly assume that at least one pixel in the disparity map is not defined. - // and we set the corresponding Z's to some fixed big value. - if( handleMissingValues ) - cv::minMaxIdx( disparity, &minDisparity, 0, 0, 0 ); - - for( int y = 0; y < disparity.rows; y++ ) - { - float* sptr = sbuf; - Vec3f* dptr = dbuf; - - if( stype == CV_8UC1 ) - { - const uchar* sptr0 = disparity.ptr(y); - for( x = 0; x < cols; x++ ) - sptr[x] = (float)sptr0[x]; - } - else if( stype == CV_16SC1 ) - { - const short* sptr0 = disparity.ptr(y); - for( x = 0; x < cols; x++ ) - sptr[x] = (float)sptr0[x]; - } - else if( stype == CV_32SC1 ) - { - const int* sptr0 = disparity.ptr(y); - for( x = 0; x < cols; x++ ) - sptr[x] = (float)sptr0[x]; - } - else - sptr = disparity.ptr(y); - - if( dtype == CV_32FC3 ) - dptr = _3dImage.ptr(y); - - for( x = 0; x < cols; x++) - { - double d = sptr[x]; - Vec4d homg_pt = _Q*Vec4d(x, y, d, 1.0); - dptr[x] = Vec3d(homg_pt.val); - dptr[x] /= homg_pt[3]; - - if( fabs(d-minDisparity) <= FLT_EPSILON ) - dptr[x][2] = bigZ; - } - - if( dtype == CV_16SC3 ) - { - Vec3s* dptr0 = _3dImage.ptr(y); - for( x = 0; x < cols; x++ ) - { - dptr0[x] = dptr[x]; - } - } - else if( dtype == CV_32SC3 ) - { - Vec3i* dptr0 = _3dImage.ptr(y); - for( x = 0; x < cols; x++ ) - { - dptr0[x] = dptr[x]; - } - } - } -} - - -void cvReprojectImageTo3D( const CvArr* disparityImage, - CvArr* _3dImage, const CvMat* matQ, - int handleMissingValues ) -{ - cv::Mat disp = cv::cvarrToMat(disparityImage); - cv::Mat _3dimg = cv::cvarrToMat(_3dImage); - cv::Mat mq = cv::cvarrToMat(matQ); - CV_Assert( disp.size() == _3dimg.size() ); - int dtype = _3dimg.type(); - CV_Assert( dtype == CV_16SC3 || dtype == CV_32SC3 || dtype == CV_32FC3 ); - - cv::reprojectImageTo3D(disp, _3dimg, mq, handleMissingValues != 0, dtype ); -} - - -CV_IMPL void cvRQDecomp3x3( const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ, CvMat *matrixQx, CvMat *matrixQy, CvMat *matrixQz, CvPoint3D64f *eulerAngles) @@ -3271,8 +2411,7 @@ cvRQDecomp3x3( const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ, cvConvert(&Qz, matrixQz); } - -CV_IMPL void +static void cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr, CvMat *rotMatr, CvMat *posVect, CvMat *rotMatrX, CvMat *rotMatrY, @@ -3320,11 +2459,7 @@ cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr, cvRQDecomp3x3(&tmpMatrixM, calibMatr, rotMatr, rotMatrX, rotMatrY, rotMatrZ, eulerAngles); } - - - -namespace cv -{ +#endif static void collectCalibrationData( InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, @@ -3443,6 +2578,19 @@ static Mat prepareCameraMatrix(Mat& cameraMatrix0, int rtype, int flags) return cameraMatrix; } +Mat initCameraMatrix2D( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, + Size imageSize, double aspectRatio ) +{ + CV_INSTRUMENT_REGION(); + + Mat objPt, imgPt, npoints, cameraMatrix; + collectCalibrationData( objectPoints, imagePoints, noArray(), + objPt, imgPt, 0, npoints ); + initIntrinsicParams2D( objPt, imgPt, npoints, imageSize, cameraMatrix, aspectRatio ); + return cameraMatrix; +} + static Mat prepareDistCoeffs(Mat& distCoeffs0, int rtype, int outputSize = 14) { CV_Assert((int)distCoeffs0.total() <= outputSize); @@ -3464,167 +2612,10 @@ static Mat prepareDistCoeffs(Mat& distCoeffs0, int rtype, int outputSize = 14) return distCoeffs; } -} // namespace cv - - -void cv::Rodrigues(InputArray _src, OutputArray _dst, OutputArray _jacobian) -{ - CV_INSTRUMENT_REGION(); - - Mat src = _src.getMat(); - const Size srcSz = src.size(); - CV_Check(srcSz, srcSz == Size(3, 1) || srcSz == Size(1, 3) || - (srcSz == Size(1, 1) && src.channels() == 3) || - srcSz == Size(3, 3), - "Input matrix must be 1x3 or 3x1 for a rotation vector, or 3x3 for a rotation matrix"); - - bool v2m = src.cols == 1 || src.rows == 1; - _dst.create(3, v2m ? 3 : 1, src.depth()); - Mat dst = _dst.getMat(); - CvMat _csrc = cvMat(src), _cdst = cvMat(dst), _cjacobian; - if( _jacobian.needed() ) - { - _jacobian.create(v2m ? Size(9, 3) : Size(3, 9), src.depth()); - _cjacobian = cvMat(_jacobian.getMat()); - } - bool ok = cvRodrigues2(&_csrc, &_cdst, _jacobian.needed() ? &_cjacobian : 0) > 0; - if( !ok ) - dst = Scalar(0); -} - -void cv::matMulDeriv( InputArray _Amat, InputArray _Bmat, - OutputArray _dABdA, OutputArray _dABdB ) -{ - CV_INSTRUMENT_REGION(); - - Mat A = _Amat.getMat(), B = _Bmat.getMat(); - _dABdA.create(A.rows*B.cols, A.rows*A.cols, A.type()); - _dABdB.create(A.rows*B.cols, B.rows*B.cols, A.type()); - Mat dABdA = _dABdA.getMat(), dABdB = _dABdB.getMat(); - CvMat matA = cvMat(A), matB = cvMat(B), c_dABdA = cvMat(dABdA), c_dABdB = cvMat(dABdB); - cvCalcMatMulDeriv(&matA, &matB, &c_dABdA, &c_dABdB); -} - - -void cv::composeRT( InputArray _rvec1, InputArray _tvec1, - InputArray _rvec2, InputArray _tvec2, - OutputArray _rvec3, OutputArray _tvec3, - OutputArray _dr3dr1, OutputArray _dr3dt1, - OutputArray _dr3dr2, OutputArray _dr3dt2, - OutputArray _dt3dr1, OutputArray _dt3dt1, - OutputArray _dt3dr2, OutputArray _dt3dt2 ) -{ - Mat rvec1 = _rvec1.getMat(), tvec1 = _tvec1.getMat(); - Mat rvec2 = _rvec2.getMat(), tvec2 = _tvec2.getMat(); - int rtype = rvec1.type(); - _rvec3.create(rvec1.size(), rtype); - _tvec3.create(tvec1.size(), rtype); - Mat rvec3 = _rvec3.getMat(), tvec3 = _tvec3.getMat(); - - CvMat c_rvec1 = cvMat(rvec1), c_tvec1 = cvMat(tvec1), c_rvec2 = cvMat(rvec2), - c_tvec2 = cvMat(tvec2), c_rvec3 = cvMat(rvec3), c_tvec3 = cvMat(tvec3); - CvMat c_dr3dr1, c_dr3dt1, c_dr3dr2, c_dr3dt2, c_dt3dr1, c_dt3dt1, c_dt3dr2, c_dt3dt2; - CvMat *p_dr3dr1=0, *p_dr3dt1=0, *p_dr3dr2=0, *p_dr3dt2=0, *p_dt3dr1=0, *p_dt3dt1=0, *p_dt3dr2=0, *p_dt3dt2=0; -#define CV_COMPOSE_RT_PARAM(name) \ - Mat name; \ - if (_ ## name.needed())\ - { \ - _ ## name.create(3, 3, rtype); \ - name = _ ## name.getMat(); \ - p_ ## name = &(c_ ## name = cvMat(name)); \ - } - - CV_COMPOSE_RT_PARAM(dr3dr1); CV_COMPOSE_RT_PARAM(dr3dt1); - CV_COMPOSE_RT_PARAM(dr3dr2); CV_COMPOSE_RT_PARAM(dr3dt2); - CV_COMPOSE_RT_PARAM(dt3dr1); CV_COMPOSE_RT_PARAM(dt3dt1); - CV_COMPOSE_RT_PARAM(dt3dr2); CV_COMPOSE_RT_PARAM(dt3dt2); -#undef CV_COMPOSE_RT_PARAM - - cvComposeRT(&c_rvec1, &c_tvec1, &c_rvec2, &c_tvec2, &c_rvec3, &c_tvec3, - p_dr3dr1, p_dr3dt1, p_dr3dr2, p_dr3dt2, - p_dt3dr1, p_dt3dt1, p_dt3dr2, p_dt3dt2); -} - - -void cv::projectPoints( InputArray _opoints, - InputArray _rvec, - InputArray _tvec, - InputArray _cameraMatrix, - InputArray _distCoeffs, - OutputArray _ipoints, - OutputArray _jacobian, - double aspectRatio ) -{ - Mat opoints = _opoints.getMat(); - int npoints = opoints.checkVector(3), depth = opoints.depth(); - if (npoints < 0) - opoints = opoints.t(); - npoints = opoints.checkVector(3); - CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_64F)); - - if (opoints.cols == 3) - opoints = opoints.reshape(3); - - CvMat dpdrot, dpdt, dpdf, dpdc, dpddist; - CvMat *pdpdrot=0, *pdpdt=0, *pdpdf=0, *pdpdc=0, *pdpddist=0; - - CV_Assert( _ipoints.needed() ); - - _ipoints.create(npoints, 1, CV_MAKETYPE(depth, 2), -1, true); - Mat imagePoints = _ipoints.getMat(); - CvMat c_imagePoints = cvMat(imagePoints); - CvMat c_objectPoints = cvMat(opoints); - Mat cameraMatrix = _cameraMatrix.getMat(); - - Mat rvec = _rvec.getMat(), tvec = _tvec.getMat(); - CvMat c_cameraMatrix = cvMat(cameraMatrix); - CvMat c_rvec = cvMat(rvec), c_tvec = cvMat(tvec); - - double dc0buf[5]={0}; - Mat dc0(5,1,CV_64F,dc0buf); - Mat distCoeffs = _distCoeffs.getMat(); - if( distCoeffs.empty() ) - distCoeffs = dc0; - CvMat c_distCoeffs = cvMat(distCoeffs); - int ndistCoeffs = distCoeffs.rows + distCoeffs.cols - 1; - - Mat jacobian; - if( _jacobian.needed() ) - { - _jacobian.create(npoints*2, 3+3+2+2+ndistCoeffs, CV_64F); - jacobian = _jacobian.getMat(); - pdpdrot = &(dpdrot = cvMat(jacobian.colRange(0, 3))); - pdpdt = &(dpdt = cvMat(jacobian.colRange(3, 6))); - pdpdf = &(dpdf = cvMat(jacobian.colRange(6, 8))); - pdpdc = &(dpdc = cvMat(jacobian.colRange(8, 10))); - pdpddist = &(dpddist = cvMat(jacobian.colRange(10, 10+ndistCoeffs))); - } - - cvProjectPoints2( &c_objectPoints, &c_rvec, &c_tvec, &c_cameraMatrix, &c_distCoeffs, - &c_imagePoints, pdpdrot, pdpdt, pdpdf, pdpdc, pdpddist, aspectRatio ); -} - -cv::Mat cv::initCameraMatrix2D( InputArrayOfArrays objectPoints, - InputArrayOfArrays imagePoints, - Size imageSize, double aspectRatio ) -{ - CV_INSTRUMENT_REGION(); - - Mat objPt, imgPt, npoints, cameraMatrix(3, 3, CV_64F); - collectCalibrationData( objectPoints, imagePoints, noArray(), - objPt, imgPt, 0, npoints ); - CvMat _objPt = cvMat(objPt), _imgPt = cvMat(imgPt), _npoints = cvMat(npoints), _cameraMatrix = cvMat(cameraMatrix); - cvInitIntrinsicParams2D( &_objPt, &_imgPt, &_npoints, - cvSize(imageSize), &_cameraMatrix, aspectRatio ); - return cameraMatrix; -} - - - -double cv::calibrateCamera( InputArrayOfArrays _objectPoints, - InputArrayOfArrays _imagePoints, - Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, - OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, int flags, TermCriteria criteria ) +double calibrateCamera( InputArrayOfArrays _objectPoints, + InputArrayOfArrays _imagePoints, + Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, + OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, int flags, TermCriteria criteria ) { CV_INSTRUMENT_REGION(); @@ -3632,13 +2623,13 @@ double cv::calibrateCamera( InputArrayOfArrays _objectPoints, _rvecs, _tvecs, noArray(), noArray(), noArray(), flags, criteria); } -double cv::calibrateCamera(InputArrayOfArrays _objectPoints, - InputArrayOfArrays _imagePoints, - Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, - OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, - OutputArray stdDeviationsIntrinsics, - OutputArray stdDeviationsExtrinsics, - OutputArray _perViewErrors, int flags, TermCriteria criteria ) +double calibrateCamera(InputArrayOfArrays _objectPoints, + InputArrayOfArrays _imagePoints, + Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, + OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, + OutputArray stdDeviationsIntrinsics, + OutputArray stdDeviationsExtrinsics, + OutputArray _perViewErrors, int flags, TermCriteria criteria ) { CV_INSTRUMENT_REGION(); @@ -3647,13 +2638,13 @@ double cv::calibrateCamera(InputArrayOfArrays _objectPoints, noArray(), _perViewErrors, flags, criteria); } -double cv::calibrateCameraRO(InputArrayOfArrays _objectPoints, - InputArrayOfArrays _imagePoints, - Size imageSize, int iFixedPoint, InputOutputArray _cameraMatrix, - InputOutputArray _distCoeffs, - OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, - OutputArray newObjPoints, - int flags, TermCriteria criteria) +double calibrateCameraRO(InputArrayOfArrays _objectPoints, + InputArrayOfArrays _imagePoints, + Size imageSize, int iFixedPoint, InputOutputArray _cameraMatrix, + InputOutputArray _distCoeffs, + OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, + OutputArray newObjPoints, + int flags, TermCriteria criteria) { CV_INSTRUMENT_REGION(); @@ -3662,16 +2653,16 @@ double cv::calibrateCameraRO(InputArrayOfArrays _objectPoints, noArray(), noArray(), flags, criteria); } -double cv::calibrateCameraRO(InputArrayOfArrays _objectPoints, - InputArrayOfArrays _imagePoints, - Size imageSize, int iFixedPoint, InputOutputArray _cameraMatrix, - InputOutputArray _distCoeffs, - OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, - OutputArray newObjPoints, - OutputArray stdDeviationsIntrinsics, - OutputArray stdDeviationsExtrinsics, - OutputArray stdDeviationsObjPoints, - OutputArray _perViewErrors, int flags, TermCriteria criteria ) +double calibrateCameraRO(InputArrayOfArrays _objectPoints, + InputArrayOfArrays _imagePoints, + Size imageSize, int iFixedPoint, InputOutputArray _cameraMatrix, + InputOutputArray _distCoeffs, + OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, + OutputArray newObjPoints, + OutputArray stdDeviationsIntrinsics, + OutputArray stdDeviationsExtrinsics, + OutputArray stdDeviationsObjPoints, + OutputArray _perViewErrors, int flags, TermCriteria criteria ) { CV_INSTRUMENT_REGION(); @@ -3740,9 +2731,9 @@ double cv::calibrateCameraRO(InputArrayOfArrays _objectPoints, if( stddev_any_needed ) { if( releaseObject ) - stdDeviationsM.create(nimages*6 + CV_CALIB_NINTRINSIC + np * 3, 1, CV_64F); + stdDeviationsM.create(nimages*6 + CALIB_NINTRINSIC + np * 3, 1, CV_64F); else - stdDeviationsM.create(nimages*6 + CV_CALIB_NINTRINSIC, 1, CV_64F); + stdDeviationsM.create(nimages*6 + CALIB_NINTRINSIC, 1, CV_64F); } if( errors_needed ) @@ -3770,10 +2761,10 @@ double cv::calibrateCameraRO(InputArrayOfArrays _objectPoints, if( stddev_needed ) { - stdDeviationsIntrinsics.create(CV_CALIB_NINTRINSIC, 1, CV_64F); + stdDeviationsIntrinsics.create(CALIB_NINTRINSIC, 1, CV_64F); Mat stdDeviationsIntrinsicsMat = stdDeviationsIntrinsics.getMat(); std::memcpy(stdDeviationsIntrinsicsMat.ptr(), stdDeviationsM.ptr(), - CV_CALIB_NINTRINSIC*sizeof(double)); + CALIB_NINTRINSIC*sizeof(double)); } if ( stddev_ext_needed ) @@ -3781,7 +2772,7 @@ double cv::calibrateCameraRO(InputArrayOfArrays _objectPoints, stdDeviationsExtrinsics.create(nimages*6, 1, CV_64F); Mat stdDeviationsExtrinsicsMat = stdDeviationsExtrinsics.getMat(); std::memcpy(stdDeviationsExtrinsicsMat.ptr(), - stdDeviationsM.ptr() + CV_CALIB_NINTRINSIC*sizeof(double), + stdDeviationsM.ptr() + CALIB_NINTRINSIC*sizeof(double), nimages*6*sizeof(double)); } @@ -3790,7 +2781,7 @@ double cv::calibrateCameraRO(InputArrayOfArrays _objectPoints, stdDeviationsObjPoints.create( np * 3, 1, CV_64F ); Mat stdDeviationsObjPointsMat = stdDeviationsObjPoints.getMat(); std::memcpy( stdDeviationsObjPointsMat.ptr(), stdDeviationsM.ptr() - + ( CV_CALIB_NINTRINSIC + nimages * 6 ) * sizeof( double ), + + ( CALIB_NINTRINSIC + nimages * 6 ) * sizeof( double ), np * 3 * sizeof( double ) ); } @@ -3818,10 +2809,10 @@ double cv::calibrateCameraRO(InputArrayOfArrays _objectPoints, } -void cv::calibrationMatrixValues( InputArray _cameraMatrix, Size imageSize, - double apertureWidth, double apertureHeight, - double& fovx, double& fovy, double& focalLength, - Point2d& principalPoint, double& aspectRatio ) +void calibrationMatrixValues( InputArray _cameraMatrix, Size imageSize, + double apertureWidth, double apertureHeight, + double& fovx, double& fovy, double& focalLength, + Point2d& principalPoint, double& aspectRatio ) { CV_INSTRUMENT_REGION(); @@ -3858,14 +2849,14 @@ void cv::calibrationMatrixValues( InputArray _cameraMatrix, Size imageSize, principalPoint = Point2d(K(0, 2) / mx, K(1, 2) / my); } -double cv::stereoCalibrate( InputArrayOfArrays _objectPoints, - InputArrayOfArrays _imagePoints1, - InputArrayOfArrays _imagePoints2, - InputOutputArray _cameraMatrix1, InputOutputArray _distCoeffs1, - InputOutputArray _cameraMatrix2, InputOutputArray _distCoeffs2, - Size imageSize, OutputArray _Rmat, OutputArray _Tmat, - OutputArray _Emat, OutputArray _Fmat, int flags, - TermCriteria criteria) +double stereoCalibrate( InputArrayOfArrays _objectPoints, + InputArrayOfArrays _imagePoints1, + InputArrayOfArrays _imagePoints2, + InputOutputArray _cameraMatrix1, InputOutputArray _distCoeffs1, + InputOutputArray _cameraMatrix2, InputOutputArray _distCoeffs2, + Size imageSize, OutputArray _Rmat, OutputArray _Tmat, + OutputArray _Emat, OutputArray _Fmat, int flags, + TermCriteria criteria) { if (flags & CALIB_USE_EXTRINSIC_GUESS) CV_Error(Error::StsBadFlag, "stereoCalibrate does not support CALIB_USE_EXTRINSIC_GUESS."); @@ -3879,15 +2870,15 @@ double cv::stereoCalibrate( InputArrayOfArrays _objectPoints, return ret; } -double cv::stereoCalibrate( InputArrayOfArrays _objectPoints, - InputArrayOfArrays _imagePoints1, - InputArrayOfArrays _imagePoints2, - InputOutputArray _cameraMatrix1, InputOutputArray _distCoeffs1, - InputOutputArray _cameraMatrix2, InputOutputArray _distCoeffs2, - Size imageSize, InputOutputArray _Rmat, InputOutputArray _Tmat, - OutputArray _Emat, OutputArray _Fmat, - OutputArray _perViewErrors, int flags , - TermCriteria criteria) +double stereoCalibrate( InputArrayOfArrays _objectPoints, + InputArrayOfArrays _imagePoints1, + InputArrayOfArrays _imagePoints2, + InputOutputArray _cameraMatrix1, InputOutputArray _distCoeffs1, + InputOutputArray _cameraMatrix2, InputOutputArray _distCoeffs2, + Size imageSize, InputOutputArray _Rmat, InputOutputArray _Tmat, + OutputArray _Emat, OutputArray _Fmat, + OutputArray _perViewErrors, int flags , + TermCriteria criteria) { int rtype = CV_64F; Mat cameraMatrix1 = _cameraMatrix1.getMat(); @@ -3960,297 +2951,6 @@ double cv::stereoCalibrate( InputArrayOfArrays _objectPoints, return err; } - -void cv::stereoRectify( InputArray _cameraMatrix1, InputArray _distCoeffs1, - InputArray _cameraMatrix2, InputArray _distCoeffs2, - Size imageSize, InputArray _Rmat, InputArray _Tmat, - OutputArray _Rmat1, OutputArray _Rmat2, - OutputArray _Pmat1, OutputArray _Pmat2, - OutputArray _Qmat, int flags, - double alpha, Size newImageSize, - Rect* validPixROI1, Rect* validPixROI2 ) -{ - Mat cameraMatrix1 = _cameraMatrix1.getMat(), cameraMatrix2 = _cameraMatrix2.getMat(); - Mat distCoeffs1 = _distCoeffs1.getMat(), distCoeffs2 = _distCoeffs2.getMat(); - Mat Rmat = _Rmat.getMat(), Tmat = _Tmat.getMat(); - CvMat c_cameraMatrix1 = cvMat(cameraMatrix1); - CvMat c_cameraMatrix2 = cvMat(cameraMatrix2); - CvMat c_distCoeffs1 = cvMat(distCoeffs1); - CvMat c_distCoeffs2 = cvMat(distCoeffs2); - CvMat c_R = cvMat(Rmat), c_T = cvMat(Tmat); - - int rtype = CV_64F; - _Rmat1.create(3, 3, rtype); - _Rmat2.create(3, 3, rtype); - _Pmat1.create(3, 4, rtype); - _Pmat2.create(3, 4, rtype); - Mat R1 = _Rmat1.getMat(), R2 = _Rmat2.getMat(), P1 = _Pmat1.getMat(), P2 = _Pmat2.getMat(), Q; - CvMat c_R1 = cvMat(R1), c_R2 = cvMat(R2), c_P1 = cvMat(P1), c_P2 = cvMat(P2); - CvMat c_Q, *p_Q = 0; - - if( _Qmat.needed() ) - { - _Qmat.create(4, 4, rtype); - p_Q = &(c_Q = cvMat(Q = _Qmat.getMat())); - } - - CvMat *p_distCoeffs1 = distCoeffs1.empty() ? NULL : &c_distCoeffs1; - CvMat *p_distCoeffs2 = distCoeffs2.empty() ? NULL : &c_distCoeffs2; - cvStereoRectify( &c_cameraMatrix1, &c_cameraMatrix2, p_distCoeffs1, p_distCoeffs2, - cvSize(imageSize), &c_R, &c_T, &c_R1, &c_R2, &c_P1, &c_P2, p_Q, flags, alpha, - cvSize(newImageSize), (CvRect*)validPixROI1, (CvRect*)validPixROI2); } -bool cv::stereoRectifyUncalibrated( InputArray _points1, InputArray _points2, - InputArray _Fmat, Size imgSize, - OutputArray _Hmat1, OutputArray _Hmat2, double threshold ) -{ - CV_INSTRUMENT_REGION(); - - int rtype = CV_64F; - _Hmat1.create(3, 3, rtype); - _Hmat2.create(3, 3, rtype); - Mat F = _Fmat.getMat(); - Mat points1 = _points1.getMat(), points2 = _points2.getMat(); - CvMat c_pt1 = cvMat(points1), c_pt2 = cvMat(points2); - Mat H1 = _Hmat1.getMat(), H2 = _Hmat2.getMat(); - CvMat c_F, *p_F=0, c_H1 = cvMat(H1), c_H2 = cvMat(H2); - if( F.size() == Size(3, 3) ) - p_F = &(c_F = cvMat(F)); - return cvStereoRectifyUncalibrated(&c_pt1, &c_pt2, p_F, cvSize(imgSize), &c_H1, &c_H2, threshold) > 0; -} - -cv::Mat cv::getOptimalNewCameraMatrix( InputArray _cameraMatrix, - InputArray _distCoeffs, - Size imgSize, double alpha, Size newImgSize, - Rect* validPixROI, bool centerPrincipalPoint ) -{ - CV_INSTRUMENT_REGION(); - - Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat(); - CvMat c_cameraMatrix = cvMat(cameraMatrix), c_distCoeffs = cvMat(distCoeffs); - - Mat newCameraMatrix(3, 3, CV_MAT_TYPE(c_cameraMatrix.type)); - CvMat c_newCameraMatrix = cvMat(newCameraMatrix); - - cvGetOptimalNewCameraMatrix(&c_cameraMatrix, &c_distCoeffs, cvSize(imgSize), - alpha, &c_newCameraMatrix, - cvSize(newImgSize), (CvRect*)validPixROI, (int)centerPrincipalPoint); - return newCameraMatrix; -} - - -cv::Vec3d cv::RQDecomp3x3( InputArray _Mmat, - OutputArray _Rmat, - OutputArray _Qmat, - OutputArray _Qx, - OutputArray _Qy, - OutputArray _Qz ) -{ - CV_INSTRUMENT_REGION(); - - Mat M = _Mmat.getMat(); - _Rmat.create(3, 3, M.type()); - _Qmat.create(3, 3, M.type()); - Mat Rmat = _Rmat.getMat(); - Mat Qmat = _Qmat.getMat(); - Vec3d eulerAngles; - - CvMat matM = cvMat(M), matR = cvMat(Rmat), matQ = cvMat(Qmat); -#define CV_RQDecomp3x3_PARAM(name) \ - Mat name; \ - CvMat c_ ## name, *p ## name = NULL; \ - if( _ ## name.needed() ) \ - { \ - _ ## name.create(3, 3, M.type()); \ - name = _ ## name.getMat(); \ - c_ ## name = cvMat(name); p ## name = &c_ ## name; \ - } - - CV_RQDecomp3x3_PARAM(Qx); - CV_RQDecomp3x3_PARAM(Qy); - CV_RQDecomp3x3_PARAM(Qz); -#undef CV_RQDecomp3x3_PARAM - cvRQDecomp3x3(&matM, &matR, &matQ, pQx, pQy, pQz, (CvPoint3D64f*)&eulerAngles[0]); - return eulerAngles; -} - - -void cv::decomposeProjectionMatrix( InputArray _projMatrix, OutputArray _cameraMatrix, - OutputArray _rotMatrix, OutputArray _transVect, - OutputArray _rotMatrixX, OutputArray _rotMatrixY, - OutputArray _rotMatrixZ, OutputArray _eulerAngles ) -{ - CV_INSTRUMENT_REGION(); - - Mat projMatrix = _projMatrix.getMat(); - int type = projMatrix.type(); - _cameraMatrix.create(3, 3, type); - _rotMatrix.create(3, 3, type); - _transVect.create(4, 1, type); - Mat cameraMatrix = _cameraMatrix.getMat(); - Mat rotMatrix = _rotMatrix.getMat(); - Mat transVect = _transVect.getMat(); - CvMat c_projMatrix = cvMat(projMatrix), c_cameraMatrix = cvMat(cameraMatrix); - CvMat c_rotMatrix = cvMat(rotMatrix), c_transVect = cvMat(transVect); - CvPoint3D64f *p_eulerAngles = 0; - -#define CV_decomposeProjectionMatrix_PARAM(name) \ - Mat name; \ - CvMat c_ ## name, *p_ ## name = NULL; \ - if( _ ## name.needed() ) \ - { \ - _ ## name.create(3, 3, type); \ - name = _ ## name.getMat(); \ - c_ ## name = cvMat(name); p_ ## name = &c_ ## name; \ - } - - CV_decomposeProjectionMatrix_PARAM(rotMatrixX); - CV_decomposeProjectionMatrix_PARAM(rotMatrixY); - CV_decomposeProjectionMatrix_PARAM(rotMatrixZ); -#undef CV_decomposeProjectionMatrix_PARAM - - if( _eulerAngles.needed() ) - { - _eulerAngles.create(3, 1, CV_64F, -1, true); - p_eulerAngles = _eulerAngles.getMat().ptr(); - } - - cvDecomposeProjectionMatrix(&c_projMatrix, &c_cameraMatrix, &c_rotMatrix, - &c_transVect, p_rotMatrixX, p_rotMatrixY, - p_rotMatrixZ, p_eulerAngles); -} - - -namespace cv -{ - -static void adjust3rdMatrix(InputArrayOfArrays _imgpt1_0, - InputArrayOfArrays _imgpt3_0, - const Mat& cameraMatrix1, const Mat& distCoeffs1, - const Mat& cameraMatrix3, const Mat& distCoeffs3, - const Mat& R1, const Mat& R3, const Mat& P1, Mat& P3 ) -{ - size_t n1 = _imgpt1_0.total(), n3 = _imgpt3_0.total(); - std::vector imgpt1, imgpt3; - - for( int i = 0; i < (int)std::min(n1, n3); i++ ) - { - Mat pt1 = _imgpt1_0.getMat(i), pt3 = _imgpt3_0.getMat(i); - int ni1 = pt1.checkVector(2, CV_32F), ni3 = pt3.checkVector(2, CV_32F); - CV_Assert( ni1 > 0 && ni1 == ni3 ); - const Point2f* pt1data = pt1.ptr(); - const Point2f* pt3data = pt3.ptr(); - std::copy(pt1data, pt1data + ni1, std::back_inserter(imgpt1)); - std::copy(pt3data, pt3data + ni3, std::back_inserter(imgpt3)); - } - - undistortPoints(imgpt1, imgpt1, cameraMatrix1, distCoeffs1, R1, P1); - undistortPoints(imgpt3, imgpt3, cameraMatrix3, distCoeffs3, R3, P3); - - double y1_ = 0, y2_ = 0, y1y1_ = 0, y1y2_ = 0; - size_t n = imgpt1.size(); - CV_DbgAssert(n > 0); - - for( size_t i = 0; i < n; i++ ) - { - double y1 = imgpt3[i].y, y2 = imgpt1[i].y; - - y1_ += y1; y2_ += y2; - y1y1_ += y1*y1; y1y2_ += y1*y2; - } - - y1_ /= n; - y2_ /= n; - y1y1_ /= n; - y1y2_ /= n; - - double a = (y1y2_ - y1_*y2_)/(y1y1_ - y1_*y1_); - double b = y2_ - a*y1_; - - P3.at(0,0) *= a; - P3.at(1,1) *= a; - P3.at(0,2) = P3.at(0,2)*a; - P3.at(1,2) = P3.at(1,2)*a + b; - P3.at(0,3) *= a; - P3.at(1,3) *= a; -} - -} - -float cv::rectify3Collinear( InputArray _cameraMatrix1, InputArray _distCoeffs1, - InputArray _cameraMatrix2, InputArray _distCoeffs2, - InputArray _cameraMatrix3, InputArray _distCoeffs3, - InputArrayOfArrays _imgpt1, - InputArrayOfArrays _imgpt3, - Size imageSize, InputArray _Rmat12, InputArray _Tmat12, - InputArray _Rmat13, InputArray _Tmat13, - OutputArray _Rmat1, OutputArray _Rmat2, OutputArray _Rmat3, - OutputArray _Pmat1, OutputArray _Pmat2, OutputArray _Pmat3, - OutputArray _Qmat, - double alpha, Size newImgSize, - Rect* roi1, Rect* roi2, int flags ) -{ - // first, rectify the 1-2 stereo pair - stereoRectify( _cameraMatrix1, _distCoeffs1, _cameraMatrix2, _distCoeffs2, - imageSize, _Rmat12, _Tmat12, _Rmat1, _Rmat2, _Pmat1, _Pmat2, _Qmat, - flags, alpha, newImgSize, roi1, roi2 ); - - Mat R12 = _Rmat12.getMat(), R13 = _Rmat13.getMat(), T12 = _Tmat12.getMat(), T13 = _Tmat13.getMat(); - - _Rmat3.create(3, 3, CV_64F); - _Pmat3.create(3, 4, CV_64F); - - Mat P1 = _Pmat1.getMat(), P2 = _Pmat2.getMat(); - Mat R3 = _Rmat3.getMat(), P3 = _Pmat3.getMat(); - - // recompute rectification transforms for cameras 1 & 2. - Mat om, r_r, r_r13; - - if( R13.size() != Size(3,3) ) - Rodrigues(R13, r_r13); - else - R13.copyTo(r_r13); - - if( R12.size() == Size(3,3) ) - Rodrigues(R12, om); - else - R12.copyTo(om); - - om *= -0.5; - Rodrigues(om, r_r); // rotate cameras to same orientation by averaging - Mat_ t12 = r_r * T12; - - int idx = fabs(t12(0,0)) > fabs(t12(1,0)) ? 0 : 1; - double c = t12(idx,0), nt = norm(t12, CV_L2); - CV_Assert(fabs(nt) > 0); - Mat_ uu = Mat_::zeros(3,1); - uu(idx, 0) = c > 0 ? 1 : -1; - - // calculate global Z rotation - Mat_ ww = t12.cross(uu), wR; - double nw = norm(ww, CV_L2); - CV_Assert(fabs(nw) > 0); - ww *= acos(fabs(c)/nt)/nw; - Rodrigues(ww, wR); - - // now rotate camera 3 to make its optical axis parallel to cameras 1 and 2. - R3 = wR*r_r.t()*r_r13.t(); - Mat_ t13 = R3 * T13; - - P2.copyTo(P3); - Mat t = P3.col(3); - t13.copyTo(t); - P3.at(0,3) *= P3.at(0,0); - P3.at(1,3) *= P3.at(1,1); - - if( !_imgpt1.empty() && !_imgpt3.empty() ) - adjust3rdMatrix(_imgpt1, _imgpt3, _cameraMatrix1.getMat(), _distCoeffs1.getMat(), - _cameraMatrix3.getMat(), _distCoeffs3.getMat(), _Rmat1.getMat(), R3, P1, P3); - - return (float)((P3.at(idx,3)/P3.at(idx,idx))/ - (P2.at(idx,3)/P2.at(idx,idx))); -} - - /* End of file. */ diff --git a/modules/calib3d/src/calibration_handeye.cpp b/modules/calib/src/calibration_handeye.cpp similarity index 99% rename from modules/calib3d/src/calibration_handeye.cpp rename to modules/calib/src/calibration_handeye.cpp index 077de110f6..8e10f2a2ff 100644 --- a/modules/calib3d/src/calibration_handeye.cpp +++ b/modules/calib/src/calibration_handeye.cpp @@ -3,7 +3,6 @@ // of this distribution and at http://opencv.org/license.html. #include "precomp.hpp" -#include "opencv2/calib3d.hpp" namespace cv { @@ -971,4 +970,5 @@ void calibrateRobotWorldHandEye(InputArrayOfArrays R_world2cam, InputArrayOfArra Mat(cRg).copyTo(R_gripper2cam); Mat(ctg).copyTo(t_gripper2cam); } + } diff --git a/modules/calib3d/src/checkchessboard.cpp b/modules/calib/src/checkchessboard.cpp similarity index 92% rename from modules/calib3d/src/checkchessboard.cpp rename to modules/calib/src/checkchessboard.cpp index 904604562d..987790eedb 100644 --- a/modules/calib3d/src/checkchessboard.cpp +++ b/modules/calib/src/checkchessboard.cpp @@ -40,13 +40,11 @@ //M*/ #include "precomp.hpp" -#include "opencv2/imgproc/imgproc_c.h" -#include "calib3d_c_api.h" - #include #include -using namespace cv; +namespace cv { + using namespace std; static void icvGetQuadrangleHypotheses(const std::vector > & contours, const std::vector< cv::Vec4i > & hierarchy, std::vector >& quads, int class_id) @@ -154,19 +152,7 @@ static bool checkQuads(vector > & quads, const cv::Size & size) return false; } -// does a fast check if a chessboard is in the input image. This is a workaround to -// a problem of cvFindChessboardCorners being slow on images with no chessboard -// - src: input image -// - size: chessboard size -// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called, -// 0 if there is no chessboard, -1 in case of error -int cvCheckChessboard(IplImage* src, CvSize size) -{ - cv::Mat img = cv::cvarrToMat(src); - return (int)cv::checkChessboard(img, size); -} - -bool cv::checkChessboard(InputArray _img, Size size) +bool checkChessboard(InputArray _img, Size size) { Mat img = _img.getMat(); CV_Assert(img.channels() == 1 && img.depth() == CV_8U); @@ -224,3 +210,5 @@ int checkChessboardBinary(const cv::Mat & img, const cv::Size & size) } return result; } + +} diff --git a/modules/calib3d/src/chessboard.cpp b/modules/calib/src/chessboard.cpp similarity index 99% rename from modules/calib3d/src/chessboard.cpp rename to modules/calib/src/chessboard.cpp index dbc47722cb..941489a792 100644 --- a/modules/calib3d/src/chessboard.cpp +++ b/modules/calib/src/chessboard.cpp @@ -1533,7 +1533,7 @@ bool Chessboard::Board::estimatePose(const cv::Size2f &real_size,cv::InputArray object_points.push_back(cv::Point3f(field_width*col-offset_x,field_height*row-offset_y,1.0)); } } - return cv::solvePnP(object_points,image_points,K,cv::Mat(),rvec,tvec);//,cv::SOLVEPNP_P3P); + return solvePnP(object_points,image_points,K,cv::Mat(),rvec,tvec);//,cv::SOLVEPNP_P3P); } float Chessboard::Board::getBlackAngle()const @@ -2238,7 +2238,7 @@ int Chessboard::Board::detectMarkers(cv::InputArray image) src[1] = *cell->top_right; src[2] = *cell->bottom_right; src[3] = *cell->bottom_left; - cv::Mat H = cv::findHomography(src,dst,cv::LMEDS); + cv::Mat H = findHomography(src,dst,LMEDS); cv::Mat field; cv::warpPerspective(image,field,H,cv::Size(DUMMY_FIELD_SIZE,DUMMY_FIELD_SIZE)); @@ -2254,7 +2254,7 @@ int Chessboard::Board::detectMarkers(cv::InputArray image) src[1] = *cell2->top_right; src[2] = *cell2->bottom_right; src[3] = *cell2->bottom_left; - H = cv::findHomography(src,dst,cv::LMEDS); + H = findHomography(src,dst,LMEDS); cv::warpPerspective(image,field,H,cv::Size(DUMMY_FIELD_SIZE,DUMMY_FIELD_SIZE)); cv::bitwise_and(field,mask2,temp); double reference = cv::sum(temp)[0]/noise_size; @@ -3136,7 +3136,7 @@ cv::Mat Chessboard::Board::estimateHomography(cv::Rect rect,int field_size)const } if(dst.size() < 4) return cv::Mat(); - return cv::findHomography(src, dst,cv::LMEDS); + return findHomography(src, dst,LMEDS); } cv::Mat Chessboard::Board::estimateHomography(int field_size)const @@ -3162,7 +3162,7 @@ cv::Mat Chessboard::Board::estimateHomography(int field_size)const } if(dst.size() < 4) return cv::Mat(); - return cv::findHomography(src, dst); + return findHomography(src, dst); } bool Chessboard::Board::findNextPoint(cv::flann::Index &index,const cv::Mat &data, @@ -3837,12 +3837,12 @@ void Chessboard::detectImpl(InputArray image, std::vector& keypoints, detectImpl(image.getMat(),keypoints,mask.getMat()); } -} // end namespace details +}} // end namespace details // public API -bool findChessboardCornersSB(cv::InputArray image_, cv::Size pattern_size, - cv::OutputArray corners_, int flags, cv::OutputArray meta_) +bool cv::findChessboardCornersSB(InputArray image_, Size pattern_size, + OutputArray corners_, int flags, OutputArray meta_) { CV_INSTRUMENT_REGION(); int type = image_.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -3950,7 +3950,7 @@ bool findChessboardCornersSB(cv::InputArray image_, cv::Size pattern_size, } // public API -cv::Scalar estimateChessboardSharpness(InputArray image_, Size patternSize, InputArray corners_, +cv::Scalar cv::estimateChessboardSharpness(InputArray image_, Size patternSize, InputArray corners_, float rise_distance,bool vertical, cv::OutputArray sharpness) { CV_INSTRUMENT_REGION(); @@ -3975,6 +3975,3 @@ cv::Scalar estimateChessboardSharpness(InputArray image_, Size patternSize, Inpu details::Chessboard::Board board(patternSize,points); return board.calcEdgeSharpness(img,rise_distance,vertical,sharpness); } - - -} // namespace cv diff --git a/modules/calib3d/src/chessboard.hpp b/modules/calib/src/chessboard.hpp similarity index 100% rename from modules/calib3d/src/chessboard.hpp rename to modules/calib/src/chessboard.hpp diff --git a/modules/calib3d/src/circlesgrid.cpp b/modules/calib/src/circlesgrid.cpp similarity index 99% rename from modules/calib3d/src/circlesgrid.cpp rename to modules/calib/src/circlesgrid.cpp index 42e0e65c8c..d60069d1c1 100644 --- a/modules/calib3d/src/circlesgrid.cpp +++ b/modules/calib/src/circlesgrid.cpp @@ -44,7 +44,7 @@ #include "circlesgrid.hpp" #include - // Requires CMake flag: DEBUG_opencv_calib3d=ON + // Requires CMake flag: DEBUG_opencv_calib=ON //#define DEBUG_CIRCLES #ifdef DEBUG_CIRCLES @@ -57,7 +57,7 @@ # endif #endif -using namespace cv; +namespace cv { #ifdef DEBUG_CIRCLES void drawPoints(const std::vector &points, Mat &outImage, int radius = 2, Scalar color = Scalar::all(255), int thickness = -1) @@ -416,7 +416,9 @@ void CirclesGridClusterFinder::rectifyPatternPoints(const std::vector &patternPoints, const std::vector &rectifiedPatternPoints, std::vector ¢ers) +void CirclesGridClusterFinder::parsePatternPoints(const std::vector &patternPoints, + const std::vector &rectifiedPatternPoints, + std::vector ¢ers) { #ifndef HAVE_OPENCV_FLANN CV_UNUSED(patternPoints); @@ -1632,3 +1634,5 @@ size_t CirclesGridFinder::getFirstCorner(std::vector &largeCornerIndices, return cornerIdx; } + +} diff --git a/modules/calib3d/src/circlesgrid.hpp b/modules/calib/src/circlesgrid.hpp similarity index 60% rename from modules/calib3d/src/circlesgrid.hpp rename to modules/calib/src/circlesgrid.hpp index f058af7a43..ce8747e654 100644 --- a/modules/calib3d/src/circlesgrid.hpp +++ b/modules/calib/src/circlesgrid.hpp @@ -49,32 +49,34 @@ #include #include +namespace cv { + class CirclesGridClusterFinder { CirclesGridClusterFinder& operator=(const CirclesGridClusterFinder&); CirclesGridClusterFinder(const CirclesGridClusterFinder&); public: - CirclesGridClusterFinder(const cv::CirclesGridFinderParameters ¶meters) + CirclesGridClusterFinder(const CirclesGridFinderParameters ¶meters) { - isAsymmetricGrid = parameters.gridType == cv::CirclesGridFinderParameters::ASYMMETRIC_GRID; + isAsymmetricGrid = parameters.gridType == CirclesGridFinderParameters::ASYMMETRIC_GRID; squareSize = parameters.squareSize; maxRectifiedDistance = parameters.maxRectifiedDistance; } - void findGrid(const std::vector &points, cv::Size patternSize, std::vector& centers); + void findGrid(const std::vector &points, Size patternSize, std::vector& centers); //cluster 2d points by geometric coordinates - void hierarchicalClustering(const std::vector &points, const cv::Size &patternSize, std::vector &patternPoints); + void hierarchicalClustering(const std::vector &points, const Size &patternSize, std::vector &patternPoints); private: - void findCorners(const std::vector &hull2f, std::vector &corners); - void findOutsideCorners(const std::vector &corners, std::vector &outsideCorners); - void getSortedCorners(const std::vector &hull2f, const std::vector &patternPoints, const std::vector &corners, const std::vector &outsideCorners, std::vector &sortedCorners); - void rectifyPatternPoints(const std::vector &patternPoints, const std::vector &sortedCorners, std::vector &rectifiedPatternPoints); - void parsePatternPoints(const std::vector &patternPoints, const std::vector &rectifiedPatternPoints, std::vector ¢ers); + void findCorners(const std::vector &hull2f, std::vector &corners); + void findOutsideCorners(const std::vector &corners, std::vector &outsideCorners); + void getSortedCorners(const std::vector &hull2f, const std::vector &patternPoints, const std::vector &corners, const std::vector &outsideCorners, std::vector &sortedCorners); + void rectifyPatternPoints(const std::vector &patternPoints, const std::vector &sortedCorners, std::vector &rectifiedPatternPoints); + void parsePatternPoints(const std::vector &patternPoints, const std::vector &rectifiedPatternPoints, std::vector ¢ers); float squareSize, maxRectifiedDistance; bool isAsymmetricGrid; - cv::Size patternSize; + Size patternSize; }; class Graph @@ -96,7 +98,7 @@ public: size_t getVerticesCount() const; size_t getDegree(size_t id) const; const Neighbors& getNeighbors(size_t id) const; - void floydWarshall(cv::Mat &distanceMatrix, int infinity = -1) const; + void floydWarshall(Mat &distanceMatrix, int infinity = -1) const; private: Vertices vertices; }; @@ -120,38 +122,38 @@ struct Path class CirclesGridFinder { public: - CirclesGridFinder(cv::Size patternSize, const std::vector &testKeypoints, - const cv::CirclesGridFinderParameters ¶meters = cv::CirclesGridFinderParameters()); + CirclesGridFinder(Size patternSize, const std::vector &testKeypoints, + const CirclesGridFinderParameters ¶meters = CirclesGridFinderParameters()); bool findHoles(); - static cv::Mat rectifyGrid(cv::Size detectedGridSize, const std::vector& centers, const std::vector< - cv::Point2f> &keypoint, std::vector &warpedKeypoints); + static Mat rectifyGrid(Size detectedGridSize, const std::vector& centers, const std::vector< + Point2f> &keypoint, std::vector &warpedKeypoints); - void getHoles(std::vector &holes) const; - void getAsymmetricHoles(std::vector &holes) const; - cv::Size getDetectedGridSize() const; + void getHoles(std::vector &holes) const; + void getAsymmetricHoles(std::vector &holes) const; + Size getDetectedGridSize() const; - void drawBasis(const std::vector &basis, cv::Point2f origin, cv::Mat &drawImg) const; - void drawBasisGraphs(const std::vector &basisGraphs, cv::Mat &drawImg, bool drawEdges = true, + void drawBasis(const std::vector &basis, Point2f origin, Mat &drawImg) const; + void drawBasisGraphs(const std::vector &basisGraphs, Mat &drawImg, bool drawEdges = true, bool drawVertices = true) const; - void drawHoles(const cv::Mat &srcImage, cv::Mat &drawImage) const; + void drawHoles(const Mat &srcImage, Mat &drawImage) const; private: - void computeRNG(Graph &rng, std::vector &vectors, cv::Mat *drawImage = 0) const; - void rng2gridGraph(Graph &rng, std::vector &vectors) const; + void computeRNG(Graph &rng, std::vector &vectors, Mat *drawImage = 0) const; + void rng2gridGraph(Graph &rng, std::vector &vectors) const; void eraseUsedGraph(std::vector &basisGraphs) const; - void filterOutliersByDensity(const std::vector &samples, std::vector &filteredSamples); - void findBasis(const std::vector &samples, std::vector &basis, + void filterOutliersByDensity(const std::vector &samples, std::vector &filteredSamples); + void findBasis(const std::vector &samples, std::vector &basis, std::vector &basisGraphs); - void findMCS(const std::vector &basis, std::vector &basisGraphs); + void findMCS(const std::vector &basis, std::vector &basisGraphs); size_t findLongestPath(std::vector &basisGraphs, Path &bestPath); float computeGraphConfidence(const std::vector &basisGraphs, bool addRow, const std::vector &points, const std::vector &seeds); - void addHolesByGraph(const std::vector &basisGraphs, bool addRow, cv::Point2f basisVec); + void addHolesByGraph(const std::vector &basisGraphs, bool addRow, Point2f basisVec); - size_t findNearestKeypoint(cv::Point2f pt) const; - void addPoint(cv::Point2f pt, std::vector &points); - void findCandidateLine(std::vector &line, size_t seedLineIdx, bool addRow, cv::Point2f basisVec, std::vector< + size_t findNearestKeypoint(Point2f pt) const; + void addPoint(Point2f pt, std::vector &points); + void findCandidateLine(std::vector &line, size_t seedLineIdx, bool addRow, Point2f basisVec, std::vector< size_t> &seeds); - void findCandidateHoles(std::vector &above, std::vector &below, bool addRow, cv::Point2f basisVec, + void findCandidateHoles(std::vector &above, std::vector &below, bool addRow, Point2f basisVec, std::vector &aboveSeeds, std::vector &belowSeeds); static bool areCentersNew(const std::vector &newCenters, const std::vector > &holes); bool isDetectionCorrect(); @@ -162,33 +164,35 @@ private: struct Segment { - cv::Point2f s; - cv::Point2f e; - Segment(cv::Point2f _s, cv::Point2f _e); + Point2f s; + Point2f e; + Segment(Point2f _s, Point2f _e); }; //if endpoint is on a segment then function return false static bool areSegmentsIntersecting(Segment seg1, Segment seg2); static bool doesIntersectionExist(const std::vector &corner, const std::vector > &segments); void getCornerSegments(const std::vector > &points, std::vector > &segments, - std::vector &cornerIndices, std::vector &firstSteps, - std::vector &secondSteps) const; - size_t getFirstCorner(std::vector &largeCornerIndices, std::vector &smallCornerIndices, - std::vector &firstSteps, std::vector &secondSteps) const; - static double getDirection(cv::Point2f p1, cv::Point2f p2, cv::Point2f p3); + std::vector &cornerIndices, std::vector &firstSteps, + std::vector &secondSteps) const; + size_t getFirstCorner(std::vector &largeCornerIndices, std::vector &smallCornerIndices, + std::vector &firstSteps, std::vector &secondSteps) const; + static double getDirection(Point2f p1, Point2f p2, Point2f p3); - std::vector keypoints; + std::vector keypoints; std::vector > holes; std::vector > holes2; std::vector > *largeHoles; std::vector > *smallHoles; - const cv::Size_ patternSize; - cv::CirclesGridFinderParameters parameters; + const Size_ patternSize; + CirclesGridFinderParameters parameters; CirclesGridFinder& operator=(const CirclesGridFinder&); CirclesGridFinder(const CirclesGridFinder&); }; +} + #endif /* CIRCLESGRID_HPP_ */ diff --git a/modules/calib/src/distortion_model.hpp b/modules/calib/src/distortion_model.hpp new file mode 100644 index 0000000000..f84cbc6597 --- /dev/null +++ b/modules/calib/src/distortion_model.hpp @@ -0,0 +1,123 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef OPENCV_IMGPROC_DETAIL_DISTORTION_MODEL_HPP +#define OPENCV_IMGPROC_DETAIL_DISTORTION_MODEL_HPP + +//! @cond IGNORED + +namespace cv { +/** +Computes the matrix for the projection onto a tilted image sensor +\param tauX angular parameter rotation around x-axis +\param tauY angular parameter rotation around y-axis +\param matTilt if not NULL returns the matrix +\f[ +\vecthreethree{R_{33}(\tau_x, \tau_y)}{0}{-R_{13}((\tau_x, \tau_y)} +{0}{R_{33}(\tau_x, \tau_y)}{-R_{23}(\tau_x, \tau_y)} +{0}{0}{1} R(\tau_x, \tau_y) +\f] +where +\f[ +R(\tau_x, \tau_y) = +\vecthreethree{\cos(\tau_y)}{0}{-\sin(\tau_y)}{0}{1}{0}{\sin(\tau_y)}{0}{\cos(\tau_y)} +\vecthreethree{1}{0}{0}{0}{\cos(\tau_x)}{\sin(\tau_x)}{0}{-\sin(\tau_x)}{\cos(\tau_x)} = +\vecthreethree{\cos(\tau_y)}{\sin(\tau_y)\sin(\tau_x)}{-\sin(\tau_y)\cos(\tau_x)} +{0}{\cos(\tau_x)}{\sin(\tau_x)} +{\sin(\tau_y)}{-\cos(\tau_y)\sin(\tau_x)}{\cos(\tau_y)\cos(\tau_x)}. +\f] +\param dMatTiltdTauX if not NULL it returns the derivative of matTilt with +respect to \f$\tau_x\f$. +\param dMatTiltdTauY if not NULL it returns the derivative of matTilt with +respect to \f$\tau_y\f$. +\param invMatTilt if not NULL it returns the inverse of matTilt +**/ +template +void computeTiltProjectionMatrix(FLOAT tauX, + FLOAT tauY, + Matx* matTilt = 0, + Matx* dMatTiltdTauX = 0, + Matx* dMatTiltdTauY = 0, + Matx* invMatTilt = 0) +{ + FLOAT cTauX = cos(tauX); + FLOAT sTauX = sin(tauX); + FLOAT cTauY = cos(tauY); + FLOAT sTauY = sin(tauY); + Matx matRotX = Matx(1,0,0,0,cTauX,sTauX,0,-sTauX,cTauX); + Matx matRotY = Matx(cTauY,0,-sTauY,0,1,0,sTauY,0,cTauY); + Matx matRotXY = matRotY * matRotX; + Matx matProjZ = Matx(matRotXY(2,2),0,-matRotXY(0,2),0,matRotXY(2,2),-matRotXY(1,2),0,0,1); + if (matTilt) + { + // Matrix for trapezoidal distortion of tilted image sensor + *matTilt = matProjZ * matRotXY; + } + if (dMatTiltdTauX) + { + // Derivative with respect to tauX + Matx dMatRotXYdTauX = matRotY * Matx(0,0,0,0,-sTauX,cTauX,0,-cTauX,-sTauX); + Matx dMatProjZdTauX = Matx(dMatRotXYdTauX(2,2),0,-dMatRotXYdTauX(0,2), + 0,dMatRotXYdTauX(2,2),-dMatRotXYdTauX(1,2),0,0,0); + *dMatTiltdTauX = (matProjZ * dMatRotXYdTauX) + (dMatProjZdTauX * matRotXY); + } + if (dMatTiltdTauY) + { + // Derivative with respect to tauY + Matx dMatRotXYdTauY = Matx(-sTauY,0,-cTauY,0,0,0,cTauY,0,-sTauY) * matRotX; + Matx dMatProjZdTauY = Matx(dMatRotXYdTauY(2,2),0,-dMatRotXYdTauY(0,2), + 0,dMatRotXYdTauY(2,2),-dMatRotXYdTauY(1,2),0,0,0); + *dMatTiltdTauY = (matProjZ * dMatRotXYdTauY) + (dMatProjZdTauY * matRotXY); + } + if (invMatTilt) + { + FLOAT inv = 1./matRotXY(2,2); + Matx invMatProjZ = Matx(inv,0,inv*matRotXY(0,2),0,inv,inv*matRotXY(1,2),0,0,1); + *invMatTilt = matRotXY.t()*invMatProjZ; + } +} +} // namespace detail, cv + + +//! @endcond + +#endif // OPENCV_IMGPROC_DETAIL_DISTORTION_MODEL_HPP diff --git a/modules/calib3d/src/fisheye.cpp b/modules/calib/src/fisheye.cpp similarity index 92% rename from modules/calib3d/src/fisheye.cpp rename to modules/calib/src/fisheye.cpp index 2325b00598..5874b7faa7 100644 --- a/modules/calib3d/src/fisheye.cpp +++ b/modules/calib/src/fisheye.cpp @@ -44,17 +44,19 @@ #include "fisheye.hpp" #include -namespace cv { namespace -{ - struct JacobianRow - { - Vec2d df, dc; - Vec4d dk; - Vec3d dom, dT; - double dalpha; - }; +namespace cv { +namespace { + +struct JacobianRow +{ + Vec2d df, dc; + Vec4d dk; + Vec3d dom, dT; + double dalpha; +}; + +void subMatrix(const Mat& src, Mat& dst, const std::vector& cols, const std::vector& rows); - void subMatrix(const Mat& src, Mat& dst, const std::vector& cols, const std::vector& rows); }} ////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -87,7 +89,7 @@ void cv::fisheye::projectPoints(InputArray objectPoints, OutputArray imagePoints CV_Assert(_K.size() == Size(3,3) && (_K.type() == CV_32F || _K.type() == CV_64F) && _D.type() == _K.type() && _D.total() == 4); - cv::Vec2d f, c; + Vec2d f, c; if (_K.depth() == CV_32F) { @@ -265,7 +267,7 @@ void cv::fisheye::distortPoints(InputArray undistorted, OutputArray distorted, I CV_Assert(K.size() == Size(3,3) && (K.type() == CV_32F || K.type() == CV_64F) && D.total() == 4); - cv::Vec2d f, c; + Vec2d f, c; if (K.depth() == CV_32F) { Matx33f camMat = K.getMat(); @@ -330,7 +332,7 @@ void cv::fisheye::undistortPoints( InputArray distorted, OutputArray undistorted CV_Assert(R.empty() || R.size() == Size(3, 3) || R.total() * R.channels() == 3); CV_Assert(D.total() == 4 && K.size() == Size(3, 3) && (K.depth() == CV_32F || K.depth() == CV_64F)); - cv::Vec2d f, c; + Vec2d f, c; if (K.depth() == CV_32F) { Matx33f camMat = K.getMat(); @@ -346,10 +348,10 @@ void cv::fisheye::undistortPoints( InputArray distorted, OutputArray undistorted Vec4d k = D.depth() == CV_32F ? (Vec4d)*D.getMat().ptr(): *D.getMat().ptr(); - cv::Matx33d RR = cv::Matx33d::eye(); + Matx33d RR = Matx33d::eye(); if (!R.empty() && R.total() * R.channels() == 3) { - cv::Vec3d rvec; + Vec3d rvec; R.getMat().convertTo(rvec, CV_64F); RR = cv::Affine3d(rvec).rotation(); } @@ -358,16 +360,16 @@ void cv::fisheye::undistortPoints( InputArray distorted, OutputArray undistorted if(!P.empty()) { - cv::Matx33d PP; + Matx33d PP; P.getMat().colRange(0, 3).convertTo(PP, CV_64F); RR = PP * RR; } // start undistorting - const cv::Vec2f* srcf = distorted.getMat().ptr(); - const cv::Vec2d* srcd = distorted.getMat().ptr(); - cv::Vec2f* dstf = undistorted.getMat().ptr(); - cv::Vec2d* dstd = undistorted.getMat().ptr(); + const Vec2f* srcf = distorted.getMat().ptr(); + const Vec2d* srcd = distorted.getMat().ptr(); + Vec2f* dstf = undistorted.getMat().ptr(); + Vec2d* dstd = undistorted.getMat().ptr(); size_t n = distorted.total(); int sdepth = distorted.depth(); @@ -466,7 +468,7 @@ void cv::fisheye::initUndistortRectifyMap( InputArray K, InputArray D, InputArra CV_Assert(R.empty() || R.size() == Size(3, 3) || R.total() * R.channels() == 3); CV_Assert(P.empty() || P.size() == Size(3, 3) || P.size() == Size(4, 3)); - cv::Vec2d f, c; + Vec2d f, c; if (K.depth() == CV_32F) { Matx33f camMat = K.getMat(); @@ -484,21 +486,21 @@ void cv::fisheye::initUndistortRectifyMap( InputArray K, InputArray D, InputArra if (!D.empty()) k = D.depth() == CV_32F ? (Vec4d)*D.getMat().ptr(): *D.getMat().ptr(); - cv::Matx33d RR = cv::Matx33d::eye(); + Matx33d RR = Matx33d::eye(); if (!R.empty() && R.total() * R.channels() == 3) { - cv::Vec3d rvec; + Vec3d rvec; R.getMat().convertTo(rvec, CV_64F); RR = Affine3d(rvec).rotation(); } else if (!R.empty() && R.size() == Size(3, 3)) R.getMat().convertTo(RR, CV_64F); - cv::Matx33d PP = cv::Matx33d::eye(); + Matx33d PP = Matx33d::eye(); if (!P.empty()) P.getMat().colRange(0, 3).convertTo(PP, CV_64F); - cv::Matx33d iR = (PP * RR).inv(cv::DECOMP_SVD); + Matx33d iR = (PP * RR).inv(cv::DECOMP_SVD); for( int i = 0; i < size.height; ++i) { @@ -565,8 +567,8 @@ void cv::fisheye::undistortImage(InputArray distorted, OutputArray undistorted, Size size = !new_size.empty() ? new_size : distorted.size(); - cv::Mat map1, map2; - fisheye::initUndistortRectifyMap(K, D, cv::Matx33d::eye(), Knew, size, CV_16SC2, map1, map2 ); + Mat map1, map2; + fisheye::initUndistortRectifyMap(K, D, Matx33d::eye(), Knew, size, CV_16SC2, map1, map2 ); cv::remap(distorted, undistorted, map1, map2, INTER_LINEAR, BORDER_CONSTANT); } @@ -585,7 +587,7 @@ void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, Input int w = image_size.width, h = image_size.height; balance = std::min(std::max(balance, 0.0), 1.0); - cv::Mat points(1, 4, CV_64FC2); + Mat points(1, 4, CV_64FC2); Vec2d* pptr = points.ptr(); pptr[0] = Vec2d(w/2, 0); pptr[1] = Vec2d(w, h/2); @@ -594,7 +596,7 @@ void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, Input fisheye::undistortPoints(points, points, K, D, R); cv::Scalar center_mass = mean(points); - cv::Vec2d cn(center_mass.val); + Vec2d cn(center_mass.val); double aspect_ratio = (K.depth() == CV_32F) ? K.getMat().at(0,0)/K.getMat().at (1,1) : K.getMat().at(0,0)/K.getMat().at(1,1); @@ -624,7 +626,7 @@ void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, Input double f = balance * fmin + (1.0 - balance) * fmax; f *= fov_scale > 0 ? 1.0/fov_scale : 1.0; - cv::Vec2d new_f(f, f), new_c = -cn * f + Vec2d(w, h * aspect_ratio) * 0.5; + Vec2d new_f(f, f), new_c = -cn * f + Vec2d(w, h * aspect_ratio) * 0.5; // restore aspect ratio new_f[1] /= aspect_ratio; @@ -658,12 +660,12 @@ void cv::fisheye::stereoRectify( InputArray K1, InputArray D1, InputArray K2, In CV_Assert(_tvec.total() * _tvec.channels() == 3 && (_tvec.depth() == CV_32F || _tvec.depth() == CV_64F)); - cv::Mat aaa = _tvec.getMat().reshape(3, 1); + Mat aaa = _tvec.getMat().reshape(3, 1); Vec3d rvec; // Rodrigues vector if (_R.size() == Size(3, 3)) { - cv::Matx33d rmat; + Matx33d rmat; _R.getMat().convertTo(rmat, CV_64F); rvec = Affine3d(rmat).rvec(); } @@ -709,7 +711,7 @@ void cv::fisheye::stereoRectify( InputArray K1, InputArray D1, InputArray K2, In // Vertical focal length must be the same for both images to keep the epipolar constraint use fy for fx also. // For simplicity, set the principal points for both cameras to be the average // of the two principal points (either one of or both x- and y- coordinates) - if( flags & cv::CALIB_ZERO_DISPARITY ) + if( flags & CALIB_ZERO_DISPARITY ) cc_new[0] = cc_new[1] = (cc_new[0] + cc_new[1]) * 0.5; else cc_new[0].y = cc_new[1].y = (cc_new[0].y + cc_new[1].y)*0.5; @@ -839,8 +841,8 @@ double cv::fisheye::calibrate(InputArrayOfArrays objectPoints, InputArrayOfArray 0, finalParam.f[1], finalParam.c[1], 0, 0, 1); - if (K.needed()) cv::Mat(_K).convertTo(K, K.empty() ? CV_64FC1 : K.type()); - if (D.needed()) cv::Mat(finalParam.k).convertTo(D, D.empty() ? CV_64FC1 : D.type()); + if (K.needed()) Mat(_K).convertTo(K, K.empty() ? CV_64FC1 : K.type()); + if (D.needed()) Mat(finalParam.k).convertTo(D, D.empty() ? CV_64FC1 : D.type()); if (rvecs.isMatVector()) { int N = (int)objectPoints.total(); @@ -861,8 +863,8 @@ double cv::fisheye::calibrate(InputArrayOfArrays objectPoints, InputArrayOfArray } else { - if (rvecs.needed()) cv::Mat(omc).convertTo(rvecs, rvecs.empty() ? CV_64FC3 : rvecs.type()); - if (tvecs.needed()) cv::Mat(Tc).convertTo(tvecs, tvecs.empty() ? CV_64FC3 : tvecs.type()); + if (rvecs.needed()) Mat(omc).convertTo(rvecs, rvecs.empty() ? CV_64FC3 : rvecs.type()); + if (tvecs.needed()) Mat(Tc).convertTo(tvecs, tvecs.empty() ? CV_64FC3 : tvecs.type()); } return rms; @@ -964,23 +966,23 @@ double cv::fisheye::stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayO selectedParams.insert(selectedParams.end(), tmp.begin(), tmp.end()); //Init values for rotation and translation between two views - cv::Mat om_list(1, n_images, CV_64FC3), T_list(1, n_images, CV_64FC3); - cv::Mat om_ref, R_ref, T_ref, R1, R2; + Mat om_list(1, n_images, CV_64FC3), T_list(1, n_images, CV_64FC3); + Mat om_ref, R_ref, T_ref, R1, R2; for (int image_idx = 0; image_idx < n_images; ++image_idx) { - cv::Rodrigues(rvecs1[image_idx], R1); - cv::Rodrigues(rvecs2[image_idx], R2); + Rodrigues(rvecs1[image_idx], R1); + Rodrigues(rvecs2[image_idx], R2); R_ref = R2 * R1.t(); - T_ref = cv::Mat(tvecs2[image_idx]) - R_ref * cv::Mat(tvecs1[image_idx]); - cv::Rodrigues(R_ref, om_ref); + T_ref = Mat(tvecs2[image_idx]) - R_ref * Mat(tvecs1[image_idx]); + Rodrigues(R_ref, om_ref); om_ref.reshape(3, 1).copyTo(om_list.col(image_idx)); T_ref.reshape(3, 1).copyTo(T_list.col(image_idx)); } - cv::Vec3d omcur = cv::internal::median3d(om_list); - cv::Vec3d Tcur = cv::internal::median3d(T_list); + Vec3d omcur = cv::internal::median3d(om_list); + Vec3d Tcur = cv::internal::median3d(T_list); - cv::Mat J = cv::Mat::zeros(4 * n_points * n_images, 18 + 6 * (n_images + 1), CV_64FC1), - e = cv::Mat::zeros(4 * n_points * n_images, 1, CV_64FC1), Jkk, ekk; + Mat J = Mat::zeros(4 * n_points * n_images, 18 + 6 * (n_images + 1), CV_64FC1), + e = Mat::zeros(4 * n_points * n_images, 1, CV_64FC1), Jkk, ekk; for(int iter = 0; ; ++iter) { @@ -994,22 +996,22 @@ double cv::fisheye::stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayO Jkk.create(4 * n_points, 18 + 6 * (n_images + 1), CV_64FC1); ekk.create(4 * n_points, 1, CV_64FC1); - cv::Mat omr, Tr, domrdomckk, domrdTckk, domrdom, domrdT, dTrdomckk, dTrdTckk, dTrdom, dTrdT; + Mat omr, Tr, domrdomckk, domrdTckk, domrdom, domrdT, dTrdomckk, dTrdTckk, dTrdom, dTrdT; for (int image_idx = 0; image_idx < n_images; ++image_idx) { - Jkk = cv::Mat::zeros(4 * n_points, 18 + 6 * (n_images + 1), CV_64FC1); + Jkk = Mat::zeros(4 * n_points, 18 + 6 * (n_images + 1), CV_64FC1); - cv::Mat object = objectPoints.getMat(image_idx).clone(); - cv::Mat imageLeft = imagePoints1.getMat(image_idx).clone(); - cv::Mat imageRight = imagePoints2.getMat(image_idx).clone(); - cv::Mat jacobians, projected; + Mat object = objectPoints.getMat(image_idx).clone(); + Mat imageLeft = imagePoints1.getMat(image_idx).clone(); + Mat imageRight = imagePoints2.getMat(image_idx).clone(); + Mat jacobians, projected; //left camera jacobian - cv::Mat rvec = cv::Mat(rvecs1[image_idx]); - cv::Mat tvec = cv::Mat(tvecs1[image_idx]); + Mat rvec = Mat(rvecs1[image_idx]); + Mat tvec = Mat(tvecs1[image_idx]); cv::internal::projectPoints(object, projected, rvec, tvec, intrinsicLeft, jacobians); - cv::Mat(cv::Mat((imageLeft - projected).t()).reshape(1, 1).t()).copyTo(ekk.rowRange(0, 2 * n_points)); + Mat(Mat((imageLeft - projected).t()).reshape(1, 1).t()).copyTo(ekk.rowRange(0, 2 * n_points)); jacobians.colRange(8, 11).copyTo(Jkk.colRange(24 + image_idx * 6, 27 + image_idx * 6).rowRange(0, 2 * n_points)); jacobians.colRange(11, 14).copyTo(Jkk.colRange(27 + image_idx * 6, 30 + image_idx * 6).rowRange(0, 2 * n_points)); jacobians.colRange(0, 2).copyTo(Jkk.colRange(0, 2).rowRange(0, 2 * n_points)); @@ -1019,15 +1021,15 @@ double cv::fisheye::stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayO //right camera jacobian cv::internal::compose_motion(rvec, tvec, omcur, Tcur, omr, Tr, domrdomckk, domrdTckk, domrdom, domrdT, dTrdomckk, dTrdTckk, dTrdom, dTrdT); - rvec = cv::Mat(rvecs2[image_idx]); - tvec = cv::Mat(tvecs2[image_idx]); + rvec = Mat(rvecs2[image_idx]); + tvec = Mat(tvecs2[image_idx]); cv::internal::projectPoints(object, projected, omr, Tr, intrinsicRight, jacobians); - cv::Mat(cv::Mat((imageRight - projected).t()).reshape(1, 1).t()).copyTo(ekk.rowRange(2 * n_points, 4 * n_points)); - cv::Mat dxrdom = jacobians.colRange(8, 11) * domrdom + jacobians.colRange(11, 14) * dTrdom; - cv::Mat dxrdT = jacobians.colRange(8, 11) * domrdT + jacobians.colRange(11, 14)* dTrdT; - cv::Mat dxrdomckk = jacobians.colRange(8, 11) * domrdomckk + jacobians.colRange(11, 14) * dTrdomckk; - cv::Mat dxrdTckk = jacobians.colRange(8, 11) * domrdTckk + jacobians.colRange(11, 14) * dTrdTckk; + Mat(Mat((imageRight - projected).t()).reshape(1, 1).t()).copyTo(ekk.rowRange(2 * n_points, 4 * n_points)); + Mat dxrdom = jacobians.colRange(8, 11) * domrdom + jacobians.colRange(11, 14) * dTrdom; + Mat dxrdT = jacobians.colRange(8, 11) * domrdT + jacobians.colRange(11, 14)* dTrdT; + Mat dxrdomckk = jacobians.colRange(8, 11) * domrdomckk + jacobians.colRange(11, 14) * dTrdomckk; + Mat dxrdTckk = jacobians.colRange(8, 11) * domrdTckk + jacobians.colRange(11, 14) * dTrdTckk; dxrdom.copyTo(Jkk.colRange(18, 21).rowRange(2 * n_points, 4 * n_points)); dxrdT.copyTo(Jkk.colRange(21, 24).rowRange(2 * n_points, 4 * n_points)); @@ -1054,27 +1056,27 @@ double cv::fisheye::stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayO ekk.copyTo(e.rowRange(image_idx * 4 * n_points, (image_idx + 1) * 4 * n_points)); } - cv::Vec6d oldTom(Tcur[0], Tcur[1], Tcur[2], omcur[0], omcur[1], omcur[2]); + Vec6d oldTom(Tcur[0], Tcur[1], Tcur[2], omcur[0], omcur[1], omcur[2]); //update all parameters cv::subMatrix(J, J, selectedParams, std::vector(J.rows, 1)); int a = cv::countNonZero(intrinsicLeft.isEstimate); int b = cv::countNonZero(intrinsicRight.isEstimate); - cv::Mat deltas; + Mat deltas; solve(J.t() * J, J.t()*e, deltas); if (a > 0) intrinsicLeft = intrinsicLeft + deltas.rowRange(0, a); if (b > 0) intrinsicRight = intrinsicRight + deltas.rowRange(a, a + b); - omcur = omcur + cv::Vec3d(deltas.rowRange(a + b, a + b + 3)); - Tcur = Tcur + cv::Vec3d(deltas.rowRange(a + b + 3, a + b + 6)); + omcur = omcur + Vec3d(deltas.rowRange(a + b, a + b + 3)); + Tcur = Tcur + Vec3d(deltas.rowRange(a + b + 3, a + b + 6)); for (int image_idx = 0; image_idx < n_images; ++image_idx) { - rvecs1[image_idx] = cv::Mat(cv::Mat(rvecs1[image_idx]) + deltas.rowRange(a + b + 6 + image_idx * 6, a + b + 9 + image_idx * 6)); - tvecs1[image_idx] = cv::Mat(cv::Mat(tvecs1[image_idx]) + deltas.rowRange(a + b + 9 + image_idx * 6, a + b + 12 + image_idx * 6)); + rvecs1[image_idx] = Mat(Mat(rvecs1[image_idx]) + deltas.rowRange(a + b + 6 + image_idx * 6, a + b + 9 + image_idx * 6)); + tvecs1[image_idx] = Mat(Mat(tvecs1[image_idx]) + deltas.rowRange(a + b + 9 + image_idx * 6, a + b + 12 + image_idx * 6)); } - cv::Vec6d newTom(Tcur[0], Tcur[1], Tcur[2], omcur[0], omcur[1], omcur[2]); + Vec6d newTom(Tcur[0], Tcur[1], Tcur[2], omcur[0], omcur[1], omcur[2]); change = cv::norm(newTom - oldTom) / cv::norm(newTom); } @@ -1099,12 +1101,12 @@ double cv::fisheye::stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayO Mat _R; Rodrigues(omcur, _R); - if (K1.needed()) cv::Mat(_K1).convertTo(K1, K1.empty() ? CV_64FC1 : K1.type()); - if (K2.needed()) cv::Mat(_K2).convertTo(K2, K2.empty() ? CV_64FC1 : K2.type()); - if (D1.needed()) cv::Mat(intrinsicLeft.k).convertTo(D1, D1.empty() ? CV_64FC1 : D1.type()); - if (D2.needed()) cv::Mat(intrinsicRight.k).convertTo(D2, D2.empty() ? CV_64FC1 : D2.type()); + if (K1.needed()) Mat(_K1).convertTo(K1, K1.empty() ? CV_64FC1 : K1.type()); + if (K2.needed()) Mat(_K2).convertTo(K2, K2.empty() ? CV_64FC1 : K2.type()); + if (D1.needed()) Mat(intrinsicLeft.k).convertTo(D1, D1.empty() ? CV_64FC1 : D1.type()); + if (D2.needed()) Mat(intrinsicRight.k).convertTo(D2, D2.empty() ? CV_64FC1 : D2.type()); if (R.needed()) _R.convertTo(R, R.empty() ? CV_64FC1 : R.type()); - if (T.needed()) cv::Mat(Tcur).convertTo(T, T.empty() ? CV_64FC1 : T.type()); + if (T.needed()) Mat(Tcur).convertTo(T, T.empty() ? CV_64FC1 : T.type()); return rms; } @@ -1189,7 +1191,7 @@ cv::internal::IntrinsicParams& cv::internal::IntrinsicParams::operator =(const M return *this; } -void cv::internal::IntrinsicParams::Init(const cv::Vec2d& _f, const cv::Vec2d& _c, const cv::Vec4d& _k, const double& _alpha) +void cv::internal::IntrinsicParams::Init(const Vec2d& _f, const Vec2d& _c, const Vec4d& _k, const double& _alpha) { this->c = _c; this->f = _f; diff --git a/modules/calib3d/src/fisheye.hpp b/modules/calib/src/fisheye.hpp similarity index 100% rename from modules/calib3d/src/fisheye.hpp rename to modules/calib/src/fisheye.hpp diff --git a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp b/modules/calib/src/main.cpp similarity index 89% rename from modules/calib3d/include/opencv2/calib3d/calib3d.hpp rename to modules/calib/src/main.cpp index b3da45edd5..127f86b26b 100644 --- a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp +++ b/modules/calib/src/main.cpp @@ -7,12 +7,12 @@ // copy or use the software. // // -// License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -41,8 +41,12 @@ // //M*/ -#ifdef __OPENCV_BUILD -#error this is a compatibility header which should not be used inside the OpenCV library -#endif +// +// Library initialization file +// -#include "opencv2/calib3d.hpp" +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ diff --git a/modules/calib3d/src/precomp.hpp b/modules/calib/src/precomp.hpp similarity index 97% rename from modules/calib3d/src/precomp.hpp rename to modules/calib/src/precomp.hpp index f2cb7123c0..f83ec63386 100644 --- a/modules/calib3d/src/precomp.hpp +++ b/modules/calib/src/precomp.hpp @@ -46,18 +46,17 @@ #include "opencv2/core/private.hpp" -#include "opencv2/calib3d.hpp" +#include "opencv2/calib.hpp" +#include "opencv2/3d.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/features2d.hpp" - #include "opencv2/core/ocl.hpp" #define GET_OPTIMIZED(func) (func) -namespace cv -{ +namespace cv { /** * Compute the number of iterations given the confidence, outlier ratio, number @@ -135,8 +134,8 @@ static inline bool haveCollinearPoints( const Mat& m, int count ) return false; } +int checkChessboardBinary(const Mat & img, const Size & size); + } // namespace cv -int checkChessboardBinary(const cv::Mat & img, const cv::Size & size); - #endif diff --git a/modules/calib3d/src/quadsubpix.cpp b/modules/calib/src/quadsubpix.cpp similarity index 98% rename from modules/calib3d/src/quadsubpix.cpp rename to modules/calib/src/quadsubpix.cpp index 24dfdc14a4..90429815b2 100644 --- a/modules/calib3d/src/quadsubpix.cpp +++ b/modules/calib/src/quadsubpix.cpp @@ -159,9 +159,7 @@ static int segment_hist_max(const Mat& hist, int& low_thresh, int& high_thresh) } } -} - -bool cv::find4QuadCornerSubpix(InputArray _img, InputOutputArray _corners, Size region_size) +bool find4QuadCornerSubpix(InputArray _img, InputOutputArray _corners, Size region_size) { CV_INSTRUMENT_REGION(); @@ -238,3 +236,5 @@ bool cv::find4QuadCornerSubpix(InputArray _img, InputOutputArray _corners, Size return true; } + +} diff --git a/modules/calib3d/test/test_calibration_hand_eye.cpp b/modules/calib/test/test_calibration_hand_eye.cpp similarity index 99% rename from modules/calib3d/test/test_calibration_hand_eye.cpp rename to modules/calib/test/test_calibration_hand_eye.cpp index 50bcbd7aff..36f20006a4 100644 --- a/modules/calib3d/test/test_calibration_hand_eye.cpp +++ b/modules/calib/test/test_calibration_hand_eye.cpp @@ -3,7 +3,6 @@ // of this distribution and at http://opencv.org/license.html. #include "test_precomp.hpp" -#include "opencv2/calib3d.hpp" namespace opencv_test { namespace { diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib/test/test_cameracalibration.cpp similarity index 99% rename from modules/calib3d/test/test_cameracalibration.cpp rename to modules/calib/test/test_cameracalibration.cpp index 9f3663e8cc..59c2891df4 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib/test/test_cameracalibration.cpp @@ -40,7 +40,7 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/calib3d/calib3d_c.h" +#include "opencv2/stereo.hpp" namespace opencv_test { namespace { @@ -773,7 +773,7 @@ void CV_CameraCalibrationTest_CPP::calibrate(Size imageSize, Mat(_objectPoints[i]).convertTo(objectPoints[i], CV_32F); } - size_t nstddev0 = CV_CALIB_NINTRINSIC + imageCount*6, nstddev1 = nstddev0 + _imagePoints[0].size()*3; + size_t nstddev0 = CALIB_NINTRINSIC + imageCount*6, nstddev1 = nstddev0 + _imagePoints[0].size()*3; for( i = nstddev0; i < nstddev1; i++ ) { stdDevs[i] = 0.0; @@ -811,7 +811,7 @@ void CV_CameraCalibrationTest_CPP::calibrate(Size imageSize, for( i = 0; i < imageCount; i++ ) { Mat r9; - cvtest::Rodrigues( rvecs[i], r9 ); + Rodrigues( rvecs[i], r9 ); cv::transpose(r9, r9); r9.convertTo(rotationMatrices[i], CV_64F); tvecs[i].convertTo(translationVectors[i], CV_64F); @@ -1046,7 +1046,7 @@ void CV_ProjectPointsTest::run(int) rvec(0,1) = rng.uniform( rMinVal, rMaxVal ); rvec(0,2) = rng.uniform( rMinVal, rMaxVal ); rmat = cv::Mat_::zeros(3, 3); - cvtest::Rodrigues( rvec, rmat ); + Rodrigues( rvec, rmat ); tvec(0,0) = rng.uniform( tMinVal, tMaxVal ); tvec(0,1) = rng.uniform( tMinVal, tMaxVal ); @@ -1429,12 +1429,12 @@ void CV_StereoCalibrationTest::run( int ) D2 = Scalar::all(0); double err = calibrateStereoCamera(objpt, imgpt1, imgpt2, M1, D1, M2, D2, imgsize, R, T, E, F, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 1e-6), - CV_CALIB_SAME_FOCAL_LENGTH + CALIB_SAME_FOCAL_LENGTH //+ CV_CALIB_FIX_ASPECT_RATIO - + CV_CALIB_FIX_PRINCIPAL_POINT - + CV_CALIB_ZERO_TANGENT_DIST - + CV_CALIB_FIX_K3 - + CV_CALIB_FIX_K4 + CV_CALIB_FIX_K5 //+ CV_CALIB_FIX_K6 + + CALIB_FIX_PRINCIPAL_POINT + + CALIB_ZERO_TANGENT_DIST + + CALIB_FIX_K3 + + CALIB_FIX_K4 + CALIB_FIX_K5 //+ CV_CALIB_FIX_K6 ); err /= nframes*npoints; if( err > maxReprojErr ) diff --git a/modules/calib3d/test/test_cameracalibration_artificial.cpp b/modules/calib/test/test_cameracalibration_artificial.cpp similarity index 99% rename from modules/calib3d/test/test_cameracalibration_artificial.cpp rename to modules/calib/test/test_cameracalibration_artificial.cpp index de4f2bfccb..f2f1be2baa 100644 --- a/modules/calib3d/test/test_cameracalibration_artificial.cpp +++ b/modules/calib/test/test_cameracalibration_artificial.cpp @@ -69,7 +69,7 @@ Mat calcRvec(const vector& points, const Size& cornerSize) *rot.ptr(2) = ez * (1.0/cv::norm(ez)); // TODO cvtest Mat res; - cvtest::Rodrigues(rot.t(), res); + Rodrigues(rot.t(), res); return res.reshape(1, 1); } @@ -194,8 +194,8 @@ protected: const int errMsgNum = 4; for(size_t i = 0; i < rvecs.size(); ++i) { - cvtest::Rodrigues(rvecs[i], rmat); - cvtest::Rodrigues(rvecs_est[i], rmat_est); + Rodrigues(rvecs[i], rmat); + Rodrigues(rvecs_est[i], rmat_est); if (cvtest::norm(rmat_est, rmat, NORM_L2) > eps* (cvtest::norm(rmat, NORM_L2) + dlt)) { diff --git a/modules/calib3d/test/test_cameracalibration_badarg.cpp b/modules/calib/test/test_cameracalibration_badarg.cpp similarity index 99% rename from modules/calib3d/test/test_cameracalibration_badarg.cpp rename to modules/calib/test/test_cameracalibration_badarg.cpp index 240bdbb1b3..2a40077bb7 100644 --- a/modules/calib3d/test/test_cameracalibration_badarg.cpp +++ b/modules/calib/test/test_cameracalibration_badarg.cpp @@ -321,7 +321,7 @@ protected: randu(objectPoints_cpp, Scalar::all(1), Scalar::all(10)); caller.objectPoints = objectPoints_cpp; caller.t_vec = Mat::zeros(1, 3, CV_32F); - cvtest::Rodrigues(Mat::eye(3, 3, CV_32F), caller.r_vec); + Rodrigues(Mat::eye(3, 3, CV_32F), caller.r_vec); caller.A = Mat::eye(3, 3, CV_32F); caller.distCoeffs = Mat::zeros(1, 5, CV_32F); caller.aspectRatio0 = 1.0; diff --git a/modules/calib3d/test/test_cameracalibration_tilt.cpp b/modules/calib/test/test_cameracalibration_tilt.cpp similarity index 100% rename from modules/calib3d/test/test_cameracalibration_tilt.cpp rename to modules/calib/test/test_cameracalibration_tilt.cpp diff --git a/modules/calib3d/test/test_chessboardgenerator.cpp b/modules/calib/test/test_chessboardgenerator.cpp similarity index 99% rename from modules/calib3d/test/test_chessboardgenerator.cpp rename to modules/calib/test/test_chessboardgenerator.cpp index 6926cb6e72..7cc5598e3f 100644 --- a/modules/calib3d/test/test_chessboardgenerator.cpp +++ b/modules/calib/test/test_chessboardgenerator.cpp @@ -50,7 +50,7 @@ ChessBoardGenerator::ChessBoardGenerator(const Size& _patternSize) : sensorWidth patternSize(_patternSize), rendererResolutionMultiplier(4), tvec(Mat::zeros(1, 3, CV_32F)) { rvec.create(3, 1, CV_32F); - cvtest::Rodrigues(Mat::eye(3, 3, CV_32F), rvec); + Rodrigues(Mat::eye(3, 3, CV_32F), rvec); } void ChessBoardGenerator::generateEdge(const Point3f& p1, const Point3f& p2, vector& out) const diff --git a/modules/calib3d/test/test_chessboardgenerator.hpp b/modules/calib/test/test_chessboardgenerator.hpp similarity index 100% rename from modules/calib3d/test/test_chessboardgenerator.hpp rename to modules/calib/test/test_chessboardgenerator.hpp diff --git a/modules/calib3d/test/test_chesscorners.cpp b/modules/calib/test/test_chesscorners.cpp similarity index 100% rename from modules/calib3d/test/test_chesscorners.cpp rename to modules/calib/test/test_chesscorners.cpp diff --git a/modules/calib3d/test/test_chesscorners_badarg.cpp b/modules/calib/test/test_chesscorners_badarg.cpp similarity index 97% rename from modules/calib3d/test/test_chesscorners_badarg.cpp rename to modules/calib/test/test_chesscorners_badarg.cpp index 85b2cb54da..f62cfc16c3 100644 --- a/modules/calib3d/test/test_chesscorners_badarg.cpp +++ b/modules/calib/test/test_chesscorners_badarg.cpp @@ -41,7 +41,6 @@ #include "test_precomp.hpp" #include "test_chessboardgenerator.hpp" -#include "opencv2/calib3d/calib3d_c.h" namespace opencv_test { namespace { @@ -89,7 +88,7 @@ void CV_ChessboardDetectorBadArgTest::run( int /*start_from */) /* /*//*/ */ int errors = 0; - flags = CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE; + flags = CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE; img = cb.clone(); initArgs(); diff --git a/modules/calib3d/test/test_chesscorners_timing.cpp b/modules/calib/test/test_chesscorners_timing.cpp similarity index 99% rename from modules/calib3d/test/test_chesscorners_timing.cpp rename to modules/calib/test/test_chesscorners_timing.cpp index 9bd0f87078..78dbffa184 100644 --- a/modules/calib3d/test/test_chesscorners_timing.cpp +++ b/modules/calib/test/test_chesscorners_timing.cpp @@ -41,7 +41,6 @@ #include "test_precomp.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/calib3d.hpp" namespace opencv_test { namespace { diff --git a/modules/calib3d/test/test_cornerssubpix.cpp b/modules/calib/test/test_cornerssubpix.cpp similarity index 100% rename from modules/calib3d/test/test_cornerssubpix.cpp rename to modules/calib/test/test_cornerssubpix.cpp diff --git a/modules/calib3d/test/test_fisheye.cpp b/modules/calib/test/test_fisheye.cpp similarity index 100% rename from modules/calib3d/test/test_fisheye.cpp rename to modules/calib/test/test_fisheye.cpp diff --git a/modules/calib/test/test_main.cpp b/modules/calib/test/test_main.cpp new file mode 100644 index 0000000000..faa8d0e2e2 --- /dev/null +++ b/modules/calib/test/test_main.cpp @@ -0,0 +1,10 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +#include "test_precomp.hpp" + +#if defined(HAVE_HPX) + #include +#endif + +CV_TEST_MAIN("") diff --git a/modules/calib/test/test_modelest.cpp b/modules/calib/test/test_modelest.cpp new file mode 100644 index 0000000000..55cb79ebaf --- /dev/null +++ b/modules/calib/test/test_modelest.cpp @@ -0,0 +1,231 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "test_precomp.hpp" + +#if 0 +#include "_modelest.h" + +using namespace std; +using namespace cv; + +class BareModelEstimator : public CvModelEstimator2 +{ +public: + BareModelEstimator(int modelPoints, CvSize modelSize, int maxBasicSolutions); + + virtual int runKernel( const CvMat*, const CvMat*, CvMat* ); + virtual void computeReprojError( const CvMat*, const CvMat*, + const CvMat*, CvMat* ); + + bool checkSubsetPublic( const CvMat* ms1, int count, bool checkPartialSubset ); +}; + +BareModelEstimator::BareModelEstimator(int _modelPoints, CvSize _modelSize, int _maxBasicSolutions) + :CvModelEstimator2(_modelPoints, _modelSize, _maxBasicSolutions) +{ +} + +int BareModelEstimator::runKernel( const CvMat*, const CvMat*, CvMat* ) +{ + return 0; +} + +void BareModelEstimator::computeReprojError( const CvMat*, const CvMat*, + const CvMat*, CvMat* ) +{ +} + +bool BareModelEstimator::checkSubsetPublic( const CvMat* ms1, int count, bool checkPartialSubset ) +{ + checkPartialSubsets = checkPartialSubset; + return checkSubset(ms1, count); +} + +class CV_ModelEstimator2_Test : public cvtest::ArrayTest +{ +public: + CV_ModelEstimator2_Test(); + +protected: + void get_test_array_types_and_sizes( int test_case_idx, vector >& sizes, vector >& types ); + void fill_array( int test_case_idx, int i, int j, Mat& arr ); + double get_success_error_level( int test_case_idx, int i, int j ); + void run_func(); + void prepare_to_validation( int test_case_idx ); + + bool checkPartialSubsets; + int usedPointsCount; + + bool checkSubsetResult; + int generalPositionsCount; + int maxPointsCount; +}; + +CV_ModelEstimator2_Test::CV_ModelEstimator2_Test() +{ + generalPositionsCount = get_test_case_count() / 2; + maxPointsCount = 100; + + test_array[INPUT].push_back(NULL); + test_array[OUTPUT].push_back(NULL); + test_array[REF_OUTPUT].push_back(NULL); +} + +void CV_ModelEstimator2_Test::get_test_array_types_and_sizes( int /*test_case_idx*/, + vector > &sizes, vector > &types ) +{ + RNG &rng = ts->get_rng(); + checkPartialSubsets = (cvtest::randInt(rng) % 2 == 0); + + int pointsCount = cvtest::randInt(rng) % maxPointsCount; + usedPointsCount = pointsCount == 0 ? 0 : cvtest::randInt(rng) % pointsCount; + + sizes[INPUT][0] = cvSize(1, pointsCount); + types[INPUT][0] = CV_64FC2; + + sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(1, 1); + types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_8UC1; +} + +void CV_ModelEstimator2_Test::fill_array( int test_case_idx, int i, int j, Mat& arr ) +{ + if( i != INPUT ) + { + cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr ); + return; + } + + if (test_case_idx < generalPositionsCount) + { + //generate points in a general position (i.e. no three points can lie on the same line.) + + bool isGeneralPosition; + do + { + ArrayTest::fill_array(test_case_idx, i, j, arr); + + //a simple check that the position is general: + // for each line check that all other points don't belong to it + isGeneralPosition = true; + for (int startPointIndex = 0; startPointIndex < usedPointsCount && isGeneralPosition; startPointIndex++) + { + for (int endPointIndex = startPointIndex + 1; endPointIndex < usedPointsCount && isGeneralPosition; endPointIndex++) + { + + for (int testPointIndex = 0; testPointIndex < usedPointsCount && isGeneralPosition; testPointIndex++) + { + if (testPointIndex == startPointIndex || testPointIndex == endPointIndex) + { + continue; + } + + CV_Assert(arr.type() == CV_64FC2); + Point2d tangentVector_1 = arr.at(endPointIndex) - arr.at(startPointIndex); + Point2d tangentVector_2 = arr.at(testPointIndex) - arr.at(startPointIndex); + + const float eps = 1e-4f; + //TODO: perhaps it is better to normalize the cross product by norms of the tangent vectors + if (fabs(tangentVector_1.cross(tangentVector_2)) < eps) + { + isGeneralPosition = false; + } + } + } + } + } + while(!isGeneralPosition); + } + else + { + //create points in a degenerate position (there are at least 3 points belonging to the same line) + + ArrayTest::fill_array(test_case_idx, i, j, arr); + if (usedPointsCount <= 2) + { + return; + } + + RNG &rng = ts->get_rng(); + int startPointIndex, endPointIndex, modifiedPointIndex; + do + { + startPointIndex = cvtest::randInt(rng) % usedPointsCount; + endPointIndex = cvtest::randInt(rng) % usedPointsCount; + modifiedPointIndex = checkPartialSubsets ? usedPointsCount - 1 : cvtest::randInt(rng) % usedPointsCount; + } + while (startPointIndex == endPointIndex || startPointIndex == modifiedPointIndex || endPointIndex == modifiedPointIndex); + + double startWeight = cvtest::randReal(rng); + CV_Assert(arr.type() == CV_64FC2); + arr.at(modifiedPointIndex) = startWeight * arr.at(startPointIndex) + (1.0 - startWeight) * arr.at(endPointIndex); + } +} + + +double CV_ModelEstimator2_Test::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) +{ + return 0; +} + +void CV_ModelEstimator2_Test::prepare_to_validation( int test_case_idx ) +{ + test_mat[OUTPUT][0].at(0) = checkSubsetResult; + test_mat[REF_OUTPUT][0].at(0) = test_case_idx < generalPositionsCount || usedPointsCount <= 2; +} + +void CV_ModelEstimator2_Test::run_func() +{ + //make the input continuous + Mat input = test_mat[INPUT][0].clone(); + CvMat _input = input; + + RNG &rng = ts->get_rng(); + int modelPoints = cvtest::randInt(rng); + CvSize modelSize = cvSize(2, modelPoints); + int maxBasicSolutions = cvtest::randInt(rng); + BareModelEstimator modelEstimator(modelPoints, modelSize, maxBasicSolutions); + checkSubsetResult = modelEstimator.checkSubsetPublic(&_input, usedPointsCount, checkPartialSubsets); +} + +TEST(Calib3d_ModelEstimator2, accuracy) { CV_ModelEstimator2_Test test; test.safe_run(); } + +#endif diff --git a/modules/calib/test/test_precomp.hpp b/modules/calib/test/test_precomp.hpp new file mode 100644 index 0000000000..0b4fa601e2 --- /dev/null +++ b/modules/calib/test/test_precomp.hpp @@ -0,0 +1,14 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +#ifndef __OPENCV_TEST_PRECOMP_HPP__ +#define __OPENCV_TEST_PRECOMP_HPP__ + +#include +#include + +#include "opencv2/ts.hpp" +#include "opencv2/3d.hpp" +#include "opencv2/calib.hpp" + +#endif diff --git a/modules/calib3d/include/opencv2/calib3d/calib3d_c.h b/modules/calib3d/include/opencv2/calib3d/calib3d_c.h deleted file mode 100644 index e2af07b2e2..0000000000 --- a/modules/calib3d/include/opencv2/calib3d/calib3d_c.h +++ /dev/null @@ -1,150 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#ifndef OPENCV_CALIB3D_C_H -#define OPENCV_CALIB3D_C_H - -#include "opencv2/core/types_c.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Calculates fundamental matrix given a set of corresponding points */ -#define CV_FM_7POINT 1 -#define CV_FM_8POINT 2 - -#define CV_LMEDS 4 -#define CV_RANSAC 8 - -#define CV_FM_LMEDS_ONLY CV_LMEDS -#define CV_FM_RANSAC_ONLY CV_RANSAC -#define CV_FM_LMEDS CV_LMEDS -#define CV_FM_RANSAC CV_RANSAC - -enum -{ - CV_ITERATIVE = 0, - CV_EPNP = 1, // F.Moreno-Noguer, V.Lepetit and P.Fua "EPnP: Efficient Perspective-n-Point Camera Pose Estimation" - CV_P3P = 2, // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang; "Complete Solution Classification for the Perspective-Three-Point Problem" - CV_DLS = 3 // Joel A. Hesch and Stergios I. Roumeliotis. "A Direct Least-Squares (DLS) Method for PnP" -}; - -#define CV_CALIB_CB_ADAPTIVE_THRESH 1 -#define CV_CALIB_CB_NORMALIZE_IMAGE 2 -#define CV_CALIB_CB_FILTER_QUADS 4 -#define CV_CALIB_CB_FAST_CHECK 8 - -#define CV_CALIB_USE_INTRINSIC_GUESS 1 -#define CV_CALIB_FIX_ASPECT_RATIO 2 -#define CV_CALIB_FIX_PRINCIPAL_POINT 4 -#define CV_CALIB_ZERO_TANGENT_DIST 8 -#define CV_CALIB_FIX_FOCAL_LENGTH 16 -#define CV_CALIB_FIX_K1 32 -#define CV_CALIB_FIX_K2 64 -#define CV_CALIB_FIX_K3 128 -#define CV_CALIB_FIX_K4 2048 -#define CV_CALIB_FIX_K5 4096 -#define CV_CALIB_FIX_K6 8192 -#define CV_CALIB_RATIONAL_MODEL 16384 -#define CV_CALIB_THIN_PRISM_MODEL 32768 -#define CV_CALIB_FIX_S1_S2_S3_S4 65536 -#define CV_CALIB_TILTED_MODEL 262144 -#define CV_CALIB_FIX_TAUX_TAUY 524288 -#define CV_CALIB_FIX_TANGENT_DIST 2097152 - -#define CV_CALIB_NINTRINSIC 18 - -#define CV_CALIB_FIX_INTRINSIC 256 -#define CV_CALIB_SAME_FOCAL_LENGTH 512 - -#define CV_CALIB_ZERO_DISPARITY 1024 - -/* stereo correspondence parameters and functions */ -#define CV_STEREO_BM_NORMALIZED_RESPONSE 0 -#define CV_STEREO_BM_XSOBEL 1 - -#ifdef __cplusplus -} // extern "C" - -////////////////////////////////////////////////////////////////////////////////////////// -class CV_EXPORTS CvLevMarq -{ -public: - CvLevMarq(); - CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria= - cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), - bool completeSymmFlag=false ); - ~CvLevMarq(); - void init( int nparams, int nerrs, CvTermCriteria criteria= - cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), - bool completeSymmFlag=false ); - bool update( const CvMat*& param, CvMat*& J, CvMat*& err ); - bool updateAlt( const CvMat*& param, CvMat*& JtJ, CvMat*& JtErr, double*& errNorm ); - - void clear(); - void step(); - enum { DONE=0, STARTED=1, CALC_J=2, CHECK_ERR=3 }; - - cv::Ptr mask; - cv::Ptr prevParam; - cv::Ptr param; - cv::Ptr J; - cv::Ptr err; - cv::Ptr JtJ; - cv::Ptr JtJN; - cv::Ptr JtErr; - cv::Ptr JtJV; - cv::Ptr JtJW; - double prevErrNorm, errNorm; - int lambdaLg10; - CvTermCriteria criteria; - int state; - int iters; - bool completeSymmFlag; - int solveMethod; -}; - -#endif - -#endif /* OPENCV_CALIB3D_C_H */ diff --git a/modules/calib3d/misc/objc/test/Calib3dTest.swift b/modules/calib3d/misc/objc/test/Calib3dTest.swift deleted file mode 100644 index 3fe4cb8dae..0000000000 --- a/modules/calib3d/misc/objc/test/Calib3dTest.swift +++ /dev/null @@ -1,465 +0,0 @@ -// -// Calib3dTest.swift -// -// Created by Giles Payne on 2020/05/26. -// - -import XCTest -import OpenCV - -class Calib3dTest: OpenCVTestCase { - - var size = Size() - - override func setUp() { - super.setUp() - size = Size(width: 3, height: 3) - } - - override func tearDown() { - super.tearDown() - } - - func testComposeRTMatMatMatMatMatMat() throws { - let rvec1 = Mat(rows: 3, cols: 1, type: CvType.CV_32F) - try rvec1.put(row: 0, col: 0, data: [0.5302828, 0.19925919, 0.40105945] as [Float]) - let tvec1 = Mat(rows: 3, cols: 1, type: CvType.CV_32F) - try tvec1.put(row: 0, col: 0, data: [0.81438506, 0.43713298, 0.2487897] as [Float]) - let rvec2 = Mat(rows: 3, cols: 1, type: CvType.CV_32F) - try rvec2.put(row: 0, col: 0, data: [0.77310503, 0.76209372, 0.30779448] as [Float]) - let tvec2 = Mat(rows: 3, cols: 1, type: CvType.CV_32F) - try tvec2.put(row: 0, col: 0, data: [0.70243168, 0.4784472, 0.79219002] as [Float]) - - let rvec3 = Mat() - let tvec3 = Mat() - - let outRvec = Mat(rows: 3, cols: 1, type: CvType.CV_32F) - try outRvec.put(row: 0, col: 0, data: [1.418641, 0.88665926, 0.56020796]) - let outTvec = Mat(rows: 3, cols: 1, type: CvType.CV_32F) - try outTvec.put(row: 0, col: 0, data: [1.4560841, 1.0680628, 0.81598103]) - - Calib3d.composeRT(rvec1: rvec1, tvec1: tvec1, rvec2: rvec2, tvec2: tvec2, rvec3: rvec3, tvec3: tvec3) - - try assertMatEqual(outRvec, rvec3, OpenCVTestCase.EPS) - try assertMatEqual(outTvec, tvec3, OpenCVTestCase.EPS) - } - - func testFilterSpecklesMatDoubleIntDouble() throws { - gray_16s_1024.copy(to: dst) - let center = Point(x: gray_16s_1024.rows() / 2, y: gray_16s_1024.cols() / 2) - Imgproc.circle(img: dst, center: center, radius: 1, color: Scalar.all(4096)) - - try assertMatNotEqual(gray_16s_1024, dst) - Calib3d.filterSpeckles(img: dst, newVal: 1024.0, maxSpeckleSize: 100, maxDiff: 0.0) - try assertMatEqual(gray_16s_1024, dst) - } - - func testFindChessboardCornersMatSizeMat() { - let patternSize = Size(width: 9, height: 6) - let corners = MatOfPoint2f() - Calib3d.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners) - XCTAssertFalse(corners.empty()) - } - - func testFindChessboardCornersMatSizeMatInt() { - let patternSize = Size(width: 9, height: 6) - let corners = MatOfPoint2f() - Calib3d.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners, flags: Calib3d.CALIB_CB_ADAPTIVE_THRESH + Calib3d.CALIB_CB_NORMALIZE_IMAGE + Calib3d.CALIB_CB_FAST_CHECK) - XCTAssertFalse(corners.empty()) - } - - func testFind4QuadCornerSubpix() { - let patternSize = Size(width: 9, height: 6) - let corners = MatOfPoint2f() - let region_size = Size(width: 5, height: 5) - Calib3d.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners) - Calib3d.find4QuadCornerSubpix(img: grayChess, corners: corners, region_size: region_size) - XCTAssertFalse(corners.empty()) - } - - func testFindCirclesGridMatSizeMat() { - let size = 300 - let img = Mat(rows:Int32(size), cols:Int32(size), type:CvType.CV_8U) - img.setTo(scalar: Scalar(255)) - let centers = Mat() - - XCTAssertFalse(Calib3d.findCirclesGrid(image: img, patternSize: Size(width: 5, height: 5), centers: centers)) - - for i in 0..<5 { - for j in 0..<5 { - let x = Int32(size * (2 * i + 1) / 10) - let y = Int32(size * (2 * j + 1) / 10) - let pt = Point(x: x, y: y) - Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1) - } - } - - XCTAssert(Calib3d.findCirclesGrid(image: img, patternSize:Size(width:5, height:5), centers:centers)) - - XCTAssertEqual(25, centers.rows()) - XCTAssertEqual(1, centers.cols()) - XCTAssertEqual(CvType.CV_32FC2, centers.type()) - } - - func testFindCirclesGridMatSizeMatInt() { - let size:Int32 = 300 - let img = Mat(rows:size, cols: size, type: CvType.CV_8U) - img.setTo(scalar: Scalar(255)) - let centers = Mat() - - XCTAssertFalse(Calib3d.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib3d.CALIB_CB_CLUSTERING | Calib3d.CALIB_CB_ASYMMETRIC_GRID)) - - let step = size * 2 / 15 - let offsetx = size / 6 - let offsety = (size - 4 * step) / 2 - for i:Int32 in 0...2 { - for j:Int32 in 0...4 { - let pt = Point(x: offsetx + (2 * i + j % 2) * step, y: offsety + step * j) - Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1) - } - } - - XCTAssert(Calib3d.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib3d.CALIB_CB_CLUSTERING | Calib3d.CALIB_CB_ASYMMETRIC_GRID)) - - XCTAssertEqual(15, centers.rows()) - XCTAssertEqual(1, centers.cols()) - XCTAssertEqual(CvType.CV_32FC2, centers.type()) - } - - func testFindHomographyListOfPointListOfPoint() throws { - let NUM:Int32 = 20 - - let originalPoints = MatOfPoint2f() - originalPoints.alloc(NUM) - let transformedPoints = MatOfPoint2f() - transformedPoints.alloc(NUM) - - for i:Int32 in 0.. src, List dst, Mat cameraMatrix, Mat distCoeffs) - func testUndistortPointsListOfPointListOfPointMatMat() { - let src = MatOfPoint2f(array: [Point2f(x: 1, y: 2), Point2f(x: 3, y: 4), Point2f(x: -1, y: -1)]) - let dst = MatOfPoint2f() - let cameraMatrix = Mat.eye(rows: 3, cols: 3, type: CvType.CV_64FC1) - let distCoeffs = Mat(rows: 8, cols: 1, type: CvType.CV_64FC1, scalar: Scalar(0)) - - Calib3d.undistortPoints(src: src, dst: dst, cameraMatrix: cameraMatrix, distCoeffs: distCoeffs) - - XCTAssertEqual(src.toArray(), dst.toArray()) - } -} diff --git a/modules/calib3d/src/calib3d_c_api.h b/modules/calib3d/src/calib3d_c_api.h deleted file mode 100644 index c9ac9b49f5..0000000000 --- a/modules/calib3d/src/calib3d_c_api.h +++ /dev/null @@ -1,425 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#ifndef OPENCV_CALIB3D_C_API_H -#define OPENCV_CALIB3D_C_API_H - -#include "opencv2/core/core_c.h" -#include "opencv2/calib3d/calib3d_c.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @addtogroup calib3d_c - @{ - */ - -/****************************************************************************************\ -* Camera Calibration, Pose Estimation and Stereo * -\****************************************************************************************/ - -typedef struct CvPOSITObject CvPOSITObject; - -/* Allocates and initializes CvPOSITObject structure before doing cvPOSIT */ -CvPOSITObject* cvCreatePOSITObject( CvPoint3D32f* points, int point_count ); - - -/* Runs POSIT (POSe from ITeration) algorithm for determining 3d position of - an object given its model and projection in a weak-perspective case */ -void cvPOSIT( CvPOSITObject* posit_object, CvPoint2D32f* image_points, - double focal_length, CvTermCriteria criteria, - float* rotation_matrix, float* translation_vector); - -/* Releases CvPOSITObject structure */ -void cvReleasePOSITObject( CvPOSITObject** posit_object ); - -/* updates the number of RANSAC iterations */ -int cvRANSACUpdateNumIters( double p, double err_prob, - int model_points, int max_iters ); - -void cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst ); - -/* Calculates fundamental matrix given a set of corresponding points */ -/*#define CV_FM_7POINT 1 -#define CV_FM_8POINT 2 - -#define CV_LMEDS 4 -#define CV_RANSAC 8 - -#define CV_FM_LMEDS_ONLY CV_LMEDS -#define CV_FM_RANSAC_ONLY CV_RANSAC -#define CV_FM_LMEDS CV_LMEDS -#define CV_FM_RANSAC CV_RANSAC*/ - -int cvFindFundamentalMat( const CvMat* points1, const CvMat* points2, - CvMat* fundamental_matrix, - int method CV_DEFAULT(CV_FM_RANSAC), - double param1 CV_DEFAULT(3.), double param2 CV_DEFAULT(0.99), - CvMat* status CV_DEFAULT(NULL) ); - -/* For each input point on one of images - computes parameters of the corresponding - epipolar line on the other image */ -void cvComputeCorrespondEpilines( const CvMat* points, - int which_image, - const CvMat* fundamental_matrix, - CvMat* correspondent_lines ); - -/* Triangulation functions */ - -void cvTriangulatePoints(CvMat* projMatr1, CvMat* projMatr2, - CvMat* projPoints1, CvMat* projPoints2, - CvMat* points4D); - -void cvCorrectMatches(CvMat* F, CvMat* points1, CvMat* points2, - CvMat* new_points1, CvMat* new_points2); - - -/* Computes the optimal new camera matrix according to the free scaling parameter alpha: - alpha=0 - only valid pixels will be retained in the undistorted image - alpha=1 - all the source image pixels will be retained in the undistorted image -*/ -void cvGetOptimalNewCameraMatrix( const CvMat* camera_matrix, - const CvMat* dist_coeffs, - CvSize image_size, double alpha, - CvMat* new_camera_matrix, - CvSize new_imag_size CV_DEFAULT(cvSize(0,0)), - CvRect* valid_pixel_ROI CV_DEFAULT(0), - int center_principal_point CV_DEFAULT(0)); - -/* Converts rotation vector to rotation matrix or vice versa */ -int cvRodrigues2( const CvMat* src, CvMat* dst, - CvMat* jacobian CV_DEFAULT(0) ); - -/* Finds perspective transformation between the object plane and image (view) plane */ -int cvFindHomography( const CvMat* src_points, - const CvMat* dst_points, - CvMat* homography, - int method CV_DEFAULT(0), - double ransacReprojThreshold CV_DEFAULT(3), - CvMat* mask CV_DEFAULT(0), - int maxIters CV_DEFAULT(2000), - double confidence CV_DEFAULT(0.995)); - -/* Computes RQ decomposition for 3x3 matrices */ -void cvRQDecomp3x3( const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ, - CvMat *matrixQx CV_DEFAULT(NULL), - CvMat *matrixQy CV_DEFAULT(NULL), - CvMat *matrixQz CV_DEFAULT(NULL), - CvPoint3D64f *eulerAngles CV_DEFAULT(NULL)); - -/* Computes projection matrix decomposition */ -void cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr, - CvMat *rotMatr, CvMat *posVect, - CvMat *rotMatrX CV_DEFAULT(NULL), - CvMat *rotMatrY CV_DEFAULT(NULL), - CvMat *rotMatrZ CV_DEFAULT(NULL), - CvPoint3D64f *eulerAngles CV_DEFAULT(NULL)); - -/* Computes d(AB)/dA and d(AB)/dB */ -void cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, CvMat* dABdB ); - -/* Computes r3 = rodrigues(rodrigues(r2)*rodrigues(r1)), - t3 = rodrigues(r2)*t1 + t2 and the respective derivatives */ -void cvComposeRT( const CvMat* _rvec1, const CvMat* _tvec1, - const CvMat* _rvec2, const CvMat* _tvec2, - CvMat* _rvec3, CvMat* _tvec3, - CvMat* dr3dr1 CV_DEFAULT(0), CvMat* dr3dt1 CV_DEFAULT(0), - CvMat* dr3dr2 CV_DEFAULT(0), CvMat* dr3dt2 CV_DEFAULT(0), - CvMat* dt3dr1 CV_DEFAULT(0), CvMat* dt3dt1 CV_DEFAULT(0), - CvMat* dt3dr2 CV_DEFAULT(0), CvMat* dt3dt2 CV_DEFAULT(0) ); - -/* Projects object points to the view plane using - the specified extrinsic and intrinsic camera parameters */ -void cvProjectPoints2( const CvMat* object_points, const CvMat* rotation_vector, - const CvMat* translation_vector, const CvMat* camera_matrix, - const CvMat* distortion_coeffs, CvMat* image_points, - CvMat* dpdrot CV_DEFAULT(NULL), CvMat* dpdt CV_DEFAULT(NULL), - CvMat* dpdf CV_DEFAULT(NULL), CvMat* dpdc CV_DEFAULT(NULL), - CvMat* dpddist CV_DEFAULT(NULL), - double aspect_ratio CV_DEFAULT(0)); - -/* Finds extrinsic camera parameters from - a few known corresponding point pairs and intrinsic parameters */ -void cvFindExtrinsicCameraParams2( const CvMat* object_points, - const CvMat* image_points, - const CvMat* camera_matrix, - const CvMat* distortion_coeffs, - CvMat* rotation_vector, - CvMat* translation_vector, - int use_extrinsic_guess CV_DEFAULT(0) ); - -/* Computes initial estimate of the intrinsic camera parameters - in case of planar calibration target (e.g. chessboard) */ -void cvInitIntrinsicParams2D( const CvMat* object_points, - const CvMat* image_points, - const CvMat* npoints, CvSize image_size, - CvMat* camera_matrix, - double aspect_ratio CV_DEFAULT(1.) ); - -// Performs a fast check if a chessboard is in the input image. This is a workaround to -// a problem of cvFindChessboardCorners being slow on images with no chessboard -// - src: input image -// - size: chessboard size -// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called, -// 0 if there is no chessboard, -1 in case of error -int cvCheckChessboard(IplImage* src, CvSize size); - - /* Detects corners on a chessboard calibration pattern */ -/*int cvFindChessboardCorners( const void* image, CvSize pattern_size, - CvPoint2D32f* corners, - int* corner_count CV_DEFAULT(NULL), - int flags CV_DEFAULT(CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE) );*/ - -/* Draws individual chessboard corners or the whole chessboard detected */ -/*void cvDrawChessboardCorners( CvArr* image, CvSize pattern_size, - CvPoint2D32f* corners, - int count, int pattern_was_found );*/ - -/*#define CV_CALIB_USE_INTRINSIC_GUESS 1 -#define CV_CALIB_FIX_ASPECT_RATIO 2 -#define CV_CALIB_FIX_PRINCIPAL_POINT 4 -#define CV_CALIB_ZERO_TANGENT_DIST 8 -#define CV_CALIB_FIX_FOCAL_LENGTH 16 -#define CV_CALIB_FIX_K1 32 -#define CV_CALIB_FIX_K2 64 -#define CV_CALIB_FIX_K3 128 -#define CV_CALIB_FIX_K4 2048 -#define CV_CALIB_FIX_K5 4096 -#define CV_CALIB_FIX_K6 8192 -#define CV_CALIB_RATIONAL_MODEL 16384 -#define CV_CALIB_THIN_PRISM_MODEL 32768 -#define CV_CALIB_FIX_S1_S2_S3_S4 65536 -#define CV_CALIB_TILTED_MODEL 262144 -#define CV_CALIB_FIX_TAUX_TAUY 524288 -#define CV_CALIB_FIX_TANGENT_DIST 2097152 - -#define CV_CALIB_NINTRINSIC 18*/ - -/* Finds intrinsic and extrinsic camera parameters - from a few views of known calibration pattern */ -double cvCalibrateCamera2( const CvMat* object_points, - const CvMat* image_points, - const CvMat* point_counts, - CvSize image_size, - CvMat* camera_matrix, - CvMat* distortion_coeffs, - CvMat* rotation_vectors CV_DEFAULT(NULL), - CvMat* translation_vectors CV_DEFAULT(NULL), - int flags CV_DEFAULT(0), - CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( - CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)) ); - -/* Finds intrinsic and extrinsic camera parameters - from a few views of known calibration pattern */ -double cvCalibrateCamera4( const CvMat* object_points, - const CvMat* image_points, - const CvMat* point_counts, - CvSize image_size, - int iFixedPoint, - CvMat* camera_matrix, - CvMat* distortion_coeffs, - CvMat* rotation_vectors CV_DEFAULT(NULL), - CvMat* translation_vectors CV_DEFAULT(NULL), - CvMat* newObjPoints CV_DEFAULT(NULL), - int flags CV_DEFAULT(0), - CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( - CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)) ); - -/* Computes various useful characteristics of the camera from the data computed by - cvCalibrateCamera2 */ -void cvCalibrationMatrixValues( const CvMat *camera_matrix, - CvSize image_size, - double aperture_width CV_DEFAULT(0), - double aperture_height CV_DEFAULT(0), - double *fovx CV_DEFAULT(NULL), - double *fovy CV_DEFAULT(NULL), - double *focal_length CV_DEFAULT(NULL), - CvPoint2D64f *principal_point CV_DEFAULT(NULL), - double *pixel_aspect_ratio CV_DEFAULT(NULL)); - -/*#define CV_CALIB_FIX_INTRINSIC 256 -#define CV_CALIB_SAME_FOCAL_LENGTH 512*/ - -/* Computes the transformation from one camera coordinate system to another one - from a few correspondent views of the same calibration target. Optionally, calibrates - both cameras */ -double cvStereoCalibrate( const CvMat* object_points, const CvMat* image_points1, - const CvMat* image_points2, const CvMat* npoints, - CvMat* camera_matrix1, CvMat* dist_coeffs1, - CvMat* camera_matrix2, CvMat* dist_coeffs2, - CvSize image_size, CvMat* R, CvMat* T, - CvMat* E CV_DEFAULT(0), CvMat* F CV_DEFAULT(0), - int flags CV_DEFAULT(CV_CALIB_FIX_INTRINSIC), - CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( - CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6)) ); - -#define CV_CALIB_ZERO_DISPARITY 1024 - -/* Computes 3D rotations (+ optional shift) for each camera coordinate system to make both - views parallel (=> to make all the epipolar lines horizontal or vertical) */ -void cvStereoRectify( const CvMat* camera_matrix1, const CvMat* camera_matrix2, - const CvMat* dist_coeffs1, const CvMat* dist_coeffs2, - CvSize image_size, const CvMat* R, const CvMat* T, - CvMat* R1, CvMat* R2, CvMat* P1, CvMat* P2, - CvMat* Q CV_DEFAULT(0), - int flags CV_DEFAULT(CV_CALIB_ZERO_DISPARITY), - double alpha CV_DEFAULT(-1), - CvSize new_image_size CV_DEFAULT(cvSize(0,0)), - CvRect* valid_pix_ROI1 CV_DEFAULT(0), - CvRect* valid_pix_ROI2 CV_DEFAULT(0)); - -/* Computes rectification transformations for uncalibrated pair of images using a set - of point correspondences */ -int cvStereoRectifyUncalibrated( const CvMat* points1, const CvMat* points2, - const CvMat* F, CvSize img_size, - CvMat* H1, CvMat* H2, - double threshold CV_DEFAULT(5)); - - - -/* stereo correspondence parameters and functions */ - -#define CV_STEREO_BM_NORMALIZED_RESPONSE 0 -#define CV_STEREO_BM_XSOBEL 1 - -/* Block matching algorithm structure */ -typedef struct CvStereoBMState -{ - // pre-filtering (normalization of input images) - int preFilterType; // =CV_STEREO_BM_NORMALIZED_RESPONSE now - int preFilterSize; // averaging window size: ~5x5..21x21 - int preFilterCap; // the output of pre-filtering is clipped by [-preFilterCap,preFilterCap] - - // correspondence using Sum of Absolute Difference (SAD) - int SADWindowSize; // ~5x5..21x21 - int minDisparity; // minimum disparity (can be negative) - int numberOfDisparities; // maximum disparity - minimum disparity (> 0) - - // post-filtering - int textureThreshold; // the disparity is only computed for pixels - // with textured enough neighborhood - int uniquenessRatio; // accept the computed disparity d* only if - // SAD(d) >= SAD(d*)*(1 + uniquenessRatio/100.) - // for any d != d*+/-1 within the search range. - int speckleWindowSize; // disparity variation window - int speckleRange; // acceptable range of variation in window - - int trySmallerWindows; // if 1, the results may be more accurate, - // at the expense of slower processing - CvRect roi1, roi2; - int disp12MaxDiff; - - // temporary buffers - CvMat* preFilteredImg0; - CvMat* preFilteredImg1; - CvMat* slidingSumBuf; - CvMat* cost; - CvMat* disp; -} CvStereoBMState; - -#define CV_STEREO_BM_BASIC 0 -#define CV_STEREO_BM_FISH_EYE 1 -#define CV_STEREO_BM_NARROW 2 - -CvStereoBMState* cvCreateStereoBMState(int preset CV_DEFAULT(CV_STEREO_BM_BASIC), - int numberOfDisparities CV_DEFAULT(0)); - -void cvReleaseStereoBMState( CvStereoBMState** state ); - -void cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right, - CvArr* disparity, CvStereoBMState* state ); - -CvRect cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity, - int numberOfDisparities, int SADWindowSize ); - -void cvValidateDisparity( CvArr* disparity, const CvArr* cost, - int minDisparity, int numberOfDisparities, - int disp12MaxDiff CV_DEFAULT(1) ); - -/* Reprojects the computed disparity image to the 3D space using the specified 4x4 matrix */ -void cvReprojectImageTo3D( const CvArr* disparityImage, - CvArr* _3dImage, const CvMat* Q, - int handleMissingValues CV_DEFAULT(0) ); - -/** @brief Transforms the input image to compensate lens distortion -@see cv::undistort -*/ -void cvUndistort2( const CvArr* src, CvArr* dst, - const CvMat* camera_matrix, - const CvMat* distortion_coeffs, - const CvMat* new_camera_matrix CV_DEFAULT(0) ); - -/** @brief Computes transformation map from intrinsic camera parameters - that can used by cvRemap -*/ -void cvInitUndistortMap( const CvMat* camera_matrix, - const CvMat* distortion_coeffs, - CvArr* mapx, CvArr* mapy ); - -/** @brief Computes undistortion+rectification map for a head of stereo camera -@see cv::initUndistortRectifyMap -*/ -void cvInitUndistortRectifyMap( const CvMat* camera_matrix, - const CvMat* dist_coeffs, - const CvMat *R, const CvMat* new_camera_matrix, - CvArr* mapx, CvArr* mapy ); - -/** @brief Computes the original (undistorted) feature coordinates - from the observed (distorted) coordinates -@see cv::undistortPoints -*/ -void cvUndistortPoints( const CvMat* src, CvMat* dst, - const CvMat* camera_matrix, - const CvMat* dist_coeffs, - const CvMat* R CV_DEFAULT(0), - const CvMat* P CV_DEFAULT(0)); - -/** @} calib3d_c */ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* OPENCV_CALIB3D_C_API_H */ diff --git a/modules/calib3d/src/posit.cpp b/modules/calib3d/src/posit.cpp deleted file mode 100644 index 22043121d0..0000000000 --- a/modules/calib3d/src/posit.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of Intel Corporation may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ -#include "precomp.hpp" -#include "calib3d_c_api.h" - -/* POSIT structure */ -struct CvPOSITObject -{ - int N; - float* inv_matr; - float* obj_vecs; - float* img_vecs; -}; - -static void icvPseudoInverse3D( float *a, float *b, int n, int method ); - -static CvStatus icvCreatePOSITObject( CvPoint3D32f *points, - int numPoints, - CvPOSITObject **ppObject ) -{ - int i; - - /* Compute size of required memory */ - /* buffer for inverse matrix = N*3*float */ - /* buffer for storing weakImagePoints = numPoints * 2 * float */ - /* buffer for storing object vectors = N*3*float */ - /* buffer for storing image vectors = N*2*float */ - - int N = numPoints - 1; - int inv_matr_size = N * 3 * sizeof( float ); - int obj_vec_size = inv_matr_size; - int img_vec_size = N * 2 * sizeof( float ); - CvPOSITObject *pObject; - - /* check bad arguments */ - if( points == NULL ) - return CV_NULLPTR_ERR; - if( numPoints < 4 ) - return CV_BADSIZE_ERR; - if( ppObject == NULL ) - return CV_NULLPTR_ERR; - - /* memory allocation */ - pObject = (CvPOSITObject *) cvAlloc( sizeof( CvPOSITObject ) + - inv_matr_size + obj_vec_size + img_vec_size ); - - if( !pObject ) - return CV_OUTOFMEM_ERR; - - /* part the memory between all structures */ - pObject->N = N; - pObject->inv_matr = (float *) ((char *) pObject + sizeof( CvPOSITObject )); - pObject->obj_vecs = (float *) ((char *) (pObject->inv_matr) + inv_matr_size); - pObject->img_vecs = (float *) ((char *) (pObject->obj_vecs) + obj_vec_size); - -/****************************************************************************************\ -* Construct object vectors from object points * -\****************************************************************************************/ - for( i = 0; i < numPoints - 1; i++ ) - { - pObject->obj_vecs[i] = points[i + 1].x - points[0].x; - pObject->obj_vecs[N + i] = points[i + 1].y - points[0].y; - pObject->obj_vecs[2 * N + i] = points[i + 1].z - points[0].z; - } -/****************************************************************************************\ -* Compute pseudoinverse matrix * -\****************************************************************************************/ - icvPseudoInverse3D( pObject->obj_vecs, pObject->inv_matr, N, 0 ); - - *ppObject = pObject; - return CV_NO_ERR; -} - - -static CvStatus icvPOSIT( CvPOSITObject *pObject, CvPoint2D32f *imagePoints, - float focalLength, CvTermCriteria criteria, - float* rotation, float* translation ) -{ - int i, j, k; - int count = 0; - bool converged = false; - float scale = 0, inv_Z = 0; - float diff = (float)criteria.epsilon; - - /* Check bad arguments */ - if( imagePoints == NULL ) - return CV_NULLPTR_ERR; - if( pObject == NULL ) - return CV_NULLPTR_ERR; - if( focalLength <= 0 ) - return CV_BADFACTOR_ERR; - if( !rotation ) - return CV_NULLPTR_ERR; - if( !translation ) - return CV_NULLPTR_ERR; - if( (criteria.type == 0) || (criteria.type > (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS))) - return CV_BADFLAG_ERR; - if( (criteria.type & CV_TERMCRIT_EPS) && criteria.epsilon < 0 ) - return CV_BADFACTOR_ERR; - if( (criteria.type & CV_TERMCRIT_ITER) && criteria.max_iter <= 0 ) - return CV_BADFACTOR_ERR; - - /* init variables */ - float inv_focalLength = 1 / focalLength; - int N = pObject->N; - float *objectVectors = pObject->obj_vecs; - float *invMatrix = pObject->inv_matr; - float *imgVectors = pObject->img_vecs; - - while( !converged ) - { - if( count == 0 ) - { - /* subtract out origin to get image vectors */ - for( i = 0; i < N; i++ ) - { - imgVectors[i] = imagePoints[i + 1].x - imagePoints[0].x; - imgVectors[N + i] = imagePoints[i + 1].y - imagePoints[0].y; - } - } - else - { - diff = 0; - /* Compute new SOP (scaled orthograthic projection) image from pose */ - for( i = 0; i < N; i++ ) - { - /* objectVector * k */ - float old; - float tmp = objectVectors[i] * rotation[6] /*[2][0]*/ + - objectVectors[N + i] * rotation[7] /*[2][1]*/ + - objectVectors[2 * N + i] * rotation[8] /*[2][2]*/; - - tmp *= inv_Z; - tmp += 1; - - old = imgVectors[i]; - imgVectors[i] = imagePoints[i + 1].x * tmp - imagePoints[0].x; - - diff = MAX( diff, (float) fabs( imgVectors[i] - old )); - - old = imgVectors[N + i]; - imgVectors[N + i] = imagePoints[i + 1].y * tmp - imagePoints[0].y; - - diff = MAX( diff, (float) fabs( imgVectors[N + i] - old )); - } - } - - /* calculate I and J vectors */ - for( i = 0; i < 2; i++ ) - { - for( j = 0; j < 3; j++ ) - { - rotation[3*i+j] /*[i][j]*/ = 0; - for( k = 0; k < N; k++ ) - { - rotation[3*i+j] /*[i][j]*/ += invMatrix[j * N + k] * imgVectors[i * N + k]; - } - } - } - - float inorm = - rotation[0] /*[0][0]*/ * rotation[0] /*[0][0]*/ + - rotation[1] /*[0][1]*/ * rotation[1] /*[0][1]*/ + - rotation[2] /*[0][2]*/ * rotation[2] /*[0][2]*/; - - float jnorm = - rotation[3] /*[1][0]*/ * rotation[3] /*[1][0]*/ + - rotation[4] /*[1][1]*/ * rotation[4] /*[1][1]*/ + - rotation[5] /*[1][2]*/ * rotation[5] /*[1][2]*/; - - const float invInorm = cvInvSqrt( inorm ); - const float invJnorm = cvInvSqrt( jnorm ); - - inorm *= invInorm; - jnorm *= invJnorm; - - rotation[0] /*[0][0]*/ *= invInorm; - rotation[1] /*[0][1]*/ *= invInorm; - rotation[2] /*[0][2]*/ *= invInorm; - - rotation[3] /*[1][0]*/ *= invJnorm; - rotation[4] /*[1][1]*/ *= invJnorm; - rotation[5] /*[1][2]*/ *= invJnorm; - - /* row2 = row0 x row1 (cross product) */ - rotation[6] /*->m[2][0]*/ = rotation[1] /*->m[0][1]*/ * rotation[5] /*->m[1][2]*/ - - rotation[2] /*->m[0][2]*/ * rotation[4] /*->m[1][1]*/; - - rotation[7] /*->m[2][1]*/ = rotation[2] /*->m[0][2]*/ * rotation[3] /*->m[1][0]*/ - - rotation[0] /*->m[0][0]*/ * rotation[5] /*->m[1][2]*/; - - rotation[8] /*->m[2][2]*/ = rotation[0] /*->m[0][0]*/ * rotation[4] /*->m[1][1]*/ - - rotation[1] /*->m[0][1]*/ * rotation[3] /*->m[1][0]*/; - - scale = (inorm + jnorm) / 2.0f; - inv_Z = scale * inv_focalLength; - - count++; - converged = ((criteria.type & CV_TERMCRIT_EPS) && (diff < criteria.epsilon)) - || ((criteria.type & CV_TERMCRIT_ITER) && (count == criteria.max_iter)); - } - const float invScale = 1 / scale; - translation[0] = imagePoints[0].x * invScale; - translation[1] = imagePoints[0].y * invScale; - translation[2] = 1 / inv_Z; - - return CV_NO_ERR; -} - - -static CvStatus icvReleasePOSITObject( CvPOSITObject ** ppObject ) -{ - cvFree( ppObject ); - return CV_NO_ERR; -} - -/*F/////////////////////////////////////////////////////////////////////////////////////// -// Name: icvPseudoInverse3D -// Purpose: Pseudoinverse N x 3 matrix N >= 3 -// Context: -// Parameters: -// a - input matrix -// b - pseudoinversed a -// n - number of rows in a -// method - if 0, then b = inv(transpose(a)*a) * transpose(a) -// if 1, then SVD used. -// Returns: -// Notes: Both matrix are stored by n-dimensional vectors. -// Now only method == 0 supported. -//F*/ -void -icvPseudoInverse3D( float *a, float *b, int n, int method ) -{ - if( method == 0 ) - { - float ata00 = 0; - float ata11 = 0; - float ata22 = 0; - float ata01 = 0; - float ata02 = 0; - float ata12 = 0; - - int k; - /* compute matrix ata = transpose(a) * a */ - for( k = 0; k < n; k++ ) - { - float a0 = a[k]; - float a1 = a[n + k]; - float a2 = a[2 * n + k]; - - ata00 += a0 * a0; - ata11 += a1 * a1; - ata22 += a2 * a2; - - ata01 += a0 * a1; - ata02 += a0 * a2; - ata12 += a1 * a2; - } - /* inverse matrix ata */ - { - float p00 = ata11 * ata22 - ata12 * ata12; - float p01 = -(ata01 * ata22 - ata12 * ata02); - float p02 = ata12 * ata01 - ata11 * ata02; - - float p11 = ata00 * ata22 - ata02 * ata02; - float p12 = -(ata00 * ata12 - ata01 * ata02); - float p22 = ata00 * ata11 - ata01 * ata01; - - float det = 0; - det += ata00 * p00; - det += ata01 * p01; - det += ata02 * p02; - - const float inv_det = 1 / det; - - /* compute resultant matrix */ - for( k = 0; k < n; k++ ) - { - float a0 = a[k]; - float a1 = a[n + k]; - float a2 = a[2 * n + k]; - - b[k] = (p00 * a0 + p01 * a1 + p02 * a2) * inv_det; - b[n + k] = (p01 * a0 + p11 * a1 + p12 * a2) * inv_det; - b[2 * n + k] = (p02 * a0 + p12 * a1 + p22 * a2) * inv_det; - } - } - } - - /*if ( method == 1 ) - { - } - */ - - return; -} - -CV_IMPL CvPOSITObject * -cvCreatePOSITObject( CvPoint3D32f * points, int numPoints ) -{ - CvPOSITObject *pObject = 0; - IPPI_CALL( icvCreatePOSITObject( points, numPoints, &pObject )); - return pObject; -} - - -CV_IMPL void -cvPOSIT( CvPOSITObject * pObject, CvPoint2D32f * imagePoints, - double focalLength, CvTermCriteria criteria, - float* rotation, float* translation ) -{ - IPPI_CALL( icvPOSIT( pObject, imagePoints,(float) focalLength, criteria, - rotation, translation )); -} - -CV_IMPL void -cvReleasePOSITObject( CvPOSITObject ** ppObject ) -{ - IPPI_CALL( icvReleasePOSITObject( ppObject )); -} - -/* End of file. */ diff --git a/modules/calib3d/src/upnp.cpp b/modules/calib3d/src/upnp.cpp deleted file mode 100644 index 24db8f1142..0000000000 --- a/modules/calib3d/src/upnp.cpp +++ /dev/null @@ -1,829 +0,0 @@ -//M*////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, all rights reserved. -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -/****************************************************************************************\ -* Exhaustive Linearization for Robust Camera Pose and Focal Length Estimation. -* Contributed by Edgar Riba -\****************************************************************************************/ - -#include "precomp.hpp" -#include "upnp.h" -#include - -#if 0 // fix buffer overflow first (FIXIT mark in .cpp file) - -using namespace std; -using namespace cv; - -upnp::upnp(const Mat& cameraMatrix, const Mat& opoints, const Mat& ipoints) -{ - if (cameraMatrix.depth() == CV_32F) - init_camera_parameters(cameraMatrix); - else - init_camera_parameters(cameraMatrix); - - number_of_correspondences = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F)); - - pws.resize(3 * number_of_correspondences); - us.resize(2 * number_of_correspondences); - - if (opoints.depth() == ipoints.depth()) - { - if (opoints.depth() == CV_32F) - init_points(opoints, ipoints); - else - init_points(opoints, ipoints); - } - else if (opoints.depth() == CV_32F) - init_points(opoints, ipoints); - else - init_points(opoints, ipoints); - - alphas.resize(4 * number_of_correspondences); - pcs.resize(3 * number_of_correspondences); - - max_nr = 0; - A1 = NULL; - A2 = NULL; -} - -upnp::~upnp() -{ - if (A1) - delete[] A1; - if (A2) - delete[] A2; -} - -double upnp::compute_pose(Mat& R, Mat& t) -{ - choose_control_points(); - compute_alphas(); - - Mat * M = new Mat(2 * number_of_correspondences, 12, CV_64F); - - for(int i = 0; i < number_of_correspondences; i++) - { - fill_M(M, 2 * i, &alphas[0] + 4 * i, us[2 * i], us[2 * i + 1]); - } - - double mtm[12 * 12], d[12], ut[12 * 12], vt[12 * 12]; - Mat MtM = Mat(12, 12, CV_64F, mtm); - Mat D = Mat(12, 1, CV_64F, d); - Mat Ut = Mat(12, 12, CV_64F, ut); - Mat Vt = Mat(12, 12, CV_64F, vt); - - MtM = M->t() * (*M); - SVD::compute(MtM, D, Ut, Vt, SVD::MODIFY_A | SVD::FULL_UV); - Mat(Ut.t()).copyTo(Ut); - M->release(); - delete M; - - double l_6x12[6 * 12], rho[6]; - Mat L_6x12 = Mat(6, 12, CV_64F, l_6x12); - Mat Rho = Mat(6, 1, CV_64F, rho); - - compute_L_6x12(ut, l_6x12); - compute_rho(rho); - - double Betas[3][4], Efs[3][1], rep_errors[3]; - double Rs[3][3][3], ts[3][3]; - - find_betas_and_focal_approx_1(&Ut, &Rho, Betas[1], Efs[1]); - gauss_newton(&L_6x12, &Rho, Betas[1], Efs[1]); - rep_errors[1] = compute_R_and_t(ut, Betas[1], Rs[1], ts[1]); - - find_betas_and_focal_approx_2(&Ut, &Rho, Betas[2], Efs[2]); - gauss_newton(&L_6x12, &Rho, Betas[2], Efs[2]); - rep_errors[2] = compute_R_and_t(ut, Betas[2], Rs[2], ts[2]); - - int N = 1; - if (rep_errors[2] < rep_errors[1]) N = 2; - - Mat(3, 1, CV_64F, ts[N]).copyTo(t); - Mat(3, 3, CV_64F, Rs[N]).copyTo(R); - fu = fv = Efs[N][0]; - - return fu; -} - -void upnp::copy_R_and_t(const double R_src[3][3], const double t_src[3], - double R_dst[3][3], double t_dst[3]) -{ - for(int i = 0; i < 3; i++) { - for(int j = 0; j < 3; j++) - R_dst[i][j] = R_src[i][j]; - t_dst[i] = t_src[i]; - } -} - -void upnp::estimate_R_and_t(double R[3][3], double t[3]) -{ - double pc0[3], pw0[3]; - - pc0[0] = pc0[1] = pc0[2] = 0.0; - pw0[0] = pw0[1] = pw0[2] = 0.0; - - for(int i = 0; i < number_of_correspondences; i++) { - const double * pc = &pcs[3 * i]; - const double * pw = &pws[3 * i]; - - for(int j = 0; j < 3; j++) { - pc0[j] += pc[j]; - pw0[j] += pw[j]; - } - } - for(int j = 0; j < 3; j++) { - pc0[j] /= number_of_correspondences; - pw0[j] /= number_of_correspondences; - } - - double abt[3 * 3] = {0}, abt_d[3], abt_u[3 * 3], abt_v[3 * 3]; - Mat ABt = Mat(3, 3, CV_64F, abt); - Mat ABt_D = Mat(3, 1, CV_64F, abt_d); - Mat ABt_U = Mat(3, 3, CV_64F, abt_u); - Mat ABt_V = Mat(3, 3, CV_64F, abt_v); - - ABt.setTo(0.0); - for(int i = 0; i < number_of_correspondences; i++) { - double * pc = &pcs[3 * i]; - double * pw = &pws[3 * i]; - - for(int j = 0; j < 3; j++) { - abt[3 * j ] += (pc[j] - pc0[j]) * (pw[0] - pw0[0]); - abt[3 * j + 1] += (pc[j] - pc0[j]) * (pw[1] - pw0[1]); - abt[3 * j + 2] += (pc[j] - pc0[j]) * (pw[2] - pw0[2]); - } - } - - SVD::compute(ABt, ABt_D, ABt_U, ABt_V, SVD::MODIFY_A); - Mat(ABt_V.t()).copyTo(ABt_V); - - for(int i = 0; i < 3; i++) - for(int j = 0; j < 3; j++) - R[i][j] = dot(abt_u + 3 * i, abt_v + 3 * j); - - const double det = - R[0][0] * R[1][1] * R[2][2] + R[0][1] * R[1][2] * R[2][0] + R[0][2] * R[1][0] * R[2][1] - - R[0][2] * R[1][1] * R[2][0] - R[0][1] * R[1][0] * R[2][2] - R[0][0] * R[1][2] * R[2][1]; - - if (det < 0) { - R[2][0] = -R[2][0]; - R[2][1] = -R[2][1]; - R[2][2] = -R[2][2]; - } - - t[0] = pc0[0] - dot(R[0], pw0); - t[1] = pc0[1] - dot(R[1], pw0); - t[2] = pc0[2] - dot(R[2], pw0); -} - -void upnp::solve_for_sign(void) -{ - if (pcs[2] < 0.0) { - for(int i = 0; i < 4; i++) - for(int j = 0; j < 3; j++) - ccs[i][j] = -ccs[i][j]; - - for(int i = 0; i < number_of_correspondences; i++) { - pcs[3 * i ] = -pcs[3 * i]; - pcs[3 * i + 1] = -pcs[3 * i + 1]; - pcs[3 * i + 2] = -pcs[3 * i + 2]; - } - } -} - -double upnp::compute_R_and_t(const double * ut, const double * betas, - double R[3][3], double t[3]) -{ - compute_ccs(betas, ut); - compute_pcs(); - - solve_for_sign(); - - estimate_R_and_t(R, t); - - return reprojection_error(R, t); -} - -double upnp::reprojection_error(const double R[3][3], const double t[3]) -{ - double sum2 = 0.0; - - for(int i = 0; i < number_of_correspondences; i++) { - double * pw = &pws[3 * i]; - double Xc = dot(R[0], pw) + t[0]; - double Yc = dot(R[1], pw) + t[1]; - double inv_Zc = 1.0 / (dot(R[2], pw) + t[2]); - double ue = uc + fu * Xc * inv_Zc; - double ve = vc + fv * Yc * inv_Zc; - double u = us[2 * i], v = us[2 * i + 1]; - - sum2 += sqrt( (u - ue) * (u - ue) + (v - ve) * (v - ve) ); - } - - return sum2 / number_of_correspondences; -} - -void upnp::choose_control_points() -{ - for (int i = 0; i < 4; ++i) - cws[i][0] = cws[i][1] = cws[i][2] = 0.0; - cws[0][0] = cws[1][1] = cws[2][2] = 1.0; -} - -void upnp::compute_alphas() -{ - Mat CC = Mat(4, 3, CV_64F, &cws); - Mat PC = Mat(number_of_correspondences, 3, CV_64F, &pws[0]); - Mat ALPHAS = Mat(number_of_correspondences, 4, CV_64F, &alphas[0]); - - Mat CC_ = CC.clone().t(); - Mat PC_ = PC.clone().t(); - - Mat row14 = Mat::ones(1, 4, CV_64F); - Mat row1n = Mat::ones(1, number_of_correspondences, CV_64F); - - CC_.push_back(row14); - PC_.push_back(row1n); - - ALPHAS = Mat( CC_.inv() * PC_ ).t(); -} - -void upnp::fill_M(Mat * M, const int row, const double * as, const double u, const double v) -{ - double * M1 = M->ptr(row); - double * M2 = M1 + 12; - - for(int i = 0; i < 4; i++) { - M1[3 * i ] = as[i] * fu; - M1[3 * i + 1] = 0.0; - M1[3 * i + 2] = as[i] * (uc - u); - - M2[3 * i ] = 0.0; - M2[3 * i + 1] = as[i] * fv; - M2[3 * i + 2] = as[i] * (vc - v); - } -} - -void upnp::compute_ccs(const double * betas, const double * ut) -{ - for(int i = 0; i < 4; ++i) - ccs[i][0] = ccs[i][1] = ccs[i][2] = 0.0; - - int N = 4; - for(int i = 0; i < N; ++i) { - const double * v = ut + 12 * (9 + i); - for(int j = 0; j < 4; ++j) - for(int k = 0; k < 3; ++k) - ccs[j][k] += betas[i] * v[3 * j + k]; // FIXIT: array subscript 144 is outside array bounds of 'double [144]' [-Warray-bounds] - // line 109: double ut[12 * 12] - // line 359: double u[12*12] - } - - for (int i = 0; i < 4; ++i) ccs[i][2] *= fu; -} - -void upnp::compute_pcs(void) -{ - for(int i = 0; i < number_of_correspondences; i++) { - double * a = &alphas[0] + 4 * i; - double * pc = &pcs[0] + 3 * i; - - for(int j = 0; j < 3; j++) - pc[j] = a[0] * ccs[0][j] + a[1] * ccs[1][j] + a[2] * ccs[2][j] + a[3] * ccs[3][j]; - } -} - -void upnp::find_betas_and_focal_approx_1(Mat * Ut, Mat * Rho, double * betas, double * efs) -{ - Mat Kmf1 = Mat(12, 1, CV_64F, Ut->ptr(11)); - Mat dsq = Mat(6, 1, CV_64F, Rho->ptr(0)); - - Mat D = compute_constraint_distance_2param_6eq_2unk_f_unk( Kmf1 ); - Mat Dt = D.t(); - - Mat A = Dt * D; - Mat b = Dt * dsq; - - Mat x = Mat(2, 1, CV_64F); - solve(A, b, x); - - betas[0] = sqrt( abs( x.at(0) ) ); - betas[1] = betas[2] = betas[3] = 0.0; - - efs[0] = sqrt( abs( x.at(1) ) ) / betas[0]; -} - -void upnp::find_betas_and_focal_approx_2(Mat * Ut, Mat * Rho, double * betas, double * efs) -{ - double u[12*12]; - Mat U = Mat(12, 12, CV_64F, u); - Ut->copyTo(U); - - Mat Kmf1 = Mat(12, 1, CV_64F, Ut->ptr(10)); - Mat Kmf2 = Mat(12, 1, CV_64F, Ut->ptr(11)); - Mat dsq = Mat(6, 1, CV_64F, Rho->ptr(0)); - - Mat D = compute_constraint_distance_3param_6eq_6unk_f_unk( Kmf1, Kmf2 ); - - Mat A = D; - Mat b = dsq; - - double x[6]; - Mat X = Mat(6, 1, CV_64F, x); - - solve(A, b, X, DECOMP_QR); - - double solutions[18][3]; - generate_all_possible_solutions_for_f_unk(x, solutions); - - // find solution with minimum reprojection error - double min_error = std::numeric_limits::max(); - int min_sol = 0; - for (int i = 0; i < 18; ++i) { - - betas[3] = solutions[i][0]; - betas[2] = solutions[i][1]; - betas[1] = betas[0] = 0.0; - fu = fv = solutions[i][2]; - - double Rs[3][3], ts[3]; - double error_i = compute_R_and_t( u, betas, Rs, ts); - - if( error_i < min_error) - { - min_error = error_i; - min_sol = i; - } -} - - betas[0] = solutions[min_sol][0]; - betas[1] = solutions[min_sol][1]; - betas[2] = betas[3] = 0.0; - - efs[0] = solutions[min_sol][2]; -} - -Mat upnp::compute_constraint_distance_2param_6eq_2unk_f_unk(const Mat& M1) -{ - Mat P = Mat(6, 2, CV_64F); - - double m[13]; - for (int i = 1; i < 13; ++i) m[i] = *M1.ptr(i-1); - - double t1 = pow( m[4], 2 ); - double t4 = pow( m[1], 2 ); - double t5 = pow( m[5], 2 ); - double t8 = pow( m[2], 2 ); - double t10 = pow( m[6], 2 ); - double t13 = pow( m[3], 2 ); - double t15 = pow( m[7], 2 ); - double t18 = pow( m[8], 2 ); - double t22 = pow( m[9], 2 ); - double t26 = pow( m[10], 2 ); - double t29 = pow( m[11], 2 ); - double t33 = pow( m[12], 2 ); - - *P.ptr(0,0) = t1 - 2 * m[4] * m[1] + t4 + t5 - 2 * m[5] * m[2] + t8; - *P.ptr(0,1) = t10 - 2 * m[6] * m[3] + t13; - *P.ptr(1,0) = t15 - 2 * m[7] * m[1] + t4 + t18 - 2 * m[8] * m[2] + t8; - *P.ptr(1,1) = t22 - 2 * m[9] * m[3] + t13; - *P.ptr(2,0) = t26 - 2 * m[10] * m[1] + t4 + t29 - 2 * m[11] * m[2] + t8; - *P.ptr(2,1) = t33 - 2 * m[12] * m[3] + t13; - *P.ptr(3,0) = t15 - 2 * m[7] * m[4] + t1 + t18 - 2 * m[8] * m[5] + t5; - *P.ptr(3,1) = t22 - 2 * m[9] * m[6] + t10; - *P.ptr(4,0) = t26 - 2 * m[10] * m[4] + t1 + t29 - 2 * m[11] * m[5] + t5; - *P.ptr(4,1) = t33 - 2 * m[12] * m[6] + t10; - *P.ptr(5,0) = t26 - 2 * m[10] * m[7] + t15 + t29 - 2 * m[11] * m[8] + t18; - *P.ptr(5,1) = t33 - 2 * m[12] * m[9] + t22; - - return P; -} - -Mat upnp::compute_constraint_distance_3param_6eq_6unk_f_unk(const Mat& M1, const Mat& M2) -{ - Mat P = Mat(6, 6, CV_64F); - - double m[3][13]; - for (int i = 1; i < 13; ++i) - { - m[1][i] = *M1.ptr(i-1); - m[2][i] = *M2.ptr(i-1); - } - - double t1 = pow( m[1][4], 2 ); - double t2 = pow( m[1][1], 2 ); - double t7 = pow( m[1][5], 2 ); - double t8 = pow( m[1][2], 2 ); - double t11 = m[1][1] * m[2][1]; - double t12 = m[1][5] * m[2][5]; - double t15 = m[1][2] * m[2][2]; - double t16 = m[1][4] * m[2][4]; - double t19 = pow( m[2][4], 2 ); - double t22 = pow( m[2][2], 2 ); - double t23 = pow( m[2][1], 2 ); - double t24 = pow( m[2][5], 2 ); - double t28 = pow( m[1][6], 2 ); - double t29 = pow( m[1][3], 2 ); - double t34 = pow( m[1][3], 2 ); - double t36 = m[1][6] * m[2][6]; - double t40 = pow( m[2][6], 2 ); - double t41 = pow( m[2][3], 2 ); - double t47 = pow( m[1][7], 2 ); - double t48 = pow( m[1][8], 2 ); - double t52 = m[1][7] * m[2][7]; - double t55 = m[1][8] * m[2][8]; - double t59 = pow( m[2][8], 2 ); - double t62 = pow( m[2][7], 2 ); - double t64 = pow( m[1][9], 2 ); - double t68 = m[1][9] * m[2][9]; - double t74 = pow( m[2][9], 2 ); - double t78 = pow( m[1][10], 2 ); - double t79 = pow( m[1][11], 2 ); - double t84 = m[1][10] * m[2][10]; - double t87 = m[1][11] * m[2][11]; - double t90 = pow( m[2][10], 2 ); - double t95 = pow( m[2][11], 2 ); - double t99 = pow( m[1][12], 2 ); - double t101 = m[1][12] * m[2][12]; - double t105 = pow( m[2][12], 2 ); - - *P.ptr(0,0) = t1 + t2 - 2 * m[1][4] * m[1][1] - 2 * m[1][5] * m[1][2] + t7 + t8; - *P.ptr(0,1) = -2 * m[2][4] * m[1][1] + 2 * t11 + 2 * t12 - 2 * m[1][4] * m[2][1] - 2 * m[2][5] * m[1][2] + 2 * t15 + 2 * t16 - 2 * m[1][5] * m[2][2]; - *P.ptr(0,2) = t19 - 2 * m[2][4] * m[2][1] + t22 + t23 + t24 - 2 * m[2][5] * m[2][2]; - *P.ptr(0,3) = t28 + t29 - 2 * m[1][6] * m[1][3]; - *P.ptr(0,4) = -2 * m[2][6] * m[1][3] + 2 * t34 - 2 * m[1][6] * m[2][3] + 2 * t36; - *P.ptr(0,5) = -2 * m[2][6] * m[2][3] + t40 + t41; - - *P.ptr(1,0) = t8 - 2 * m[1][8] * m[1][2] - 2 * m[1][7] * m[1][1] + t47 + t48 + t2; - *P.ptr(1,1) = 2 * t15 - 2 * m[1][8] * m[2][2] - 2 * m[2][8] * m[1][2] + 2 * t52 - 2 * m[1][7] * m[2][1] - 2 * m[2][7] * m[1][1] + 2 * t55 + 2 * t11; - *P.ptr(1,2) = -2 * m[2][8] * m[2][2] + t22 + t23 + t59 - 2 * m[2][7] * m[2][1] + t62; - *P.ptr(1,3) = t29 + t64 - 2 * m[1][9] * m[1][3]; - *P.ptr(1,4) = 2 * t34 + 2 * t68 - 2 * m[2][9] * m[1][3] - 2 * m[1][9] * m[2][3]; - *P.ptr(1,5) = -2 * m[2][9] * m[2][3] + t74 + t41; - - *P.ptr(2,0) = -2 * m[1][11] * m[1][2] + t2 + t8 + t78 + t79 - 2 * m[1][10] * m[1][1]; - *P.ptr(2,1) = 2 * t15 - 2 * m[1][11] * m[2][2] + 2 * t84 - 2 * m[1][10] * m[2][1] - 2 * m[2][10] * m[1][1] + 2 * t87 - 2 * m[2][11] * m[1][2]+ 2 * t11; - *P.ptr(2,2) = t90 + t22 - 2 * m[2][10] * m[2][1] + t23 - 2 * m[2][11] * m[2][2] + t95; - *P.ptr(2,3) = -2 * m[1][12] * m[1][3] + t99 + t29; - *P.ptr(2,4) = 2 * t34 + 2 * t101 - 2 * m[2][12] * m[1][3] - 2 * m[1][12] * m[2][3]; - *P.ptr(2,5) = t41 + t105 - 2 * m[2][12] * m[2][3]; - - *P.ptr(3,0) = t48 + t1 - 2 * m[1][8] * m[1][5] + t7 - 2 * m[1][7] * m[1][4] + t47; - *P.ptr(3,1) = 2 * t16 - 2 * m[1][7] * m[2][4] + 2 * t55 + 2 * t52 - 2 * m[1][8] * m[2][5] - 2 * m[2][8] * m[1][5] - 2 * m[2][7] * m[1][4] + 2 * t12; - *P.ptr(3,2) = t24 - 2 * m[2][8] * m[2][5] + t19 - 2 * m[2][7] * m[2][4] + t62 + t59; - *P.ptr(3,3) = -2 * m[1][9] * m[1][6] + t64 + t28; - *P.ptr(3,4) = 2 * t68 + 2 * t36 - 2 * m[2][9] * m[1][6] - 2 * m[1][9] * m[2][6]; - *P.ptr(3,5) = t40 + t74 - 2 * m[2][9] * m[2][6]; - - *P.ptr(4,0) = t1 - 2 * m[1][10] * m[1][4] + t7 + t78 + t79 - 2 * m[1][11] * m[1][5]; - *P.ptr(4,1) = 2 * t84 - 2 * m[1][11] * m[2][5] - 2 * m[1][10] * m[2][4] + 2 * t16 - 2 * m[2][11] * m[1][5] + 2 * t87 - 2 * m[2][10] * m[1][4] + 2 * t12; - *P.ptr(4,2) = t19 + t24 - 2 * m[2][10] * m[2][4] - 2 * m[2][11] * m[2][5] + t95 + t90; - *P.ptr(4,3) = t28 - 2 * m[1][12] * m[1][6] + t99; - *P.ptr(4,4) = 2 * t101 + 2 * t36 - 2 * m[2][12] * m[1][6] - 2 * m[1][12] * m[2][6]; - *P.ptr(4,5) = t105 - 2 * m[2][12] * m[2][6] + t40; - - *P.ptr(5,0) = -2 * m[1][10] * m[1][7] + t47 + t48 + t78 + t79 - 2 * m[1][11] * m[1][8]; - *P.ptr(5,1) = 2 * t84 + 2 * t87 - 2 * m[2][11] * m[1][8] - 2 * m[1][10] * m[2][7] - 2 * m[2][10] * m[1][7] + 2 * t55 + 2 * t52 - 2 * m[1][11] * m[2][8]; - *P.ptr(5,2) = -2 * m[2][10] * m[2][7] - 2 * m[2][11] * m[2][8] + t62 + t59 + t90 + t95; - *P.ptr(5,3) = t64 - 2 * m[1][12] * m[1][9] + t99; - *P.ptr(5,4) = 2 * t68 - 2 * m[2][12] * m[1][9] - 2 * m[1][12] * m[2][9] + 2 * t101; - *P.ptr(5,5) = t105 - 2 * m[2][12] * m[2][9] + t74; - - return P; -} - -void upnp::generate_all_possible_solutions_for_f_unk(const double betas[5], double solutions[18][3]) -{ - int matrix_to_resolve[18][9] = { - { 2, 0, 0, 1, 1, 0, 2, 0, 2 }, { 2, 0, 0, 1, 1, 0, 1, 1, 2 }, - { 2, 0, 0, 1, 1, 0, 0, 2, 2 }, { 2, 0, 0, 0, 2, 0, 2, 0, 2 }, - { 2, 0, 0, 0, 2, 0, 1, 1, 2 }, { 2, 0, 0, 0, 2, 0, 0, 2, 2 }, - { 2, 0, 0, 2, 0, 2, 1, 1, 2 }, { 2, 0, 0, 2, 0, 2, 0, 2, 2 }, - { 2, 0, 0, 1, 1, 2, 0, 2, 2 }, { 1, 1, 0, 0, 2, 0, 2, 0, 2 }, - { 1, 1, 0, 0, 2, 0, 1, 1, 2 }, { 1, 1, 0, 2, 0, 2, 0, 2, 2 }, - { 1, 1, 0, 2, 0, 2, 1, 1, 2 }, { 1, 1, 0, 2, 0, 2, 0, 2, 2 }, - { 1, 1, 0, 1, 1, 2, 0, 2, 2 }, { 0, 2, 0, 2, 0, 2, 1, 1, 2 }, - { 0, 2, 0, 2, 0, 2, 0, 2, 2 }, { 0, 2, 0, 1, 1, 2, 0, 2, 2 } - }; - - int combination[18][3] = { - { 1, 2, 4 }, { 1, 2, 5 }, { 1, 2, 6 }, { 1, 3, 4 }, - { 1, 3, 5 }, { 1, 3, 6 }, { 1, 4, 5 }, { 1, 4, 6 }, - { 1, 5, 6 }, { 2, 3, 4 }, { 2, 3, 5 }, { 2, 3, 6 }, - { 2, 4, 5 }, { 2, 4, 6 }, { 2, 5, 6 }, { 3, 4, 5 }, - { 3, 4, 6 }, { 3, 5, 6 } - }; - - for (int i = 0; i < 18; ++i) { - double matrix[9], independent_term[3]; - Mat M = Mat(3, 3, CV_64F, matrix); - Mat I = Mat(3, 1, CV_64F, independent_term); - Mat S = Mat(1, 3, CV_64F); - - for (int j = 0; j < 9; ++j) matrix[j] = (double)matrix_to_resolve[i][j]; - - independent_term[0] = log( abs( betas[ combination[i][0]-1 ] ) ); - independent_term[1] = log( abs( betas[ combination[i][1]-1 ] ) ); - independent_term[2] = log( abs( betas[ combination[i][2]-1 ] ) ); - - exp( Mat(M.inv() * I), S); - - solutions[i][0] = S.at(0); - solutions[i][1] = S.at(1) * sign( betas[1] ); - solutions[i][2] = abs( S.at(2) ); - } -} - -void upnp::gauss_newton(const Mat * L_6x12, const Mat * Rho, double betas[4], double * f) -{ - const int iterations_number = 50; - - double a[6*4], b[6], x[4] = {0}; - Mat * A = new Mat(6, 4, CV_64F, a); - Mat * B = new Mat(6, 1, CV_64F, b); - Mat * X = new Mat(4, 1, CV_64F, x); - - for(int k = 0; k < iterations_number; k++) - { - compute_A_and_b_gauss_newton(L_6x12->ptr(0), Rho->ptr(0), betas, A, B, f[0]); - qr_solve(A, B, X); - for(int i = 0; i < 3; i++) - betas[i] += x[i]; - f[0] += x[3]; - } - - if (f[0] < 0) f[0] = -f[0]; - fu = fv = f[0]; - - A->release(); - delete A; - - B->release(); - delete B; - - X->release(); - delete X; - -} - -void upnp::compute_A_and_b_gauss_newton(const double * l_6x12, const double * rho, - const double betas[4], Mat * A, Mat * b, double const f) -{ - - for(int i = 0; i < 6; i++) { - const double * rowL = l_6x12 + i * 12; - double * rowA = A->ptr(i); - - rowA[0] = 2 * rowL[0] * betas[0] + rowL[1] * betas[1] + rowL[2] * betas[2] + f*f * ( 2 * rowL[6]*betas[0] + rowL[7]*betas[1] + rowL[8]*betas[2] ); - rowA[1] = rowL[1] * betas[0] + 2 * rowL[3] * betas[1] + rowL[4] * betas[2] + f*f * ( rowL[7]*betas[0] + 2 * rowL[9]*betas[1] + rowL[10]*betas[2] ); - rowA[2] = rowL[2] * betas[0] + rowL[4] * betas[1] + 2 * rowL[5] * betas[2] + f*f * ( rowL[8]*betas[0] + rowL[10]*betas[1] + 2 * rowL[11]*betas[2] ); - rowA[3] = 2*f * ( rowL[6]*betas[0]*betas[0] + rowL[7]*betas[0]*betas[1] + rowL[8]*betas[0]*betas[2] + rowL[9]*betas[1]*betas[1] + rowL[10]*betas[1]*betas[2] + rowL[11]*betas[2]*betas[2] ) ; - - *b->ptr(i) = rho[i] - - ( - rowL[0] * betas[0] * betas[0] + - rowL[1] * betas[0] * betas[1] + - rowL[2] * betas[0] * betas[2] + - rowL[3] * betas[1] * betas[1] + - rowL[4] * betas[1] * betas[2] + - rowL[5] * betas[2] * betas[2] + - f*f * rowL[6] * betas[0] * betas[0] + - f*f * rowL[7] * betas[0] * betas[1] + - f*f * rowL[8] * betas[0] * betas[2] + - f*f * rowL[9] * betas[1] * betas[1] + - f*f * rowL[10] * betas[1] * betas[2] + - f*f * rowL[11] * betas[2] * betas[2] - ); - } -} - -void upnp::compute_L_6x12(const double * ut, double * l_6x12) -{ - const double * v[3]; - - v[0] = ut + 12 * 9; - v[1] = ut + 12 * 10; - v[2] = ut + 12 * 11; - - double dv[3][6][3]; - - for(int i = 0; i < 3; i++) { - int a = 0, b = 1; - for(int j = 0; j < 6; j++) { - dv[i][j][0] = v[i][3 * a ] - v[i][3 * b]; - dv[i][j][1] = v[i][3 * a + 1] - v[i][3 * b + 1]; - dv[i][j][2] = v[i][3 * a + 2] - v[i][3 * b + 2]; - - b++; - if (b > 3) { - a++; - b = a + 1; - } - } - } - - for(int i = 0; i < 6; i++) { - double * row = l_6x12 + 12 * i; - - row[0] = dotXY(dv[0][i], dv[0][i]); - row[1] = 2.0f * dotXY(dv[0][i], dv[1][i]); - row[2] = dotXY(dv[1][i], dv[1][i]); - row[3] = 2.0f * dotXY(dv[0][i], dv[2][i]); - row[4] = 2.0f * dotXY(dv[1][i], dv[2][i]); - row[5] = dotXY(dv[2][i], dv[2][i]); - - row[6] = dotZ(dv[0][i], dv[0][i]); - row[7] = 2.0f * dotZ(dv[0][i], dv[1][i]); - row[8] = 2.0f * dotZ(dv[0][i], dv[2][i]); - row[9] = dotZ(dv[1][i], dv[1][i]); - row[10] = 2.0f * dotZ(dv[1][i], dv[2][i]); - row[11] = dotZ(dv[2][i], dv[2][i]); - } -} - -void upnp::compute_rho(double * rho) -{ - rho[0] = dist2(cws[0], cws[1]); - rho[1] = dist2(cws[0], cws[2]); - rho[2] = dist2(cws[0], cws[3]); - rho[3] = dist2(cws[1], cws[2]); - rho[4] = dist2(cws[1], cws[3]); - rho[5] = dist2(cws[2], cws[3]); -} - -double upnp::dist2(const double * p1, const double * p2) -{ - return - (p1[0] - p2[0]) * (p1[0] - p2[0]) + - (p1[1] - p2[1]) * (p1[1] - p2[1]) + - (p1[2] - p2[2]) * (p1[2] - p2[2]); -} - -double upnp::dot(const double * v1, const double * v2) -{ - return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; -} - -double upnp::dotXY(const double * v1, const double * v2) -{ - return v1[0] * v2[0] + v1[1] * v2[1]; -} - -double upnp::dotZ(const double * v1, const double * v2) -{ - return v1[2] * v2[2]; -} - -double upnp::sign(const double v) -{ - return ( v < 0.0 ) ? -1.0 : ( v > 0.0 ) ? 1.0 : 0.0; -} - -void upnp::qr_solve(Mat * A, Mat * b, Mat * X) -{ - const int nr = A->rows; - const int nc = A->cols; - if (nr <= 0 || nc <= 0) - return; - - if (max_nr != 0 && max_nr < nr) - { - delete [] A1; - delete [] A2; - } - if (max_nr < nr) - { - max_nr = nr; - A1 = new double[nr]; - A2 = new double[nr]; - } - - double * pA = A->ptr(0), * ppAkk = pA; - for(int k = 0; k < nc; k++) - { - double * ppAik1 = ppAkk, eta = fabs(*ppAik1); - for(int i = k + 1; i < nr; i++) - { - double elt = fabs(*ppAik1); - if (eta < elt) eta = elt; - ppAik1 += nc; - } - if (eta == 0) - { - A1[k] = A2[k] = 0.0; - //cerr << "God damnit, A is singular, this shouldn't happen." << endl; - return; - } - else - { - double * ppAik2 = ppAkk, sum2 = 0.0, inv_eta = 1. / eta; - for(int i = k; i < nr; i++) - { - *ppAik2 *= inv_eta; - sum2 += *ppAik2 * *ppAik2; - ppAik2 += nc; - } - double sigma = sqrt(sum2); - if (*ppAkk < 0) - sigma = -sigma; - *ppAkk += sigma; - A1[k] = sigma * *ppAkk; - A2[k] = -eta * sigma; - for(int j = k + 1; j < nc; j++) - { - double * ppAik = ppAkk, sum = 0; - for(int i = k; i < nr; i++) - { - sum += *ppAik * ppAik[j - k]; - ppAik += nc; - } - double tau = sum / A1[k]; - ppAik = ppAkk; - for(int i = k; i < nr; i++) - { - ppAik[j - k] -= tau * *ppAik; - ppAik += nc; - } - } - } - ppAkk += nc + 1; - } - - // b <- Qt b - double * ppAjj = pA, * pb = b->ptr(0); - for(int j = 0; j < nc; j++) - { - double * ppAij = ppAjj, tau = 0; - for(int i = j; i < nr; i++) - { - tau += *ppAij * pb[i]; - ppAij += nc; - } - tau /= A1[j]; - ppAij = ppAjj; - for(int i = j; i < nr; i++) - { - pb[i] -= tau * *ppAij; - ppAij += nc; - } - ppAjj += nc + 1; - } - - // X = R-1 b - double * pX = X->ptr(0); - pX[nc - 1] = pb[nc - 1] / A2[nc - 1]; - for(int i = nc - 2; i >= 0; i--) - { - double * ppAij = pA + i * nc + (i + 1), sum = 0; - - for(int j = i + 1; j < nc; j++) - { - sum += *ppAij * pX[j]; - ppAij++; - } - pX[i] = (pb[i] - sum) / A2[i]; - } -} - -#endif diff --git a/modules/calib3d/src/upnp.h b/modules/calib3d/src/upnp.h deleted file mode 100644 index 513c6be7a1..0000000000 --- a/modules/calib3d/src/upnp.h +++ /dev/null @@ -1,140 +0,0 @@ -//M*////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, all rights reserved. -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -/****************************************************************************************\ -* Exhaustive Linearization for Robust Camera Pose and Focal Length Estimation. -* Contributed by Edgar Riba -\****************************************************************************************/ - -#ifndef OPENCV_CALIB3D_UPNP_H_ -#define OPENCV_CALIB3D_UPNP_H_ - -#include "precomp.hpp" -#include "opencv2/core/core_c.h" -#include - -#if 0 // fix buffer overflow first (FIXIT mark in .cpp file) - -class upnp -{ -public: - upnp(const cv::Mat& cameraMatrix, const cv::Mat& opoints, const cv::Mat& ipoints); - ~upnp(); - - double compute_pose(cv::Mat& R, cv::Mat& t); -private: - upnp(const upnp &); // copy disabled - upnp& operator=(const upnp &); // assign disabled - template - void init_camera_parameters(const cv::Mat& cameraMatrix) - { - uc = cameraMatrix.at (0, 2); - vc = cameraMatrix.at (1, 2); - fu = 1; - fv = 1; - } - template - void init_points(const cv::Mat& opoints, const cv::Mat& ipoints) - { - for(int i = 0; i < number_of_correspondences; i++) - { - pws[3 * i ] = opoints.at(i).x; - pws[3 * i + 1] = opoints.at(i).y; - pws[3 * i + 2] = opoints.at(i).z; - - us[2 * i ] = ipoints.at(i).x; - us[2 * i + 1] = ipoints.at(i).y; - } - } - - double reprojection_error(const double R[3][3], const double t[3]); - void choose_control_points(); - void compute_alphas(); - void fill_M(cv::Mat * M, const int row, const double * alphas, const double u, const double v); - void compute_ccs(const double * betas, const double * ut); - void compute_pcs(void); - - void solve_for_sign(void); - - void find_betas_and_focal_approx_1(cv::Mat * Ut, cv::Mat * Rho, double * betas, double * efs); - void find_betas_and_focal_approx_2(cv::Mat * Ut, cv::Mat * Rho, double * betas, double * efs); - void qr_solve(cv::Mat * A, cv::Mat * b, cv::Mat * X); - - cv::Mat compute_constraint_distance_2param_6eq_2unk_f_unk(const cv::Mat& M1); - cv::Mat compute_constraint_distance_3param_6eq_6unk_f_unk(const cv::Mat& M1, const cv::Mat& M2); - void generate_all_possible_solutions_for_f_unk(const double betas[5], double solutions[18][3]); - - double sign(const double v); - double dot(const double * v1, const double * v2); - double dotXY(const double * v1, const double * v2); - double dotZ(const double * v1, const double * v2); - double dist2(const double * p1, const double * p2); - - void compute_rho(double * rho); - void compute_L_6x12(const double * ut, double * l_6x12); - - void gauss_newton(const cv::Mat * L_6x12, const cv::Mat * Rho, double current_betas[4], double * efs); - void compute_A_and_b_gauss_newton(const double * l_6x12, const double * rho, - const double cb[4], cv::Mat * A, cv::Mat * b, double const f); - - double compute_R_and_t(const double * ut, const double * betas, - double R[3][3], double t[3]); - - void estimate_R_and_t(double R[3][3], double t[3]); - - void copy_R_and_t(const double R_dst[3][3], const double t_dst[3], - double R_src[3][3], double t_src[3]); - - - double uc, vc, fu, fv; - - std::vector pws, us, alphas, pcs; - int number_of_correspondences; - - double cws[4][3], ccs[4][3]; - int max_nr; - double * A1, * A2; -}; - -#endif - -#endif // OPENCV_CALIB3D_UPNP_H_ diff --git a/modules/calib3d/test/test_posit.cpp b/modules/calib3d/test/test_posit.cpp deleted file mode 100644 index d63ce33e0f..0000000000 --- a/modules/calib3d/test/test_posit.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of Intel Corporation may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#include "test_precomp.hpp" - -// POSIT is not exposed to C++ API yet, so the test is disabled -#if 0 - -namespace opencv_test { namespace { - -class CV_POSITTest : public cvtest::BaseTest -{ -public: - CV_POSITTest(); -protected: - void run(int); -}; - - -CV_POSITTest::CV_POSITTest() -{ - test_case_count = 20; -} - -void CV_POSITTest::run( int start_from ) -{ - int code = cvtest::TS::OK; - - /* fixed parameters output */ - /*float rot[3][3]={ 0.49010f, 0.85057f, 0.19063f, - -0.56948f, 0.14671f, 0.80880f, - 0.65997f, -0.50495f, 0.55629f }; - - float trans[3] = { 0.0f, 0.0f, 40.02637f }; - */ - - /* Some variables */ - int i, counter; - - CvTermCriteria criteria; - CvPoint3D32f* obj_points; - CvPoint2D32f* img_points; - CvPOSITObject* object; - - float angleX, angleY, angleZ; - RNG& rng = ts->get_rng(); - int progress = 0; - - CvMat* true_rotationX = cvCreateMat( 3, 3, CV_32F ); - CvMat* true_rotationY = cvCreateMat( 3, 3, CV_32F ); - CvMat* true_rotationZ = cvCreateMat( 3, 3, CV_32F ); - CvMat* tmp_matrix = cvCreateMat( 3, 3, CV_32F ); - CvMat* true_rotation = cvCreateMat( 3, 3, CV_32F ); - CvMat* rotation = cvCreateMat( 3, 3, CV_32F ); - CvMat* translation = cvCreateMat( 3, 1, CV_32F ); - CvMat* true_translation = cvCreateMat( 3, 1, CV_32F ); - - const float flFocalLength = 760.f; - const float flEpsilon = 0.5f; - - /* Initialization */ - criteria.type = CV_TERMCRIT_EPS|CV_TERMCRIT_ITER; - criteria.epsilon = flEpsilon; - criteria.max_iter = 10000; - - /* Allocating source arrays; */ - obj_points = (CvPoint3D32f*)cvAlloc( 8 * sizeof(CvPoint3D32f) ); - img_points = (CvPoint2D32f*)cvAlloc( 8 * sizeof(CvPoint2D32f) ); - - /* Fill points arrays with values */ - - /* cube model with edge size 10 */ - obj_points[0].x = 0; obj_points[0].y = 0; obj_points[0].z = 0; - obj_points[1].x = 10; obj_points[1].y = 0; obj_points[1].z = 0; - obj_points[2].x = 10; obj_points[2].y = 10; obj_points[2].z = 0; - obj_points[3].x = 0; obj_points[3].y = 10; obj_points[3].z = 0; - obj_points[4].x = 0; obj_points[4].y = 0; obj_points[4].z = 10; - obj_points[5].x = 10; obj_points[5].y = 0; obj_points[5].z = 10; - obj_points[6].x = 10; obj_points[6].y = 10; obj_points[6].z = 10; - obj_points[7].x = 0; obj_points[7].y = 10; obj_points[7].z = 10; - - /* Loop for test some random object positions */ - for( counter = start_from; counter < test_case_count; counter++ ) - { - ts->update_context( this, counter, true ); - progress = update_progress( progress, counter, test_case_count, 0 ); - - /* set all rotation matrix to zero */ - cvZero( true_rotationX ); - cvZero( true_rotationY ); - cvZero( true_rotationZ ); - - /* fill random rotation matrix */ - angleX = (float)(cvtest::randReal(rng)*2*CV_PI); - angleY = (float)(cvtest::randReal(rng)*2*CV_PI); - angleZ = (float)(cvtest::randReal(rng)*2*CV_PI); - - true_rotationX->data.fl[0 *3+ 0] = 1; - true_rotationX->data.fl[1 *3+ 1] = (float)cos(angleX); - true_rotationX->data.fl[2 *3+ 2] = true_rotationX->data.fl[1 *3+ 1]; - true_rotationX->data.fl[1 *3+ 2] = -(float)sin(angleX); - true_rotationX->data.fl[2 *3+ 1] = -true_rotationX->data.fl[1 *3+ 2]; - - true_rotationY->data.fl[1 *3+ 1] = 1; - true_rotationY->data.fl[0 *3+ 0] = (float)cos(angleY); - true_rotationY->data.fl[2 *3+ 2] = true_rotationY->data.fl[0 *3+ 0]; - true_rotationY->data.fl[0 *3+ 2] = -(float)sin(angleY); - true_rotationY->data.fl[2 *3+ 0] = -true_rotationY->data.fl[0 *3+ 2]; - - true_rotationZ->data.fl[2 *3+ 2] = 1; - true_rotationZ->data.fl[0 *3+ 0] = (float)cos(angleZ); - true_rotationZ->data.fl[1 *3+ 1] = true_rotationZ->data.fl[0 *3+ 0]; - true_rotationZ->data.fl[0 *3+ 1] = -(float)sin(angleZ); - true_rotationZ->data.fl[1 *3+ 0] = -true_rotationZ->data.fl[0 *3+ 1]; - - cvMatMul( true_rotationX, true_rotationY, tmp_matrix); - cvMatMul( tmp_matrix, true_rotationZ, true_rotation); - - /* fill translation vector */ - true_translation->data.fl[2] = (float)(cvtest::randReal(rng)*(2*flFocalLength-40) + 60); - true_translation->data.fl[0] = (float)((cvtest::randReal(rng)*2-1)*true_translation->data.fl[2]); - true_translation->data.fl[1] = (float)((cvtest::randReal(rng)*2-1)*true_translation->data.fl[2]); - - /* calculate perspective projection */ - for ( i = 0; i < 8; i++ ) - { - float vec[3]; - CvMat Vec = cvMat( 3, 1, CV_32F, vec ); - CvMat Obj_point = cvMat( 3, 1, CV_32F, &obj_points[i].x ); - - cvMatMul( true_rotation, &Obj_point, &Vec ); - - vec[0] += true_translation->data.fl[0]; - vec[1] += true_translation->data.fl[1]; - vec[2] += true_translation->data.fl[2]; - - img_points[i].x = flFocalLength * vec[0] / vec[2]; - img_points[i].y = flFocalLength * vec[1] / vec[2]; - } - - /*img_points[0].x = 0 ; img_points[0].y = 0; - img_points[1].x = 80; img_points[1].y = -93; - img_points[2].x = 245;img_points[2].y = -77; - img_points[3].x = 185;img_points[3].y = 32; - img_points[4].x = 32; img_points[4].y = 135; - img_points[5].x = 99; img_points[5].y = 35; - img_points[6].x = 247; img_points[6].y = 62; - img_points[7].x = 195; img_points[7].y = 179; - */ - - object = cvCreatePOSITObject( obj_points, 8 ); - cvPOSIT( object, img_points, flFocalLength, criteria, - rotation->data.fl, translation->data.fl ); - cvReleasePOSITObject( &object ); - - Mat _rotation = cvarrToMat(rotation), _true_rotation = cvarrToMat(true_rotation); - Mat _translation = cvarrToMat(translation), _true_translation = cvarrToMat(true_translation); - code = cvtest::cmpEps2( ts, _rotation, _true_rotation, flEpsilon, false, "rotation matrix" ); - if( code < 0 ) - break; - - code = cvtest::cmpEps2( ts, _translation, _true_translation, flEpsilon, false, "translation vector" ); - if( code < 0 ) - break; - } - - cvFree( &obj_points ); - cvFree( &img_points ); - - cvReleaseMat( &true_rotationX ); - cvReleaseMat( &true_rotationY ); - cvReleaseMat( &true_rotationZ ); - cvReleaseMat( &tmp_matrix ); - cvReleaseMat( &true_rotation ); - cvReleaseMat( &rotation ); - cvReleaseMat( &translation ); - cvReleaseMat( &true_translation ); - - if( code < 0 ) - ts->set_failed_test_info( code ); -} - -TEST(Calib3d_POSIT, accuracy) { CV_POSITTest test; test.safe_run(); } - -}} // namespace - -#endif - -/* End of file. */ diff --git a/modules/core/doc/intro.markdown b/modules/core/doc/intro.markdown index 65494508b5..0378510f3d 100644 --- a/modules/core/doc/intro.markdown +++ b/modules/core/doc/intro.markdown @@ -16,11 +16,12 @@ libraries. The following modules are available: remapping), color space conversion, histograms, and so on. - @ref video (**video**) - a video analysis module that includes motion estimation, background subtraction, and object tracking algorithms. -- @ref calib3d (**calib3d**) - basic multiple-view geometry algorithms, single and stereo camera calibration, - object pose estimation, stereo correspondence algorithms, and elements of 3D reconstruction. +- @ref _3d "3d" (**3d**) - basic multiple-view geometry algorithms, object pose estimation and elements of 3D reconstruction. - @ref features2d (**features2d**) - salient feature detectors, descriptors, and descriptor matchers. - @ref objdetect (**objdetect**) - detection of objects and instances of the predefined classes (for example, faces, eyes, mugs, people, cars, and so on). +- @ref calib (**calib**) - single and stereo camera calibration +- @ref stereo (**stereo**) - stereo correspondence algorithms - @ref highgui (**highgui**) - an easy-to-use interface to simple UI capabilities. - @ref videoio (**videoio**) - an easy-to-use interface to video capturing and video codecs. - ... some other helper modules, such as FLANN and Google test wrappers, Python bindings, and diff --git a/modules/features2d/misc/java/test/Features2dTest.java b/modules/features2d/misc/java/test/Features2dTest.java index db9739bd44..f6979d7168 100644 --- a/modules/features2d/misc/java/test/Features2dTest.java +++ b/modules/features2d/misc/java/test/Features2dTest.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.opencv.calib3d.Calib3d; +import org.opencv.cv3d.Cv3d; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.MatOfInt; @@ -133,7 +133,7 @@ public class Features2dTest extends OpenCVTestCase { MatOfPoint2f points1 = new MatOfPoint2f(lp1.toArray(new Point[0])); MatOfPoint2f points2 = new MatOfPoint2f(lp2.toArray(new Point[0])); - Mat hmg = Calib3d.findHomography(points1, points2, Calib3d.RANSAC, 3); + Mat hmg = Cv3d.findHomography(points1, points2, Cv3d.RANSAC, 3); assertMatEqual(Mat.eye(3, 3, CvType.CV_64F), hmg, EPS); diff --git a/modules/features2d/misc/python/test/test_feature_homography.py b/modules/features2d/misc/python/test/test_feature_homography.py old mode 100644 new mode 100755 diff --git a/modules/features2d/test/test_nearestneighbors.cpp b/modules/features2d/test/test_nearestneighbors.cpp index f63ebb8d92..42fc6fe948 100644 --- a/modules/features2d/test/test_nearestneighbors.cpp +++ b/modules/features2d/test/test_nearestneighbors.cpp @@ -112,7 +112,7 @@ int NearestNeighborTest::checkFind( const Mat& data ) } double correctPerc = correctMatches / (double)pointsCount; - EXPECT_GE(correctPerc, .75) << "correctMatches=" << correctMatches << " pointsCount=" << pointsCount; + EXPECT_GE(correctPerc, .73) << "correctMatches=" << correctMatches << " pointsCount=" << pointsCount; } return code; diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 00e3dfa353..d42a07cb43 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -4642,9 +4642,9 @@ class CV_EXPORTS_W_SIMPLE FontFace public: /** @brief loads default font */ CV_WRAP FontFace(); - /** @brief - loads font at the specified path or with specified name. - Empty fontPathOrName means the default embedded font. + /** @brief loads font at the specified path or with specified name. + @param fontPathOrName either path to the custom font or the name of embedded font: "sans", "italic" or "uni". + Empty fontPathOrName means the default embedded font. */ CV_WRAP FontFace(const String& fontPathOrName); diff --git a/modules/imgproc/src/stb_truetype.cpp b/modules/imgproc/src/stb_truetype.cpp index d33962005d..edbf72d104 100644 --- a/modules/imgproc/src/stb_truetype.cpp +++ b/modules/imgproc/src/stb_truetype.cpp @@ -4154,384 +4154,6 @@ STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int *xpos += b->xadvance; } -////////////////////////////////////////////////////////////////////////////// -// -// sdf computation -// - -static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) -{ - float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; - float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; - float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; - float roperp = orig[1]*ray[0] - orig[0]*ray[1]; - - float a = q0perp - 2*q1perp + q2perp; - float b = q1perp - q0perp; - float c = q0perp - roperp; - - float s0 = 0., s1 = 0.; - int num_s = 0; - - if (a != 0.0) { - float discr = b*b - a*c; - if (discr > 0.0) { - float rcpna = -1 / a; - float d = (float) STBTT_sqrt(discr); - s0 = (b+d) * rcpna; - s1 = (b-d) * rcpna; - if (s0 >= 0.0 && s0 <= 1.0) - num_s = 1; - if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { - if (num_s == 0) s0 = s1; - ++num_s; - } - } - } else { - // 2*b*s + c = 0 - // s = -c / (2*b) - s0 = c / (-2 * b); - if (s0 >= 0.0 && s0 <= 1.0) - num_s = 1; - } - - if (num_s == 0) - return 0; - else { - float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); - float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; - - float q0d = q0[0]*rayn_x + q0[1]*rayn_y; - float q1d = q1[0]*rayn_x + q1[1]*rayn_y; - float q2d = q2[0]*rayn_x + q2[1]*rayn_y; - float rod = orig[0]*rayn_x + orig[1]*rayn_y; - - float q10d = q1d - q0d; - float q20d = q2d - q0d; - float q0rd = q0d - rod; - - hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; - hits[0][1] = a*s0+b; - - if (num_s > 1) { - hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; - hits[1][1] = a*s1+b; - return 2; - } else { - return 1; - } - } -} - -static int equal(float *a, float *b) -{ - return (a[0] == b[0] && a[1] == b[1]); -} - -static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) -{ - int i; - float orig[2], ray[2] = { 1, 0 }; - float y_frac; - int winding = 0; - - orig[0] = x; - orig[1] = y; - - // make sure y never passes through a vertex of the shape - y_frac = (float) STBTT_fmod(y, 1.0f); - if (y_frac < 0.01f) - y += 0.01f; - else if (y_frac > 0.99f) - y -= 0.01f; - orig[1] = y; - - // test a ray from (-infinity,y) to (x,y) - for (i=0; i < nverts; ++i) { - if (verts[i].type == STBTT_vline) { - int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; - int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; - if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { - float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) - winding += (y0 < y1) ? 1 : -1; - } - } - if (verts[i].type == STBTT_vcurve) { - int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; - int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; - int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; - int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); - int by = STBTT_max(y0,STBTT_max(y1,y2)); - if (y > ay && y < by && x > ax) { - float q0[2],q1[2],q2[2]; - float hits[2][2]; - q0[0] = (float)x0; - q0[1] = (float)y0; - q1[0] = (float)x1; - q1[1] = (float)y1; - q2[0] = (float)x2; - q2[1] = (float)y2; - if (equal(q0,q1) || equal(q1,q2)) { - x0 = (int)verts[i-1].x; - y0 = (int)verts[i-1].y; - x1 = (int)verts[i ].x; - y1 = (int)verts[i ].y; - if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { - float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) - winding += (y0 < y1) ? 1 : -1; - } - } else { - int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); - if (num_hits >= 1) - if (hits[0][0] < 0) - winding += (hits[0][1] < 0 ? -1 : 1); - if (num_hits >= 2) - if (hits[1][0] < 0) - winding += (hits[1][1] < 0 ? -1 : 1); - } - } - } - } - return winding; -} - -static float stbtt__cuberoot( float x ) -{ - if (x<0) - return -(float) STBTT_pow(-x,1.0f/3.0f); - else - return (float) STBTT_pow( x,1.0f/3.0f); -} - -// x^3 + c*x^2 + b*x + a = 0 -static int stbtt__solve_cubic(float a, float b, float c, float* r) -{ - float s = -a / 3; - float p = b - a*a / 3; - float q = a * (2*a*a - 9*b) / 27 + c; - float p3 = p*p*p; - float d = q*q + 4*p3 / 27; - if (d >= 0) { - float z = (float) STBTT_sqrt(d); - float u = (-q + z) / 2; - float v = (-q - z) / 2; - u = stbtt__cuberoot(u); - v = stbtt__cuberoot(v); - r[0] = s + u + v; - return 1; - } else { - float u = (float) STBTT_sqrt(-p/3); - float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative - float m = (float) STBTT_cos(v); - float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; - r[0] = s + u * 2 * m; - r[1] = s - u * (m + n); - r[2] = s - u * (m - n); - - //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? - //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); - //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); - return 3; - } -} - -STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, - int padding, unsigned char onedge_value, float pixel_dist_scale, - int *width, int *height, int *xoff, int *yoff) -{ - float scale_x = scale, scale_y = scale; - int w, h, ix0 = 0, iy0 = 0, ix1 = 0, iy1 = 0; - unsigned char *data; - - if (scale == 0) return NULL; - - stbtt_vertex *verts; - int num_verts = stbtt_GetGlyphShape(info, glyph, &verts, &ix0, &iy0, &ix1, &iy1); - stbtt__ScaleGlyphBox(ix0, iy0, ix1, iy1, scale, scale, 0.f, 0.f, &ix0, &iy0, &ix1, &iy1); - - // if empty, return NULL - if (ix0 == ix1 || iy0 == iy1) { - STBTT_free(verts, info->userdata); - return 0; - } - - ix0 -= padding; - iy0 -= padding; - ix1 += padding; - iy1 += padding; - - w = (ix1 - ix0); - h = (iy1 - iy0); - - if (width ) *width = w; - if (height) *height = h; - if (xoff ) *xoff = ix0; - if (yoff ) *yoff = iy0; - - // invert for y-downwards bitmaps - scale_y = -scale_y; - - { - int x,y,i,j; - float *precompute; - - data = (unsigned char *) STBTT_malloc(w * h, info->userdata); - precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); - - for (i=0,j=num_verts-1; i < num_verts; j=i++) { - if (verts[i].type == STBTT_vline) { - float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; - float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; - float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); - precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; - } else if (verts[i].type == STBTT_vcurve) { - float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; - float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; - float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; - float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; - float len2 = bx*bx + by*by; - if (len2 != 0.0f) - precompute[i] = 1.0f / (bx*bx + by*by); - else - precompute[i] = 0.0f; - } else - precompute[i] = 0.0f; - } - - for (y=iy0; y < iy1; ++y) { - for (x=ix0; x < ix1; ++x) { - float val; - float min_dist = 999999.0f; - float sx = (float) x + 0.5f; - float sy = (float) y + 0.5f; - float x_gspace = (sx / scale_x); - float y_gspace = (sy / scale_y); - - int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path - - for (i=0; i < num_verts; ++i) { - float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; - - // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve - float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); - if (dist2 < min_dist*min_dist) - min_dist = (float) STBTT_sqrt(dist2); - - if (verts[i].type == STBTT_vline) { - float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; - - // coarse culling against bbox - //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && - // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) - float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; - STBTT_assert(i != 0); - if (dist < min_dist) { - // check position along line - // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) - // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) - float dx = x1-x0, dy = y1-y0; - float px = x0-sx, py = y0-sy; - // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy - // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve - float t = -(px*dx + py*dy) / (dx*dx + dy*dy); - if (t >= 0.0f && t <= 1.0f) - min_dist = dist; - } - } else if (verts[i].type == STBTT_vcurve) { - float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; - float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; - float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); - float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); - float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); - float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); - // coarse culling against bbox to avoid computing cubic unnecessarily - if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { - int num=0; - float ax = x1-x0, ay = y1-y0; - float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; - float mx = x0 - sx, my = y0 - sy; - float res[3],px,py,t,it; - float a_inv = precompute[i]; - if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula - float a = 3*(ax*bx + ay*by); - float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); - float c = mx*ax+my*ay; - if (a == 0.0) { // if a is 0, it's linear - if (b != 0.0) { - res[num++] = -c/b; - } - } else { - float discriminant = b*b - 4*a*c; - if (discriminant < 0) - num = 0; - else { - float root = (float) STBTT_sqrt(discriminant); - res[0] = (-b - root)/(2*a); - res[1] = (-b + root)/(2*a); - num = 2; // don't bother distinguishing 1-solution case, as code below will still work - } - } - } else { - float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point - float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; - float d = (mx*ax+my*ay) * a_inv; - num = stbtt__solve_cubic(b, c, d, res); - } - if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { - t = res[0], it = 1.0f - t; - px = it*it*x0 + 2*t*it*x1 + t*t*x2; - py = it*it*y0 + 2*t*it*y1 + t*t*y2; - dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); - if (dist2 < min_dist * min_dist) - min_dist = (float) STBTT_sqrt(dist2); - } - if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { - t = res[1], it = 1.0f - t; - px = it*it*x0 + 2*t*it*x1 + t*t*x2; - py = it*it*y0 + 2*t*it*y1 + t*t*y2; - dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); - if (dist2 < min_dist * min_dist) - min_dist = (float) STBTT_sqrt(dist2); - } - if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { - t = res[2], it = 1.0f - t; - px = it*it*x0 + 2*t*it*x1 + t*t*x2; - py = it*it*y0 + 2*t*it*y1 + t*t*y2; - dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); - if (dist2 < min_dist * min_dist) - min_dist = (float) STBTT_sqrt(dist2); - } - } - } - } - if (winding == 0) - min_dist = -min_dist; // if outside the shape, value is negative - val = onedge_value + pixel_dist_scale * min_dist; - if (val < 0) - val = 0; - else if (val > 255) - val = 255; - data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; - } - } - STBTT_free(precompute, info->userdata); - STBTT_free(verts, info->userdata); - } - return data; -} - -STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) -{ - return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); -} - -STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) -{ - STBTT_free(bitmap, userdata); -} - ////////////////////////////////////////////////////////////////////////////// // // font name matching -- recommended not to use this diff --git a/modules/imgproc/test/test_drawing.cpp b/modules/imgproc/test/test_drawing.cpp index ab559e790e..47a282926c 100644 --- a/modules/imgproc/test/test_drawing.cpp +++ b/modules/imgproc/test/test_drawing.cpp @@ -83,7 +83,7 @@ void CV_DrawingTest::run( int ) { // image should match exactly float err = (float)cvtest::norm( testImg, valImg, NORM_L1 ); - float Eps = 1; + float Eps = 10; if( err > Eps) { //imshow("reference", valImg); diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index e41117558a..b0769178c6 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -116,6 +116,15 @@ def mkdir_p(path): else: raise +def make_jname(m): + return "Cv"+m if (m[0] in "0123456789") else m + +def make_jmodule(m): + return "cv"+m if (m[0] in "0123456789") else m + +def make_namespace(ci): + return ('using namespace ' + ci.namespace.replace('.', '::') + ';') if ci.namespace and ci.namespace != 'cv' else '' + T_JAVA_START_INHERITED = read_contents(os.path.join(SCRIPT_DIR, 'templates/java_class_inherited.prolog')) T_JAVA_START_ORPHAN = read_contents(os.path.join(SCRIPT_DIR, 'templates/java_class.prolog')) T_JAVA_START_MODULE = read_contents(os.path.join(SCRIPT_DIR, 'templates/java_module.prolog')) @@ -270,6 +279,7 @@ class ClassInfo(GeneralInfo): self.name = '%s_%s' % (prefix, self.name) self.jname = '%s_%s' % (prefix, self.jname) + self.jname = make_jname(self.jname) self.base = '' if decl[1]: # FIXIT Use generator to find type properly instead of hacks below @@ -354,6 +364,7 @@ class ClassInfo(GeneralInfo): return Template(self.j_code.getvalue() + "\n\n" + self.jn_code.getvalue() + "\n}\n").substitute( module = m, + jmodule = make_jmodule(m), name = self.name, jname = self.jname, imports = "\n".join(self.getAllImports(M)), @@ -414,6 +425,7 @@ class FuncInfo(GeneralInfo): else: self.jname = '%s_%s' % (prefix, self.jname) + self.jname = make_jname(self.jname) self.static = ["","static"][ "/S" in decl[2] ] self.ctype = re.sub(r"^CvTermCriteria", "TermCriteria", decl[1] or "") self.args = [] @@ -611,7 +623,8 @@ class JavaWrapperGenerator(object): logging.info("\n\n===== Generating... =====") moduleCppCode = StringIO() - package_path = os.path.join(output_java_path, module) + package_path = os.path.join(output_java_path, make_jmodule(module)) + #print("package path: %s\n" % package_path) mkdir_p(package_path) for ci in sorted(self.classes.values(), key=lambda x: x.symbol_id): if ci.name == "Mat": @@ -619,7 +632,7 @@ class JavaWrapperGenerator(object): ci.initCodeStreams(self.Module) self.gen_class(ci) classJavaCode = ci.generateJavaCode(self.module, self.Module) - self.save("%s/%s/%s.java" % (output_java_path, module, ci.jname), classJavaCode) + self.save("%s/%s.java" % (package_path, ci.jname), classJavaCode) moduleCppCode.write(ci.generateCppCode()) ci.cleanupCodeStreams() cpp_file = os.path.abspath(os.path.join(output_jni_path, module + ".inl.hpp")) @@ -1040,13 +1053,13 @@ class JavaWrapperGenerator(object): clazz = ci.jname cpp_code.write ( Template( """ -JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname ($argst); +JNIEXPORT $rtype JNICALL Java_org_opencv_${jmodule}_${clazz}_$fname ($argst); -JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname +JNIEXPORT $rtype JNICALL Java_org_opencv_${jmodule}_${clazz}_$fname ($args) { ${namespace} - static const char method_name[] = "$module::$fname()"; + static const char method_name[] = "$jmodule::$fname()"; try { LOGD("%s", method_name);$prologue $retval$cvname($cvargs);$epilogue$ret @@ -1061,6 +1074,7 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname """ ).substitute( rtype = rtype, module = self.module.replace('_', '_1'), + jmodule = make_jmodule(self.module.replace('_', '_1')), clazz = clazz.replace('_', '_1'), fname = (fi.jname + '_' + str(suffix_counter)).replace('_', '_1'), args = ", ".join(["%s %s" % (type_dict[a.ctype].get("jni_type"), a.name) for a in jni_args]), @@ -1072,7 +1086,7 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname cvargs = " " + ", ".join(cvargs) + " " if cvargs else "", default = "\n " + default if default else "", retval = retval, - namespace = ('using namespace ' + ci.namespace.replace('.', '::') + ';') if ci.namespace and ci.namespace != 'cv' else '' + namespace = make_namespace(ci) ) ) # adding method signature to dictionary diff --git a/modules/java/generator/templates/java_class.prolog b/modules/java/generator/templates/java_class.prolog index 5662534bc5..d9134fe9c0 100644 --- a/modules/java/generator/templates/java_class.prolog +++ b/modules/java/generator/templates/java_class.prolog @@ -1,7 +1,7 @@ // // This file is auto-generated. Please don't modify it! // -package org.opencv.$module; +package org.opencv.$jmodule; $imports diff --git a/modules/java/generator/templates/java_class_inherited.prolog b/modules/java/generator/templates/java_class_inherited.prolog index 5865afa1ad..7b4393b994 100644 --- a/modules/java/generator/templates/java_class_inherited.prolog +++ b/modules/java/generator/templates/java_class_inherited.prolog @@ -1,7 +1,7 @@ // // This file is auto-generated. Please don't modify it! // -package org.opencv.$module; +package org.opencv.$jmodule; $imports diff --git a/modules/java/generator/templates/java_module.prolog b/modules/java/generator/templates/java_module.prolog index 5ff6a83fd1..0f735e6d79 100644 --- a/modules/java/generator/templates/java_module.prolog +++ b/modules/java/generator/templates/java_module.prolog @@ -1,7 +1,7 @@ // // This file is auto-generated. Please don't modify it! // -package org.opencv.$module; +package org.opencv.$jmodule; $imports diff --git a/modules/java/test/pure_test/CMakeLists.txt b/modules/java/test/pure_test/CMakeLists.txt index 82972fd147..e6904f927f 100644 --- a/modules/java/test/pure_test/CMakeLists.txt +++ b/modules/java/test/pure_test/CMakeLists.txt @@ -1,6 +1,6 @@ if(NOT ANT_EXECUTABLE OR NOT BUILD_opencv_imgcodecs - OR NOT BUILD_opencv_calib3d) + OR NOT BUILD_opencv_3d) return() endif() diff --git a/modules/objc/generator/gen_objc.py b/modules/objc/generator/gen_objc.py index bd9743c757..3f51402ad2 100755 --- a/modules/objc/generator/gen_objc.py +++ b/modules/objc/generator/gen_objc.py @@ -124,6 +124,11 @@ def header_import(hdr): #hdr = hdr[pos+8 if pos >= 0 else 0:] return hdr +def make_objcname(m): + return "Cv"+m if (m[0] in "0123456789") else m + +def make_objcmodule(m): + return "cv"+m if (m[0] in "0123456789") else m T_OBJC_CLASS_HEADER = read_contents(os.path.join(SCRIPT_DIR, 'templates/objc_class_header.template')) T_OBJC_CLASS_BODY = read_contents(os.path.join(SCRIPT_DIR, 'templates/objc_class_body.template')) @@ -289,7 +294,7 @@ class ClassInfo(GeneralInfo): return Template("CLASS $namespace::$classpath.$name : $base").substitute(**self.__dict__) def getImports(self, module): - return ["#import \"%s.h\"" % c for c in sorted([m for m in [type_dict[m]["import_module"] if m in type_dict and "import_module" in type_dict[m] else m for m in self.imports] if m != self.name])] + return ["#import \"%s.h\"" % make_objcname(c) for c in sorted([m for m in [type_dict[m]["import_module"] if m in type_dict and "import_module" in type_dict[m] else m for m in self.imports] if m != self.name])] def isEnum(self, c): return c in type_dict and type_dict[c].get("is_enum", False) @@ -298,7 +303,7 @@ class ClassInfo(GeneralInfo): enum_decl = [x for x in self.imports if self.isEnum(x) and type_dict[x]["import_module"] != module] enum_imports = sorted(list(set([type_dict[m]["import_module"] for m in enum_decl]))) class_decl = [x for x in self.imports if not self.isEnum(x)] - return ["#import \"%s.h\"" % c for c in enum_imports] + [""] + ["@class %s;" % c for c in sorted(class_decl)] + return ["#import \"%s.h\"" % make_objcname(c) for c in enum_imports] + [""] + ["@class %s;" % c for c in sorted(class_decl)] def addImports(self, ctype, is_out_type): if ctype == self.cname: @@ -371,7 +376,7 @@ class ClassInfo(GeneralInfo): return Template(self.objc_header_template + "\n\n").substitute( module = M, additionalImports = self.additionalImports.getvalue(), - importBaseClass = '#import "' + self.base + '.h"' if not self.is_base_class else "", + importBaseClass = '#import "' + make_objcname(self.base) + '.h"' if not self.is_base_class else "", forwardDeclarations = "\n".join([_f for _f in self.getForwardDeclarations(objcM) if _f]), enumDeclarations = self.enum_declarations.getvalue(), nativePointerHandling = Template( @@ -392,7 +397,7 @@ class ClassInfo(GeneralInfo): manualMethodDeclations = "", methodDeclarations = self.method_declarations.getvalue(), name = self.name, - objcName = self.objc_name, + objcName = make_objcname(self.objc_name), cName = self.cname, imports = "\n".join(self.getImports(M)), docs = gen_class_doc(self.docstring, M, self.member_classes, self.member_enums), @@ -401,6 +406,7 @@ class ClassInfo(GeneralInfo): def generateObjcBodyCode(self, m, M): return Template(self.objc_body_template + "\n\n").substitute( module = M, + objcname = make_objcname(M), nativePointerHandling=Template( """ - (instancetype)initWithNativePtr:(cv::Ptr<$cName>)nativePtr { @@ -417,14 +423,14 @@ class ClassInfo(GeneralInfo): """ ).substitute( cName = self.fullName(isCPP=True), - objcName = self.objc_name, + objcName = make_objcname(self.objc_name), native_ptr_name = self.native_ptr_name, init_call = "init" if self.is_base_class else "initWithNativePtr:nativePtr" ), manualMethodDeclations = "", methodImplementations = self.method_implementations.getvalue(), name = self.name, - objcName = self.objc_name, + objcName = make_objcname(self.objc_name), cName = self.cname, imports = "\n".join(self.getImports(M)), docs = gen_class_doc(self.docstring, M, self.member_classes, self.member_enums), @@ -628,7 +634,7 @@ def build_swift_signature(args): return swift_signature def build_unrefined_call(name, args, constructor, static, classname, has_ret): - swift_refine_call = ("let ret = " if has_ret and not constructor else "") + ((classname + ".") if static else "") + (name if not constructor else "self.init") + swift_refine_call = ("let ret = " if has_ret and not constructor else "") + ((make_objcname(classname) + ".") if static else "") + (name if not constructor else "self.init") call_args = [] for a in args: if a.ctype not in type_dict: @@ -865,6 +871,7 @@ class ObjectiveCWrapperGenerator(object): def gen(self, srcfiles, module, output_path, output_objc_path, common_headers, manual_classes): self.clear() self.module = module + self.objcmodule = make_objcmodule(module) self.Module = module.capitalize() extension_implementations = StringIO() # Swift extensions implementations stream extension_signatures = [] @@ -909,9 +916,9 @@ class ObjectiveCWrapperGenerator(object): self.classes[self.Module].member_classes += manual_classes logging.info("\n\n===== Generating... =====") - package_path = os.path.join(output_objc_path, module) + package_path = os.path.join(output_objc_path, self.objcmodule) mkdir_p(package_path) - extension_file = "%s/%s/%sExt.swift" % (output_objc_path, module, self.Module) + extension_file = "%s/%sExt.swift" % (package_path, make_objcname(self.Module)) for ci in sorted(self.classes.values(), key=lambda x: x.symbol_id): if ci.name == "Mat": @@ -919,15 +926,16 @@ class ObjectiveCWrapperGenerator(object): ci.initCodeStreams(self.Module) self.gen_class(ci, self.module, extension_implementations, extension_signatures) classObjcHeaderCode = ci.generateObjcHeaderCode(self.module, self.Module, ci.objc_name) - header_file = "%s/%s/%s.h" % (output_objc_path, module, ci.objc_name) + objc_mangled_name = make_objcname(ci.objc_name) + header_file = "%s/%s.h" % (package_path, objc_mangled_name) self.save(header_file, classObjcHeaderCode) self.header_files.append(header_file) classObjcBodyCode = ci.generateObjcBodyCode(self.module, self.Module) - self.save("%s/%s/%s.mm" % (output_objc_path, module, ci.objc_name), classObjcBodyCode) + self.save("%s/%s.mm" % (package_path, objc_mangled_name), classObjcBodyCode) ci.cleanupCodeStreams() self.save(extension_file, extension_implementations.getvalue()) extension_implementations.close() - self.save(os.path.join(output_path, module+".txt"), self.makeReport()) + self.save(os.path.join(output_path, self.objcmodule+".txt"), self.makeReport()) def makeReport(self): ''' @@ -1209,7 +1217,7 @@ $unrefined_call$epilogue$ret """ ).substitute( - classname = ci.name, + classname = make_objcname(ci.name), deprecation_decl = "@available(*, deprecated)\n " if fi.deprecated else "", prototype = prototype, prologue = " " + "\n ".join(pro), @@ -1250,7 +1258,7 @@ $unrefined_call$epilogue$ret additional_imports.insert(0, h) if additional_imports: - ci.additionalImports.write('\n'.join(['#import %s' % h for h in additional_imports])) + ci.additionalImports.write('\n'.join(['#import %s' % make_objcname(h) for h in additional_imports])) # constants wrote_consts_pragma = False @@ -1404,7 +1412,7 @@ typedef NS_ENUM(int, {1}) {{ opencv_header = "#import \n\n" opencv_header += "// ! Project version number\nFOUNDATION_EXPORT double " + framework_name + "VersionNumber;\n\n" opencv_header += "// ! Project version string\nFOUNDATION_EXPORT const unsigned char " + framework_name + "VersionString[];\n\n" - opencv_header += "\n".join(["#import <" + framework_name + "/%s>" % os.path.basename(f) for f in self.header_files]) + opencv_header += "\n".join(["#import <" + framework_name + "/%s>" % os.path.basename(f) for f in self.header_files]) self.save(opencv_header_file, opencv_header) opencv_modulemap_file = os.path.join(output_objc_path, framework_name + ".modulemap") opencv_modulemap = "framework module " + framework_name + " {\n" diff --git a/modules/objc/generator/templates/objc_module_body.template b/modules/objc/generator/templates/objc_module_body.template index a11d2404f3..a8dc1fa80f 100644 --- a/modules/objc/generator/templates/objc_module_body.template +++ b/modules/objc/generator/templates/objc_module_body.template @@ -2,12 +2,12 @@ // This file is auto-generated. Please don't modify it! // -#import "$module.h" +#import "$objcName.h" #import "CVObjcUtil.h" $imports -@implementation $module +@implementation $objcName $methodImplementations diff --git a/modules/objc/generator/templates/objc_module_header.template b/modules/objc/generator/templates/objc_module_header.template index 88f45a11cf..a0ff298bb9 100644 --- a/modules/objc/generator/templates/objc_module_header.template +++ b/modules/objc/generator/templates/objc_module_header.template @@ -19,7 +19,7 @@ $enumDeclarations NS_ASSUME_NONNULL_BEGIN $docs -CV_EXPORTS @interface $module : $base +CV_EXPORTS @interface $objcName : $base $methodDeclarations diff --git a/modules/objdetect/CMakeLists.txt b/modules/objdetect/CMakeLists.txt index 3fa0c5d33b..8f31d097eb 100644 --- a/modules/objdetect/CMakeLists.txt +++ b/modules/objdetect/CMakeLists.txt @@ -1,5 +1,5 @@ set(the_description "Object Detection") -ocv_define_module(objdetect opencv_core opencv_imgproc opencv_calib3d WRAP java objc python js) +ocv_define_module(objdetect opencv_core opencv_imgproc opencv_3d WRAP java objc python js) if(HAVE_QUIRC) get_property(QUIRC_INCLUDE GLOBAL PROPERTY QUIRC_INCLUDE_DIR) diff --git a/modules/objdetect/src/qrcode.cpp b/modules/objdetect/src/qrcode.cpp index d47f1d3a20..c6700628a2 100644 --- a/modules/objdetect/src/qrcode.cpp +++ b/modules/objdetect/src/qrcode.cpp @@ -7,7 +7,7 @@ #include "precomp.hpp" #include "opencv2/objdetect.hpp" -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" #ifdef HAVE_QUIRC #include "quirc.h" diff --git a/modules/python/src2/hdr_parser.py b/modules/python/src2/hdr_parser.py index 897465010c..271f5b8fbe 100755 --- a/modules/python/src2/hdr_parser.py +++ b/modules/python/src2/hdr_parser.py @@ -11,7 +11,9 @@ opencv_hdr_list = [ "../../flann/include/opencv2/flann/miniflann.hpp", "../../ml/include/opencv2/ml.hpp", "../../imgproc/include/opencv2/imgproc.hpp", -"../../calib3d/include/opencv2/calib3d.hpp", +"../../3d/include/opencv2/3d.hpp", +"../../stereo/include/opencv2/stereo.hpp", +"../../calib/include/opencv2/calib.hpp", "../../features2d/include/opencv2/features2d.hpp", "../../video/include/opencv2/video/tracking.hpp", "../../video/include/opencv2/video/background_segm.hpp", diff --git a/modules/python/test/test_legacy.py b/modules/python/test/test_legacy.py old mode 100644 new mode 100755 diff --git a/modules/python/test/test_misc.py b/modules/python/test/test_misc.py old mode 100644 new mode 100755 diff --git a/modules/stereo/CMakeLists.txt b/modules/stereo/CMakeLists.txt new file mode 100644 index 0000000000..ab493af050 --- /dev/null +++ b/modules/stereo/CMakeLists.txt @@ -0,0 +1,9 @@ +set(the_description "Depth from Stereo") + +set(debug_modules "") +if(DEBUG_opencv_stereo) + list(APPEND debug_modules opencv_highgui) +endif() +ocv_define_module(stereo opencv_imgproc opencv_3d ${debug_modules} + WRAP java objc python js +) diff --git a/modules/stereo/include/opencv2/stereo.hpp b/modules/stereo/include/opencv2/stereo.hpp new file mode 100644 index 0000000000..984ba4a6a8 --- /dev/null +++ b/modules/stereo/include/opencv2/stereo.hpp @@ -0,0 +1,437 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#ifndef OPENCV_STEREO_HPP +#define OPENCV_STEREO_HPP + +#include "opencv2/core.hpp" + +/** + @defgroup stereo Stereo Correspondence + + */ + +namespace cv { + +enum +{ + STEREO_ZERO_DISPARITY=0x00400 +}; + +//! @addtogroup stereo +//! @{ + +/** @brief Computes rectification transforms for each head of a calibrated stereo camera. + +@param cameraMatrix1 First camera intrinsic matrix. +@param distCoeffs1 First camera distortion parameters. +@param cameraMatrix2 Second camera intrinsic matrix. +@param distCoeffs2 Second camera distortion parameters. +@param imageSize Size of the image used for stereo calibration. +@param R Rotation matrix from the coordinate system of the first camera to the second camera, +see @ref stereoCalibrate. +@param T Translation vector from the coordinate system of the first camera to the second camera, +see @ref stereoCalibrate. +@param R1 Output 3x3 rectification transform (rotation matrix) for the first camera. This matrix +brings points given in the unrectified first camera's coordinate system to points in the rectified +first camera's coordinate system. In more technical terms, it performs a change of basis from the +unrectified first camera's coordinate system to the rectified first camera's coordinate system. +@param R2 Output 3x3 rectification transform (rotation matrix) for the second camera. This matrix +brings points given in the unrectified second camera's coordinate system to points in the rectified +second camera's coordinate system. In more technical terms, it performs a change of basis from the +unrectified second camera's coordinate system to the rectified second camera's coordinate system. +@param P1 Output 3x4 projection matrix in the new (rectified) coordinate systems for the first +camera, i.e. it projects points given in the rectified first camera coordinate system into the +rectified first camera's image. +@param P2 Output 3x4 projection matrix in the new (rectified) coordinate systems for the second +camera, i.e. it projects points given in the rectified first camera coordinate system into the +rectified second camera's image. +@param Q Output \f$4 \times 4\f$ disparity-to-depth mapping matrix (see @ref reprojectImageTo3D). +@param flags Operation flags that may be zero or STEREO_ZERO_DISPARITY . If the flag is set, +the function makes the principal points of each camera have the same pixel coordinates in the +rectified views. And if the flag is not set, the function may still shift the images in the +horizontal or vertical direction (depending on the orientation of epipolar lines) to maximize the +useful image area. +@param alpha Free scaling parameter. If it is -1 or absent, the function performs the default +scaling. Otherwise, the parameter should be between 0 and 1. alpha=0 means that the rectified +images are zoomed and shifted so that only valid pixels are visible (no black areas after +rectification). alpha=1 means that the rectified image is decimated and shifted so that all the +pixels from the original images from the cameras are retained in the rectified images (no source +image pixels are lost). Any intermediate value yields an intermediate result between +those two extreme cases. +@param newImageSize New image resolution after rectification. The same size should be passed to +initUndistortRectifyMap (see the stereo_calib.cpp sample in OpenCV samples directory). When (0,0) +is passed (default), it is set to the original imageSize . Setting it to a larger value can help you +preserve details in the original image, especially when there is a big radial distortion. +@param validPixROI1 Optional output rectangles inside the rectified images where all the pixels +are valid. If alpha=0 , the ROIs cover the whole images. Otherwise, they are likely to be smaller +(see the picture below). +@param validPixROI2 Optional output rectangles inside the rectified images where all the pixels +are valid. If alpha=0 , the ROIs cover the whole images. Otherwise, they are likely to be smaller +(see the picture below). + +The function computes the rotation matrices for each camera that (virtually) make both camera image +planes the same plane. Consequently, this makes all the epipolar lines parallel and thus simplifies +the dense stereo correspondence problem. The function takes the matrices computed by stereoCalibrate +as input. As output, it provides two rotation matrices and also two projection matrices in the new +coordinates. The function distinguishes the following two cases: + +- **Horizontal stereo**: the first and the second camera views are shifted relative to each other + mainly along the x-axis (with possible small vertical shift). In the rectified images, the + corresponding epipolar lines in the left and right cameras are horizontal and have the same + y-coordinate. P1 and P2 look like: + + \f[\texttt{P1} = \begin{bmatrix} + f & 0 & cx_1 & 0 \\ + 0 & f & cy & 0 \\ + 0 & 0 & 1 & 0 + \end{bmatrix}\f] + + \f[\texttt{P2} = \begin{bmatrix} + f & 0 & cx_2 & T_x*f \\ + 0 & f & cy & 0 \\ + 0 & 0 & 1 & 0 + \end{bmatrix} ,\f] + + where \f$T_x\f$ is a horizontal shift between the cameras and \f$cx_1=cx_2\f$ if + STEREO_ZERO_DISPARITY is set. + +- **Vertical stereo**: the first and the second camera views are shifted relative to each other + mainly in the vertical direction (and probably a bit in the horizontal direction too). The epipolar + lines in the rectified images are vertical and have the same x-coordinate. P1 and P2 look like: + + \f[\texttt{P1} = \begin{bmatrix} + f & 0 & cx & 0 \\ + 0 & f & cy_1 & 0 \\ + 0 & 0 & 1 & 0 + \end{bmatrix}\f] + + \f[\texttt{P2} = \begin{bmatrix} + f & 0 & cx & 0 \\ + 0 & f & cy_2 & T_y*f \\ + 0 & 0 & 1 & 0 + \end{bmatrix},\f] + + where \f$T_y\f$ is a vertical shift between the cameras and \f$cy_1=cy_2\f$ if + STEREO_ZERO_DISPARITY is set. + +As you can see, the first three columns of P1 and P2 will effectively be the new "rectified" camera +matrices. The matrices, together with R1 and R2 , can then be passed to initUndistortRectifyMap to +initialize the rectification map for each camera. + +See below the screenshot from the stereo_calib.cpp sample. Some red horizontal lines pass through +the corresponding image regions. This means that the images are well rectified, which is what most +stereo correspondence algorithms rely on. The green rectangles are roi1 and roi2 . You see that +their interiors are all valid pixels. + +![image](pics/stereo_undistort.jpg) + */ +CV_EXPORTS_W void stereoRectify( InputArray cameraMatrix1, InputArray distCoeffs1, + InputArray cameraMatrix2, InputArray distCoeffs2, + Size imageSize, InputArray R, InputArray T, + OutputArray R1, OutputArray R2, + OutputArray P1, OutputArray P2, + OutputArray Q, int flags = STEREO_ZERO_DISPARITY, + double alpha = -1, Size newImageSize = Size(), + CV_OUT Rect* validPixROI1 = 0, CV_OUT Rect* validPixROI2 = 0 ); + +/** @brief Computes a rectification transform for an uncalibrated stereo camera. + +@param points1 Array of feature points in the first image. +@param points2 The corresponding points in the second image. The same formats as in +findFundamentalMat are supported. +@param F Input fundamental matrix. It can be computed from the same set of point pairs using +findFundamentalMat . +@param imgSize Size of the image. +@param H1 Output rectification homography matrix for the first image. +@param H2 Output rectification homography matrix for the second image. +@param threshold Optional threshold used to filter out the outliers. If the parameter is greater +than zero, all the point pairs that do not comply with the epipolar geometry (that is, the points +for which \f$|\texttt{points2[i]}^T*\texttt{F}*\texttt{points1[i]}|>\texttt{threshold}\f$ ) are +rejected prior to computing the homographies. Otherwise, all the points are considered inliers. + +The function computes the rectification transformations without knowing intrinsic parameters of the +cameras and their relative position in the space, which explains the suffix "uncalibrated". Another +related difference from stereoRectify is that the function outputs not the rectification +transformations in the object (3D) space, but the planar perspective transformations encoded by the +homography matrices H1 and H2 . The function implements the algorithm @cite Hartley99 . + +@note + While the algorithm does not need to know the intrinsic parameters of the cameras, it heavily + depends on the epipolar geometry. Therefore, if the camera lenses have a significant distortion, + it would be better to correct it before computing the fundamental matrix and calling this + function. For example, distortion coefficients can be estimated for each head of stereo camera + separately by using calibrateCamera . Then, the images can be corrected using undistort , or + just the point coordinates can be corrected with undistortPoints . + */ +CV_EXPORTS_W bool stereoRectifyUncalibrated( InputArray points1, InputArray points2, + InputArray F, Size imgSize, + OutputArray H1, OutputArray H2, + double threshold = 5 ); + + +CV_EXPORTS float rectify3Collinear( InputArray _cameraMatrix1, InputArray _distCoeffs1, + InputArray _cameraMatrix2, InputArray _distCoeffs2, + InputArray _cameraMatrix3, InputArray _distCoeffs3, + InputArrayOfArrays _imgpt1, + InputArrayOfArrays _imgpt3, + Size imageSize, InputArray _Rmat12, InputArray _Tmat12, + InputArray _Rmat13, InputArray _Tmat13, + OutputArray _Rmat1, OutputArray _Rmat2, OutputArray _Rmat3, + OutputArray _Pmat1, OutputArray _Pmat2, OutputArray _Pmat3, + OutputArray _Qmat, + double alpha, Size newImgSize, + Rect* roi1, Rect* roi2, int flags ); + +/** @brief The base class for stereo correspondence algorithms. + */ +class CV_EXPORTS_W StereoMatcher : public Algorithm +{ +public: + enum { DISP_SHIFT = 4, + DISP_SCALE = (1 << DISP_SHIFT) + }; + + /** @brief Computes disparity map for the specified stereo pair + + @param left Left 8-bit single-channel image. + @param right Right image of the same size and the same type as the left one. + @param disparity Output disparity map. It has the same size as the input images. Some algorithms, + like StereoBM or StereoSGBM compute 16-bit fixed-point disparity map (where each disparity value + has 4 fractional bits), whereas other algorithms output 32-bit floating-point disparity map. + */ + CV_WRAP virtual void compute( InputArray left, InputArray right, + OutputArray disparity ) = 0; + + CV_WRAP virtual int getMinDisparity() const = 0; + CV_WRAP virtual void setMinDisparity(int minDisparity) = 0; + + CV_WRAP virtual int getNumDisparities() const = 0; + CV_WRAP virtual void setNumDisparities(int numDisparities) = 0; + + CV_WRAP virtual int getBlockSize() const = 0; + CV_WRAP virtual void setBlockSize(int blockSize) = 0; + + CV_WRAP virtual int getSpeckleWindowSize() const = 0; + CV_WRAP virtual void setSpeckleWindowSize(int speckleWindowSize) = 0; + + CV_WRAP virtual int getSpeckleRange() const = 0; + CV_WRAP virtual void setSpeckleRange(int speckleRange) = 0; + + CV_WRAP virtual int getDisp12MaxDiff() const = 0; + CV_WRAP virtual void setDisp12MaxDiff(int disp12MaxDiff) = 0; +}; + + +/** @brief Class for computing stereo correspondence using the block matching algorithm, introduced and +contributed to OpenCV by K. Konolige. + */ +class CV_EXPORTS_W StereoBM : public StereoMatcher +{ +public: + enum { PREFILTER_NORMALIZED_RESPONSE = 0, + PREFILTER_XSOBEL = 1 + }; + + CV_WRAP virtual int getPreFilterType() const = 0; + CV_WRAP virtual void setPreFilterType(int preFilterType) = 0; + + CV_WRAP virtual int getPreFilterSize() const = 0; + CV_WRAP virtual void setPreFilterSize(int preFilterSize) = 0; + + CV_WRAP virtual int getPreFilterCap() const = 0; + CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; + + CV_WRAP virtual int getTextureThreshold() const = 0; + CV_WRAP virtual void setTextureThreshold(int textureThreshold) = 0; + + CV_WRAP virtual int getUniquenessRatio() const = 0; + CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + CV_WRAP virtual int getSmallerBlockSize() const = 0; + CV_WRAP virtual void setSmallerBlockSize(int blockSize) = 0; + + CV_WRAP virtual Rect getROI1() const = 0; + CV_WRAP virtual void setROI1(Rect roi1) = 0; + + CV_WRAP virtual Rect getROI2() const = 0; + CV_WRAP virtual void setROI2(Rect roi2) = 0; + + /** @brief Creates StereoBM object + + @param numDisparities the disparity search range. For each pixel algorithm will find the best + disparity from 0 (default minimum disparity) to numDisparities. The search range can then be + shifted by changing the minimum disparity. + @param blockSize the linear size of the blocks compared by the algorithm. The size should be odd + (as the block is centered at the current pixel). Larger block size implies smoother, though less + accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher + chance for algorithm to find a wrong correspondence. + + The function create StereoBM object. You can then call StereoBM::compute() to compute disparity for + a specific stereo pair. + */ + CV_WRAP static Ptr create(int numDisparities = 0, int blockSize = 21); +}; + +/** @brief The class implements the modified H. Hirschmuller algorithm @cite HH08 that differs from the original +one as follows: + +- By default, the algorithm is single-pass, which means that you consider only 5 directions +instead of 8. Set mode=StereoSGBM::MODE_HH in createStereoSGBM to run the full variant of the +algorithm but beware that it may consume a lot of memory. +- The algorithm matches blocks, not individual pixels. Though, setting blockSize=1 reduces the +blocks to single pixels. +- Mutual information cost function is not implemented. Instead, a simpler Birchfield-Tomasi +sub-pixel metric from @cite BT98 is used. Though, the color images are supported as well. +- Some pre- and post- processing steps from K. Konolige algorithm StereoBM are included, for +example: pre-filtering (StereoBM::PREFILTER_XSOBEL type) and post-filtering (uniqueness +check, quadratic interpolation and speckle filtering). + +@note + - (Python) An example illustrating the use of the StereoSGBM matching algorithm can be found + at opencv_source_code/samples/python/stereo_match.py + */ +class CV_EXPORTS_W StereoSGBM : public StereoMatcher +{ +public: + enum + { + MODE_SGBM = 0, + MODE_HH = 1, + MODE_SGBM_3WAY = 2, + MODE_HH4 = 3 + }; + + CV_WRAP virtual int getPreFilterCap() const = 0; + CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; + + CV_WRAP virtual int getUniquenessRatio() const = 0; + CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + CV_WRAP virtual int getP1() const = 0; + CV_WRAP virtual void setP1(int P1) = 0; + + CV_WRAP virtual int getP2() const = 0; + CV_WRAP virtual void setP2(int P2) = 0; + + CV_WRAP virtual int getMode() const = 0; + CV_WRAP virtual void setMode(int mode) = 0; + + /** @brief Creates StereoSGBM object + + @param minDisparity Minimum possible disparity value. Normally, it is zero but sometimes + rectification algorithms can shift images, so this parameter needs to be adjusted accordingly. + @param numDisparities Maximum disparity minus minimum disparity. The value is always greater than + zero. In the current implementation, this parameter must be divisible by 16. + @param blockSize Matched block size. It must be an odd number \>=1 . Normally, it should be + somewhere in the 3..11 range. + @param P1 The first parameter controlling the disparity smoothness. See below. + @param P2 The second parameter controlling the disparity smoothness. The larger the values are, + the smoother the disparity is. P1 is the penalty on the disparity change by plus or minus 1 + between neighbor pixels. P2 is the penalty on the disparity change by more than 1 between neighbor + pixels. The algorithm requires P2 \> P1 . See stereo_match.cpp sample where some reasonably good + P1 and P2 values are shown (like 8\*number_of_image_channels\*blockSize\*blockSize and + 32\*number_of_image_channels\*blockSize\*blockSize , respectively). + @param disp12MaxDiff Maximum allowed difference (in integer pixel units) in the left-right + disparity check. Set it to a non-positive value to disable the check. + @param preFilterCap Truncation value for the prefiltered image pixels. The algorithm first + computes x-derivative at each pixel and clips its value by [-preFilterCap, preFilterCap] interval. + The result values are passed to the Birchfield-Tomasi pixel cost function. + @param uniquenessRatio Margin in percentage by which the best (minimum) computed cost function + value should "win" the second best value to consider the found match correct. Normally, a value + within the 5-15 range is good enough. + @param speckleWindowSize Maximum size of smooth disparity regions to consider their noise speckles + and invalidate. Set it to 0 to disable speckle filtering. Otherwise, set it somewhere in the + 50-200 range. + @param speckleRange Maximum disparity variation within each connected component. If you do speckle + filtering, set the parameter to a positive value, it will be implicitly multiplied by 16. + Normally, 1 or 2 is good enough. + @param mode Set it to StereoSGBM::MODE_HH to run the full-scale two-pass dynamic programming + algorithm. It will consume O(W\*H\*numDisparities) bytes, which is large for 640x480 stereo and + huge for HD-size pictures. By default, it is set to false . + + The first constructor initializes StereoSGBM with all the default parameters. So, you only have to + set StereoSGBM::numDisparities at minimum. The second constructor enables you to set each parameter + to a custom value. + */ + CV_WRAP static Ptr create(int minDisparity = 0, int numDisparities = 16, int blockSize = 3, + int P1 = 0, int P2 = 0, int disp12MaxDiff = 0, + int preFilterCap = 0, int uniquenessRatio = 0, + int speckleWindowSize = 0, int speckleRange = 0, + int mode = StereoSGBM::MODE_SGBM); +}; + +/** @brief Filters off small noise blobs (speckles) in the disparity map + +@param img The input 16-bit signed disparity image +@param newVal The disparity value used to paint-off the speckles +@param maxSpeckleSize The maximum speckle size to consider it a speckle. Larger blobs are not +affected by the algorithm +@param maxDiff Maximum difference between neighbor disparity pixels to put them into the same +blob. Note that since StereoBM, StereoSGBM and may be other algorithms return a fixed-point +disparity map, where disparity values are multiplied by 16, this scale factor should be taken into +account when specifying this parameter value. +@param buf The optional temporary buffer to avoid memory allocation within the function. + */ +CV_EXPORTS_W void filterSpeckles( InputOutputArray img, double newVal, + int maxSpeckleSize, double maxDiff, + InputOutputArray buf = noArray() ); + +//! computes valid disparity ROI from the valid ROIs of the rectified images (that are returned by cv::stereoRectify()) +CV_EXPORTS_W Rect getValidDisparityROI( Rect roi1, Rect roi2, + int minDisparity, int numberOfDisparities, + int blockSize ); + +//! validates disparity using the left-right check. The matrix "cost" should be computed by the stereo correspondence algorithm +CV_EXPORTS_W void validateDisparity( InputOutputArray disparity, InputArray cost, + int minDisparity, int numberOfDisparities, + int disp12MaxDisp = 1 ); + +/** @brief Reprojects a disparity image to 3D space. + +@param disparity Input single-channel 8-bit unsigned, 16-bit signed, 32-bit signed or 32-bit +floating-point disparity image. The values of 8-bit / 16-bit signed formats are assumed to have no +fractional bits. If the disparity is 16-bit signed format, as computed by @ref StereoBM or +@ref StereoSGBM and maybe other algorithms, it should be divided by 16 (and scaled to float) before +being used here. +@param _3dImage Output 3-channel floating-point image of the same size as disparity. Each element of +_3dImage(x,y) contains 3D coordinates of the point (x,y) computed from the disparity map. If one +uses Q obtained by @ref stereoRectify, then the returned points are represented in the first +camera's rectified coordinate system. +@param Q \f$4 \times 4\f$ perspective transformation matrix that can be obtained with +@ref stereoRectify. +@param handleMissingValues Indicates, whether the function should handle missing values (i.e. +points where the disparity was not computed). If handleMissingValues=true, then pixels with the +minimal disparity that corresponds to the outliers (see StereoMatcher::compute ) are transformed +to 3D points with a very large Z value (currently set to 10000). +@param ddepth The optional output array depth. If it is -1, the output image will have CV_32F +depth. ddepth can also be set to CV_16S, CV_32S or CV_32F. + +The function transforms a single-channel disparity map to a 3-channel image representing a 3D +surface. That is, for each pixel (x,y) and the corresponding disparity d=disparity(x,y) , it +computes: + +\f[\begin{bmatrix} +X \\ +Y \\ +Z \\ +W +\end{bmatrix} = Q \begin{bmatrix} +x \\ +y \\ +\texttt{disparity} (x,y) \\ +z +\end{bmatrix}.\f] + +@sa + To reproject a sparse set of points {(x,y,d),...} to 3D space, use perspectiveTransform. + */ +CV_EXPORTS_W void reprojectImageTo3D( InputArray disparity, + OutputArray _3dImage, InputArray Q, + bool handleMissingValues = false, + int ddepth = -1 ); + +} // namespace cv + +#endif diff --git a/modules/calib3d/misc/java/test/StereoBMTest.java b/modules/stereo/misc/java/test/StereoBMTest.java similarity index 94% rename from modules/calib3d/misc/java/test/StereoBMTest.java rename to modules/stereo/misc/java/test/StereoBMTest.java index eac6673985..79451048c7 100644 --- a/modules/calib3d/misc/java/test/StereoBMTest.java +++ b/modules/stereo/misc/java/test/StereoBMTest.java @@ -1,4 +1,4 @@ -package org.opencv.test.calib3d; +package org.opencv.test.stereo; import org.opencv.test.OpenCVTestCase; diff --git a/modules/stereo/misc/java/test/StereoBaseTest.java b/modules/stereo/misc/java/test/StereoBaseTest.java new file mode 100644 index 0000000000..cbb827c4d9 --- /dev/null +++ b/modules/stereo/misc/java/test/StereoBaseTest.java @@ -0,0 +1,183 @@ +package org.opencv.test.stereoBase; + +import java.util.ArrayList; + +import org.opencv.cv3d.Cv3d; +import org.opencv.stereo.Stereo; +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDouble; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.MatOfPoint3f; +import org.opencv.core.Point; +import org.opencv.core.Scalar; +import org.opencv.core.Size; +import org.opencv.test.OpenCVTestCase; +import org.opencv.imgproc.Imgproc; + +public class StereoBaseTest extends OpenCVTestCase { + + Size size; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + size = new Size(3, 3); + } + + public void testFilterSpecklesMatDoubleIntDouble() { + gray_16s_1024.copyTo(dst); + Point center = new Point(gray_16s_1024.rows() / 2., gray_16s_1024.cols() / 2.); + Imgproc.circle(dst, center, 1, Scalar.all(4096)); + + assertMatNotEqual(gray_16s_1024, dst); + Stereo.filterSpeckles(dst, 1024.0, 100, 0.); + assertMatEqual(gray_16s_1024, dst); + } + + public void testFilterSpecklesMatDoubleIntDoubleMat() { + fail("Not yet implemented"); + } + + public void testGetValidDisparityROI() { + fail("Not yet implemented"); + } + + public void testRectify3Collinear() { + fail("Not yet implemented"); + } + + public void testReprojectImageTo3DMatMatMat() { + Mat transformMatrix = new Mat(4, 4, CvType.CV_64F); + transformMatrix.put(0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + + Mat disparity = new Mat(matSize, matSize, CvType.CV_32F); + + float[] disp = new float[matSize * matSize]; + for (int i = 0; i < matSize; i++) + for (int j = 0; j < matSize; j++) + disp[i * matSize + j] = i - j; + disparity.put(0, 0, disp); + + Mat _3dPoints = new Mat(); + + Stereo.reprojectImageTo3D(disparity, _3dPoints, transformMatrix); + + assertEquals(CvType.CV_32FC3, _3dPoints.type()); + assertEquals(matSize, _3dPoints.rows()); + assertEquals(matSize, _3dPoints.cols()); + + truth = new Mat(matSize, matSize, CvType.CV_32FC3); + + float[] _truth = new float[matSize * matSize * 3]; + for (int i = 0; i < matSize; i++) + for (int j = 0; j < matSize; j++) { + _truth[(i * matSize + j) * 3 + 0] = i; + _truth[(i * matSize + j) * 3 + 1] = j; + _truth[(i * matSize + j) * 3 + 2] = i - j; + } + truth.put(0, 0, _truth); + + assertMatEqual(truth, _3dPoints, EPS); + } + + public void testReprojectImageTo3DMatMatMatBoolean() { + Mat transformMatrix = new Mat(4, 4, CvType.CV_64F); + transformMatrix.put(0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + + Mat disparity = new Mat(matSize, matSize, CvType.CV_32F); + + float[] disp = new float[matSize * matSize]; + for (int i = 0; i < matSize; i++) + for (int j = 0; j < matSize; j++) + disp[i * matSize + j] = i - j; + disp[0] = -Float.MAX_VALUE; + disparity.put(0, 0, disp); + + Mat _3dPoints = new Mat(); + + Stereo.reprojectImageTo3D(disparity, _3dPoints, transformMatrix, true); + + assertEquals(CvType.CV_32FC3, _3dPoints.type()); + assertEquals(matSize, _3dPoints.rows()); + assertEquals(matSize, _3dPoints.cols()); + + truth = new Mat(matSize, matSize, CvType.CV_32FC3); + + float[] _truth = new float[matSize * matSize * 3]; + for (int i = 0; i < matSize; i++) + for (int j = 0; j < matSize; j++) { + _truth[(i * matSize + j) * 3 + 0] = i; + _truth[(i * matSize + j) * 3 + 1] = j; + _truth[(i * matSize + j) * 3 + 2] = i - j; + } + _truth[2] = 10000; + truth.put(0, 0, _truth); + + assertMatEqual(truth, _3dPoints, EPS); + } + + public void testReprojectImageTo3DMatMatMatBooleanInt() { + Mat transformMatrix = new Mat(4, 4, CvType.CV_64F); + transformMatrix.put(0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + + Mat disparity = new Mat(matSize, matSize, CvType.CV_32F); + + float[] disp = new float[matSize * matSize]; + for (int i = 0; i < matSize; i++) + for (int j = 0; j < matSize; j++) + disp[i * matSize + j] = i - j; + disparity.put(0, 0, disp); + + Mat _3dPoints = new Mat(); + + Stereo.reprojectImageTo3D(disparity, _3dPoints, transformMatrix, false, CvType.CV_16S); + + assertEquals(CvType.CV_16SC3, _3dPoints.type()); + assertEquals(matSize, _3dPoints.rows()); + assertEquals(matSize, _3dPoints.cols()); + + truth = new Mat(matSize, matSize, CvType.CV_16SC3); + + short[] _truth = new short[matSize * matSize * 3]; + for (short i = 0; i < matSize; i++) + for (short j = 0; j < matSize; j++) { + _truth[(i * matSize + j) * 3 + 0] = i; + _truth[(i * matSize + j) * 3 + 1] = j; + _truth[(i * matSize + j) * 3 + 2] = (short) (i - j); + } + truth.put(0, 0, _truth); + + assertMatEqual(truth, _3dPoints, EPS); + } + + public void testStereoCalibrateListOfMatListOfMatListOfMatMatMatMatMatSizeMatMatMatMat() { + fail("Not yet implemented"); + } + + public void testStereoCalibrateListOfMatListOfMatListOfMatMatMatMatMatSizeMatMatMatMatTermCriteria() { + fail("Not yet implemented"); + } + + public void testStereoCalibrateListOfMatListOfMatListOfMatMatMatMatMatSizeMatMatMatMatTermCriteriaInt() { + fail("Not yet implemented"); + } + + public void testStereoRectifyUncalibratedMatMatMatSizeMatMat() { + fail("Not yet implemented"); + } + + public void testStereoRectifyUncalibratedMatMatMatSizeMatMatDouble() { + fail("Not yet implemented"); + } + + public void testValidateDisparityMatMatIntInt() { + fail("Not yet implemented"); + } + + public void testValidateDisparityMatMatIntIntInt() { + fail("Not yet implemented"); + } +} diff --git a/modules/calib3d/misc/java/test/StereoSGBMTest.java b/modules/stereo/misc/java/test/StereoSGBMTest.java similarity index 98% rename from modules/calib3d/misc/java/test/StereoSGBMTest.java rename to modules/stereo/misc/java/test/StereoSGBMTest.java index 313f4aaff8..90b0dedb4d 100644 --- a/modules/calib3d/misc/java/test/StereoSGBMTest.java +++ b/modules/stereo/misc/java/test/StereoSGBMTest.java @@ -1,4 +1,4 @@ -package org.opencv.test.calib3d; +package org.opencv.test.stereo; import org.opencv.test.OpenCVTestCase; diff --git a/modules/calib3d/perf/opencl/perf_stereobm.cpp b/modules/stereo/perf/opencl/perf_stereobm.cpp similarity index 100% rename from modules/calib3d/perf/opencl/perf_stereobm.cpp rename to modules/stereo/perf/opencl/perf_stereobm.cpp diff --git a/modules/stereo/perf/perf_main.cpp b/modules/stereo/perf/perf_main.cpp new file mode 100644 index 0000000000..54c334da13 --- /dev/null +++ b/modules/stereo/perf/perf_main.cpp @@ -0,0 +1,7 @@ +#include "perf_precomp.hpp" + +#if defined(HAVE_HPX) + #include +#endif + +CV_PERF_TEST_MAIN(calib3d) diff --git a/modules/stereo/perf/perf_precomp.hpp b/modules/stereo/perf/perf_precomp.hpp new file mode 100644 index 0000000000..27cdb2262c --- /dev/null +++ b/modules/stereo/perf/perf_precomp.hpp @@ -0,0 +1,10 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html +#ifndef __OPENCV_PERF_PRECOMP_HPP__ +#define __OPENCV_PERF_PRECOMP_HPP__ + +#include "opencv2/ts.hpp" +#include "opencv2/stereo.hpp" + +#endif diff --git a/modules/calib3d/perf/perf_stereosgbm.cpp b/modules/stereo/perf/perf_stereosgbm.cpp similarity index 100% rename from modules/calib3d/perf/perf_stereosgbm.cpp rename to modules/stereo/perf/perf_stereosgbm.cpp diff --git a/modules/stereo/src/main.cpp b/modules/stereo/src/main.cpp new file mode 100644 index 0000000000..127f86b26b --- /dev/null +++ b/modules/stereo/src/main.cpp @@ -0,0 +1,52 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +// +// Library initialization file +// + +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ diff --git a/modules/stereo/src/opencl/stereobm.cl b/modules/stereo/src/opencl/stereobm.cl new file mode 100644 index 0000000000..16386a6733 --- /dev/null +++ b/modules/stereo/src/opencl/stereobm.cl @@ -0,0 +1,334 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors as is and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////// stereoBM ////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// + +#define MAX_VAL 32767 + +#ifndef WSZ +#define WSZ 2 +#endif + +#define WSZ2 (WSZ / 2) + +#ifdef DEFINE_KERNEL_STEREOBM + +#define DISPARITY_SHIFT 4 +#define FILTERED ((MIN_DISP - 1) << DISPARITY_SHIFT) + +void calcDisp(__local short * cost, __global short * disp, int uniquenessRatio, + __local int * bestDisp, __local int * bestCost, int d, int x, int y, int cols, int rows) +{ + int best_disp = *bestDisp, best_cost = *bestCost; + barrier(CLK_LOCAL_MEM_FENCE); + + short c = cost[0]; + int thresh = best_cost + (best_cost * uniquenessRatio / 100); + bool notUniq = ( (c <= thresh) && (d < (best_disp - 1) || d > (best_disp + 1) ) ); + + if (notUniq) + *bestCost = FILTERED; + barrier(CLK_LOCAL_MEM_FENCE); + + if( *bestCost != FILTERED && x < cols - WSZ2 - MIN_DISP && y < rows - WSZ2 && d == best_disp) + { + int d_aprox = 0; + int yp =0, yn = 0; + if ((0 < best_disp) && (best_disp < NUM_DISP - 1)) + { + yp = cost[-2 * BLOCK_SIZE_Y]; + yn = cost[2 * BLOCK_SIZE_Y]; + d_aprox = yp + yn - 2 * c + abs(yp - yn); + } + disp[0] = (short)(((best_disp + MIN_DISP)*256 + (d_aprox != 0 ? (yp - yn) * 256 / d_aprox : 0) + 15) >> 4); + } +} + +short calcCostBorder(__global const uchar * leftptr, __global const uchar * rightptr, int x, int y, int nthread, + short * costbuf, int *h, int cols, int d, short cost) +{ + int head = (*h) % WSZ; + __global const uchar * left, * right; + int idx = mad24(y + WSZ2 * (2 * nthread - 1), cols, x + WSZ2 * (1 - 2 * nthread)); + left = leftptr + idx; + right = rightptr + (idx - d); + + short costdiff = 0; + if (0 == nthread) + { + #pragma unroll + for (int i = 0; i < WSZ; i++) + { + costdiff += abs( left[0] - right[0] ); + left += cols; + right += cols; + } + } + else // (1 == nthread) + { + #pragma unroll + for (int i = 0; i < WSZ; i++) + { + costdiff += abs(left[i] - right[i]); + } + } + cost += costdiff - costbuf[head]; + costbuf[head] = costdiff; + *h = head + 1; + return cost; +} + +short calcCostInside(__global const uchar * leftptr, __global const uchar * rightptr, int x, int y, + int cols, int d, short cost_up_left, short cost_up, short cost_left) +{ + __global const uchar * left, * right; + int idx = mad24(y - WSZ2 - 1, cols, x - WSZ2 - 1); + left = leftptr + idx; + right = rightptr + (idx - d); + int idx2 = WSZ*cols; + + uchar corrner1 = abs(left[0] - right[0]), + corrner2 = abs(left[WSZ] - right[WSZ]), + corrner3 = abs(left[idx2] - right[idx2]), + corrner4 = abs(left[idx2 + WSZ] - right[idx2 + WSZ]); + + return cost_up + cost_left - cost_up_left + corrner1 - + corrner2 - corrner3 + corrner4; +} + +__kernel void stereoBM(__global const uchar * leftptr, + __global const uchar * rightptr, + __global uchar * dispptr, int disp_step, int disp_offset, + int rows, int cols, // rows, cols of left and right images, not disp + int textureThreshold, int uniquenessRatio) +{ + int lz = get_local_id(0); + int gx = get_global_id(1) * BLOCK_SIZE_X; + int gy = get_global_id(2) * BLOCK_SIZE_Y; + + int nthread = lz / NUM_DISP; + int disp_idx = lz % NUM_DISP; + + __global short * disp; + __global const uchar * left, * right; + + __local short costFunc[2 * BLOCK_SIZE_Y * NUM_DISP]; + + __local short * cost; + __local int best_disp[2]; + __local int best_cost[2]; + best_cost[nthread] = MAX_VAL; + best_disp[nthread] = -1; + barrier(CLK_LOCAL_MEM_FENCE); + + short costbuf[WSZ]; + int head = 0; + + int shiftX = WSZ2 + NUM_DISP + MIN_DISP - 1; + int shiftY = WSZ2; + + int x = gx + shiftX, y = gy + shiftY, lx = 0, ly = 0; + + int costIdx = disp_idx * 2 * BLOCK_SIZE_Y + (BLOCK_SIZE_Y - 1); + cost = costFunc + costIdx; + + int tempcost = 0; + if (x < cols - WSZ2 - MIN_DISP && y < rows - WSZ2) + { + if (0 == nthread) + { + #pragma unroll + for (int i = 0; i < WSZ; i++) + { + int idx = mad24(y - WSZ2, cols, x - WSZ2 + i); + left = leftptr + idx; + right = rightptr + (idx - disp_idx); + short costdiff = 0; + for(int j = 0; j < WSZ; j++) + { + costdiff += abs( left[0] - right[0] ); + left += cols; + right += cols; + } + costbuf[i] = costdiff; + } + } + else // (1 == nthread) + { + #pragma unroll + for (int i = 0; i < WSZ; i++) + { + int idx = mad24(y - WSZ2 + i, cols, x - WSZ2); + left = leftptr + idx; + right = rightptr + (idx - disp_idx); + short costdiff = 0; + for (int j = 0; j < WSZ; j++) + { + costdiff += abs( left[j] - right[j]); + } + tempcost += costdiff; + costbuf[i] = costdiff; + } + } + } + if (nthread == 1) + { + cost[0] = tempcost; + atomic_min(best_cost + 1, tempcost); + } + barrier(CLK_LOCAL_MEM_FENCE); + + if (best_cost[1] == tempcost) + atomic_max(best_disp + 1, disp_idx); + barrier(CLK_LOCAL_MEM_FENCE); + + int dispIdx = mad24(gy, disp_step, mad24((int)sizeof(short), gx, disp_offset)); + disp = (__global short *)(dispptr + dispIdx); + calcDisp(cost, disp, uniquenessRatio, best_disp + 1, best_cost + 1, disp_idx, x, y, cols, rows); + barrier(CLK_LOCAL_MEM_FENCE); + + lx = 1 - nthread; + ly = nthread; + + for (int i = 0; i < BLOCK_SIZE_Y * BLOCK_SIZE_X / 2; i++) + { + x = (lx < BLOCK_SIZE_X) ? gx + shiftX + lx : cols; + y = (ly < BLOCK_SIZE_Y) ? gy + shiftY + ly : rows; + + best_cost[nthread] = MAX_VAL; + best_disp[nthread] = -1; + barrier(CLK_LOCAL_MEM_FENCE); + + costIdx = mad24(2 * BLOCK_SIZE_Y, disp_idx, (BLOCK_SIZE_Y - 1 - ly + lx)); + if (0 > costIdx) + costIdx = BLOCK_SIZE_Y - 1; + cost = costFunc + costIdx; + if (x < cols - WSZ2 - MIN_DISP && y < rows - WSZ2) + { + tempcost = (ly * (1 - nthread) + lx * nthread == 0) ? + calcCostBorder(leftptr, rightptr, x, y, nthread, costbuf, &head, cols, disp_idx, cost[2*nthread-1]) : + calcCostInside(leftptr, rightptr, x, y, cols, disp_idx, cost[0], cost[1], cost[-1]); + } + cost[0] = tempcost; + atomic_min(best_cost + nthread, tempcost); + barrier(CLK_LOCAL_MEM_FENCE); + + if (best_cost[nthread] == tempcost) + atomic_max(best_disp + nthread, disp_idx); + barrier(CLK_LOCAL_MEM_FENCE); + + dispIdx = mad24(gy + ly, disp_step, mad24((int)sizeof(short), (gx + lx), disp_offset)); + disp = (__global short *)(dispptr + dispIdx); + calcDisp(cost, disp, uniquenessRatio, best_disp + nthread, best_cost + nthread, disp_idx, x, y, cols, rows); + + barrier(CLK_LOCAL_MEM_FENCE); + + if (lx + nthread - 1 == ly) + { + lx = (lx + nthread + 1) * (1 - nthread); + ly = (ly + 1) * nthread; + } + else + { + lx += nthread; + ly = ly - nthread + 1; + } + } +} +#endif //DEFINE_KERNEL_STEREOBM + +////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////// Norm Prefiler //////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// + +__kernel void prefilter_norm(__global unsigned char *input, __global unsigned char *output, + int rows, int cols, int prefilterCap, int scale_g, int scale_s) +{ + // prefilterCap in range 1..63, checked in StereoBMImpl::compute + + int x = get_global_id(0); + int y = get_global_id(1); + + if(x < cols && y < rows) + { + int cov1 = input[ max(y-1, 0) * cols + x] * 1 + + input[y * cols + max(x-1,0)] * 1 + input[ y * cols + x] * 4 + input[y * cols + min(x+1, cols-1)] * 1 + + input[min(y+1, rows-1) * cols + x] * 1; + int cov2 = 0; + for(int i = -WSZ2; i < WSZ2+1; i++) + for(int j = -WSZ2; j < WSZ2+1; j++) + cov2 += input[clamp(y+i, 0, rows-1) * cols + clamp(x+j, 0, cols-1)]; + + int res = (cov1*scale_g - cov2*scale_s)>>10; + res = clamp(res, -prefilterCap, prefilterCap) + prefilterCap; + output[y * cols + x] = res; + } +} + + +////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////// Sobel Prefiler //////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// + +__kernel void prefilter_xsobel(__global unsigned char *input, __global unsigned char *output, + int rows, int cols, int prefilterCap) +{ + // prefilterCap in range 1..63, checked in StereoBMImpl::compute + int x = get_global_id(0); + int y = get_global_id(1); + if(x < cols && y < rows) + { + if (0 < x && !((y == rows-1) & (rows%2==1) ) ) + { + int cov = input[ ((y > 0) ? y-1 : y+1) * cols + (x-1)] * (-1) + input[ ((y > 0) ? y-1 : y+1) * cols + ((x& cb) = 0; + virtual bool run(InputArray m1, InputArray m2, OutputArray model, OutputArray mask) const = 0; +}; + +CV_EXPORTS Ptr createRANSACPointSetRegistrator(const Ptr& cb, + int modelPoints, double threshold, + double confidence=0.99, int maxIters=1000 ); + +CV_EXPORTS Ptr createLMeDSPointSetRegistrator(const Ptr& cb, + int modelPoints, double confidence=0.99, int maxIters=1000 ); + +template inline int compressElems( T* ptr, const uchar* mask, int mstep, int count ) +{ + int i, j; + for( i = j = 0; i < count; i++ ) + if( mask[i*mstep] ) + { + if( i > j ) + ptr[j] = ptr[i]; + j++; + } + return j; +} + +static inline bool haveCollinearPoints( const Mat& m, int count ) +{ + int j, k, i = count-1; + const Point2f* ptr = m.ptr(); + + // check that the i-th selected point does not belong + // to a line connecting some previously selected points + // also checks that points are not too close to each other + for( j = 0; j < i; j++ ) + { + double dx1 = ptr[j].x - ptr[i].x; + double dy1 = ptr[j].y - ptr[i].y; + for( k = 0; k < j; k++ ) + { + double dx2 = ptr[k].x - ptr[i].x; + double dy2 = ptr[k].y - ptr[i].y; + if( fabs(dx2*dy1 - dy2*dx1) <= FLT_EPSILON*(fabs(dx1) + fabs(dy1) + fabs(dx2) + fabs(dy2))) + return true; + } + } + return false; +} + +} // namespace cv + +#endif diff --git a/modules/stereo/src/stereo_geom.cpp b/modules/stereo/src/stereo_geom.cpp new file mode 100644 index 0000000000..752d591661 --- /dev/null +++ b/modules/stereo/src/stereo_geom.cpp @@ -0,0 +1,631 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#include "precomp.hpp" + +namespace cv { + +void reprojectImageTo3D( InputArray _disparity, OutputArray __3dImage, + InputArray _Qmat, bool handleMissingValues, int dtype ) +{ + CV_INSTRUMENT_REGION(); + + Mat disparity = _disparity.getMat(), Q = _Qmat.getMat(); + int stype = disparity.type(); + + CV_Assert( stype == CV_8UC1 || stype == CV_16SC1 || + stype == CV_32SC1 || stype == CV_32FC1 ); + CV_Assert( Q.size() == Size(4,4) ); + + if( dtype >= 0 ) + dtype = CV_MAKETYPE(CV_MAT_DEPTH(dtype), 3); + + if( __3dImage.fixedType() ) + { + int dtype_ = __3dImage.type(); + CV_Assert( dtype == -1 || dtype == dtype_ ); + dtype = dtype_; + } + + if( dtype < 0 ) + dtype = CV_32FC3; + else + CV_Assert( dtype == CV_16SC3 || dtype == CV_32SC3 || dtype == CV_32FC3 ); + + __3dImage.create(disparity.size(), dtype); + Mat _3dImage = __3dImage.getMat(); + + const float bigZ = 10000.f; + Matx44d _Q; + Q.convertTo(_Q, CV_64F); + + int x, cols = disparity.cols; + CV_Assert( cols >= 0 ); + + std::vector _sbuf(cols); + std::vector _dbuf(cols); + float* sbuf = &_sbuf[0]; + Vec3f* dbuf = &_dbuf[0]; + double minDisparity = FLT_MAX; + + // NOTE: here we quietly assume that at least one pixel in the disparity map is not defined. + // and we set the corresponding Z's to some fixed big value. + if( handleMissingValues ) + cv::minMaxIdx( disparity, &minDisparity, 0, 0, 0 ); + + for( int y = 0; y < disparity.rows; y++ ) + { + float* sptr = sbuf; + Vec3f* dptr = dbuf; + + if( stype == CV_8UC1 ) + { + const uchar* sptr0 = disparity.ptr(y); + for( x = 0; x < cols; x++ ) + sptr[x] = (float)sptr0[x]; + } + else if( stype == CV_16SC1 ) + { + const short* sptr0 = disparity.ptr(y); + for( x = 0; x < cols; x++ ) + sptr[x] = (float)sptr0[x]; + } + else if( stype == CV_32SC1 ) + { + const int* sptr0 = disparity.ptr(y); + for( x = 0; x < cols; x++ ) + sptr[x] = (float)sptr0[x]; + } + else + sptr = disparity.ptr(y); + + if( dtype == CV_32FC3 ) + dptr = _3dImage.ptr(y); + + for( x = 0; x < cols; x++) + { + double d = sptr[x]; + Vec4d homg_pt = _Q*Vec4d(x, y, d, 1.0); + dptr[x] = Vec3d(homg_pt.val); + dptr[x] /= homg_pt[3]; + + if( fabs(d-minDisparity) <= FLT_EPSILON ) + dptr[x][2] = bigZ; + } + + if( dtype == CV_16SC3 ) + { + Vec3s* dptr0 = _3dImage.ptr(y); + for( x = 0; x < cols; x++ ) + { + dptr0[x] = dptr[x]; + } + } + else if( dtype == CV_32SC3 ) + { + Vec3i* dptr0 = _3dImage.ptr(y); + for( x = 0; x < cols; x++ ) + { + dptr0[x] = dptr[x]; + } + } + } +} + +void stereoRectify( InputArray _cameraMatrix1, InputArray _distCoeffs1, + InputArray _cameraMatrix2, InputArray _distCoeffs2, + Size imageSize, InputArray R, InputArray T, + OutputArray _R1, OutputArray _R2, + OutputArray _P1, OutputArray _P2, + OutputArray _Qmat, int flags, + double alpha, Size newImgSize, + Rect* roi1, Rect* roi2 ) +{ + Mat matR = Mat_(R.getMat()), matT = Mat_(T.getMat()); + + Mat om, r_r; + Mat Z = Mat::zeros(3, 1, CV_64F); + double nx = imageSize.width, ny = imageSize.height; + + if( matR.rows == 3 && matR.cols == 3 ) + Rodrigues(matR, om); // get vector rotation + else + matR.copyTo(om); + om *= -0.5; // get average rotation + Rodrigues(om, r_r); + Mat t = r_r * matT; // rotate cameras to same orientation by averaging + + int idx = fabs(t.at(0)) > fabs(t.at(1)) ? 0 : 1; + double c = t.at(idx), nt = norm(t, NORM_L2); + double _uu[3]={0, 0, 0}; + _uu[idx] = c > 0 ? 1 : -1; + + CV_Assert(nt > 0.0); + + // calculate global Z rotation + Mat ww = t.cross(Mat(3, 1, CV_64F, _uu)), wR; + double nw = norm(ww, NORM_L2); + if (nw > 0.0) + ww *= acos(fabs(c)/nt)/nw; + Rodrigues(ww, wR); + + Mat Ri; + // apply to both views + gemm(wR, r_r, 1, Mat(), 0, Ri, GEMM_2_T); + Ri.copyTo(_R1); + gemm(wR, r_r, 1, Mat(), 0, Ri, 0); + Ri.copyTo(_R2); + t = Ri * matT; + + // calculate projection/camera matrices + // these contain the relevant rectified image internal params (fx, fy=fx, cx, cy) + Point2d cc_new[2]={}; + + newImgSize = newImgSize.width * newImgSize.height != 0 ? newImgSize : imageSize; + const double ratio_x = (double)newImgSize.width / imageSize.width / 2; + const double ratio_y = (double)newImgSize.height / imageSize.height / 2; + const double ratio = idx == 1 ? ratio_x : ratio_y; + + Mat cameraMatrix1 = Mat_(_cameraMatrix1.getMat()); + Mat cameraMatrix2 = Mat_(_cameraMatrix2.getMat()); + Mat distCoeffs1, distCoeffs2; + if (!_distCoeffs1.empty()) + distCoeffs1 = Mat_(_distCoeffs1.getMat()); + if (!_distCoeffs2.empty()) + distCoeffs2 = Mat_(_distCoeffs2.getMat()); + + double fc_new = (cameraMatrix1.at(idx ^ 1, idx ^ 1) + cameraMatrix2.at(idx ^ 1, idx ^ 1)) * ratio; + + for( int k = 0; k < 2; k++ ) + { + const Mat& A = k == 0 ? cameraMatrix1 : cameraMatrix2; + const Mat& Dk = k == 0 ? distCoeffs1 : distCoeffs2; + Point2f _pts[4] = {}; + Point3f _pts_3[4] = {}; + Mat pts(1, 4, CV_32FC2, _pts); + Mat pts_3(1, 4, CV_32FC3, _pts_3); + + for( int i = 0; i < 4; i++ ) + { + int j = (i<2) ? 0 : 1; + _pts[i].x = (float)((i % 2)*(nx-1)); + _pts[i].y = (float)(j*(ny-1)); + } + undistortPoints(pts, pts, A, Dk, Mat(), Mat()); + convertPointsToHomogeneous(pts, pts_3); + + // Change the camera matrix to have cc=[0,0] and fc = fc_new + double _a_tmp[3][3] = {{fc_new, 0, 0}, {0, fc_new, 0}, {0, 0, 1}}; + Mat A_tmp(3, 3, CV_64F, _a_tmp); + projectPoints(pts_3, (k == 0 ? _R1 : _R2), Z, A_tmp, Mat(), pts); + Scalar avg = mean(pts); + cc_new[k].x = (nx-1)/2 - avg.val[0]; + cc_new[k].y = (ny-1)/2 - avg.val[1]; + } + + // vertical focal length must be the same for both images to keep the epipolar constraint + // (for horizontal epipolar lines -- TBD: check for vertical epipolar lines) + // use fy for fx also, for simplicity + + // For simplicity, set the principal points for both cameras to be the average + // of the two principal points (either one of or both x- and y- coordinates) + if( flags & STEREO_ZERO_DISPARITY ) + { + cc_new[0].x = cc_new[1].x = (cc_new[0].x + cc_new[1].x)*0.5; + cc_new[0].y = cc_new[1].y = (cc_new[0].y + cc_new[1].y)*0.5; + } + else if( idx == 0 ) // horizontal stereo + cc_new[0].y = cc_new[1].y = (cc_new[0].y + cc_new[1].y)*0.5; + else // vertical stereo + cc_new[0].x = cc_new[1].x = (cc_new[0].x + cc_new[1].x)*0.5; + + double t_idx = t.at(idx); + + Mat pp = Mat::zeros(3, 4, CV_64F); + pp.at(0, 0) = pp.at(1, 1) = fc_new; + pp.at(0, 2) = cc_new[0].x; + pp.at(1, 2) = cc_new[0].y; + pp.at(2, 2) = 1.; + pp.copyTo(_P1); + + pp.at(0, 2) = cc_new[1].x; + pp.at(1, 2) = cc_new[1].y; + pp.at(idx, 3) = t_idx*fc_new; // baseline * focal length + pp.copyTo(_P2); + + alpha = MIN(alpha, 1.); + + cv::Rect_ inner1, inner2, outer1, outer2; + getUndistortRectangles(cameraMatrix1, distCoeffs1, _R1, _P1, imageSize, inner1, outer1); + getUndistortRectangles(cameraMatrix2, distCoeffs2, _R2, _P2, imageSize, inner2, outer2); + + { + newImgSize = newImgSize.width*newImgSize.height != 0 ? newImgSize : imageSize; + double cx1_0 = cc_new[0].x; + double cy1_0 = cc_new[0].y; + double cx2_0 = cc_new[1].x; + double cy2_0 = cc_new[1].y; + double cx1 = newImgSize.width*cx1_0/imageSize.width; + double cy1 = newImgSize.height*cy1_0/imageSize.height; + double cx2 = newImgSize.width*cx2_0/imageSize.width; + double cy2 = newImgSize.height*cy2_0/imageSize.height; + double s = 1.; + + if( alpha >= 0 ) + { + double s0 = std::max(std::max(std::max((double)cx1/(cx1_0 - inner1.x), (double)cy1/(cy1_0 - inner1.y)), + (double)(newImgSize.width - cx1)/(inner1.x + inner1.width - cx1_0)), + (double)(newImgSize.height - cy1)/(inner1.y + inner1.height - cy1_0)); + s0 = std::max(std::max(std::max(std::max((double)cx2/(cx2_0 - inner2.x), (double)cy2/(cy2_0 - inner2.y)), + (double)(newImgSize.width - cx2)/(inner2.x + inner2.width - cx2_0)), + (double)(newImgSize.height - cy2)/(inner2.y + inner2.height - cy2_0)), + s0); + + double s1 = std::min(std::min(std::min((double)cx1/(cx1_0 - outer1.x), (double)cy1/(cy1_0 - outer1.y)), + (double)(newImgSize.width - cx1)/(outer1.x + outer1.width - cx1_0)), + (double)(newImgSize.height - cy1)/(outer1.y + outer1.height - cy1_0)); + s1 = std::min(std::min(std::min(std::min((double)cx2/(cx2_0 - outer2.x), (double)cy2/(cy2_0 - outer2.y)), + (double)(newImgSize.width - cx2)/(outer2.x + outer2.width - cx2_0)), + (double)(newImgSize.height - cy2)/(outer2.y + outer2.height - cy2_0)), + s1); + + s = s0*(1 - alpha) + s1*alpha; + } + + fc_new *= s; + cc_new[0] = Point2d(cx1, cy1); + cc_new[1] = Point2d(cx2, cy2); + + pp.at(0, 0) = pp.at(1, 1) = fc_new; + pp.at(0, 2) = cx2; + pp.at(1, 2) = cy2; + pp.at(idx, 3) *= s; + pp.copyTo(_P2); + + pp.at(0, 2) = cx1; + pp.at(1, 2) = cy1; + pp.at(idx, 3) = 0.; + pp.copyTo(_P1); + + if(roi1) + { + *roi1 = cvRect( + cv::Rect(cvCeil((inner1.x - cx1_0)*s + cx1), + cvCeil((inner1.y - cy1_0)*s + cy1), + cvFloor(inner1.width*s), cvFloor(inner1.height*s)) + & cv::Rect(0, 0, newImgSize.width, newImgSize.height) + ); + } + + if(roi2) + { + *roi2 = cvRect( + cv::Rect(cvCeil((inner2.x - cx2_0)*s + cx2), + cvCeil((inner2.y - cy2_0)*s + cy2), + cvFloor(inner2.width*s), cvFloor(inner2.height*s)) + & cv::Rect(0, 0, newImgSize.width, newImgSize.height) + ); + } + } + + if( _Qmat.needed() ) + { + double q[] = + { + 1, 0, 0, -cc_new[0].x, + 0, 1, 0, -cc_new[0].y, + 0, 0, 0, fc_new, + 0, 0, -1./t_idx, + (idx == 0 ? cc_new[0].x - cc_new[1].x : cc_new[0].y - cc_new[1].y)/t_idx + }; + Mat Q(4, 4, CV_64F, q); + Q.copyTo(_Qmat); + } +} + +/* +CV_IMPL int cvStereoRectifyUncalibrated( + const CvMat* _points1, const CvMat* _points2, + const CvMat* F0, CvSize imgSize, + CvMat* _H1, CvMat* _H2, double threshold ) +*/ +bool stereoRectifyUncalibrated( InputArray _points1, InputArray _points2, + InputArray _Fmat, Size imgSize, + OutputArray _Hmat1, OutputArray _Hmat2, double threshold ) +{ + Mat points1 = _points1.getMat(), points2 = _points2.getMat(); + CV_Assert( points1.size() == points2.size() ); + + int npoints = points1.checkVector(2); + CV_Assert(npoints > 0); + + Mat _m1, _m2; + + points1.convertTo(_m1, CV_64F); + points2.convertTo(_m2, CV_64F); + _m1 = _m1.reshape(2, 1); + _m2 = _m2.reshape(2, 1); + + Mat F0 = _Fmat.getMat(), F, Wdiag, U, Vt; + F0.convertTo(F, CV_64F); + + SVDecomp(F, Wdiag, U, Vt, 0); + Wdiag.at(2) = 0.; + Mat W = Mat::diag(Wdiag), UW; + gemm(U, W, 1, Mat(), 0, UW); + gemm(UW, Vt, 1, Mat(), 0, F); + + double cx = cvRound( (imgSize.width-1)*0.5 ); + double cy = cvRound( (imgSize.height-1)*0.5 ); + + if( threshold > 0 ) + { + Mat _lines1, _lines2; + computeCorrespondEpilines(_m1, 1, F, _lines1); + computeCorrespondEpilines(_m2, 2, F, _lines2); + CV_Assert(_m1.isContinuous() && _m2.isContinuous() && + _lines1.isContinuous() && _lines2.isContinuous()); + Point2d* m1 = (Point2d*)_m1.data; + Point2d* m2 = (Point2d*)_m2.data; + Point3d* lines1 = (Point3d*)_lines1.data; + Point3d* lines2 = (Point3d*)_lines2.data; + + // measure distance from points to the corresponding epilines, mark outliers + int i, j; + for( i = j = 0; i < npoints; i++ ) + { + if( fabs(m1[i].x*lines2[i].x + + m1[i].y*lines2[i].y + + lines2[i].z) <= threshold && + fabs(m2[i].x*lines1[i].x + + m2[i].y*lines1[i].y + + lines1[i].z) <= threshold ) + { + if( j < i ) + { + m1[j] = m1[i]; + m2[j] = m2[i]; + } + j++; + } + } + + npoints = j; + if( npoints == 0 ) + return false; + _m1.cols = _m2.cols = npoints; + } + + Mat E2 = U.col(2).clone(); + if (E2.at(2) < 0) + E2 *= -1.0; + + double t[] = + { + 1, 0, -cx, + 0, 1, -cy, + 0, 0, 1 + }; + Mat T(3, 3, CV_64F, t); + E2 = T*E2; + + double* e2 = (double*)E2.data; + int mirror = e2[0] < 0; + double d = std::sqrt(e2[0]*e2[0] + e2[1]*e2[1]); + d = MAX(d, DBL_EPSILON); + double alpha = e2[0]/d; + double beta = e2[1]/d; + double r[] = + { + alpha, beta, 0, + -beta, alpha, 0, + 0, 0, 1 + }; + Mat R(3, 3, CV_64F, r); + T = R*T; + E2 = R*E2; + double invf = fabs(e2[2]) < 1e-6*fabs(e2[0]) ? 0 : -e2[2]/e2[0]; + double k[] = + { + 1, 0, 0, + 0, 1, 0, + invf, 0, 1 + }; + Mat K(3, 3, CV_64F, k); + Mat H2 = K*T; + E2 = K*E2; + + double it[] = + { + 1, 0, cx, + 0, 1, cy, + 0, 0, 1 + }; + Mat iT( 3, 3, CV_64F, it ); + H2 = iT*H2; + + U.col(2).copyTo(E2); + if (E2.at(2) < 0) + E2 *= -1.0; + + double e2_x[] = + { + 0, -e2[2], e2[1], + e2[2], 0, -e2[0], + -e2[1], e2[0], 0 + }; + double e2_111[] = + { + e2[0], e2[0], e2[0], + e2[1], e2[1], e2[1], + e2[2], e2[2], e2[2], + }; + Mat E2_x(3, 3, CV_64F, e2_x); + Mat E2_111(3, 3, CV_64F, e2_111); + Mat H0 = E2_x*F + E2_111; + H0 = H2*H0; + Mat E1(3, 1, CV_64F, (double*)Vt.data+6); + E1 = H0*E1; + + perspectiveTransform( _m1, _m1, H0 ); + perspectiveTransform( _m2, _m2, H2 ); + Mat A, X; + convertPointsToHomogeneous(_m1, A, CV_64F); + A = A.reshape(1, npoints); + Mat BxBy = _m2.reshape(1, npoints); + Mat B = BxBy.col(0); + solve(A, B, X, DECOMP_SVD); + CV_Assert(X.isContinuous()); + double* x = X.ptr(); + + double ha[] = + { + x[0], x[1], x[2], + 0, 1, 0, + 0, 0, 1 + }; + Mat Ha(3, 3, CV_64F, ha); + Mat H1 = Ha*H0; + perspectiveTransform( _m1, _m1, Ha ); + + if( mirror ) + { + double mm[] = { -1, 0, cx*2, 0, -1, cy*2, 0, 0, 1 }; + Mat MM(3, 3, CV_64F, mm); + H1 = MM*H1; + H2 = MM*H2; + } + + H1.copyTo(_Hmat1); + H2.copyTo(_Hmat2); + return true; +} + + +static void adjust3rdMatrix(InputArrayOfArrays _imgpt1_0, + InputArrayOfArrays _imgpt3_0, + const Mat& cameraMatrix1, const Mat& distCoeffs1, + const Mat& cameraMatrix3, const Mat& distCoeffs3, + const Mat& R1, const Mat& R3, const Mat& P1, Mat& P3 ) +{ + size_t n1 = _imgpt1_0.total(), n3 = _imgpt3_0.total(); + std::vector imgpt1, imgpt3; + + for( int i = 0; i < (int)std::min(n1, n3); i++ ) + { + Mat pt1 = _imgpt1_0.getMat(i), pt3 = _imgpt3_0.getMat(i); + int ni1 = pt1.checkVector(2, CV_32F), ni3 = pt3.checkVector(2, CV_32F); + CV_Assert( ni1 > 0 && ni1 == ni3 ); + const Point2f* pt1data = pt1.ptr(); + const Point2f* pt3data = pt3.ptr(); + std::copy(pt1data, pt1data + ni1, std::back_inserter(imgpt1)); + std::copy(pt3data, pt3data + ni3, std::back_inserter(imgpt3)); + } + + undistortPoints(imgpt1, imgpt1, cameraMatrix1, distCoeffs1, R1, P1); + undistortPoints(imgpt3, imgpt3, cameraMatrix3, distCoeffs3, R3, P3); + + double y1_ = 0, y2_ = 0, y1y1_ = 0, y1y2_ = 0; + size_t n = imgpt1.size(); + CV_DbgAssert(n > 0); + + for( size_t i = 0; i < n; i++ ) + { + double y1 = imgpt3[i].y, y2 = imgpt1[i].y; + + y1_ += y1; y2_ += y2; + y1y1_ += y1*y1; y1y2_ += y1*y2; + } + + y1_ /= n; + y2_ /= n; + y1y1_ /= n; + y1y2_ /= n; + + double a = (y1y2_ - y1_*y2_)/(y1y1_ - y1_*y1_); + double b = y2_ - a*y1_; + + P3.at(0,0) *= a; + P3.at(1,1) *= a; + P3.at(0,2) = P3.at(0,2)*a; + P3.at(1,2) = P3.at(1,2)*a + b; + P3.at(0,3) *= a; + P3.at(1,3) *= a; +} + +float rectify3Collinear( InputArray _cameraMatrix1, InputArray _distCoeffs1, + InputArray _cameraMatrix2, InputArray _distCoeffs2, + InputArray _cameraMatrix3, InputArray _distCoeffs3, + InputArrayOfArrays _imgpt1, + InputArrayOfArrays _imgpt3, + Size imageSize, InputArray _Rmat12, InputArray _Tmat12, + InputArray _Rmat13, InputArray _Tmat13, + OutputArray _Rmat1, OutputArray _Rmat2, OutputArray _Rmat3, + OutputArray _Pmat1, OutputArray _Pmat2, OutputArray _Pmat3, + OutputArray _Qmat, + double alpha, Size newImgSize, + Rect* roi1, Rect* roi2, int flags ) +{ + // first, rectify the 1-2 stereo pair + stereoRectify( _cameraMatrix1, _distCoeffs1, _cameraMatrix2, _distCoeffs2, + imageSize, _Rmat12, _Tmat12, _Rmat1, _Rmat2, _Pmat1, _Pmat2, _Qmat, + flags, alpha, newImgSize, roi1, roi2 ); + + Mat R12 = _Rmat12.getMat(), R13 = _Rmat13.getMat(), T12 = _Tmat12.getMat(), T13 = _Tmat13.getMat(); + + _Rmat3.create(3, 3, CV_64F); + _Pmat3.create(3, 4, CV_64F); + + Mat P1 = _Pmat1.getMat(), P2 = _Pmat2.getMat(); + Mat R3 = _Rmat3.getMat(), P3 = _Pmat3.getMat(); + + // recompute rectification transforms for cameras 1 & 2. + Mat om, r_r, r_r13; + + if( R13.size() != Size(3,3) ) + Rodrigues(R13, r_r13); + else + R13.copyTo(r_r13); + + if( R12.size() == Size(3,3) ) + Rodrigues(R12, om); + else + R12.copyTo(om); + + om *= -0.5; + Rodrigues(om, r_r); // rotate cameras to same orientation by averaging + Mat_ t12 = r_r * T12; + + int idx = fabs(t12(0,0)) > fabs(t12(1,0)) ? 0 : 1; + double c = t12(idx,0), nt = norm(t12, NORM_L2); + CV_Assert(fabs(nt) > 0); + Mat_ uu = Mat_::zeros(3,1); + uu(idx, 0) = c > 0 ? 1 : -1; + + // calculate global Z rotation + Mat_ ww = t12.cross(uu), wR; + double nw = norm(ww, NORM_L2); + CV_Assert(fabs(nw) > 0); + ww *= acos(fabs(c)/nt)/nw; + Rodrigues(ww, wR); + + // now rotate camera 3 to make its optical axis parallel to cameras 1 and 2. + R3 = wR*r_r.t()*r_r13.t(); + Mat_ t13 = R3 * T13; + + P2.copyTo(P3); + Mat t = P3.col(3); + t13.copyTo(t); + P3.at(0,3) *= P3.at(0,0); + P3.at(1,3) *= P3.at(1,1); + + if( !_imgpt1.empty() && !_imgpt3.empty() ) + adjust3rdMatrix(_imgpt1, _imgpt3, _cameraMatrix1.getMat(), _distCoeffs1.getMat(), + _cameraMatrix3.getMat(), _distCoeffs3.getMat(), _Rmat1.getMat(), R3, P1, P3); + + return (float)((P3.at(idx,3)/P3.at(idx,idx))/ + (P2.at(idx,3)/P2.at(idx,idx))); +} + +} diff --git a/modules/calib3d/src/stereobm.cpp b/modules/stereo/src/stereobm.cpp similarity index 99% rename from modules/calib3d/src/stereobm.cpp rename to modules/stereo/src/stereobm.cpp index 96c8d0662d..b8a8c4a157 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/stereo/src/stereobm.cpp @@ -49,12 +49,11 @@ #include #include #include -#include "opencl_kernels_calib3d.hpp" +#include "opencl_kernels_stereo.hpp" #include "opencv2/core/hal/intrin.hpp" #include "opencv2/core/utils/buffer_area.private.hpp" -namespace cv -{ +namespace cv { struct StereoBMParams { @@ -105,7 +104,7 @@ struct StereoBMParams #ifdef HAVE_OPENCL static bool ocl_prefilter_norm(InputArray _input, OutputArray _output, int winsize, int prefilterCap) { - ocl::Kernel k("prefilter_norm", ocl::calib3d::stereobm_oclsrc, cv::format("-D WSZ=%d", winsize)); + ocl::Kernel k("prefilter_norm", ocl::stereo::stereobm_oclsrc, format("-D WSZ=%d", winsize)); if(k.empty()) return false; @@ -191,7 +190,7 @@ static void prefilterNorm( const Mat& src, Mat& dst, int winsize, int ftzero, in #ifdef HAVE_OPENCL static bool ocl_prefilter_xsobel(InputArray _input, OutputArray _output, int prefilterCap) { - ocl::Kernel k("prefilter_xsobel", ocl::calib3d::stereobm_oclsrc); + ocl::Kernel k("prefilter_xsobel", ocl::stereo::stereobm_oclsrc); if(k.empty()) return false; @@ -1023,7 +1022,7 @@ static bool ocl_stereobm( InputArray _left, InputArray _right, " -D BLOCK_SIZE_X=%d -D BLOCK_SIZE_Y=%d -D WSZ=%d", mindisp, ndisp, sizeX, sizeY, wsz); - ocl::Kernel k("stereoBM", ocl::calib3d::stereobm_oclsrc, opt); + ocl::Kernel k("stereoBM", ocl::stereo::stereobm_oclsrc, opt); if(k.empty()) return false; diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/stereo/src/stereosgbm.cpp similarity index 99% rename from modules/calib3d/src/stereosgbm.cpp rename to modules/stereo/src/stereosgbm.cpp index 7d5d23c18d..786f216e0f 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/stereo/src/stereosgbm.cpp @@ -55,8 +55,7 @@ #include "opencv2/core/hal/intrin.hpp" #include "opencv2/core/utils/buffer_area.private.hpp" -namespace cv -{ +namespace cv { typedef uchar PixType; typedef short CostType; @@ -2470,9 +2469,7 @@ static bool ipp_filterSpeckles(Mat &img, int maxSpeckleSize, int newVal, int max } #endif -} - -void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize, +void filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize, double _maxDiff, InputOutputArray __buf ) { CV_INSTRUMENT_REGION(); @@ -2492,7 +2489,7 @@ void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSi filterSpecklesImpl(img, newVal, maxSpeckleSize, maxDiff, _buf); } -void cv::validateDisparity( InputOutputArray _disp, InputArray _cost, int minDisparity, +void validateDisparity( InputOutputArray _disp, InputArray _cost, int minDisparity, int numberOfDisparities, int disp12MaxDiff ) { CV_INSTRUMENT_REGION(); @@ -2582,3 +2579,5 @@ void cv::validateDisparity( InputOutputArray _disp, InputArray _cost, int minDis } } } + +} diff --git a/modules/calib3d/test/opencl/test_stereobm.cpp b/modules/stereo/test/opencl/test_stereobm.cpp similarity index 100% rename from modules/calib3d/test/opencl/test_stereobm.cpp rename to modules/stereo/test/opencl/test_stereobm.cpp diff --git a/modules/stereo/test/test_main.cpp b/modules/stereo/test/test_main.cpp new file mode 100644 index 0000000000..faa8d0e2e2 --- /dev/null +++ b/modules/stereo/test/test_main.cpp @@ -0,0 +1,10 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +#include "test_precomp.hpp" + +#if defined(HAVE_HPX) + #include +#endif + +CV_TEST_MAIN("") diff --git a/modules/stereo/test/test_precomp.hpp b/modules/stereo/test/test_precomp.hpp new file mode 100644 index 0000000000..9d95108575 --- /dev/null +++ b/modules/stereo/test/test_precomp.hpp @@ -0,0 +1,13 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +#ifndef __OPENCV_TEST_PRECOMP_HPP__ +#define __OPENCV_TEST_PRECOMP_HPP__ + +#include +#include + +#include "opencv2/ts.hpp" +#include "opencv2/stereo.hpp" + +#endif diff --git a/modules/calib3d/test/test_reproject_image_to_3d.cpp b/modules/stereo/test/test_reproject_image_to_3d.cpp similarity index 100% rename from modules/calib3d/test/test_reproject_image_to_3d.cpp rename to modules/stereo/test/test_reproject_image_to_3d.cpp diff --git a/modules/calib3d/test/test_stereomatching.cpp b/modules/stereo/test/test_stereomatching.cpp similarity index 100% rename from modules/calib3d/test/test_stereomatching.cpp rename to modules/stereo/test/test_stereomatching.cpp diff --git a/modules/stitching/CMakeLists.txt b/modules/stitching/CMakeLists.txt index 44f35eb59b..76dd80b159 100644 --- a/modules/stitching/CMakeLists.txt +++ b/modules/stitching/CMakeLists.txt @@ -8,6 +8,6 @@ set(STITCHING_CONTRIB_DEPS "opencv_xfeatures2d") if(BUILD_SHARED_LIBS AND BUILD_opencv_world AND OPENCV_WORLD_EXCLUDE_EXTRA_MODULES) set(STITCHING_CONTRIB_DEPS "") endif() -ocv_define_module(stitching opencv_imgproc opencv_features2d opencv_calib3d opencv_flann +ocv_define_module(stitching opencv_imgproc opencv_features2d opencv_3d opencv_flann OPTIONAL opencv_cudaarithm opencv_cudawarping opencv_cudafeatures2d opencv_cudalegacy opencv_cudaimgproc ${STITCHING_CONTRIB_DEPS} WRAP python) diff --git a/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp b/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp index 074c9b6dfb..23db56dd41 100644 --- a/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp @@ -44,7 +44,8 @@ #define OPENCV_STITCHING_EXPOSURE_COMPENSATE_HPP #if defined(NO) -# warning Detected Apple 'NO' macro definition, it can cause build conflicts. Please, include this header before any Apple headers. +#undef NO +//#warning Detected Apple 'NO' macro definition, it can cause build conflicts. Please, include this header before any Apple headers. #endif #include "opencv2/core.hpp" diff --git a/modules/stitching/src/motion_estimators.cpp b/modules/stitching/src/motion_estimators.cpp index c0b46b101d..69fdc8473a 100644 --- a/modules/stitching/src/motion_estimators.cpp +++ b/modules/stitching/src/motion_estimators.cpp @@ -42,7 +42,6 @@ #include "precomp.hpp" #include "opencv2/core/core_c.h" -#include "opencv2/calib3d/calib3d_c.h" #include "opencv2/core/cvdef.h" using namespace cv; diff --git a/modules/stitching/src/precomp.hpp b/modules/stitching/src/precomp.hpp index debc0d2088..3b9cf0f85b 100644 --- a/modules/stitching/src/precomp.hpp +++ b/modules/stitching/src/precomp.hpp @@ -69,7 +69,7 @@ #include "opencv2/stitching/detail/warpers.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/features2d.hpp" -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" #ifdef HAVE_OPENCV_CUDAARITHM # include "opencv2/cudaarithm.hpp" diff --git a/modules/ts/misc/run_long.py b/modules/ts/misc/run_long.py old mode 100644 new mode 100755 index b55eb067d0..7870592063 --- a/modules/ts/misc/run_long.py +++ b/modules/ts/misc/run_long.py @@ -5,7 +5,7 @@ from glob import glob from pprint import PrettyPrinter as PP LONG_TESTS_DEBUG_VALGRIND = [ - ('calib3d', 'Calib3d_InitUndistortRectifyMap.accuracy', 2017.22), + ('3d', 'Calib3d_InitUndistortRectifyMap.accuracy', 2017.22), ('dnn', 'Reproducibility*', 1000), # large DNN models ('dnn', '*RCNN*', 1000), # very large DNN models ('dnn', '*RFCN*', 1000), # very large DNN models diff --git a/modules/video/CMakeLists.txt b/modules/video/CMakeLists.txt index 8499de9169..05830f0da7 100644 --- a/modules/video/CMakeLists.txt +++ b/modules/video/CMakeLists.txt @@ -2,7 +2,7 @@ set(the_description "Video Analysis") ocv_define_module(video opencv_imgproc OPTIONAL - opencv_calib3d + opencv_3d opencv_dnn WRAP java diff --git a/modules/video/misc/python/test/test_lk_homography.py b/modules/video/misc/python/test/test_lk_homography.py old mode 100644 new mode 100755 diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 29307053f3..fd27c9288a 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -45,8 +45,8 @@ #include "lkpyramid.hpp" #include "opencl_kernels_video.hpp" #include "opencv2/core/hal/intrin.hpp" -#ifdef HAVE_OPENCV_CALIB3D -#include "opencv2/calib3d.hpp" +#ifdef HAVE_OPENCV_3D +#include "opencv2/3d.hpp" #endif #include "opencv2/core/openvx/ovx_defs.hpp" @@ -1419,9 +1419,9 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, cv::Mat cv::estimateRigidTransform( InputArray src1, InputArray src2, bool fullAffine ) { CV_INSTRUMENT_REGION(); -#ifndef HAVE_OPENCV_CALIB3D +#ifndef HAVE_OPENCV_3D CV_UNUSED(src1); CV_UNUSED(src2); CV_UNUSED(fullAffine); - CV_Error(Error::StsError, "estimateRigidTransform requires calib3d module"); + CV_Error(Error::StsError, "estimateRigidTransform requires 3d module"); #else Mat A = src1.getMat(), B = src2.getMat(); diff --git a/platforms/js/build_js.py b/platforms/js/build_js.py old mode 100644 new mode 100755 index 8a4b64a4da..e741037700 --- a/platforms/js/build_js.py +++ b/platforms/js/build_js.py @@ -116,7 +116,7 @@ class Builder: "-DWITH_QUIRC=OFF", "-DBUILD_ZLIB=ON", "-DBUILD_opencv_apps=OFF", - "-DBUILD_opencv_calib3d=ON", + "-DBUILD_opencv_3d=ON", "-DBUILD_opencv_dnn=ON", "-DBUILD_opencv_features2d=ON", "-DBUILD_opencv_flann=ON", # No bindings provided. This module is used as a dependency for other modules. diff --git a/platforms/js/opencv_js.config.py b/platforms/js/opencv_js.config.py index 72efd46faf..63822a2d9b 100644 --- a/platforms/js/opencv_js.config.py +++ b/platforms/js/opencv_js.config.py @@ -76,7 +76,7 @@ aruco = {'': ['detectMarkers', 'drawDetectedMarkers', 'drawAxis', 'estimatePoseS 'aruco_CharucoBoard': ['create', 'draw'], } -calib3d = {'': ['findHomography', 'calibrateCameraExtended', 'drawFrameAxes', 'estimateAffine2D', 'getDefaultNewCameraMatrix', 'initUndistortRectifyMap', 'Rodrigues']} +_3d = {'': ['findHomography', 'calibrateCameraExtended', 'drawFrameAxes', 'estimateAffine2D', 'getDefaultNewCameraMatrix', 'initUndistortRectifyMap', 'Rodrigues']} white_list = makeWhiteList([core, imgproc, objdetect, video, dnn, features2d, photo, aruco, calib3d]) diff --git a/platforms/wince/readme.md b/platforms/wince/readme.md index 652087368d..acb6dd2467 100644 --- a/platforms/wince/readme.md +++ b/platforms/wince/readme.md @@ -22,7 +22,7 @@ For headless WEC2013, this configuration may not be limited to but is known to w ``` -DBUILD_EXAMPLES=OFF ` -DBUILD_opencv_apps=OFF ` --DBUILD_opencv_calib3d=OFF ` +-DBUILD_opencv_3d=OFF ` -DBUILD_opencv_highgui=OFF ` -DBUILD_opencv_features2d=OFF ` -DBUILD_opencv_flann=OFF ` diff --git a/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrator.java b/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrator.java index aa2c1b5e58..caf351b758 100644 --- a/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrator.java +++ b/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/CameraCalibrator.java @@ -3,7 +3,8 @@ package org.opencv.samples.cameracalibration; import java.util.ArrayList; import java.util.List; -import org.opencv.calib3d.Calib3d; +import org.opencv.cv3d.Cv3d; +import org.opencv.calib.Calib; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; @@ -36,11 +37,11 @@ public class CameraCalibrator { public CameraCalibrator(int width, int height) { mImageSize = new Size(width, height); - mFlags = Calib3d.CALIB_FIX_PRINCIPAL_POINT + - Calib3d.CALIB_ZERO_TANGENT_DIST + - Calib3d.CALIB_FIX_ASPECT_RATIO + - Calib3d.CALIB_FIX_K4 + - Calib3d.CALIB_FIX_K5; + mFlags = Calib.CALIB_FIX_PRINCIPAL_POINT + + Calib.CALIB_ZERO_TANGENT_DIST + + Calib.CALIB_FIX_ASPECT_RATIO + + Calib.CALIB_FIX_K4 + + Calib.CALIB_FIX_K5; Mat.eye(3, 3, CvType.CV_64FC1).copyTo(mCameraMatrix); mCameraMatrix.put(0, 0, 1.0); Mat.zeros(5, 1, CvType.CV_64FC1).copyTo(mDistortionCoefficients); @@ -63,7 +64,7 @@ public class CameraCalibrator { objectPoints.add(objectPoints.get(0)); } - Calib3d.calibrateCamera(objectPoints, mCornersBuffer, mImageSize, + Calib.calibrateCamera(objectPoints, mCornersBuffer, mImageSize, mCameraMatrix, mDistortionCoefficients, rvecs, tvecs, mFlags); mIsCalibrated = Core.checkRange(mCameraMatrix) @@ -107,7 +108,7 @@ public class CameraCalibrator { int totalPoints = 0; for (int i = 0; i < objectPoints.size(); i++) { MatOfPoint3f points = new MatOfPoint3f(objectPoints.get(i)); - Calib3d.projectPoints(points, rvecs.get(i), tvecs.get(i), + Cv3d.projectPoints(points, rvecs.get(i), tvecs.get(i), mCameraMatrix, distortionCoefficients, cornersProjected); error = Core.norm(mCornersBuffer.get(i), cornersProjected, Core.NORM_L2); @@ -123,8 +124,8 @@ public class CameraCalibrator { } private void findPattern(Mat grayFrame) { - mPatternWasFound = Calib3d.findCirclesGrid(grayFrame, mPatternSize, - mCorners, Calib3d.CALIB_CB_ASYMMETRIC_GRID); + mPatternWasFound = Calib.findCirclesGrid(grayFrame, mPatternSize, + mCorners, Calib.CALIB_CB_ASYMMETRIC_GRID); } public void addCorners() { @@ -134,7 +135,7 @@ public class CameraCalibrator { } private void drawPoints(Mat rgbaFrame) { - Calib3d.drawChessboardCorners(rgbaFrame, mPatternSize, mCorners, mPatternWasFound); + Calib.drawChessboardCorners(rgbaFrame, mPatternSize, mCorners, mPatternWasFound); } private void renderFrame(Mat rgbaFrame) { diff --git a/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/OnCameraFrameRender.java b/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/OnCameraFrameRender.java index a89cdf6a82..5cf9e5a9e6 100644 --- a/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/OnCameraFrameRender.java +++ b/samples/android/camera-calibration/src/org/opencv/samples/cameracalibration/OnCameraFrameRender.java @@ -4,7 +4,8 @@ import java.util.ArrayList; import java.util.List; import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame; -import org.opencv.calib3d.Calib3d; +import org.opencv.cv3d.Cv3d; +import org.opencv.calib.Calib; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.MatOfPoint; @@ -51,7 +52,7 @@ class UndistortionFrameRender extends FrameRender { @Override public Mat render(CvCameraViewFrame inputFrame) { Mat renderedFrame = new Mat(inputFrame.rgba().size(), inputFrame.rgba().type()); - Calib3d.undistort(inputFrame.rgba(), renderedFrame, + Cv3d.undistort(inputFrame.rgba(), renderedFrame, mCalibrator.getCameraMatrix(), mCalibrator.getDistortionCoefficients()); return renderedFrame; @@ -72,7 +73,7 @@ class ComparisonFrameRender extends FrameRender { @Override public Mat render(CvCameraViewFrame inputFrame) { Mat undistortedFrame = new Mat(inputFrame.rgba().size(), inputFrame.rgba().type()); - Calib3d.undistort(inputFrame.rgba(), undistortedFrame, + Cv3d.undistort(inputFrame.rgba(), undistortedFrame, mCalibrator.getCameraMatrix(), mCalibrator.getDistortionCoefficients()); Mat comparisonFrame = inputFrame.rgba(); diff --git a/samples/cpp/3calibration.cpp b/samples/cpp/3calibration.cpp index 2495dbd041..f26a6cebce 100644 --- a/samples/cpp/3calibration.cpp +++ b/samples/cpp/3calibration.cpp @@ -2,7 +2,9 @@ * 3calibration.cpp -- Calibrate 3 cameras in a horizontal line together. */ -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" +#include "opencv2/stereo.hpp" +#include "opencv2/calib.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" diff --git a/samples/cpp/CMakeLists.txt b/samples/cpp/CMakeLists.txt index 14ab6141df..baef445ace 100644 --- a/samples/cpp/CMakeLists.txt +++ b/samples/cpp/CMakeLists.txt @@ -12,7 +12,9 @@ set(OPENCV_CPP_SAMPLES_REQUIRED_DEPS opencv_objdetect opencv_photo opencv_features2d - opencv_calib3d + opencv_3d + opencv_stereo + opencv_calib opencv_stitching opencv_dnn ${OPENCV_MODULES_PUBLIC} diff --git a/samples/cpp/asift.cpp b/samples/cpp/asift.cpp index 568954058d..60d8e0f18a 100644 --- a/samples/cpp/asift.cpp +++ b/samples/cpp/asift.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include diff --git a/samples/cpp/calibration.cpp b/samples/cpp/calibration.cpp index 3e978736e7..8c8be66929 100644 --- a/samples/cpp/calibration.cpp +++ b/samples/cpp/calibration.cpp @@ -1,7 +1,8 @@ #include "opencv2/core.hpp" #include #include "opencv2/imgproc.hpp" -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" +#include "opencv2/calib.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" diff --git a/samples/cpp/epipolar_lines.cpp b/samples/cpp/epipolar_lines.cpp index ed514c911e..52bfcfec12 100644 --- a/samples/cpp/epipolar_lines.cpp +++ b/samples/cpp/epipolar_lines.cpp @@ -2,7 +2,8 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" +#include "opencv2/features2d.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" diff --git a/samples/cpp/essential_mat_reconstr.cpp b/samples/cpp/essential_mat_reconstr.cpp index bc9868d059..87f0840451 100644 --- a/samples/cpp/essential_mat_reconstr.cpp +++ b/samples/cpp/essential_mat_reconstr.cpp @@ -2,7 +2,8 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" +#include "opencv2/features2d.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" diff --git a/samples/cpp/select3dobj.cpp b/samples/cpp/select3dobj.cpp index 252bc266cc..c9128ec7fe 100644 --- a/samples/cpp/select3dobj.cpp +++ b/samples/cpp/select3dobj.cpp @@ -11,7 +11,8 @@ #include "opencv2/core.hpp" #include #include "opencv2/imgproc.hpp" -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" +#include "opencv2/calib.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" diff --git a/samples/cpp/stereo_calib.cpp b/samples/cpp/stereo_calib.cpp index 5c1471e4c2..6079be033e 100644 --- a/samples/cpp/stereo_calib.cpp +++ b/samples/cpp/stereo_calib.cpp @@ -21,7 +21,9 @@ GitHub: https://github.com/opencv/opencv/ ************************************************** */ -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" +#include "opencv2/stereo.hpp" +#include "opencv2/calib.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" diff --git a/samples/cpp/stereo_match.cpp b/samples/cpp/stereo_match.cpp index 55cd89c26e..7f83922d2d 100644 --- a/samples/cpp/stereo_match.cpp +++ b/samples/cpp/stereo_match.cpp @@ -6,8 +6,8 @@ * Copyright 2010 Argus Corp. All rights reserved. * */ - -#include "opencv2/calib3d/calib3d.hpp" +#include "opencv2/3d.hpp" +#include "opencv2/stereo.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" @@ -196,7 +196,7 @@ int main(int argc, char** argv) fs["R"] >> R; fs["T"] >> T; - stereoRectify( M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, -1, img_size, &roi1, &roi2 ); + stereoRectify( M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q, STEREO_ZERO_DISPARITY, -1, img_size, &roi1, &roi2 ); Mat map11, map12, map21, map22; initUndistortRectifyMap(M1, D1, R1, P1, img_size, CV_16SC2, map11, map12); diff --git a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp index 2d8b1ddac4..9e1ca42c20 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp @@ -7,7 +7,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.cpp index c99b0eca05..b714a64977 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/PnPProblem.cpp @@ -11,7 +11,7 @@ #include "PnPProblem.h" #include "Mesh.h" -#include +#include /* Functions for Möller-Trumbore intersection algorithm */ static cv::Point3f CROSS(cv::Point3f v1, cv::Point3f v2) diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp index 6b1d553330..5efa2520f0 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #if defined (HAVE_OPENCV_XFEATURES2D) #include @@ -182,7 +182,7 @@ double get_rotation_error(const cv::Mat &R_true, const cv::Mat &R) { cv::Mat error_vec, error_mat; error_mat = -R_true * R.t(); - cv::Rodrigues(error_mat, error_vec); + Rodrigues(error_mat, error_vec); return cv::norm(error_vec); } diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_detection.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_detection.cpp index 8313d56c76..9d19d166ec 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_detection.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_detection.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include // PnP Tutorial #include "Mesh.h" diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_registration.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_registration.cpp index 31ffb2e01e..d7a10bc683 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_registration.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/main_registration.cpp @@ -3,7 +3,7 @@ // OpenCV #include #include -#include +#include #include // PnP Tutorial #include "Mesh.h" diff --git a/samples/cpp/tutorial_code/features2D/AKAZE_tracking/planar_tracking.cpp b/samples/cpp/tutorial_code/features2D/AKAZE_tracking/planar_tracking.cpp index 83c4daad64..1396885345 100644 --- a/samples/cpp/tutorial_code/features2D/AKAZE_tracking/planar_tracking.cpp +++ b/samples/cpp/tutorial_code/features2D/AKAZE_tracking/planar_tracking.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include //for imshow #include #include diff --git a/samples/cpp/tutorial_code/features2D/Homography/decompose_homography.cpp b/samples/cpp/tutorial_code/features2D/Homography/decompose_homography.cpp index acc2faa88b..5558354c85 100644 --- a/samples/cpp/tutorial_code/features2D/Homography/decompose_homography.cpp +++ b/samples/cpp/tutorial_code/features2D/Homography/decompose_homography.cpp @@ -1,7 +1,8 @@ #include #include #include -#include +#include +#include using namespace std; using namespace cv; diff --git a/samples/cpp/tutorial_code/features2D/Homography/homography_from_camera_displacement.cpp b/samples/cpp/tutorial_code/features2D/Homography/homography_from_camera_displacement.cpp index 5bcb6dbb7b..5f902438d6 100644 --- a/samples/cpp/tutorial_code/features2D/Homography/homography_from_camera_displacement.cpp +++ b/samples/cpp/tutorial_code/features2D/Homography/homography_from_camera_displacement.cpp @@ -2,7 +2,8 @@ #include #include #include -#include +#include +#include using namespace std; using namespace cv; diff --git a/samples/cpp/tutorial_code/features2D/Homography/perspective_correction.cpp b/samples/cpp/tutorial_code/features2D/Homography/perspective_correction.cpp index 9d5bc2442e..8c4a2c7dae 100644 --- a/samples/cpp/tutorial_code/features2D/Homography/perspective_correction.cpp +++ b/samples/cpp/tutorial_code/features2D/Homography/perspective_correction.cpp @@ -1,7 +1,8 @@ #include #include #include -#include +#include +#include #include using namespace std; diff --git a/samples/cpp/tutorial_code/features2D/Homography/pose_from_homography.cpp b/samples/cpp/tutorial_code/features2D/Homography/pose_from_homography.cpp index 37ebcac7be..b04d929641 100644 --- a/samples/cpp/tutorial_code/features2D/Homography/pose_from_homography.cpp +++ b/samples/cpp/tutorial_code/features2D/Homography/pose_from_homography.cpp @@ -1,7 +1,8 @@ #include #include #include -#include +#include +#include #include using namespace std; diff --git a/samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp b/samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp index 2aa0bcd9cb..dd3e45203c 100644 --- a/samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp +++ b/samples/cpp/tutorial_code/features2D/feature_homography/SURF_FLANN_matching_homography_Demo.cpp @@ -1,7 +1,7 @@ #include #include "opencv2/core.hpp" #ifdef HAVE_OPENCV_XFEATURES2D -#include "opencv2/calib3d.hpp" +#include "opencv2/3d.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/features2d.hpp" diff --git a/samples/gpu/CMakeLists.txt b/samples/gpu/CMakeLists.txt index eeab50a993..2535138109 100644 --- a/samples/gpu/CMakeLists.txt +++ b/samples/gpu/CMakeLists.txt @@ -11,7 +11,7 @@ set(OPENCV_CUDA_SAMPLES_REQUIRED_DEPS opencv_video opencv_objdetect opencv_features2d - opencv_calib3d + opencv_3d opencv_superres opencv_cudaarithm opencv_cudafilters diff --git a/samples/java/tutorial_code/features2D/Homography/PerspectiveCorrection.java b/samples/java/tutorial_code/features2D/Homography/PerspectiveCorrection.java index f702c1944a..ac94462295 100644 --- a/samples/java/tutorial_code/features2D/Homography/PerspectiveCorrection.java +++ b/samples/java/tutorial_code/features2D/Homography/PerspectiveCorrection.java @@ -3,7 +3,8 @@ import java.util.List; import java.util.Random; import org.opencv.core.*; -import org.opencv.calib3d.Calib3d; +import org.opencv.3d.Cv3d; +import org.opencv.calib.Calib; import org.opencv.highgui.HighGui; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; @@ -17,8 +18,8 @@ class PerspectiveCorrectionRun { //! [find-corners] MatOfPoint2f corners1 = new MatOfPoint2f(), corners2 = new MatOfPoint2f(); - boolean found1 = Calib3d.findChessboardCorners(img1, new Size(9, 6), corners1 ); - boolean found2 = Calib3d.findChessboardCorners(img2, new Size(9, 6), corners2 ); + boolean found1 = Calib.findChessboardCorners(img1, new Size(9, 6), corners1 ); + boolean found2 = Calib.findChessboardCorners(img2, new Size(9, 6), corners2 ); //! [find-corners] if (!found1 || !found2) { @@ -28,7 +29,7 @@ class PerspectiveCorrectionRun { //! [estimate-homography] Mat H = new Mat(); - H = Calib3d.findHomography(corners1, corners2); + H = Cv3d.findHomography(corners1, corners2); System.out.println(H.dump()); //! [estimate-homography] diff --git a/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java b/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java index 1ee33b44f5..3a27a13097 100644 --- a/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java +++ b/samples/java/tutorial_code/features2D/feature_homography/SURFFLANNMatchingHomographyDemo.java @@ -1,7 +1,7 @@ import java.util.ArrayList; import java.util.List; -import org.opencv.calib3d.Calib3d; +import org.opencv._3d; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.DMatch; @@ -82,7 +82,7 @@ class SURFFLANNMatchingHomography { objMat.fromList(obj); sceneMat.fromList(scene); double ransacReprojThreshold = 3.0; - Mat H = Calib3d.findHomography( objMat, sceneMat, Calib3d.RANSAC, ransacReprojThreshold ); + Mat H = Cv3d.findHomography( objMat, sceneMat, Cv3d.RANSAC, ransacReprojThreshold ); //-- Get the corners from the image_1 ( the object to be "detected" ) Mat objCorners = new Mat(4, 1, CvType.CV_32FC2), sceneCorners = new Mat(); diff --git a/samples/python/tutorial_code/features2D/Homography/perspective_correction.py b/samples/python/tutorial_code/features2D/Homography/perspective_correction.py old mode 100644 new mode 100755 diff --git a/samples/tapi/CMakeLists.txt b/samples/tapi/CMakeLists.txt index 1f00326137..5d13a5fdfa 100644 --- a/samples/tapi/CMakeLists.txt +++ b/samples/tapi/CMakeLists.txt @@ -9,7 +9,8 @@ set(OPENCV_TAPI_SAMPLES_REQUIRED_DEPS opencv_highgui opencv_objdetect opencv_features2d - opencv_calib3d + opencv_3d + opencv_stereo opencv_flann) ocv_check_dependencies(${OPENCV_TAPI_SAMPLES_REQUIRED_DEPS})