"atomic bomb" commit. Reorganized OpenCV directory structure
This commit is contained in:
1
modules/calib3d/CMakeLists.txt
Normal file
1
modules/calib3d/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
define_opencv_module(calib3d opencv_core opencv_imgproc)
|
||||
697
modules/calib3d/include/opencv2/calib3d/calib3d.hpp
Normal file
697
modules/calib3d/include/opencv2/calib3d/calib3d.hpp
Normal file
@@ -0,0 +1,697 @@
|
||||
/*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_CALIB3D_HPP__
|
||||
#define __OPENCV_CALIB3D_HPP__
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************\
|
||||
* Camera Calibration, Pose Estimation and Stereo *
|
||||
\****************************************************************************************/
|
||||
|
||||
typedef struct CvPOSITObject CvPOSITObject;
|
||||
|
||||
/* Allocates and initializes CvPOSITObject structure before doing cvPOSIT */
|
||||
CVAPI(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 */
|
||||
CVAPI(void) cvPOSIT( CvPOSITObject* posit_object, CvPoint2D32f* image_points,
|
||||
double focal_length, CvTermCriteria criteria,
|
||||
float* rotation_matrix, float* translation_vector);
|
||||
|
||||
/* Releases CvPOSITObject structure */
|
||||
CVAPI(void) cvReleasePOSITObject( CvPOSITObject** posit_object );
|
||||
|
||||
/* updates the number of RANSAC iterations */
|
||||
CVAPI(int) cvRANSACUpdateNumIters( double p, double err_prob,
|
||||
int model_points, int max_iters );
|
||||
|
||||
CVAPI(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_FM_LMEDS_ONLY 8
|
||||
#define CV_FM_RANSAC_ONLY 4
|
||||
#define CV_FM_LMEDS 8
|
||||
#define CV_FM_RANSAC 4
|
||||
CVAPI(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 */
|
||||
CVAPI(void) cvComputeCorrespondEpilines( const CvMat* points,
|
||||
int which_image,
|
||||
const CvMat* fundamental_matrix,
|
||||
CvMat* correspondent_lines );
|
||||
|
||||
/* Triangulation functions */
|
||||
|
||||
CVAPI(void) cvTriangulatePoints(CvMat* projMatr1, CvMat* projMatr2,
|
||||
CvMat* projPoints1, CvMat* projPoints2,
|
||||
CvMat* points4D);
|
||||
|
||||
CVAPI(void) cvCorrectMatches(CvMat* F, CvMat* points1, CvMat* points2,
|
||||
CvMat* new_points1, CvMat* new_points2);
|
||||
|
||||
/* Transforms the input image to compensate lens distortion */
|
||||
CVAPI(void) cvUndistort2( const CvArr* src, CvArr* dst,
|
||||
const CvMat* camera_matrix,
|
||||
const CvMat* distortion_coeffs,
|
||||
const CvMat* new_camera_matrix CV_DEFAULT(0) );
|
||||
|
||||
/* Computes transformation map from intrinsic camera parameters
|
||||
that can used by cvRemap */
|
||||
CVAPI(void) cvInitUndistortMap( const CvMat* camera_matrix,
|
||||
const CvMat* distortion_coeffs,
|
||||
CvArr* mapx, CvArr* mapy );
|
||||
|
||||
/* Computes undistortion+rectification map for a head of stereo camera */
|
||||
CVAPI(void) cvInitUndistortRectifyMap( const CvMat* camera_matrix,
|
||||
const CvMat* dist_coeffs,
|
||||
const CvMat *R, const CvMat* new_camera_matrix,
|
||||
CvArr* mapx, CvArr* mapy );
|
||||
|
||||
/* Computes the original (undistorted) feature coordinates
|
||||
from the observed (distorted) coordinates */
|
||||
CVAPI(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));
|
||||
|
||||
/* 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
|
||||
*/
|
||||
CVAPI(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) );
|
||||
|
||||
/* Converts rotation vector to rotation matrix or vice versa */
|
||||
CVAPI(int) cvRodrigues2( const CvMat* src, CvMat* dst,
|
||||
CvMat* jacobian CV_DEFAULT(0) );
|
||||
|
||||
#define CV_LMEDS 4
|
||||
#define CV_RANSAC 8
|
||||
|
||||
/* Finds perspective transformation between the object plane and image (view) plane */
|
||||
CVAPI(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));
|
||||
|
||||
/* Computes RQ decomposition for 3x3 matrices */
|
||||
CVAPI(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 */
|
||||
CVAPI(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 */
|
||||
CVAPI(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 */
|
||||
CVAPI(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 */
|
||||
CVAPI(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 */
|
||||
CVAPI(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) */
|
||||
CVAPI(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.) );
|
||||
|
||||
#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
|
||||
|
||||
// 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
|
||||
CVAPI(int) cvCheckChessboard(IplImage* src, CvSize size);
|
||||
|
||||
/* Detects corners on a chessboard calibration pattern */
|
||||
CVAPI(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 */
|
||||
CVAPI(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
|
||||
|
||||
/* Finds intrinsic and extrinsic camera parameters
|
||||
from a few views of known calibration pattern */
|
||||
CVAPI(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) );
|
||||
|
||||
/* Computes various useful characteristics of the camera from the data computed by
|
||||
cvCalibrateCamera2 */
|
||||
CVAPI(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 */
|
||||
CVAPI(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),
|
||||
CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria(
|
||||
CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6)),
|
||||
int flags CV_DEFAULT(CV_CALIB_FIX_INTRINSIC));
|
||||
|
||||
#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) */
|
||||
CVAPI(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 */
|
||||
CVAPI(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
|
||||
|
||||
CVAPI(CvStereoBMState*) cvCreateStereoBMState(int preset CV_DEFAULT(CV_STEREO_BM_BASIC),
|
||||
int numberOfDisparities CV_DEFAULT(0));
|
||||
|
||||
CVAPI(void) cvReleaseStereoBMState( CvStereoBMState** state );
|
||||
|
||||
CVAPI(void) cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right,
|
||||
CvArr* disparity, CvStereoBMState* state );
|
||||
|
||||
CVAPI(CvRect) cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity,
|
||||
int numberOfDisparities, int SADWindowSize );
|
||||
|
||||
CVAPI(void) cvValidateDisparity( CvArr* disparity, const CvArr* cost,
|
||||
int minDisparity, int numberOfDisparities,
|
||||
int disp12MaxDiff CV_DEFAULT(1) );
|
||||
|
||||
/* Kolmogorov-Zabin stereo-correspondence algorithm (a.k.a. KZ1) */
|
||||
#define CV_STEREO_GC_OCCLUDED SHRT_MAX
|
||||
|
||||
typedef struct CvStereoGCState
|
||||
{
|
||||
int Ithreshold;
|
||||
int interactionRadius;
|
||||
float K, lambda, lambda1, lambda2;
|
||||
int occlusionCost;
|
||||
int minDisparity;
|
||||
int numberOfDisparities;
|
||||
int maxIters;
|
||||
|
||||
CvMat* left;
|
||||
CvMat* right;
|
||||
CvMat* dispLeft;
|
||||
CvMat* dispRight;
|
||||
CvMat* ptrLeft;
|
||||
CvMat* ptrRight;
|
||||
CvMat* vtxBuf;
|
||||
CvMat* edgeBuf;
|
||||
} CvStereoGCState;
|
||||
|
||||
CVAPI(CvStereoGCState*) cvCreateStereoGCState( int numberOfDisparities, int maxIters );
|
||||
CVAPI(void) cvReleaseStereoGCState( CvStereoGCState** state );
|
||||
|
||||
CVAPI(void) cvFindStereoCorrespondenceGC( const CvArr* left, const CvArr* right,
|
||||
CvArr* disparityLeft, CvArr* disparityRight,
|
||||
CvStereoGCState* state,
|
||||
int useDisparityGuess CV_DEFAULT(0) );
|
||||
|
||||
/* Reprojects the computed disparity image to the 3D space using the specified 4x4 matrix */
|
||||
CVAPI(void) cvReprojectImageTo3D( const CvArr* disparityImage,
|
||||
CvArr* _3dImage, const CvMat* Q,
|
||||
int handleMissingValues CV_DEFAULT(0) );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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<CvMat> mask;
|
||||
cv::Ptr<CvMat> prevParam;
|
||||
cv::Ptr<CvMat> param;
|
||||
cv::Ptr<CvMat> J;
|
||||
cv::Ptr<CvMat> err;
|
||||
cv::Ptr<CvMat> JtJ;
|
||||
cv::Ptr<CvMat> JtJN;
|
||||
cv::Ptr<CvMat> JtErr;
|
||||
cv::Ptr<CvMat> JtJV;
|
||||
cv::Ptr<CvMat> JtJW;
|
||||
double prevErrNorm, errNorm;
|
||||
int lambdaLg10;
|
||||
CvTermCriteria criteria;
|
||||
int state;
|
||||
int iters;
|
||||
bool completeSymmFlag;
|
||||
};
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
CV_EXPORTS void undistortPoints( const Mat& src, vector<Point2f>& dst,
|
||||
const Mat& cameraMatrix, const Mat& distCoeffs,
|
||||
const Mat& R=Mat(), const Mat& P=Mat());
|
||||
CV_EXPORTS void undistortPoints( const Mat& src, Mat& dst,
|
||||
const Mat& cameraMatrix, const Mat& distCoeffs,
|
||||
const Mat& R=Mat(), const Mat& P=Mat());
|
||||
|
||||
CV_EXPORTS void Rodrigues(const Mat& src, Mat& dst);
|
||||
CV_EXPORTS void Rodrigues(const Mat& src, Mat& dst, Mat& jacobian);
|
||||
|
||||
enum { LMEDS=4, RANSAC=8 };
|
||||
|
||||
CV_EXPORTS Mat findHomography( const Mat& srcPoints,
|
||||
const Mat& dstPoints,
|
||||
Mat& mask, int method=0,
|
||||
double ransacReprojThreshold=3 );
|
||||
|
||||
CV_EXPORTS Mat findHomography( const Mat& srcPoints,
|
||||
const Mat& dstPoints,
|
||||
vector<uchar>& mask, int method=0,
|
||||
double ransacReprojThreshold=3 );
|
||||
|
||||
CV_EXPORTS Mat findHomography( const Mat& srcPoints,
|
||||
const Mat& dstPoints,
|
||||
int method=0, double ransacReprojThreshold=3 );
|
||||
|
||||
/* Computes RQ decomposition for 3x3 matrices */
|
||||
CV_EXPORTS void RQDecomp3x3( const Mat& M, Mat& R, Mat& Q );
|
||||
CV_EXPORTS Vec3d RQDecomp3x3( const Mat& M, Mat& R, Mat& Q,
|
||||
Mat& Qx, Mat& Qy, Mat& Qz );
|
||||
|
||||
CV_EXPORTS void decomposeProjectionMatrix( const Mat& projMatrix, Mat& cameraMatrix,
|
||||
Mat& rotMatrix, Mat& transVect );
|
||||
CV_EXPORTS void decomposeProjectionMatrix( const Mat& projMatrix, Mat& cameraMatrix,
|
||||
Mat& rotMatrix, Mat& transVect,
|
||||
Mat& rotMatrixX, Mat& rotMatrixY,
|
||||
Mat& rotMatrixZ, Vec3d& eulerAngles );
|
||||
|
||||
CV_EXPORTS void matMulDeriv( const Mat& A, const Mat& B, Mat& dABdA, Mat& dABdB );
|
||||
|
||||
CV_EXPORTS void composeRT( const Mat& rvec1, const Mat& tvec1,
|
||||
const Mat& rvec2, const Mat& tvec2,
|
||||
Mat& rvec3, Mat& tvec3 );
|
||||
|
||||
CV_EXPORTS void composeRT( const Mat& rvec1, const Mat& tvec1,
|
||||
const Mat& rvec2, const Mat& tvec2,
|
||||
Mat& rvec3, Mat& tvec3,
|
||||
Mat& dr3dr1, Mat& dr3dt1,
|
||||
Mat& dr3dr2, Mat& dr3dt2,
|
||||
Mat& dt3dr1, Mat& dt3dt1,
|
||||
Mat& dt3dr2, Mat& dt3dt2 );
|
||||
|
||||
CV_EXPORTS void projectPoints( const Mat& objectPoints,
|
||||
const Mat& rvec, const Mat& tvec,
|
||||
const Mat& cameraMatrix,
|
||||
const Mat& distCoeffs,
|
||||
vector<Point2f>& imagePoints );
|
||||
|
||||
CV_EXPORTS void projectPoints( const Mat& objectPoints,
|
||||
const Mat& rvec, const Mat& tvec,
|
||||
const Mat& cameraMatrix,
|
||||
const Mat& distCoeffs,
|
||||
vector<Point2f>& imagePoints,
|
||||
Mat& dpdrot, Mat& dpdt, Mat& dpdf,
|
||||
Mat& dpdc, Mat& dpddist,
|
||||
double aspectRatio=0 );
|
||||
|
||||
CV_EXPORTS void solvePnP( const Mat& objectPoints,
|
||||
const Mat& imagePoints,
|
||||
const Mat& cameraMatrix,
|
||||
const Mat& distCoeffs,
|
||||
Mat& rvec, Mat& tvec,
|
||||
bool useExtrinsicGuess=false );
|
||||
|
||||
CV_EXPORTS Mat initCameraMatrix2D( const vector<vector<Point3f> >& objectPoints,
|
||||
const vector<vector<Point2f> >& imagePoints,
|
||||
Size imageSize, double aspectRatio=1. );
|
||||
|
||||
enum { CALIB_CB_ADAPTIVE_THRESH = 1, CALIB_CB_NORMALIZE_IMAGE = 2,
|
||||
CALIB_CB_FILTER_QUADS = 4, CALIB_CB_FAST_CHECK = 8 };
|
||||
|
||||
CV_EXPORTS bool findChessboardCorners( const Mat& image, Size patternSize,
|
||||
vector<Point2f>& corners,
|
||||
int flags=CALIB_CB_ADAPTIVE_THRESH+
|
||||
CALIB_CB_NORMALIZE_IMAGE );
|
||||
|
||||
CV_EXPORTS void drawChessboardCorners( Mat& image, Size patternSize,
|
||||
const Mat& corners,
|
||||
bool patternWasFound );
|
||||
|
||||
enum
|
||||
{
|
||||
CALIB_USE_INTRINSIC_GUESS = 1,
|
||||
CALIB_FIX_ASPECT_RATIO = 2,
|
||||
CALIB_FIX_PRINCIPAL_POINT = 4,
|
||||
CALIB_ZERO_TANGENT_DIST = 8,
|
||||
CALIB_FIX_FOCAL_LENGTH = 16,
|
||||
CALIB_FIX_K1 = 32,
|
||||
CALIB_FIX_K2 = 64,
|
||||
CALIB_FIX_K3 = 128,
|
||||
// only for stereo
|
||||
CALIB_FIX_INTRINSIC = 256,
|
||||
CALIB_SAME_FOCAL_LENGTH = 512,
|
||||
// for stereo rectification
|
||||
CALIB_ZERO_DISPARITY = 1024
|
||||
};
|
||||
|
||||
CV_EXPORTS double calibrateCamera( const vector<vector<Point3f> >& objectPoints,
|
||||
const vector<vector<Point2f> >& imagePoints,
|
||||
Size imageSize,
|
||||
Mat& cameraMatrix, Mat& distCoeffs,
|
||||
vector<Mat>& rvecs, vector<Mat>& tvecs,
|
||||
int flags=0 );
|
||||
|
||||
CV_EXPORTS void calibrationMatrixValues( const Mat& cameraMatrix,
|
||||
Size imageSize,
|
||||
double apertureWidth,
|
||||
double apertureHeight,
|
||||
double& fovx,
|
||||
double& fovy,
|
||||
double& focalLength,
|
||||
Point2d& principalPoint,
|
||||
double& aspectRatio );
|
||||
|
||||
CV_EXPORTS double stereoCalibrate( const vector<vector<Point3f> >& objectPoints,
|
||||
const vector<vector<Point2f> >& imagePoints1,
|
||||
const vector<vector<Point2f> >& imagePoints2,
|
||||
Mat& cameraMatrix1, Mat& distCoeffs1,
|
||||
Mat& cameraMatrix2, Mat& distCoeffs2,
|
||||
Size imageSize, Mat& R, Mat& T,
|
||||
Mat& E, Mat& F,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+
|
||||
TermCriteria::EPS, 30, 1e-6),
|
||||
int flags=CALIB_FIX_INTRINSIC );
|
||||
|
||||
CV_EXPORTS void stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
|
||||
const Mat& cameraMatrix2, const Mat& distCoeffs2,
|
||||
Size imageSize, const Mat& R, const Mat& T,
|
||||
Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
|
||||
int flags=CALIB_ZERO_DISPARITY );
|
||||
|
||||
CV_EXPORTS void stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
|
||||
const Mat& cameraMatrix2, const Mat& distCoeffs2,
|
||||
Size imageSize, const Mat& R, const Mat& T,
|
||||
Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
|
||||
double alpha, Size newImageSize=Size(),
|
||||
Rect* validPixROI1=0, Rect* validPixROI2=0,
|
||||
int flags=CALIB_ZERO_DISPARITY );
|
||||
|
||||
CV_EXPORTS bool stereoRectifyUncalibrated( const Mat& points1,
|
||||
const Mat& points2,
|
||||
const Mat& F, Size imgSize,
|
||||
Mat& H1, Mat& H2,
|
||||
double threshold=5 );
|
||||
|
||||
CV_EXPORTS void convertPointsHomogeneous( const Mat& src, vector<Point3f>& dst );
|
||||
CV_EXPORTS void convertPointsHomogeneous( const Mat& src, vector<Point2f>& dst );
|
||||
|
||||
enum
|
||||
{
|
||||
FM_7POINT = 1, FM_8POINT = 2, FM_LMEDS = 4, FM_RANSAC = 8
|
||||
};
|
||||
|
||||
CV_EXPORTS Mat findFundamentalMat( const Mat& points1, const Mat& points2,
|
||||
vector<uchar>& mask, int method=FM_RANSAC,
|
||||
double param1=3., double param2=0.99 );
|
||||
|
||||
CV_EXPORTS Mat findFundamentalMat( const Mat& points1, const Mat& points2,
|
||||
int method=FM_RANSAC,
|
||||
double param1=3., double param2=0.99 );
|
||||
|
||||
CV_EXPORTS void computeCorrespondEpilines( const Mat& points1,
|
||||
int whichImage, const Mat& F,
|
||||
vector<Vec3f>& lines );
|
||||
|
||||
template<> CV_EXPORTS void Ptr<CvStereoBMState>::delete_obj();
|
||||
|
||||
// Block matching stereo correspondence algorithm
|
||||
class CV_EXPORTS StereoBM
|
||||
{
|
||||
public:
|
||||
enum { PREFILTER_NORMALIZED_RESPONSE = 0, PREFILTER_XSOBEL = 1,
|
||||
BASIC_PRESET=0, FISH_EYE_PRESET=1, NARROW_PRESET=2 };
|
||||
|
||||
StereoBM();
|
||||
StereoBM(int preset, int ndisparities=0, int SADWindowSize=21);
|
||||
void init(int preset, int ndisparities=0, int SADWindowSize=21);
|
||||
void operator()( const Mat& left, const Mat& right, Mat& disparity, int disptype=CV_16S );
|
||||
|
||||
Ptr<CvStereoBMState> state;
|
||||
};
|
||||
|
||||
|
||||
class CV_EXPORTS StereoSGBM
|
||||
{
|
||||
public:
|
||||
enum { DISP_SHIFT=4, DISP_SCALE = (1<<DISP_SHIFT) };
|
||||
|
||||
StereoSGBM();
|
||||
StereoSGBM(int minDisparity, int numDisparities, int SADWindowSize,
|
||||
int P1=0, int P2=0, int disp12MaxDiff=0,
|
||||
int preFilterCap=0, int uniquenessRatio=0,
|
||||
int speckleWindowSize=0, int speckleRange=0,
|
||||
bool fullDP=false);
|
||||
virtual ~StereoSGBM();
|
||||
|
||||
virtual void operator()(const Mat& left, const Mat& right, Mat& disp);
|
||||
|
||||
int minDisparity;
|
||||
int numberOfDisparities;
|
||||
int SADWindowSize;
|
||||
int preFilterCap;
|
||||
int uniquenessRatio;
|
||||
int P1, P2;
|
||||
int speckleWindowSize;
|
||||
int speckleRange;
|
||||
int disp12MaxDiff;
|
||||
bool fullDP;
|
||||
|
||||
protected:
|
||||
Mat buffer;
|
||||
};
|
||||
|
||||
|
||||
CV_EXPORTS void filterSpeckles( Mat& img, double newVal, int maxSpeckleSize, double maxDiff, Mat& buf );
|
||||
|
||||
CV_EXPORTS Rect getValidDisparityROI( Rect roi1, Rect roi2,
|
||||
int minDisparity, int numberOfDisparities,
|
||||
int SADWindowSize );
|
||||
|
||||
CV_EXPORTS void validateDisparity( Mat& disparity, const Mat& cost,
|
||||
int minDisparity, int numberOfDisparities,
|
||||
int disp12MaxDisp=1 );
|
||||
|
||||
CV_EXPORTS void reprojectImageTo3D( const Mat& disparity,
|
||||
Mat& _3dImage, const Mat& Q,
|
||||
bool handleMissingValues=false );
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#include "opencv2/calib3d/compat_c.h"
|
||||
|
||||
#endif
|
||||
321
modules/calib3d/include/opencv2/calib3d/compat_c.h
Normal file
321
modules/calib3d/include/opencv2/calib3d/compat_c.h
Normal file
@@ -0,0 +1,321 @@
|
||||
/*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_CALIB3D_COMPAT_C_H__
|
||||
#define __OPENCV_CALIB3D_COMPAT_C_H__
|
||||
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Find fundamental matrix */
|
||||
CV_INLINE void cvFindFundamentalMatrix( int* points1, int* points2,
|
||||
int numpoints, int CV_UNREFERENCED(method), float* matrix )
|
||||
{
|
||||
CvMat* pointsMat1;
|
||||
CvMat* pointsMat2;
|
||||
CvMat fundMatr = cvMat(3,3,CV_32F,matrix);
|
||||
int i, curr = 0;
|
||||
|
||||
pointsMat1 = cvCreateMat(3,numpoints,CV_64F);
|
||||
pointsMat2 = cvCreateMat(3,numpoints,CV_64F);
|
||||
|
||||
for( i = 0; i < numpoints; i++ )
|
||||
{
|
||||
cvmSet(pointsMat1,0,i,points1[curr]);//x
|
||||
cvmSet(pointsMat1,1,i,points1[curr+1]);//y
|
||||
cvmSet(pointsMat1,2,i,1.0);
|
||||
|
||||
cvmSet(pointsMat2,0,i,points2[curr]);//x
|
||||
cvmSet(pointsMat2,1,i,points2[curr+1]);//y
|
||||
cvmSet(pointsMat2,2,i,1.0);
|
||||
curr += 2;
|
||||
}
|
||||
|
||||
cvFindFundamentalMat(pointsMat1,pointsMat2,&fundMatr,CV_FM_RANSAC,1,0.99,0);
|
||||
|
||||
cvReleaseMat(&pointsMat1);
|
||||
cvReleaseMat(&pointsMat2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
CV_INLINE int
|
||||
cvFindChessBoardCornerGuesses( const void* arr, void* CV_UNREFERENCED(thresharr),
|
||||
CvMemStorage * CV_UNREFERENCED(storage),
|
||||
CvSize pattern_size, CvPoint2D32f * corners,
|
||||
int *corner_count )
|
||||
{
|
||||
return cvFindChessboardCorners( arr, pattern_size, corners,
|
||||
corner_count, CV_CALIB_CB_ADAPTIVE_THRESH );
|
||||
}
|
||||
|
||||
|
||||
/* Calibrates camera using multiple views of calibration pattern */
|
||||
CV_INLINE void cvCalibrateCamera( int image_count, int* _point_counts,
|
||||
CvSize image_size, CvPoint2D32f* _image_points, CvPoint3D32f* _object_points,
|
||||
float* _distortion_coeffs, float* _camera_matrix, float* _translation_vectors,
|
||||
float* _rotation_matrices, int flags )
|
||||
{
|
||||
int i, total = 0;
|
||||
CvMat point_counts = cvMat( image_count, 1, CV_32SC1, _point_counts );
|
||||
CvMat image_points, object_points;
|
||||
CvMat dist_coeffs = cvMat( 4, 1, CV_32FC1, _distortion_coeffs );
|
||||
CvMat camera_matrix = cvMat( 3, 3, CV_32FC1, _camera_matrix );
|
||||
CvMat rotation_matrices = cvMat( image_count, 9, CV_32FC1, _rotation_matrices );
|
||||
CvMat translation_vectors = cvMat( image_count, 3, CV_32FC1, _translation_vectors );
|
||||
|
||||
for( i = 0; i < image_count; i++ )
|
||||
total += _point_counts[i];
|
||||
|
||||
image_points = cvMat( total, 1, CV_32FC2, _image_points );
|
||||
object_points = cvMat( total, 1, CV_32FC3, _object_points );
|
||||
|
||||
cvCalibrateCamera2( &object_points, &image_points, &point_counts, image_size,
|
||||
&camera_matrix, &dist_coeffs, &rotation_matrices, &translation_vectors,
|
||||
flags );
|
||||
}
|
||||
|
||||
|
||||
CV_INLINE void cvCalibrateCamera_64d( int image_count, int* _point_counts,
|
||||
CvSize image_size, CvPoint2D64f* _image_points, CvPoint3D64f* _object_points,
|
||||
double* _distortion_coeffs, double* _camera_matrix, double* _translation_vectors,
|
||||
double* _rotation_matrices, int flags )
|
||||
{
|
||||
int i, total = 0;
|
||||
CvMat point_counts = cvMat( image_count, 1, CV_32SC1, _point_counts );
|
||||
CvMat image_points, object_points;
|
||||
CvMat dist_coeffs = cvMat( 4, 1, CV_64FC1, _distortion_coeffs );
|
||||
CvMat camera_matrix = cvMat( 3, 3, CV_64FC1, _camera_matrix );
|
||||
CvMat rotation_matrices = cvMat( image_count, 9, CV_64FC1, _rotation_matrices );
|
||||
CvMat translation_vectors = cvMat( image_count, 3, CV_64FC1, _translation_vectors );
|
||||
|
||||
for( i = 0; i < image_count; i++ )
|
||||
total += _point_counts[i];
|
||||
|
||||
image_points = cvMat( total, 1, CV_64FC2, _image_points );
|
||||
object_points = cvMat( total, 1, CV_64FC3, _object_points );
|
||||
|
||||
cvCalibrateCamera2( &object_points, &image_points, &point_counts, image_size,
|
||||
&camera_matrix, &dist_coeffs, &rotation_matrices, &translation_vectors,
|
||||
flags );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Find 3d position of object given intrinsic camera parameters,
|
||||
3d model of the object and projection of the object into view plane */
|
||||
CV_INLINE void cvFindExtrinsicCameraParams( int point_count,
|
||||
CvSize CV_UNREFERENCED(image_size), CvPoint2D32f* _image_points,
|
||||
CvPoint3D32f* _object_points, float* focal_length,
|
||||
CvPoint2D32f principal_point, float* _distortion_coeffs,
|
||||
float* _rotation_vector, float* _translation_vector )
|
||||
{
|
||||
CvMat image_points = cvMat( point_count, 1, CV_32FC2, _image_points );
|
||||
CvMat object_points = cvMat( point_count, 1, CV_32FC3, _object_points );
|
||||
CvMat dist_coeffs = cvMat( 4, 1, CV_32FC1, _distortion_coeffs );
|
||||
float a[9];
|
||||
CvMat camera_matrix = cvMat( 3, 3, CV_32FC1, a );
|
||||
CvMat rotation_vector = cvMat( 1, 1, CV_32FC3, _rotation_vector );
|
||||
CvMat translation_vector = cvMat( 1, 1, CV_32FC3, _translation_vector );
|
||||
|
||||
a[0] = focal_length[0]; a[4] = focal_length[1];
|
||||
a[2] = principal_point.x; a[5] = principal_point.y;
|
||||
a[1] = a[3] = a[6] = a[7] = 0.f;
|
||||
a[8] = 1.f;
|
||||
|
||||
cvFindExtrinsicCameraParams2( &object_points, &image_points, &camera_matrix,
|
||||
&dist_coeffs, &rotation_vector, &translation_vector, 0 );
|
||||
}
|
||||
|
||||
|
||||
/* Variant of the previous function that takes double-precision parameters */
|
||||
CV_INLINE void cvFindExtrinsicCameraParams_64d( int point_count,
|
||||
CvSize CV_UNREFERENCED(image_size), CvPoint2D64f* _image_points,
|
||||
CvPoint3D64f* _object_points, double* focal_length,
|
||||
CvPoint2D64f principal_point, double* _distortion_coeffs,
|
||||
double* _rotation_vector, double* _translation_vector )
|
||||
{
|
||||
CvMat image_points = cvMat( point_count, 1, CV_64FC2, _image_points );
|
||||
CvMat object_points = cvMat( point_count, 1, CV_64FC3, _object_points );
|
||||
CvMat dist_coeffs = cvMat( 4, 1, CV_64FC1, _distortion_coeffs );
|
||||
double a[9];
|
||||
CvMat camera_matrix = cvMat( 3, 3, CV_64FC1, a );
|
||||
CvMat rotation_vector = cvMat( 1, 1, CV_64FC3, _rotation_vector );
|
||||
CvMat translation_vector = cvMat( 1, 1, CV_64FC3, _translation_vector );
|
||||
|
||||
a[0] = focal_length[0]; a[4] = focal_length[1];
|
||||
a[2] = principal_point.x; a[5] = principal_point.y;
|
||||
a[1] = a[3] = a[6] = a[7] = 0.;
|
||||
a[8] = 1.;
|
||||
|
||||
cvFindExtrinsicCameraParams2( &object_points, &image_points, &camera_matrix,
|
||||
&dist_coeffs, &rotation_vector, &translation_vector, 0 );
|
||||
}
|
||||
|
||||
|
||||
/* Rodrigues transform */
|
||||
#define CV_RODRIGUES_M2V 0
|
||||
#define CV_RODRIGUES_V2M 1
|
||||
|
||||
/* Converts rotation_matrix matrix to rotation_matrix vector or vice versa */
|
||||
CV_INLINE void cvRodrigues( CvMat* rotation_matrix, CvMat* rotation_vector,
|
||||
CvMat* jacobian, int conv_type )
|
||||
{
|
||||
if( conv_type == CV_RODRIGUES_V2M )
|
||||
cvRodrigues2( rotation_vector, rotation_matrix, jacobian );
|
||||
else
|
||||
cvRodrigues2( rotation_matrix, rotation_vector, jacobian );
|
||||
}
|
||||
|
||||
|
||||
/* Does reprojection of 3d object points to the view plane */
|
||||
CV_INLINE void cvProjectPoints( int point_count, CvPoint3D64f* _object_points,
|
||||
double* _rotation_vector, double* _translation_vector,
|
||||
double* focal_length, CvPoint2D64f principal_point,
|
||||
double* _distortion, CvPoint2D64f* _image_points,
|
||||
double* _deriv_points_rotation_matrix,
|
||||
double* _deriv_points_translation_vect,
|
||||
double* _deriv_points_focal,
|
||||
double* _deriv_points_principal_point,
|
||||
double* _deriv_points_distortion_coeffs )
|
||||
{
|
||||
CvMat object_points = cvMat( point_count, 1, CV_64FC3, _object_points );
|
||||
CvMat image_points = cvMat( point_count, 1, CV_64FC2, _image_points );
|
||||
CvMat rotation_vector = cvMat( 3, 1, CV_64FC1, _rotation_vector );
|
||||
CvMat translation_vector = cvMat( 3, 1, CV_64FC1, _translation_vector );
|
||||
double a[9];
|
||||
CvMat camera_matrix = cvMat( 3, 3, CV_64FC1, a );
|
||||
CvMat dist_coeffs = cvMat( 4, 1, CV_64FC1, _distortion );
|
||||
CvMat dpdr = cvMat( 2*point_count, 3, CV_64FC1, _deriv_points_rotation_matrix );
|
||||
CvMat dpdt = cvMat( 2*point_count, 3, CV_64FC1, _deriv_points_translation_vect );
|
||||
CvMat dpdf = cvMat( 2*point_count, 2, CV_64FC1, _deriv_points_focal );
|
||||
CvMat dpdc = cvMat( 2*point_count, 2, CV_64FC1, _deriv_points_principal_point );
|
||||
CvMat dpdk = cvMat( 2*point_count, 4, CV_64FC1, _deriv_points_distortion_coeffs );
|
||||
|
||||
a[0] = focal_length[0]; a[4] = focal_length[1];
|
||||
a[2] = principal_point.x; a[5] = principal_point.y;
|
||||
a[1] = a[3] = a[6] = a[7] = 0.;
|
||||
a[8] = 1.;
|
||||
|
||||
cvProjectPoints2( &object_points, &rotation_vector, &translation_vector,
|
||||
&camera_matrix, &dist_coeffs, &image_points,
|
||||
&dpdr, &dpdt, &dpdf, &dpdc, &dpdk, 0 );
|
||||
}
|
||||
|
||||
|
||||
/* Simpler version of the previous function */
|
||||
CV_INLINE void cvProjectPointsSimple( int point_count, CvPoint3D64f* _object_points,
|
||||
double* _rotation_matrix, double* _translation_vector,
|
||||
double* _camera_matrix, double* _distortion, CvPoint2D64f* _image_points )
|
||||
{
|
||||
CvMat object_points = cvMat( point_count, 1, CV_64FC3, _object_points );
|
||||
CvMat image_points = cvMat( point_count, 1, CV_64FC2, _image_points );
|
||||
CvMat rotation_matrix = cvMat( 3, 3, CV_64FC1, _rotation_matrix );
|
||||
CvMat translation_vector = cvMat( 3, 1, CV_64FC1, _translation_vector );
|
||||
CvMat camera_matrix = cvMat( 3, 3, CV_64FC1, _camera_matrix );
|
||||
CvMat dist_coeffs = cvMat( 4, 1, CV_64FC1, _distortion );
|
||||
|
||||
cvProjectPoints2( &object_points, &rotation_matrix, &translation_vector,
|
||||
&camera_matrix, &dist_coeffs, &image_points,
|
||||
0, 0, 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
CV_INLINE void cvUnDistortOnce( const CvArr* src, CvArr* dst,
|
||||
const float* intrinsic_matrix,
|
||||
const float* distortion_coeffs,
|
||||
int CV_UNREFERENCED(interpolate) )
|
||||
{
|
||||
CvMat _a = cvMat( 3, 3, CV_32F, (void*)intrinsic_matrix );
|
||||
CvMat _k = cvMat( 4, 1, CV_32F, (void*)distortion_coeffs );
|
||||
cvUndistort2( src, dst, &_a, &_k, 0 );
|
||||
}
|
||||
|
||||
|
||||
/* the two functions below have quite hackerish implementations, use with care
|
||||
(or, which is better, switch to cvUndistortInitMap and cvRemap instead */
|
||||
CV_INLINE void cvUnDistortInit( const CvArr* CV_UNREFERENCED(src),
|
||||
CvArr* undistortion_map,
|
||||
const float* A, const float* k,
|
||||
int CV_UNREFERENCED(interpolate) )
|
||||
{
|
||||
union { uchar* ptr; float* fl; } data;
|
||||
CvSize sz;
|
||||
cvGetRawData( undistortion_map, &data.ptr, 0, &sz );
|
||||
assert( sz.width >= 8 );
|
||||
/* just save the intrinsic parameters to the map */
|
||||
data.fl[0] = A[0]; data.fl[1] = A[4];
|
||||
data.fl[2] = A[2]; data.fl[3] = A[5];
|
||||
data.fl[4] = k[0]; data.fl[5] = k[1];
|
||||
data.fl[6] = k[2]; data.fl[7] = k[3];
|
||||
}
|
||||
|
||||
CV_INLINE void cvUnDistort( const CvArr* src, CvArr* dst,
|
||||
const CvArr* undistortion_map,
|
||||
int CV_UNREFERENCED(interpolate) )
|
||||
{
|
||||
union { uchar* ptr; float* fl; } data;
|
||||
float a[] = {0,0,0,0,0,0,0,0,1};
|
||||
CvSize sz;
|
||||
cvGetRawData( undistortion_map, &data.ptr, 0, &sz );
|
||||
assert( sz.width >= 8 );
|
||||
a[0] = data.fl[0]; a[4] = data.fl[1];
|
||||
a[2] = data.fl[2]; a[5] = data.fl[3];
|
||||
cvUnDistortOnce( src, dst, a, data.fl + 4, 1 );
|
||||
}
|
||||
|
||||
#define cvMake2DPoints cvConvertPointsHomogeneous
|
||||
#define cvMake3DPoints cvConvertPointsHomogeneous
|
||||
|
||||
#define cvWarpPerspectiveQMatrix cvGetPerspectiveTransform
|
||||
|
||||
#define cvConvertPointsHomogenious cvConvertPointsHomogeneous
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
81
modules/calib3d/src/_modelest.h
Normal file
81
modules/calib3d/src/_modelest.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*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*/
|
||||
|
||||
|
||||
#ifndef _CV_MODEL_EST_H_
|
||||
#define _CV_MODEL_EST_H_
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
class CvModelEstimator2
|
||||
{
|
||||
public:
|
||||
CvModelEstimator2(int _modelPoints, CvSize _modelSize, int _maxBasicSolutions);
|
||||
virtual ~CvModelEstimator2();
|
||||
|
||||
virtual int runKernel( const CvMat* m1, const CvMat* m2, CvMat* model )=0;
|
||||
virtual bool runLMeDS( const CvMat* m1, const CvMat* m2, CvMat* model,
|
||||
CvMat* mask, double confidence=0.99, int maxIters=2000 );
|
||||
virtual bool runRANSAC( const CvMat* m1, const CvMat* m2, CvMat* model,
|
||||
CvMat* mask, double threshold,
|
||||
double confidence=0.99, int maxIters=2000 );
|
||||
virtual bool refine( const CvMat*, const CvMat*, CvMat*, int ) { return true; }
|
||||
virtual void setSeed( int64 seed );
|
||||
|
||||
protected:
|
||||
virtual void computeReprojError( const CvMat* m1, const CvMat* m2,
|
||||
const CvMat* model, CvMat* error ) = 0;
|
||||
virtual int findInliers( const CvMat* m1, const CvMat* m2,
|
||||
const CvMat* model, CvMat* error,
|
||||
CvMat* mask, double threshold );
|
||||
virtual bool getSubset( const CvMat* m1, const CvMat* m2,
|
||||
CvMat* ms1, CvMat* ms2, int maxAttempts=1000 );
|
||||
virtual bool checkSubset( const CvMat* ms1, int count );
|
||||
|
||||
CvRNG rng;
|
||||
int modelPoints;
|
||||
CvSize modelSize;
|
||||
int maxBasicSolutions;
|
||||
bool checkPartialSubsets;
|
||||
};
|
||||
|
||||
#endif // _CV_MODEL_EST_H_
|
||||
|
||||
1921
modules/calib3d/src/calibinit.cpp
Normal file
1921
modules/calib3d/src/calibinit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3452
modules/calib3d/src/calibration.cpp
Normal file
3452
modules/calib3d/src/calibration.cpp
Normal file
File diff suppressed because it is too large
Load Diff
200
modules/calib3d/src/checkchessboard.cpp
Normal file
200
modules/calib3d/src/checkchessboard.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/*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 <vector>
|
||||
#include <algorithm>
|
||||
|
||||
//#define DEBUG_WINDOWS
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
#include "highgui.h"
|
||||
#endif
|
||||
|
||||
void icvGetQuadrangleHypotheses(CvSeq* contours, std::vector<std::pair<float, int> >& quads, int class_id)
|
||||
{
|
||||
const float min_aspect_ratio = 0.3f;
|
||||
const float max_aspect_ratio = 3.0f;
|
||||
const float min_box_size = 10.0f;
|
||||
|
||||
for(CvSeq* seq = contours; seq != NULL; seq = seq->h_next)
|
||||
{
|
||||
CvBox2D box = cvMinAreaRect2(seq);
|
||||
float box_size = MAX(box.size.width, box.size.height);
|
||||
if(box_size < min_box_size)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float aspect_ratio = box.size.width/MAX(box.size.height, 1);
|
||||
if(aspect_ratio < min_aspect_ratio || aspect_ratio > max_aspect_ratio)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
quads.push_back(std::pair<float, int>(box_size, class_id));
|
||||
}
|
||||
}
|
||||
|
||||
void countClasses(const std::vector<std::pair<float, int> >& pairs, size_t idx1, size_t idx2, std::vector<int>& counts)
|
||||
{
|
||||
counts.assign(2, 0);
|
||||
for(size_t i = idx1; i != idx2; i++)
|
||||
{
|
||||
counts[pairs[i].second]++;
|
||||
}
|
||||
}
|
||||
|
||||
bool less_pred(const std::pair<float, int>& p1, const std::pair<float, int>& p2)
|
||||
{
|
||||
return p1.first < p2.first;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if(src->nChannels > 1)
|
||||
{
|
||||
cvError(CV_BadNumChannels, "cvCheckChessboard", "supports single-channel images only",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
if(src->depth != 8)
|
||||
{
|
||||
cvError(CV_BadDepth, "cvCheckChessboard", "supports depth=8 images only",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
const int erosion_count = 1;
|
||||
const float black_level = 20.f;
|
||||
const float white_level = 130.f;
|
||||
const float black_white_gap = 70.f;
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
cvNamedWindow("1", 1);
|
||||
cvShowImage("1", src);
|
||||
cvWaitKey(0);
|
||||
#endif //DEBUG_WINDOWS
|
||||
|
||||
CvMemStorage* storage = cvCreateMemStorage();
|
||||
|
||||
IplImage* white = cvCloneImage(src);
|
||||
IplImage* black = cvCloneImage(src);
|
||||
|
||||
cvErode(white, white, NULL, erosion_count);
|
||||
cvDilate(black, black, NULL, erosion_count);
|
||||
IplImage* thresh = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
|
||||
|
||||
int result = 0;
|
||||
for(float thresh_level = black_level; thresh_level < white_level && !result; thresh_level += 20.0f)
|
||||
{
|
||||
cvThreshold(white, thresh, thresh_level + black_white_gap, 255, CV_THRESH_BINARY);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
cvShowImage("1", thresh);
|
||||
cvWaitKey(0);
|
||||
#endif //DEBUG_WINDOWS
|
||||
|
||||
CvSeq* first = 0;
|
||||
std::vector<std::pair<float, int> > quads;
|
||||
cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
|
||||
icvGetQuadrangleHypotheses(first, quads, 1);
|
||||
|
||||
cvThreshold(black, thresh, thresh_level, 255, CV_THRESH_BINARY_INV);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
cvShowImage("1", thresh);
|
||||
cvWaitKey(0);
|
||||
#endif //DEBUG_WINDOWS
|
||||
|
||||
cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
|
||||
icvGetQuadrangleHypotheses(first, quads, 0);
|
||||
|
||||
const size_t min_quads_count = size.width*size.height/2;
|
||||
std::sort(quads.begin(), quads.end(), less_pred);
|
||||
|
||||
// now check if there are many hypotheses with similar sizes
|
||||
// do this by floodfill-style algorithm
|
||||
const float size_rel_dev = 0.4f;
|
||||
|
||||
for(size_t i = 0; i < quads.size(); i++)
|
||||
{
|
||||
size_t j = i + 1;
|
||||
for(; j < quads.size(); j++)
|
||||
{
|
||||
if(quads[j].first/quads[i].first > 1.0f + size_rel_dev)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(j + 1 > min_quads_count + i)
|
||||
{
|
||||
// check the number of black and white squares
|
||||
std::vector<int> counts;
|
||||
countClasses(quads, i, j, counts);
|
||||
const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0));
|
||||
const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0));
|
||||
if(counts[0] < black_count*0.75 ||
|
||||
counts[1] < white_count*0.75)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cvReleaseImage(&thresh);
|
||||
cvReleaseImage(&white);
|
||||
cvReleaseImage(&black);
|
||||
cvReleaseMemStorage(&storage);
|
||||
|
||||
return result;
|
||||
}
|
||||
1163
modules/calib3d/src/fundam.cpp
Normal file
1163
modules/calib3d/src/fundam.cpp
Normal file
File diff suppressed because it is too large
Load Diff
484
modules/calib3d/src/modelest.cpp
Normal file
484
modules/calib3d/src/modelest.cpp
Normal file
@@ -0,0 +1,484 @@
|
||||
/*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 "_modelest.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
CvModelEstimator2::CvModelEstimator2(int _modelPoints, CvSize _modelSize, int _maxBasicSolutions)
|
||||
{
|
||||
modelPoints = _modelPoints;
|
||||
modelSize = _modelSize;
|
||||
maxBasicSolutions = _maxBasicSolutions;
|
||||
checkPartialSubsets = true;
|
||||
rng = cvRNG(-1);
|
||||
}
|
||||
|
||||
CvModelEstimator2::~CvModelEstimator2()
|
||||
{
|
||||
}
|
||||
|
||||
void CvModelEstimator2::setSeed( int64 seed )
|
||||
{
|
||||
rng = cvRNG(seed);
|
||||
}
|
||||
|
||||
|
||||
int CvModelEstimator2::findInliers( const CvMat* m1, const CvMat* m2,
|
||||
const CvMat* model, CvMat* _err,
|
||||
CvMat* _mask, double threshold )
|
||||
{
|
||||
int i, count = _err->rows*_err->cols, goodCount = 0;
|
||||
const float* err = _err->data.fl;
|
||||
uchar* mask = _mask->data.ptr;
|
||||
|
||||
computeReprojError( m1, m2, model, _err );
|
||||
threshold *= threshold;
|
||||
for( i = 0; i < count; i++ )
|
||||
goodCount += mask[i] = err[i] <= threshold;
|
||||
return goodCount;
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL int
|
||||
cvRANSACUpdateNumIters( double p, double ep,
|
||||
int model_points, int max_iters )
|
||||
{
|
||||
if( model_points <= 0 )
|
||||
CV_Error( CV_StsOutOfRange, "the number of model points should be positive" );
|
||||
|
||||
p = MAX(p, 0.);
|
||||
p = MIN(p, 1.);
|
||||
ep = MAX(ep, 0.);
|
||||
ep = MIN(ep, 1.);
|
||||
|
||||
// avoid inf's & nan's
|
||||
double num = MAX(1. - p, DBL_MIN);
|
||||
double denom = 1. - pow(1. - ep,model_points);
|
||||
if( denom < DBL_MIN )
|
||||
return 0;
|
||||
|
||||
num = log(num);
|
||||
denom = log(denom);
|
||||
|
||||
return denom >= 0 || -num >= max_iters*(-denom) ?
|
||||
max_iters : cvRound(num/denom);
|
||||
}
|
||||
|
||||
bool CvModelEstimator2::runRANSAC( const CvMat* m1, const CvMat* m2, CvMat* model,
|
||||
CvMat* mask0, double reprojThreshold,
|
||||
double confidence, int maxIters )
|
||||
{
|
||||
bool result = false;
|
||||
cv::Ptr<CvMat> mask = cvCloneMat(mask0);
|
||||
cv::Ptr<CvMat> models, err, tmask;
|
||||
cv::Ptr<CvMat> ms1, ms2;
|
||||
|
||||
int iter, niters = maxIters;
|
||||
int count = m1->rows*m1->cols, maxGoodCount = 0;
|
||||
CV_Assert( CV_ARE_SIZES_EQ(m1, m2) && CV_ARE_SIZES_EQ(m1, mask) );
|
||||
|
||||
if( count < modelPoints )
|
||||
return false;
|
||||
|
||||
models = cvCreateMat( modelSize.height*maxBasicSolutions, modelSize.width, CV_64FC1 );
|
||||
err = cvCreateMat( 1, count, CV_32FC1 );
|
||||
tmask = cvCreateMat( 1, count, CV_8UC1 );
|
||||
|
||||
if( count > modelPoints )
|
||||
{
|
||||
ms1 = cvCreateMat( 1, modelPoints, m1->type );
|
||||
ms2 = cvCreateMat( 1, modelPoints, m2->type );
|
||||
}
|
||||
else
|
||||
{
|
||||
niters = 1;
|
||||
ms1 = cvCloneMat(m1);
|
||||
ms2 = cvCloneMat(m2);
|
||||
}
|
||||
|
||||
for( iter = 0; iter < niters; iter++ )
|
||||
{
|
||||
int i, goodCount, nmodels;
|
||||
if( count > modelPoints )
|
||||
{
|
||||
bool found = getSubset( m1, m2, ms1, ms2, 300 );
|
||||
if( !found )
|
||||
{
|
||||
if( iter == 0 )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nmodels = runKernel( ms1, ms2, models );
|
||||
if( nmodels <= 0 )
|
||||
continue;
|
||||
for( i = 0; i < nmodels; i++ )
|
||||
{
|
||||
CvMat model_i;
|
||||
cvGetRows( models, &model_i, i*modelSize.height, (i+1)*modelSize.height );
|
||||
goodCount = findInliers( m1, m2, &model_i, err, tmask, reprojThreshold );
|
||||
|
||||
if( goodCount > MAX(maxGoodCount, modelPoints-1) )
|
||||
{
|
||||
std::swap(tmask, mask);
|
||||
cvCopy( &model_i, model );
|
||||
maxGoodCount = goodCount;
|
||||
niters = cvRANSACUpdateNumIters( confidence,
|
||||
(double)(count - goodCount)/count, modelPoints, niters );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( maxGoodCount > 0 )
|
||||
{
|
||||
if( mask != mask0 )
|
||||
cvCopy( mask, mask0 );
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static CV_IMPLEMENT_QSORT( icvSortDistances, int, CV_LT )
|
||||
|
||||
bool CvModelEstimator2::runLMeDS( const CvMat* m1, const CvMat* m2, CvMat* model,
|
||||
CvMat* mask, double confidence, int maxIters )
|
||||
{
|
||||
const double outlierRatio = 0.45;
|
||||
bool result = false;
|
||||
cv::Ptr<CvMat> models;
|
||||
cv::Ptr<CvMat> ms1, ms2;
|
||||
cv::Ptr<CvMat> err;
|
||||
|
||||
int iter, niters = maxIters;
|
||||
int count = m1->rows*m1->cols;
|
||||
double minMedian = DBL_MAX, sigma;
|
||||
|
||||
CV_Assert( CV_ARE_SIZES_EQ(m1, m2) && CV_ARE_SIZES_EQ(m1, mask) );
|
||||
|
||||
if( count < modelPoints )
|
||||
return false;
|
||||
|
||||
models = cvCreateMat( modelSize.height*maxBasicSolutions, modelSize.width, CV_64FC1 );
|
||||
err = cvCreateMat( 1, count, CV_32FC1 );
|
||||
|
||||
if( count > modelPoints )
|
||||
{
|
||||
ms1 = cvCreateMat( 1, modelPoints, m1->type );
|
||||
ms2 = cvCreateMat( 1, modelPoints, m2->type );
|
||||
}
|
||||
else
|
||||
{
|
||||
niters = 1;
|
||||
ms1 = cvCloneMat(m1);
|
||||
ms2 = cvCloneMat(m2);
|
||||
}
|
||||
|
||||
niters = cvRound(log(1-confidence)/log(1-pow(1-outlierRatio,(double)modelPoints)));
|
||||
niters = MIN( MAX(niters, 3), maxIters );
|
||||
|
||||
for( iter = 0; iter < niters; iter++ )
|
||||
{
|
||||
int i, nmodels;
|
||||
if( count > modelPoints )
|
||||
{
|
||||
bool found = getSubset( m1, m2, ms1, ms2, 300 );
|
||||
if( !found )
|
||||
{
|
||||
if( iter == 0 )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nmodels = runKernel( ms1, ms2, models );
|
||||
if( nmodels <= 0 )
|
||||
continue;
|
||||
for( i = 0; i < nmodels; i++ )
|
||||
{
|
||||
CvMat model_i;
|
||||
cvGetRows( models, &model_i, i*modelSize.height, (i+1)*modelSize.height );
|
||||
computeReprojError( m1, m2, &model_i, err );
|
||||
icvSortDistances( err->data.i, count, 0 );
|
||||
|
||||
double median = count % 2 != 0 ?
|
||||
err->data.fl[count/2] : (err->data.fl[count/2-1] + err->data.fl[count/2])*0.5;
|
||||
|
||||
if( median < minMedian )
|
||||
{
|
||||
minMedian = median;
|
||||
cvCopy( &model_i, model );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( minMedian < DBL_MAX )
|
||||
{
|
||||
sigma = 2.5*1.4826*(1 + 5./(count - modelPoints))*sqrt(minMedian);
|
||||
sigma = MAX( sigma, FLT_EPSILON*100 );
|
||||
|
||||
count = findInliers( m1, m2, model, err, mask, sigma );
|
||||
result = count >= modelPoints;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool CvModelEstimator2::getSubset( const CvMat* m1, const CvMat* m2,
|
||||
CvMat* ms1, CvMat* ms2, int maxAttempts )
|
||||
{
|
||||
int* idx = (int*)cvStackAlloc( modelPoints*sizeof(idx[0]) );
|
||||
int i = 0, j, k, idx_i, iters = 0;
|
||||
int type = CV_MAT_TYPE(m1->type), elemSize = CV_ELEM_SIZE(type);
|
||||
const int *m1ptr = m1->data.i, *m2ptr = m2->data.i;
|
||||
int *ms1ptr = ms1->data.i, *ms2ptr = ms2->data.i;
|
||||
int count = m1->cols*m1->rows;
|
||||
|
||||
assert( CV_IS_MAT_CONT(m1->type & m2->type) && (elemSize % sizeof(int) == 0) );
|
||||
elemSize /= sizeof(int);
|
||||
|
||||
for(; iters < maxAttempts; iters++)
|
||||
{
|
||||
for( i = 0; i < modelPoints && iters < maxAttempts; )
|
||||
{
|
||||
idx[i] = idx_i = cvRandInt(&rng) % count;
|
||||
for( j = 0; j < i; j++ )
|
||||
if( idx_i == idx[j] )
|
||||
break;
|
||||
if( j < i )
|
||||
continue;
|
||||
for( k = 0; k < elemSize; k++ )
|
||||
{
|
||||
ms1ptr[i*elemSize + k] = m1ptr[idx_i*elemSize + k];
|
||||
ms2ptr[i*elemSize + k] = m2ptr[idx_i*elemSize + k];
|
||||
}
|
||||
if( checkPartialSubsets && (!checkSubset( ms1, i+1 ) || !checkSubset( ms2, i+1 )))
|
||||
{
|
||||
iters++;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if( !checkPartialSubsets && i == modelPoints &&
|
||||
(!checkSubset( ms1, i ) || !checkSubset( ms2, i )))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
return i == modelPoints && iters < maxAttempts;
|
||||
}
|
||||
|
||||
|
||||
bool CvModelEstimator2::checkSubset( const CvMat* m, int count )
|
||||
{
|
||||
int j, k, i, i0, i1;
|
||||
CvPoint2D64f* ptr = (CvPoint2D64f*)m->data.ptr;
|
||||
|
||||
assert( CV_MAT_TYPE(m->type) == CV_64FC2 );
|
||||
|
||||
if( checkPartialSubsets )
|
||||
i0 = i1 = count - 1;
|
||||
else
|
||||
i0 = 0, i1 = count - 1;
|
||||
|
||||
for( i = i0; i <= i1; i++ )
|
||||
{
|
||||
// check that the i-th selected point does not belong
|
||||
// to a line connecting some previously selected points
|
||||
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)))
|
||||
break;
|
||||
}
|
||||
if( k < j )
|
||||
break;
|
||||
}
|
||||
if( j < i )
|
||||
break;
|
||||
}
|
||||
|
||||
return i >= i1;
|
||||
}
|
||||
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class Affine3DEstimator : public CvModelEstimator2
|
||||
{
|
||||
public:
|
||||
Affine3DEstimator() : CvModelEstimator2(4, cvSize(4, 3), 1) {}
|
||||
virtual int runKernel( const CvMat* m1, const CvMat* m2, CvMat* model );
|
||||
protected:
|
||||
virtual void computeReprojError( const CvMat* m1, const CvMat* m2, const CvMat* model, CvMat* error );
|
||||
virtual bool checkSubset( const CvMat* ms1, int count );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
int cv::Affine3DEstimator::runKernel( const CvMat* m1, const CvMat* m2, CvMat* model )
|
||||
{
|
||||
const Point3d* from = reinterpret_cast<const Point3d*>(m1->data.ptr);
|
||||
const Point3d* to = reinterpret_cast<const Point3d*>(m2->data.ptr);
|
||||
|
||||
Mat A(12, 12, CV_64F);
|
||||
Mat B(12, 1, CV_64F);
|
||||
A = Scalar(0.0);
|
||||
|
||||
for(int i = 0; i < modelPoints; ++i)
|
||||
{
|
||||
*B.ptr<Point3d>(3*i) = to[i];
|
||||
|
||||
double *aptr = A.ptr<double>(3*i);
|
||||
for(int k = 0; k < 3; ++k)
|
||||
{
|
||||
aptr[3] = 1.0;
|
||||
*reinterpret_cast<Point3d*>(aptr) = from[i];
|
||||
aptr += 16;
|
||||
}
|
||||
}
|
||||
|
||||
CvMat cvA = A;
|
||||
CvMat cvB = B;
|
||||
CvMat cvX;
|
||||
cvReshape(model, &cvX, 1, 12);
|
||||
cvSolve(&cvA, &cvB, &cvX, CV_SVD );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cv::Affine3DEstimator::computeReprojError( const CvMat* m1, const CvMat* m2, const CvMat* model, CvMat* error )
|
||||
{
|
||||
int count = m1->rows * m1->cols;
|
||||
const Point3d* from = reinterpret_cast<const Point3d*>(m1->data.ptr);
|
||||
const Point3d* to = reinterpret_cast<const Point3d*>(m2->data.ptr);
|
||||
const double* F = model->data.db;
|
||||
float* err = error->data.fl;
|
||||
|
||||
for(int i = 0; i < count; i++ )
|
||||
{
|
||||
const Point3d& f = from[i];
|
||||
const Point3d& t = to[i];
|
||||
|
||||
double a = F[0]*f.x + F[1]*f.y + F[ 2]*f.z + F[ 3] - t.x;
|
||||
double b = F[4]*f.x + F[5]*f.y + F[ 6]*f.z + F[ 7] - t.y;
|
||||
double c = F[8]*f.x + F[9]*f.y + F[10]*f.z + F[11] - t.z;
|
||||
|
||||
err[i] = (float)sqrt(a*a + b*b + c*c);
|
||||
}
|
||||
}
|
||||
|
||||
bool cv::Affine3DEstimator::checkSubset( const CvMat* ms1, int count )
|
||||
{
|
||||
CV_Assert( CV_MAT_TYPE(ms1->type) == CV_64FC3 );
|
||||
|
||||
int j, k, i = count - 1;
|
||||
const Point3d* ptr = reinterpret_cast<const Point3d*>(ms1->data.ptr);
|
||||
|
||||
// check that the i-th selected point does not belong
|
||||
// to a line connecting some previously selected points
|
||||
|
||||
for(j = 0; j < i; ++j)
|
||||
{
|
||||
Point3d d1 = ptr[j] - ptr[i];
|
||||
double n1 = norm(d1);
|
||||
|
||||
for(k = 0; k < j; ++k)
|
||||
{
|
||||
Point3d d2 = ptr[k] - ptr[i];
|
||||
double n = norm(d2) * n1;
|
||||
|
||||
if (fabs(d1.dot(d2) / n) > 0.996)
|
||||
break;
|
||||
}
|
||||
if( k < j )
|
||||
break;
|
||||
}
|
||||
|
||||
return j == i;
|
||||
}
|
||||
|
||||
int cv::estimateAffine3D(const Mat& from, const Mat& to, Mat& out, vector<uchar>& outliers, double param1, double param2)
|
||||
{
|
||||
size_t count = from.cols*from.rows*from.channels()/3;
|
||||
|
||||
CV_Assert( count >= 4 && from.isContinuous() && to.isContinuous() &&
|
||||
from.depth() == CV_32F && to.depth() == CV_32F &&
|
||||
((from.rows == 1 && from.channels() == 3) || from.cols*from.channels() == 3) &&
|
||||
((to.rows == 1 && to.channels() == 3) || to.cols*to.channels() == 3) &&
|
||||
count == (size_t)to.cols*to.rows*to.channels()/3);
|
||||
|
||||
out.create(3, 4, CV_64F);
|
||||
outliers.resize(count);
|
||||
fill(outliers.begin(), outliers.end(), (uchar)1);
|
||||
|
||||
vector<Point3d> dFrom;
|
||||
vector<Point3d> dTo;
|
||||
|
||||
copy(from.ptr<Point3f>(), from.ptr<Point3f>() + count, back_inserter(dFrom));
|
||||
copy(to.ptr<Point3f>(), to.ptr<Point3f>() + count, back_inserter(dTo));
|
||||
|
||||
CvMat F3x4 = out;
|
||||
CvMat mask = cvMat( 1, count, CV_8U, &outliers[0] );
|
||||
CvMat m1 = cvMat( 1, count, CV_64FC3, &dFrom[0] );
|
||||
CvMat m2 = cvMat( 1, count, CV_64FC3, &dTo[0] );
|
||||
|
||||
const double epsilon = numeric_limits<double>::epsilon();
|
||||
param1 = param1 <= 0 ? 3 : param1;
|
||||
param2 = (param2 < epsilon) ? 0.99 : (param2 > 1 - epsilon) ? 0.99 : param2;
|
||||
|
||||
return Affine3DEstimator().runRANSAC(&m1,& m2, &F3x4, &mask, param1, param2 );
|
||||
}
|
||||
358
modules/calib3d/src/posit.cpp
Normal file
358
modules/calib3d/src/posit.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
/*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"
|
||||
|
||||
/* 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, converged = 0;
|
||||
float inorm, jnorm, invInorm, invJnorm, invScale, scale = 0, inv_Z = 0;
|
||||
float diff = (float)criteria.epsilon;
|
||||
float inv_focalLength = 1 / focalLength;
|
||||
|
||||
/* init variables */
|
||||
int N = pObject->N;
|
||||
float *objectVectors = pObject->obj_vecs;
|
||||
float *invMatrix = pObject->inv_matr;
|
||||
float *imgVectors = pObject->img_vecs;
|
||||
|
||||
/* 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;
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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]*/;
|
||||
|
||||
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]*/;
|
||||
|
||||
invInorm = cvInvSqrt( inorm );
|
||||
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));
|
||||
converged |= ((criteria.type & CV_TERMCRIT_ITER) && (count == criteria.max_iter));
|
||||
}
|
||||
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 )
|
||||
{
|
||||
int k;
|
||||
|
||||
if( method == 0 )
|
||||
{
|
||||
float ata00 = 0;
|
||||
float ata11 = 0;
|
||||
float ata22 = 0;
|
||||
float ata01 = 0;
|
||||
float ata02 = 0;
|
||||
float ata12 = 0;
|
||||
float det = 0;
|
||||
|
||||
/* 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 inv_det;
|
||||
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;
|
||||
|
||||
det += ata00 * p00;
|
||||
det += ata01 * p01;
|
||||
det += ata02 * p02;
|
||||
|
||||
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. */
|
||||
44
modules/calib3d/src/precomp.cpp
Normal file
44
modules/calib3d/src/precomp.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*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"
|
||||
|
||||
/* End of file. */
|
||||
54
modules/calib3d/src/precomp.hpp
Normal file
54
modules/calib3d/src/precomp.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*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__
|
||||
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning( disable: 4251 4710 4711 4514 4996 ) /* function AAA selected for automatic inline expansion */
|
||||
#endif
|
||||
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/core/internal.hpp"
|
||||
|
||||
#endif
|
||||
945
modules/calib3d/src/stereobm.cpp
Normal file
945
modules/calib3d/src/stereobm.cpp
Normal file
@@ -0,0 +1,945 @@
|
||||
//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*/
|
||||
|
||||
/****************************************************************************************\
|
||||
* Very fast SAD-based (Sum-of-Absolute-Diffrences) stereo correspondence algorithm. *
|
||||
* Contributed by Kurt Konolige *
|
||||
\****************************************************************************************/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
|
||||
//#undef CV_SSE2
|
||||
//#define CV_SSE2 0
|
||||
//#include "emmintrin.h"
|
||||
|
||||
|
||||
#include <limits>
|
||||
|
||||
CV_IMPL CvStereoBMState* cvCreateStereoBMState( int /*preset*/, int numberOfDisparities )
|
||||
{
|
||||
CvStereoBMState* state = (CvStereoBMState*)cvAlloc( sizeof(*state) );
|
||||
if( !state )
|
||||
return 0;
|
||||
|
||||
state->preFilterType = CV_STEREO_BM_XSOBEL; //CV_STEREO_BM_NORMALIZED_RESPONSE;
|
||||
state->preFilterSize = 9;
|
||||
state->preFilterCap = 31;
|
||||
state->SADWindowSize = 15;
|
||||
state->minDisparity = 0;
|
||||
state->numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : 64;
|
||||
state->textureThreshold = 10;
|
||||
state->uniquenessRatio = 15;
|
||||
state->speckleRange = state->speckleWindowSize = 0;
|
||||
state->trySmallerWindows = 0;
|
||||
state->roi1 = state->roi2 = cvRect(0,0,0,0);
|
||||
state->disp12MaxDiff = -1;
|
||||
|
||||
state->preFilteredImg0 = state->preFilteredImg1 = state->slidingSumBuf =
|
||||
state->disp = state->cost = 0;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
CV_IMPL void cvReleaseStereoBMState( CvStereoBMState** state )
|
||||
{
|
||||
if( !state )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
|
||||
if( !*state )
|
||||
return;
|
||||
|
||||
cvReleaseMat( &(*state)->preFilteredImg0 );
|
||||
cvReleaseMat( &(*state)->preFilteredImg1 );
|
||||
cvReleaseMat( &(*state)->slidingSumBuf );
|
||||
cvReleaseMat( &(*state)->disp );
|
||||
cvReleaseMat( &(*state)->cost );
|
||||
cvFree( state );
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
static void prefilterNorm( const Mat& src, Mat& dst, int winsize, int ftzero, uchar* buf )
|
||||
{
|
||||
int x, y, wsz2 = winsize/2;
|
||||
int* vsum = (int*)alignPtr(buf + (wsz2 + 1)*sizeof(vsum[0]), 32);
|
||||
int scale_g = winsize*winsize/8, scale_s = (1024 + scale_g)/(scale_g*2);
|
||||
const int OFS = 256*5, TABSZ = OFS*2 + 256;
|
||||
uchar tab[TABSZ];
|
||||
const uchar* sptr = src.data;
|
||||
int srcstep = src.step;
|
||||
Size size = src.size();
|
||||
|
||||
scale_g *= scale_s;
|
||||
|
||||
for( x = 0; x < TABSZ; x++ )
|
||||
tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero*2 : x - OFS + ftzero);
|
||||
|
||||
for( x = 0; x < size.width; x++ )
|
||||
vsum[x] = (ushort)(sptr[x]*(wsz2 + 2));
|
||||
|
||||
for( y = 1; y < wsz2; y++ )
|
||||
{
|
||||
for( x = 0; x < size.width; x++ )
|
||||
vsum[x] = (ushort)(vsum[x] + sptr[srcstep*y + x]);
|
||||
}
|
||||
|
||||
for( y = 0; y < size.height; y++ )
|
||||
{
|
||||
const uchar* top = sptr + srcstep*MAX(y-wsz2-1,0);
|
||||
const uchar* bottom = sptr + srcstep*MIN(y+wsz2,size.height-1);
|
||||
const uchar* prev = sptr + srcstep*MAX(y-1,0);
|
||||
const uchar* curr = sptr + srcstep*y;
|
||||
const uchar* next = sptr + srcstep*MIN(y+1,size.height-1);
|
||||
uchar* dptr = dst.ptr<uchar>(y);
|
||||
x = 0;
|
||||
|
||||
for( ; x < size.width; x++ )
|
||||
vsum[x] = (ushort)(vsum[x] + bottom[x] - top[x]);
|
||||
|
||||
for( x = 0; x <= wsz2; x++ )
|
||||
{
|
||||
vsum[-x-1] = vsum[0];
|
||||
vsum[size.width+x] = vsum[size.width-1];
|
||||
}
|
||||
|
||||
int sum = vsum[0]*(wsz2 + 1);
|
||||
for( x = 1; x <= wsz2; x++ )
|
||||
sum += vsum[x];
|
||||
|
||||
int val = ((curr[0]*5 + curr[1] + prev[0] + next[0])*scale_g - sum*scale_s) >> 10;
|
||||
dptr[0] = tab[val + OFS];
|
||||
|
||||
for( x = 1; x < size.width-1; x++ )
|
||||
{
|
||||
sum += vsum[x+wsz2] - vsum[x-wsz2-1];
|
||||
val = ((curr[x]*4 + curr[x-1] + curr[x+1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10;
|
||||
dptr[x] = tab[val + OFS];
|
||||
}
|
||||
|
||||
sum += vsum[x+wsz2] - vsum[x-wsz2-1];
|
||||
val = ((curr[x]*5 + curr[x-1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10;
|
||||
dptr[x] = tab[val + OFS];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
prefilterXSobel( const Mat& src, Mat& dst, int ftzero )
|
||||
{
|
||||
int x, y;
|
||||
const int OFS = 256*4, TABSZ = OFS*2 + 256;
|
||||
uchar tab[TABSZ];
|
||||
Size size = src.size();
|
||||
|
||||
for( x = 0; x < TABSZ; x++ )
|
||||
tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero*2 : x - OFS + ftzero);
|
||||
uchar val0 = tab[0 + OFS];
|
||||
|
||||
#if CV_SSE2
|
||||
volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2);
|
||||
#endif
|
||||
|
||||
for( y = 0; y < size.height-1; y += 2 )
|
||||
{
|
||||
const uchar* srow1 = src.ptr<uchar>(y);
|
||||
const uchar* srow0 = y > 0 ? srow1 - src.step : size.height > 1 ? srow1 + src.step : srow1;
|
||||
const uchar* srow2 = y < size.height-1 ? srow1 + src.step : size.height > 1 ? srow1 - src.step : srow1;
|
||||
const uchar* srow3 = y < size.height-2 ? srow1 + src.step*2 : srow1;
|
||||
uchar* dptr0 = dst.ptr<uchar>(y);
|
||||
uchar* dptr1 = dptr0 + dst.step;
|
||||
|
||||
dptr0[0] = dptr0[size.width-1] = dptr1[0] = dptr1[size.width-1] = val0;
|
||||
x = 1;
|
||||
|
||||
#if CV_SSE2
|
||||
if( useSIMD )
|
||||
{
|
||||
__m128i z = _mm_setzero_si128(), ftz = _mm_set1_epi16((short)ftzero),
|
||||
ftz2 = _mm_set1_epi8(CV_CAST_8U(ftzero*2));
|
||||
for( ; x <= size.width-9; x += 8 )
|
||||
{
|
||||
__m128i c0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x - 1)), z);
|
||||
__m128i c1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x - 1)), z);
|
||||
__m128i d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x + 1)), z);
|
||||
__m128i d1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x + 1)), z);
|
||||
|
||||
d0 = _mm_sub_epi16(d0, c0);
|
||||
d1 = _mm_sub_epi16(d1, c1);
|
||||
|
||||
__m128i c2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x - 1)), z);
|
||||
__m128i c3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x - 1)), z);
|
||||
__m128i d2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x + 1)), z);
|
||||
__m128i d3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x + 1)), z);
|
||||
|
||||
d2 = _mm_sub_epi16(d2, c2);
|
||||
d3 = _mm_sub_epi16(d3, c3);
|
||||
|
||||
__m128i v0 = _mm_add_epi16(d0, _mm_add_epi16(d2, _mm_add_epi16(d1, d1)));
|
||||
__m128i v1 = _mm_add_epi16(d1, _mm_add_epi16(d3, _mm_add_epi16(d2, d2)));
|
||||
v0 = _mm_packus_epi16(_mm_add_epi16(v0, ftz), _mm_add_epi16(v1, ftz));
|
||||
v0 = _mm_min_epu8(v0, ftz2);
|
||||
|
||||
_mm_storel_epi64((__m128i*)(dptr0 + x), v0);
|
||||
_mm_storel_epi64((__m128i*)(dptr1 + x), _mm_unpackhi_epi64(v0, v0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for( ; x < size.width-1; x++ )
|
||||
{
|
||||
int d0 = srow0[x+1] - srow0[x-1], d1 = srow1[x+1] - srow1[x-1],
|
||||
d2 = srow2[x+1] - srow2[x-1], d3 = srow3[x+1] - srow3[x-1];
|
||||
int v0 = tab[d0 + d1*2 + d2 + OFS];
|
||||
int v1 = tab[d1 + d2*2 + d3 + OFS];
|
||||
dptr0[x] = (uchar)v0;
|
||||
dptr1[x] = (uchar)v1;
|
||||
}
|
||||
}
|
||||
|
||||
for( ; y < size.height; y++ )
|
||||
{
|
||||
uchar* dptr = dst.ptr<uchar>(y);
|
||||
for( x = 0; x < size.width; x++ )
|
||||
dptr[x] = val0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const int DISPARITY_SHIFT = 4;
|
||||
|
||||
#if CV_SSE2
|
||||
static void findStereoCorrespondenceBM_SSE2( const Mat& left, const Mat& right,
|
||||
Mat& disp, Mat& cost, CvStereoBMState& state,
|
||||
uchar* buf, int _dy0, int _dy1 )
|
||||
{
|
||||
const int ALIGN = 16;
|
||||
int x, y, d;
|
||||
int wsz = state.SADWindowSize, wsz2 = wsz/2;
|
||||
int dy0 = MIN(_dy0, wsz2+1), dy1 = MIN(_dy1, wsz2+1);
|
||||
int ndisp = state.numberOfDisparities;
|
||||
int mindisp = state.minDisparity;
|
||||
int lofs = MAX(ndisp - 1 + mindisp, 0);
|
||||
int rofs = -MIN(ndisp - 1 + mindisp, 0);
|
||||
int width = left.cols, height = left.rows;
|
||||
int width1 = width - rofs - ndisp + 1;
|
||||
int ftzero = state.preFilterCap;
|
||||
int textureThreshold = state.textureThreshold;
|
||||
int uniquenessRatio = state.uniquenessRatio*256/100;
|
||||
short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT);
|
||||
|
||||
ushort *sad, *hsad0, *hsad, *hsad_sub;
|
||||
int *htext;
|
||||
uchar *cbuf0, *cbuf;
|
||||
const uchar* lptr0 = left.data + lofs;
|
||||
const uchar* rptr0 = right.data + rofs;
|
||||
const uchar *lptr, *lptr_sub, *rptr;
|
||||
short* dptr = (short*)disp.data;
|
||||
int sstep = left.step;
|
||||
int dstep = disp.step/sizeof(dptr[0]);
|
||||
int cstep = (height + dy0 + dy1)*ndisp;
|
||||
short costbuf = 0;
|
||||
int coststep = cost.data ? cost.step/sizeof(costbuf) : 0;
|
||||
const int TABSZ = 256;
|
||||
uchar tab[TABSZ];
|
||||
const __m128i d0_8 = _mm_setr_epi16(0,1,2,3,4,5,6,7), dd_8 = _mm_set1_epi16(8);
|
||||
|
||||
sad = (ushort*)alignPtr(buf + sizeof(sad[0]), ALIGN);
|
||||
hsad0 = (ushort*)alignPtr(sad + ndisp + 1 + dy0*ndisp, ALIGN);
|
||||
htext = (int*)alignPtr((int*)(hsad0 + (height+dy1)*ndisp) + wsz2 + 2, ALIGN);
|
||||
cbuf0 = (uchar*)alignPtr(htext + height + wsz2 + 2 + dy0*ndisp, ALIGN);
|
||||
|
||||
for( x = 0; x < TABSZ; x++ )
|
||||
tab[x] = (uchar)std::abs(x - ftzero);
|
||||
|
||||
// initialize buffers
|
||||
memset( hsad0 - dy0*ndisp, 0, (height + dy0 + dy1)*ndisp*sizeof(hsad0[0]) );
|
||||
memset( htext - wsz2 - 1, 0, (height + wsz + 1)*sizeof(htext[0]) );
|
||||
|
||||
for( x = -wsz2-1; x < wsz2; x++ )
|
||||
{
|
||||
hsad = hsad0 - dy0*ndisp; cbuf = cbuf0 + (x + wsz2 + 1)*cstep - dy0*ndisp;
|
||||
lptr = lptr0 + MIN(MAX(x, -lofs), width-lofs-1) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x, -rofs), width-rofs-1) - dy0*sstep;
|
||||
|
||||
for( y = -dy0; y < height + dy1; y++, hsad += ndisp, cbuf += ndisp, lptr += sstep, rptr += sstep )
|
||||
{
|
||||
int lval = lptr[0];
|
||||
__m128i lv = _mm_set1_epi8((char)lval), z = _mm_setzero_si128();
|
||||
for( d = 0; d < ndisp; d += 16 )
|
||||
{
|
||||
__m128i rv = _mm_loadu_si128((const __m128i*)(rptr + d));
|
||||
__m128i hsad_l = _mm_load_si128((__m128i*)(hsad + d));
|
||||
__m128i hsad_h = _mm_load_si128((__m128i*)(hsad + d + 8));
|
||||
__m128i diff = _mm_adds_epu8(_mm_subs_epu8(lv, rv), _mm_subs_epu8(rv, lv));
|
||||
_mm_store_si128((__m128i*)(cbuf + d), diff);
|
||||
hsad_l = _mm_add_epi16(hsad_l, _mm_unpacklo_epi8(diff,z));
|
||||
hsad_h = _mm_add_epi16(hsad_h, _mm_unpackhi_epi8(diff,z));
|
||||
_mm_store_si128((__m128i*)(hsad + d), hsad_l);
|
||||
_mm_store_si128((__m128i*)(hsad + d + 8), hsad_h);
|
||||
}
|
||||
htext[y] += tab[lval];
|
||||
}
|
||||
}
|
||||
|
||||
// initialize the left and right borders of the disparity map
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
for( x = 0; x < lofs; x++ )
|
||||
dptr[y*dstep + x] = FILTERED;
|
||||
for( x = lofs + width1; x < width; x++ )
|
||||
dptr[y*dstep + x] = FILTERED;
|
||||
}
|
||||
dptr += lofs;
|
||||
|
||||
for( x = 0; x < width1; x++, dptr++ )
|
||||
{
|
||||
short* costptr = cost.data ? (short*)cost.data + lofs + x : &costbuf;
|
||||
int x0 = x - wsz2 - 1, x1 = x + wsz2;
|
||||
const uchar* cbuf_sub = cbuf0 + ((x0 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp;
|
||||
uchar* cbuf = cbuf0 + ((x1 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp;
|
||||
hsad = hsad0 - dy0*ndisp;
|
||||
lptr_sub = lptr0 + MIN(MAX(x0, -lofs), width-1-lofs) - dy0*sstep;
|
||||
lptr = lptr0 + MIN(MAX(x1, -lofs), width-1-lofs) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x1, -rofs), width-1-rofs) - dy0*sstep;
|
||||
|
||||
for( y = -dy0; y < height + dy1; y++, cbuf += ndisp, cbuf_sub += ndisp,
|
||||
hsad += ndisp, lptr += sstep, lptr_sub += sstep, rptr += sstep )
|
||||
{
|
||||
int lval = lptr[0];
|
||||
__m128i lv = _mm_set1_epi8((char)lval), z = _mm_setzero_si128();
|
||||
for( d = 0; d < ndisp; d += 16 )
|
||||
{
|
||||
__m128i rv = _mm_loadu_si128((const __m128i*)(rptr + d));
|
||||
__m128i hsad_l = _mm_load_si128((__m128i*)(hsad + d));
|
||||
__m128i hsad_h = _mm_load_si128((__m128i*)(hsad + d + 8));
|
||||
__m128i cbs = _mm_load_si128((const __m128i*)(cbuf_sub + d));
|
||||
__m128i diff = _mm_adds_epu8(_mm_subs_epu8(lv, rv), _mm_subs_epu8(rv, lv));
|
||||
__m128i diff_h = _mm_sub_epi16(_mm_unpackhi_epi8(diff, z), _mm_unpackhi_epi8(cbs, z));
|
||||
_mm_store_si128((__m128i*)(cbuf + d), diff);
|
||||
diff = _mm_sub_epi16(_mm_unpacklo_epi8(diff, z), _mm_unpacklo_epi8(cbs, z));
|
||||
hsad_h = _mm_add_epi16(hsad_h, diff_h);
|
||||
hsad_l = _mm_add_epi16(hsad_l, diff);
|
||||
_mm_store_si128((__m128i*)(hsad + d), hsad_l);
|
||||
_mm_store_si128((__m128i*)(hsad + d + 8), hsad_h);
|
||||
}
|
||||
htext[y] += tab[lval] - tab[lptr_sub[0]];
|
||||
}
|
||||
|
||||
// fill borders
|
||||
for( y = dy1; y <= wsz2; y++ )
|
||||
htext[height+y] = htext[height+dy1-1];
|
||||
for( y = -wsz2-1; y < -dy0; y++ )
|
||||
htext[y] = htext[-dy0];
|
||||
|
||||
// initialize sums
|
||||
for( d = 0; d < ndisp; d++ )
|
||||
sad[d] = (ushort)(hsad0[d-ndisp*dy0]*(wsz2 + 2 - dy0));
|
||||
|
||||
hsad = hsad0 + (1 - dy0)*ndisp;
|
||||
for( y = 1 - dy0; y < wsz2; y++, hsad += ndisp )
|
||||
for( d = 0; d < ndisp; d += 16 )
|
||||
{
|
||||
__m128i s0 = _mm_load_si128((__m128i*)(sad + d));
|
||||
__m128i s1 = _mm_load_si128((__m128i*)(sad + d + 8));
|
||||
__m128i t0 = _mm_load_si128((__m128i*)(hsad + d));
|
||||
__m128i t1 = _mm_load_si128((__m128i*)(hsad + d + 8));
|
||||
s0 = _mm_add_epi16(s0, t0);
|
||||
s1 = _mm_add_epi16(s1, t1);
|
||||
_mm_store_si128((__m128i*)(sad + d), s0);
|
||||
_mm_store_si128((__m128i*)(sad + d + 8), s1);
|
||||
}
|
||||
int tsum = 0;
|
||||
for( y = -wsz2-1; y < wsz2; y++ )
|
||||
tsum += htext[y];
|
||||
|
||||
// finally, start the real processing
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
int minsad = INT_MAX, mind = -1;
|
||||
hsad = hsad0 + MIN(y + wsz2, height+dy1-1)*ndisp;
|
||||
hsad_sub = hsad0 + MAX(y - wsz2 - 1, -dy0)*ndisp;
|
||||
__m128i minsad8 = _mm_set1_epi16(SHRT_MAX);
|
||||
__m128i mind8 = _mm_set1_epi16(0), d8 = d0_8, mask;
|
||||
|
||||
for( d = 0; d < ndisp; d += 16 )
|
||||
{
|
||||
__m128i u0 = _mm_load_si128((__m128i*)(hsad_sub + d));
|
||||
__m128i u1 = _mm_load_si128((__m128i*)(hsad + d));
|
||||
|
||||
__m128i v0 = _mm_load_si128((__m128i*)(hsad_sub + d + 8));
|
||||
__m128i v1 = _mm_load_si128((__m128i*)(hsad + d + 8));
|
||||
|
||||
__m128i usad8 = _mm_load_si128((__m128i*)(sad + d));
|
||||
__m128i vsad8 = _mm_load_si128((__m128i*)(sad + d + 8));
|
||||
|
||||
u1 = _mm_sub_epi16(u1, u0);
|
||||
v1 = _mm_sub_epi16(v1, v0);
|
||||
usad8 = _mm_add_epi16(usad8, u1);
|
||||
vsad8 = _mm_add_epi16(vsad8, v1);
|
||||
|
||||
mask = _mm_cmpgt_epi16(minsad8, usad8);
|
||||
minsad8 = _mm_min_epi16(minsad8, usad8);
|
||||
mind8 = _mm_max_epi16(mind8, _mm_and_si128(mask, d8));
|
||||
|
||||
_mm_store_si128((__m128i*)(sad + d), usad8);
|
||||
_mm_store_si128((__m128i*)(sad + d + 8), vsad8);
|
||||
|
||||
mask = _mm_cmpgt_epi16(minsad8, vsad8);
|
||||
minsad8 = _mm_min_epi16(minsad8, vsad8);
|
||||
|
||||
d8 = _mm_add_epi16(d8, dd_8);
|
||||
mind8 = _mm_max_epi16(mind8, _mm_and_si128(mask, d8));
|
||||
d8 = _mm_add_epi16(d8, dd_8);
|
||||
}
|
||||
|
||||
tsum += htext[y + wsz2] - htext[y - wsz2 - 1];
|
||||
if( tsum < textureThreshold )
|
||||
{
|
||||
dptr[y*dstep] = FILTERED;
|
||||
continue;
|
||||
}
|
||||
|
||||
__m128i minsad82 = _mm_unpackhi_epi64(minsad8, minsad8);
|
||||
__m128i mind82 = _mm_unpackhi_epi64(mind8, mind8);
|
||||
mask = _mm_cmpgt_epi16(minsad8, minsad82);
|
||||
mind8 = _mm_xor_si128(mind8,_mm_and_si128(_mm_xor_si128(mind82,mind8),mask));
|
||||
minsad8 = _mm_min_epi16(minsad8, minsad82);
|
||||
|
||||
minsad82 = _mm_shufflelo_epi16(minsad8, _MM_SHUFFLE(3,2,3,2));
|
||||
mind82 = _mm_shufflelo_epi16(mind8, _MM_SHUFFLE(3,2,3,2));
|
||||
mask = _mm_cmpgt_epi16(minsad8, minsad82);
|
||||
mind8 = _mm_xor_si128(mind8,_mm_and_si128(_mm_xor_si128(mind82,mind8),mask));
|
||||
minsad8 = _mm_min_epi16(minsad8, minsad82);
|
||||
|
||||
minsad82 = _mm_shufflelo_epi16(minsad8, 1);
|
||||
mind82 = _mm_shufflelo_epi16(mind8, 1);
|
||||
mask = _mm_cmpgt_epi16(minsad8, minsad82);
|
||||
mind8 = _mm_xor_si128(mind8,_mm_and_si128(_mm_xor_si128(mind82,mind8),mask));
|
||||
mind = (short)_mm_cvtsi128_si32(mind8);
|
||||
minsad = sad[mind];
|
||||
|
||||
if( uniquenessRatio > 0 )
|
||||
{
|
||||
int thresh = minsad + ((minsad * uniquenessRatio) >> 8);
|
||||
__m128i thresh8 = _mm_set1_epi16((short)(thresh + 1));
|
||||
__m128i d1 = _mm_set1_epi16((short)(mind-1)), d2 = _mm_set1_epi16((short)(mind+1));
|
||||
__m128i dd_16 = _mm_add_epi16(dd_8, dd_8), d8 = _mm_sub_epi16(d0_8, dd_16);
|
||||
|
||||
for( d = 0; d < ndisp; d += 16 )
|
||||
{
|
||||
__m128i usad8 = _mm_load_si128((__m128i*)(sad + d));
|
||||
__m128i vsad8 = _mm_load_si128((__m128i*)(sad + d + 8));
|
||||
mask = _mm_cmpgt_epi16( thresh8, _mm_min_epi16(usad8,vsad8));
|
||||
d8 = _mm_add_epi16(d8, dd_16);
|
||||
if( !_mm_movemask_epi8(mask) )
|
||||
continue;
|
||||
mask = _mm_cmpgt_epi16( thresh8, usad8);
|
||||
mask = _mm_and_si128(mask, _mm_or_si128(_mm_cmpgt_epi16(d1,d8), _mm_cmpgt_epi16(d8,d2)));
|
||||
if( _mm_movemask_epi8(mask) )
|
||||
break;
|
||||
__m128i t8 = _mm_add_epi16(d8, dd_8);
|
||||
mask = _mm_cmpgt_epi16( thresh8, vsad8);
|
||||
mask = _mm_and_si128(mask, _mm_or_si128(_mm_cmpgt_epi16(d1,t8), _mm_cmpgt_epi16(t8,d2)));
|
||||
if( _mm_movemask_epi8(mask) )
|
||||
break;
|
||||
}
|
||||
if( d < ndisp )
|
||||
{
|
||||
dptr[y*dstep] = FILTERED;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if( 0 < mind && mind < ndisp - 1 )
|
||||
{
|
||||
int p = sad[mind+1], n = sad[mind-1], d = p + n - 2*sad[mind];
|
||||
dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*128/d : 0) + 15) >> 4);
|
||||
}
|
||||
else
|
||||
dptr[y*dstep] = (short)((ndisp - mind - 1)*16);
|
||||
costptr[y*coststep] = sad[mind];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
findStereoCorrespondenceBM( const Mat& left, const Mat& right,
|
||||
Mat& disp, Mat& cost, const CvStereoBMState& state,
|
||||
uchar* buf, int _dy0, int _dy1 )
|
||||
{
|
||||
const int ALIGN = 16;
|
||||
int x, y, d;
|
||||
int wsz = state.SADWindowSize, wsz2 = wsz/2;
|
||||
int dy0 = MIN(_dy0, wsz2+1), dy1 = MIN(_dy1, wsz2+1);
|
||||
int ndisp = state.numberOfDisparities;
|
||||
int mindisp = state.minDisparity;
|
||||
int lofs = MAX(ndisp - 1 + mindisp, 0);
|
||||
int rofs = -MIN(ndisp - 1 + mindisp, 0);
|
||||
int width = left.cols, height = left.rows;
|
||||
int width1 = width - rofs - ndisp + 1;
|
||||
int ftzero = state.preFilterCap;
|
||||
int textureThreshold = state.textureThreshold;
|
||||
int uniquenessRatio = state.uniquenessRatio;
|
||||
short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT);
|
||||
|
||||
int *sad, *hsad0, *hsad, *hsad_sub, *htext;
|
||||
uchar *cbuf0, *cbuf;
|
||||
const uchar* lptr0 = left.data + lofs;
|
||||
const uchar* rptr0 = right.data + rofs;
|
||||
const uchar *lptr, *lptr_sub, *rptr;
|
||||
short* dptr = (short*)disp.data;
|
||||
int sstep = left.step;
|
||||
int dstep = disp.step/sizeof(dptr[0]);
|
||||
int cstep = (height+dy0+dy1)*ndisp;
|
||||
int costbuf = 0;
|
||||
int coststep = cost.data ? cost.step/sizeof(costbuf) : 0;
|
||||
const int TABSZ = 256;
|
||||
uchar tab[TABSZ];
|
||||
|
||||
sad = (int*)alignPtr(buf + sizeof(sad[0]), ALIGN);
|
||||
hsad0 = (int*)alignPtr(sad + ndisp + 1 + dy0*ndisp, ALIGN);
|
||||
htext = (int*)alignPtr((int*)(hsad0 + (height+dy1)*ndisp) + wsz2 + 2, ALIGN);
|
||||
cbuf0 = (uchar*)alignPtr(htext + height + wsz2 + 2 + dy0*ndisp, ALIGN);
|
||||
|
||||
for( x = 0; x < TABSZ; x++ )
|
||||
tab[x] = (uchar)std::abs(x - ftzero);
|
||||
|
||||
// initialize buffers
|
||||
memset( hsad0 - dy0*ndisp, 0, (height + dy0 + dy1)*ndisp*sizeof(hsad0[0]) );
|
||||
memset( htext - wsz2 - 1, 0, (height + wsz + 1)*sizeof(htext[0]) );
|
||||
|
||||
for( x = -wsz2-1; x < wsz2; x++ )
|
||||
{
|
||||
hsad = hsad0 - dy0*ndisp; cbuf = cbuf0 + (x + wsz2 + 1)*cstep - dy0*ndisp;
|
||||
lptr = lptr0 + MIN(MAX(x, -lofs), width-lofs-1) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x, -rofs), width-rofs-1) - dy0*sstep;
|
||||
|
||||
for( y = -dy0; y < height + dy1; y++, hsad += ndisp, cbuf += ndisp, lptr += sstep, rptr += sstep )
|
||||
{
|
||||
int lval = lptr[0];
|
||||
for( d = 0; d < ndisp; d++ )
|
||||
{
|
||||
int diff = std::abs(lval - rptr[d]);
|
||||
cbuf[d] = (uchar)diff;
|
||||
hsad[d] = (int)(hsad[d] + diff);
|
||||
}
|
||||
htext[y] += tab[lval];
|
||||
}
|
||||
}
|
||||
|
||||
// initialize the left and right borders of the disparity map
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
for( x = 0; x < lofs; x++ )
|
||||
dptr[y*dstep + x] = FILTERED;
|
||||
for( x = lofs + width1; x < width; x++ )
|
||||
dptr[y*dstep + x] = FILTERED;
|
||||
}
|
||||
dptr += lofs;
|
||||
|
||||
for( x = 0; x < width1; x++, dptr++ )
|
||||
{
|
||||
int* costptr = cost.data ? (int*)cost.data + lofs + x : &costbuf;
|
||||
int x0 = x - wsz2 - 1, x1 = x + wsz2;
|
||||
const uchar* cbuf_sub = cbuf0 + ((x0 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp;
|
||||
uchar* cbuf = cbuf0 + ((x1 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp;
|
||||
hsad = hsad0 - dy0*ndisp;
|
||||
lptr_sub = lptr0 + MIN(MAX(x0, -lofs), width-1-lofs) - dy0*sstep;
|
||||
lptr = lptr0 + MIN(MAX(x1, -lofs), width-1-lofs) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x1, -rofs), width-1-rofs) - dy0*sstep;
|
||||
|
||||
for( y = -dy0; y < height + dy1; y++, cbuf += ndisp, cbuf_sub += ndisp,
|
||||
hsad += ndisp, lptr += sstep, lptr_sub += sstep, rptr += sstep )
|
||||
{
|
||||
int lval = lptr[0];
|
||||
for( d = 0; d < ndisp; d++ )
|
||||
{
|
||||
int diff = std::abs(lval - rptr[d]);
|
||||
cbuf[d] = (uchar)diff;
|
||||
hsad[d] = hsad[d] + diff - cbuf_sub[d];
|
||||
}
|
||||
htext[y] += tab[lval] - tab[lptr_sub[0]];
|
||||
}
|
||||
|
||||
// fill borders
|
||||
for( y = dy1; y <= wsz2; y++ )
|
||||
htext[height+y] = htext[height+dy1-1];
|
||||
for( y = -wsz2-1; y < -dy0; y++ )
|
||||
htext[y] = htext[-dy0];
|
||||
|
||||
// initialize sums
|
||||
for( d = 0; d < ndisp; d++ )
|
||||
sad[d] = (int)(hsad0[d-ndisp*dy0]*(wsz2 + 2 - dy0));
|
||||
|
||||
hsad = hsad0 + (1 - dy0)*ndisp;
|
||||
for( y = 1 - dy0; y < wsz2; y++, hsad += ndisp )
|
||||
for( d = 0; d < ndisp; d++ )
|
||||
sad[d] = (int)(sad[d] + hsad[d]);
|
||||
int tsum = 0;
|
||||
for( y = -wsz2-1; y < wsz2; y++ )
|
||||
tsum += htext[y];
|
||||
|
||||
// finally, start the real processing
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
int minsad = INT_MAX, mind = -1;
|
||||
hsad = hsad0 + MIN(y + wsz2, height+dy1-1)*ndisp;
|
||||
hsad_sub = hsad0 + MAX(y - wsz2 - 1, -dy0)*ndisp;
|
||||
|
||||
for( d = 0; d < ndisp; d++ )
|
||||
{
|
||||
int currsad = sad[d] + hsad[d] - hsad_sub[d];
|
||||
sad[d] = currsad;
|
||||
if( currsad < minsad )
|
||||
{
|
||||
minsad = currsad;
|
||||
mind = d;
|
||||
}
|
||||
}
|
||||
tsum += htext[y + wsz2] - htext[y - wsz2 - 1];
|
||||
if( tsum < textureThreshold )
|
||||
{
|
||||
dptr[y*dstep] = FILTERED;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( uniquenessRatio > 0 )
|
||||
{
|
||||
int thresh = minsad + (minsad * uniquenessRatio/100);
|
||||
for( d = 0; d < ndisp; d++ )
|
||||
{
|
||||
if( sad[d] <= thresh && (d < mind-1 || d > mind+1))
|
||||
break;
|
||||
}
|
||||
if( d < ndisp )
|
||||
{
|
||||
dptr[y*dstep] = FILTERED;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
sad[-1] = sad[1];
|
||||
sad[ndisp] = sad[ndisp-2];
|
||||
int p = sad[mind+1], n = sad[mind-1], d = p + n - 2*sad[mind];
|
||||
dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*128/d : 0) + 15) >> 4);
|
||||
costptr[y*coststep] = sad[mind];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PrefilterInvoker
|
||||
{
|
||||
PrefilterInvoker(const Mat& left0, const Mat& right0, Mat& left, Mat& right,
|
||||
uchar* buf0, uchar* buf1, CvStereoBMState* _state )
|
||||
{
|
||||
imgs0[0] = &left0; imgs0[1] = &right0;
|
||||
imgs[0] = &left; imgs[1] = &right;
|
||||
buf[0] = buf0; buf[1] = buf1;
|
||||
state = _state;
|
||||
}
|
||||
|
||||
void operator()( int ind ) const
|
||||
{
|
||||
if( state->preFilterType == CV_STEREO_BM_NORMALIZED_RESPONSE )
|
||||
prefilterNorm( *imgs0[ind], *imgs[ind], state->preFilterSize, state->preFilterCap, buf[ind] );
|
||||
else
|
||||
prefilterXSobel( *imgs0[ind], *imgs[ind], state->preFilterCap );
|
||||
}
|
||||
|
||||
const Mat* imgs0[2];
|
||||
Mat* imgs[2];
|
||||
uchar* buf[2];
|
||||
CvStereoBMState *state;
|
||||
};
|
||||
|
||||
|
||||
struct FindStereoCorrespInvoker
|
||||
{
|
||||
FindStereoCorrespInvoker( const Mat& _left, const Mat& _right,
|
||||
Mat& _disp, CvStereoBMState* _state,
|
||||
int _nstripes, int _stripeBufSize,
|
||||
bool _useShorts, Rect _validDisparityRect )
|
||||
{
|
||||
left = &_left; right = &_right;
|
||||
disp = &_disp; state = _state;
|
||||
nstripes = _nstripes; stripeBufSize = _stripeBufSize;
|
||||
useShorts = _useShorts;
|
||||
validDisparityRect = _validDisparityRect;
|
||||
}
|
||||
|
||||
void operator()( const BlockedRange& range ) const
|
||||
{
|
||||
int cols = left->cols, rows = left->rows;
|
||||
int _row0 = min(cvRound(range.begin() * rows / nstripes), rows);
|
||||
int _row1 = min(cvRound(range.end() * rows / nstripes), rows);
|
||||
uchar *ptr = state->slidingSumBuf->data.ptr + range.begin() * stripeBufSize;
|
||||
int FILTERED = (state->minDisparity - 1)*16;
|
||||
|
||||
Rect roi = validDisparityRect & Rect(0, _row0, cols, _row1);
|
||||
if( roi.height == 0 )
|
||||
return;
|
||||
int row0 = roi.y;
|
||||
int row1 = roi.y + roi.height;
|
||||
|
||||
Mat part;
|
||||
if( row0 > _row0 )
|
||||
{
|
||||
part = disp->rowRange(_row0, row0);
|
||||
part = Scalar::all(FILTERED);
|
||||
}
|
||||
if( _row1 > row1 )
|
||||
{
|
||||
part = disp->rowRange(row1, _row1);
|
||||
part = Scalar::all(FILTERED);
|
||||
}
|
||||
|
||||
Mat left_i = left->rowRange(row0, row1);
|
||||
Mat right_i = right->rowRange(row0, row1);
|
||||
Mat disp_i = disp->rowRange(row0, row1);
|
||||
Mat cost_i = state->disp12MaxDiff >= 0 ? Mat(state->cost).rowRange(row0, row1) : Mat();
|
||||
|
||||
#if CV_SSE2
|
||||
if( useShorts )
|
||||
findStereoCorrespondenceBM_SSE2( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
|
||||
else
|
||||
#endif
|
||||
findStereoCorrespondenceBM( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
|
||||
|
||||
if( state->disp12MaxDiff >= 0 )
|
||||
validateDisparity( disp_i, cost_i, state->minDisparity, state->numberOfDisparities, state->disp12MaxDiff );
|
||||
|
||||
if( roi.x > 0 )
|
||||
{
|
||||
part = disp_i.colRange(0, roi.x);
|
||||
part = Scalar::all(FILTERED);
|
||||
}
|
||||
if( roi.x + roi.width < cols )
|
||||
{
|
||||
part = disp_i.colRange(roi.x + roi.width, cols);
|
||||
part = Scalar::all(FILTERED);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
const Mat *left, *right;
|
||||
Mat* disp;
|
||||
CvStereoBMState *state;
|
||||
|
||||
int nstripes;
|
||||
int stripeBufSize;
|
||||
bool useShorts;
|
||||
Rect validDisparityRect;
|
||||
};
|
||||
|
||||
static void findStereoCorrespondenceBM( const Mat& left0, const Mat& right0, Mat& disp0, CvStereoBMState* state)
|
||||
{
|
||||
if (left0.size() != right0.size() || disp0.size() != left0.size())
|
||||
CV_Error( CV_StsUnmatchedSizes, "All the images must have the same size" );
|
||||
|
||||
if (left0.type() != CV_8UC1 || right0.type() != CV_8UC1)
|
||||
CV_Error( CV_StsUnsupportedFormat, "Both input images must have CV_8UC1" );
|
||||
|
||||
if (disp0.type() != CV_16SC1 && disp0.type() != CV_32FC1)
|
||||
CV_Error( CV_StsUnsupportedFormat, "Disparity image must have CV_16SC1 or CV_32FC1 format" );
|
||||
|
||||
if( !state )
|
||||
CV_Error( CV_StsNullPtr, "Stereo BM state is NULL." );
|
||||
|
||||
if( state->preFilterType != CV_STEREO_BM_NORMALIZED_RESPONSE && state->preFilterType != CV_STEREO_BM_XSOBEL )
|
||||
CV_Error( CV_StsOutOfRange, "preFilterType must be = CV_STEREO_BM_NORMALIZED_RESPONSE" );
|
||||
|
||||
if( state->preFilterSize < 5 || state->preFilterSize > 255 || state->preFilterSize % 2 == 0 )
|
||||
CV_Error( CV_StsOutOfRange, "preFilterSize must be odd and be within 5..255" );
|
||||
|
||||
if( state->preFilterCap < 1 || state->preFilterCap > 63 )
|
||||
CV_Error( CV_StsOutOfRange, "preFilterCap must be within 1..63" );
|
||||
|
||||
if( state->SADWindowSize < 5 || state->SADWindowSize > 255 || state->SADWindowSize % 2 == 0 ||
|
||||
state->SADWindowSize >= min(left0.cols, left0.rows) )
|
||||
CV_Error( CV_StsOutOfRange, "SADWindowSize must be odd, be within 5..255 and be not larger than image width or height" );
|
||||
|
||||
if( state->numberOfDisparities <= 0 || state->numberOfDisparities % 16 != 0 )
|
||||
CV_Error( CV_StsOutOfRange, "numberOfDisparities must be positive and divisble by 16" );
|
||||
|
||||
if( state->textureThreshold < 0 )
|
||||
CV_Error( CV_StsOutOfRange, "texture threshold must be non-negative" );
|
||||
|
||||
if( state->uniquenessRatio < 0 )
|
||||
CV_Error( CV_StsOutOfRange, "uniqueness ratio must be non-negative" );
|
||||
|
||||
if( !state->preFilteredImg0 || state->preFilteredImg0->cols * state->preFilteredImg0->rows < left0.cols * left0.rows )
|
||||
{
|
||||
cvReleaseMat( &state->preFilteredImg0 );
|
||||
cvReleaseMat( &state->preFilteredImg1 );
|
||||
cvReleaseMat( &state->cost );
|
||||
|
||||
state->preFilteredImg0 = cvCreateMat( left0.rows, left0.cols, CV_8U );
|
||||
state->preFilteredImg1 = cvCreateMat( left0.rows, left0.cols, CV_8U );
|
||||
state->cost = cvCreateMat( left0.rows, left0.cols, CV_16S );
|
||||
}
|
||||
Mat left(left0.size(), CV_8U, state->preFilteredImg0->data.ptr);
|
||||
Mat right(right0.size(), CV_8U, state->preFilteredImg1->data.ptr);
|
||||
|
||||
int mindisp = state->minDisparity;
|
||||
int ndisp = state->numberOfDisparities;
|
||||
|
||||
int width = left0.cols;
|
||||
int height = left0.rows;
|
||||
int lofs = max(ndisp - 1 + mindisp, 0);
|
||||
int rofs = -min(ndisp - 1 + mindisp, 0);
|
||||
int width1 = width - rofs - ndisp + 1;
|
||||
int FILTERED = (state->minDisparity - 1) << DISPARITY_SHIFT;
|
||||
|
||||
if( lofs >= width || rofs >= width || width1 < 1 )
|
||||
{
|
||||
disp0 = Scalar::all( FILTERED * ( disp0.type() < CV_32F ? 1 : 1./(1 << DISPARITY_SHIFT) ) );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat disp = disp0;
|
||||
|
||||
if( disp0.type() == CV_32F)
|
||||
{
|
||||
if( !state->disp || state->disp->rows != disp0.rows || state->disp->cols != disp0.cols )
|
||||
{
|
||||
cvReleaseMat( &state->disp );
|
||||
state->disp = cvCreateMat(disp0.rows, disp0.cols, CV_16S);
|
||||
}
|
||||
disp = cv::cvarrToMat(state->disp);
|
||||
}
|
||||
|
||||
int wsz = state->SADWindowSize;
|
||||
int bufSize0 = (ndisp + 2)*sizeof(int) + (height+wsz+2)*ndisp*sizeof(int) +
|
||||
(height + wsz + 2)*sizeof(int) +
|
||||
(height+wsz+2)*ndisp*(wsz+1)*sizeof(uchar) + 256;
|
||||
int bufSize1 = (width + state->preFilterSize + 2) * sizeof(int) + 256;
|
||||
int bufSize2 = 0;
|
||||
if( state->speckleRange >= 0 && state->speckleWindowSize > 0 )
|
||||
bufSize2 = width*height*(sizeof(cv::Point_<short>) + sizeof(int) + sizeof(uchar));
|
||||
|
||||
#if CV_SSE2
|
||||
bool useShorts = state->preFilterCap <= 31 && state->SADWindowSize <= 21 && checkHardwareSupport(CV_CPU_SSE2);
|
||||
#else
|
||||
const bool useShorts = false;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
const double SAD_overhead_coeff = 10.0;
|
||||
double N0 = 8000000 / (useShorts ? 1 : 4); // approx tbb's min number instructions reasonable for one thread
|
||||
double maxStripeSize = min(max(N0 / (width * ndisp), (wsz-1) * SAD_overhead_coeff), (double)height);
|
||||
int nstripes = cvCeil(height / maxStripeSize);
|
||||
printf("nstripes=%d\n", nstripes);
|
||||
#else
|
||||
const int nstripes = 1;
|
||||
#endif
|
||||
|
||||
int bufSize = max(bufSize0 * nstripes, max(bufSize1 * 2, bufSize2));
|
||||
|
||||
if( !state->slidingSumBuf || state->slidingSumBuf->cols < bufSize )
|
||||
{
|
||||
cvReleaseMat( &state->slidingSumBuf );
|
||||
state->slidingSumBuf = cvCreateMat( 1, bufSize, CV_8U );
|
||||
}
|
||||
|
||||
uchar *_buf = state->slidingSumBuf->data.ptr;
|
||||
int idx[] = {0,1};
|
||||
parallel_do(idx, idx+2, PrefilterInvoker(left0, right0, left, right, _buf, _buf + bufSize1, state));
|
||||
|
||||
Rect validDisparityRect(0, 0, width, height), R1 = state->roi1, R2 = state->roi2;
|
||||
validDisparityRect = getValidDisparityROI(R1.area() > 0 ? Rect(0, 0, width, height) : validDisparityRect,
|
||||
R2.area() > 0 ? Rect(0, 0, width, height) : validDisparityRect,
|
||||
state->minDisparity, state->numberOfDisparities,
|
||||
state->SADWindowSize);
|
||||
|
||||
parallel_for(BlockedRange(0, nstripes),
|
||||
FindStereoCorrespInvoker(left, right, disp, state, nstripes,
|
||||
bufSize0, useShorts, validDisparityRect));
|
||||
|
||||
if( state->speckleRange >= 0 && state->speckleWindowSize > 0 )
|
||||
{
|
||||
Mat buf(state->slidingSumBuf);
|
||||
filterSpeckles(disp, FILTERED, state->speckleRange, state->speckleWindowSize, buf);
|
||||
}
|
||||
|
||||
if (disp0.data != disp.data)
|
||||
disp.convertTo(disp0, disp0.type(), 1./(1 << DISPARITY_SHIFT), 0);
|
||||
}
|
||||
|
||||
StereoBM::StereoBM()
|
||||
{ state = cvCreateStereoBMState(); }
|
||||
|
||||
StereoBM::StereoBM(int _preset, int _ndisparities, int _SADWindowSize)
|
||||
{ init(_preset, _ndisparities, _SADWindowSize); }
|
||||
|
||||
void StereoBM::init(int _preset, int _ndisparities, int _SADWindowSize)
|
||||
{
|
||||
state = cvCreateStereoBMState(_preset, _ndisparities);
|
||||
state->SADWindowSize = _SADWindowSize;
|
||||
}
|
||||
|
||||
void StereoBM::operator()( const Mat& left, const Mat& right, Mat& disparity, int disptype )
|
||||
{
|
||||
CV_Assert( disptype == CV_16S || disptype == CV_32F );
|
||||
disparity.create(left.size(), disptype);
|
||||
|
||||
findStereoCorrespondenceBM(left, right, disparity, state);
|
||||
}
|
||||
|
||||
template<> void Ptr<CvStereoBMState>::delete_obj()
|
||||
{ cvReleaseStereoBMState(&obj); }
|
||||
|
||||
}
|
||||
|
||||
CV_IMPL void cvFindStereoCorrespondenceBM( const CvArr* leftarr, const CvArr* rightarr,
|
||||
CvArr* disparr, CvStereoBMState* state )
|
||||
{
|
||||
cv::Mat left = cv::cvarrToMat(leftarr),
|
||||
right = cv::cvarrToMat(rightarr),
|
||||
disp = cv::cvarrToMat(disparr);
|
||||
cv::findStereoCorrespondenceBM(left, right, disp, state);
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
948
modules/calib3d/src/stereogc.cpp
Normal file
948
modules/calib3d/src/stereogc.cpp
Normal file
@@ -0,0 +1,948 @@
|
||||
//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"
|
||||
|
||||
#undef INFINITY
|
||||
#define INFINITY 10000
|
||||
#define OCCLUSION_PENALTY 10000
|
||||
#define OCCLUSION_PENALTY2 1000
|
||||
#define DENOMINATOR 16
|
||||
#undef OCCLUDED
|
||||
#define OCCLUDED CV_STEREO_GC_OCCLUDED
|
||||
#define CUTOFF 1000
|
||||
#define IS_BLOCKED(d1, d2) ((d1) > (d2))
|
||||
|
||||
typedef struct GCVtx
|
||||
{
|
||||
GCVtx *next;
|
||||
int parent;
|
||||
int first;
|
||||
int ts;
|
||||
int dist;
|
||||
short weight;
|
||||
uchar t;
|
||||
}
|
||||
GCVtx;
|
||||
|
||||
typedef struct GCEdge
|
||||
{
|
||||
GCVtx* dst;
|
||||
int next;
|
||||
int weight;
|
||||
}
|
||||
GCEdge;
|
||||
|
||||
typedef struct CvStereoGCState2
|
||||
{
|
||||
int Ithreshold, interactionRadius;
|
||||
int lambda, lambda1, lambda2, K;
|
||||
int dataCostFuncTab[CUTOFF+1];
|
||||
int smoothnessR[CUTOFF*2+1];
|
||||
int smoothnessGrayDiff[512];
|
||||
GCVtx** orphans;
|
||||
int maxOrphans;
|
||||
}
|
||||
CvStereoGCState2;
|
||||
|
||||
// truncTab[x+255] = MAX(x-255,0)
|
||||
static uchar icvTruncTab[512];
|
||||
// cutoffSqrTab[x] = MIN(x*x, CUTOFF)
|
||||
static int icvCutoffSqrTab[256];
|
||||
|
||||
static void icvInitStereoConstTabs()
|
||||
{
|
||||
static volatile int initialized = 0;
|
||||
if( !initialized )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < 512; i++ )
|
||||
icvTruncTab[i] = (uchar)MIN(MAX(i-255,0),255);
|
||||
for( i = 0; i < 256; i++ )
|
||||
icvCutoffSqrTab[i] = MIN(i*i, CUTOFF);
|
||||
initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void icvInitStereoTabs( CvStereoGCState2* state2 )
|
||||
{
|
||||
int i, K = state2->K;
|
||||
|
||||
for( i = 0; i <= CUTOFF; i++ )
|
||||
state2->dataCostFuncTab[i] = MIN(i*DENOMINATOR - K, 0);
|
||||
|
||||
for( i = 0; i < CUTOFF*2 + 1; i++ )
|
||||
state2->smoothnessR[i] = MIN(abs(i-CUTOFF), state2->interactionRadius);
|
||||
|
||||
for( i = 0; i < 512; i++ )
|
||||
{
|
||||
int diff = abs(i - 255);
|
||||
state2->smoothnessGrayDiff[i] = diff < state2->Ithreshold ? state2->lambda1 : state2->lambda2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int icvGCResizeOrphansBuf( GCVtx**& orphans, int norphans )
|
||||
{
|
||||
int i, newNOrphans = MAX(norphans*3/2, 256);
|
||||
GCVtx** newOrphans = (GCVtx**)cvAlloc( newNOrphans*sizeof(orphans[0]) );
|
||||
for( i = 0; i < norphans; i++ )
|
||||
newOrphans[i] = orphans[i];
|
||||
cvFree( &orphans );
|
||||
orphans = newOrphans;
|
||||
return newNOrphans;
|
||||
}
|
||||
|
||||
static int64 icvGCMaxFlow( GCVtx* vtx, int nvtx, GCEdge* edges, GCVtx**& _orphans, int& _maxOrphans )
|
||||
{
|
||||
const int TERMINAL = -1, ORPHAN = -2;
|
||||
GCVtx stub, *nilNode = &stub, *first = nilNode, *last = nilNode;
|
||||
int i, k;
|
||||
int curr_ts = 0;
|
||||
int64 flow = 0;
|
||||
int norphans = 0, maxOrphans = _maxOrphans;
|
||||
GCVtx** orphans = _orphans;
|
||||
stub.next = nilNode;
|
||||
|
||||
// initialize the active queue and the graph vertices
|
||||
for( i = 0; i < nvtx; i++ )
|
||||
{
|
||||
GCVtx* v = vtx + i;
|
||||
v->ts = 0;
|
||||
if( v->weight != 0 )
|
||||
{
|
||||
last = last->next = v;
|
||||
v->dist = 1;
|
||||
v->parent = TERMINAL;
|
||||
v->t = v->weight < 0;
|
||||
}
|
||||
else
|
||||
v->parent = 0;
|
||||
}
|
||||
|
||||
first = first->next;
|
||||
last->next = nilNode;
|
||||
nilNode->next = 0;
|
||||
|
||||
// run the search-path -> augment-graph -> restore-trees loop
|
||||
for(;;)
|
||||
{
|
||||
GCVtx* v, *u;
|
||||
int e0 = -1, ei = 0, ej = 0, min_weight, weight;
|
||||
uchar vt;
|
||||
|
||||
// grow S & T search trees, find an edge connecting them
|
||||
while( first != nilNode )
|
||||
{
|
||||
v = first;
|
||||
if( v->parent )
|
||||
{
|
||||
vt = v->t;
|
||||
for( ei = v->first; ei != 0; ei = edges[ei].next )
|
||||
{
|
||||
if( edges[ei^vt].weight == 0 )
|
||||
continue;
|
||||
u = edges[ei].dst;
|
||||
if( !u->parent )
|
||||
{
|
||||
u->t = vt;
|
||||
u->parent = ei ^ 1;
|
||||
u->ts = v->ts;
|
||||
u->dist = v->dist + 1;
|
||||
if( !u->next )
|
||||
{
|
||||
u->next = nilNode;
|
||||
last = last->next = u;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if( u->t != vt )
|
||||
{
|
||||
e0 = ei ^ vt;
|
||||
break;
|
||||
}
|
||||
|
||||
if( u->dist > v->dist+1 && u->ts <= v->ts )
|
||||
{
|
||||
// reassign the parent
|
||||
u->parent = ei ^ 1;
|
||||
u->ts = v->ts;
|
||||
u->dist = v->dist + 1;
|
||||
}
|
||||
}
|
||||
if( e0 > 0 )
|
||||
break;
|
||||
}
|
||||
// exclude the vertex from the active list
|
||||
first = first->next;
|
||||
v->next = 0;
|
||||
}
|
||||
|
||||
if( e0 <= 0 )
|
||||
break;
|
||||
|
||||
// find the minimum edge weight along the path
|
||||
min_weight = edges[e0].weight;
|
||||
assert( min_weight > 0 );
|
||||
// k = 1: source tree, k = 0: destination tree
|
||||
for( k = 1; k >= 0; k-- )
|
||||
{
|
||||
for( v = edges[e0^k].dst;; v = edges[ei].dst )
|
||||
{
|
||||
if( (ei = v->parent) < 0 )
|
||||
break;
|
||||
weight = edges[ei^k].weight;
|
||||
min_weight = MIN(min_weight, weight);
|
||||
assert( min_weight > 0 );
|
||||
}
|
||||
weight = abs(v->weight);
|
||||
min_weight = MIN(min_weight, weight);
|
||||
assert( min_weight > 0 );
|
||||
}
|
||||
|
||||
// modify weights of the edges along the path and collect orphans
|
||||
edges[e0].weight -= min_weight;
|
||||
edges[e0^1].weight += min_weight;
|
||||
flow += min_weight;
|
||||
|
||||
// k = 1: source tree, k = 0: destination tree
|
||||
for( k = 1; k >= 0; k-- )
|
||||
{
|
||||
for( v = edges[e0^k].dst;; v = edges[ei].dst )
|
||||
{
|
||||
if( (ei = v->parent) < 0 )
|
||||
break;
|
||||
edges[ei^(k^1)].weight += min_weight;
|
||||
if( (edges[ei^k].weight -= min_weight) == 0 )
|
||||
{
|
||||
if( norphans >= maxOrphans )
|
||||
maxOrphans = icvGCResizeOrphansBuf( orphans, norphans );
|
||||
orphans[norphans++] = v;
|
||||
v->parent = ORPHAN;
|
||||
}
|
||||
}
|
||||
|
||||
v->weight = (short)(v->weight + min_weight*(1-k*2));
|
||||
if( v->weight == 0 )
|
||||
{
|
||||
if( norphans >= maxOrphans )
|
||||
maxOrphans = icvGCResizeOrphansBuf( orphans, norphans );
|
||||
orphans[norphans++] = v;
|
||||
v->parent = ORPHAN;
|
||||
}
|
||||
}
|
||||
|
||||
// restore the search trees by finding new parents for the orphans
|
||||
curr_ts++;
|
||||
while( norphans > 0 )
|
||||
{
|
||||
GCVtx* v = orphans[--norphans];
|
||||
int d, min_dist = INT_MAX;
|
||||
e0 = 0;
|
||||
vt = v->t;
|
||||
|
||||
for( ei = v->first; ei != 0; ei = edges[ei].next )
|
||||
{
|
||||
if( edges[ei^(vt^1)].weight == 0 )
|
||||
continue;
|
||||
u = edges[ei].dst;
|
||||
if( u->t != vt || u->parent == 0 )
|
||||
continue;
|
||||
// compute the distance to the tree root
|
||||
for( d = 0;; )
|
||||
{
|
||||
if( u->ts == curr_ts )
|
||||
{
|
||||
d += u->dist;
|
||||
break;
|
||||
}
|
||||
ej = u->parent;
|
||||
d++;
|
||||
if( ej < 0 )
|
||||
{
|
||||
if( ej == ORPHAN )
|
||||
d = INT_MAX-1;
|
||||
else
|
||||
{
|
||||
u->ts = curr_ts;
|
||||
u->dist = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
u = edges[ej].dst;
|
||||
}
|
||||
|
||||
// update the distance
|
||||
if( ++d < INT_MAX )
|
||||
{
|
||||
if( d < min_dist )
|
||||
{
|
||||
min_dist = d;
|
||||
e0 = ei;
|
||||
}
|
||||
for( u = edges[ei].dst; u->ts != curr_ts; u = edges[u->parent].dst )
|
||||
{
|
||||
u->ts = curr_ts;
|
||||
u->dist = --d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (v->parent = e0) > 0 )
|
||||
{
|
||||
v->ts = curr_ts;
|
||||
v->dist = min_dist;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* no parent is found */
|
||||
v->ts = 0;
|
||||
for( ei = v->first; ei != 0; ei = edges[ei].next )
|
||||
{
|
||||
u = edges[ei].dst;
|
||||
ej = u->parent;
|
||||
if( u->t != vt || !ej )
|
||||
continue;
|
||||
if( edges[ei^(vt^1)].weight && !u->next )
|
||||
{
|
||||
u->next = nilNode;
|
||||
last = last->next = u;
|
||||
}
|
||||
if( ej > 0 && edges[ej].dst == v )
|
||||
{
|
||||
if( norphans >= maxOrphans )
|
||||
maxOrphans = icvGCResizeOrphansBuf( orphans, norphans );
|
||||
orphans[norphans++] = u;
|
||||
u->parent = ORPHAN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_orphans = orphans;
|
||||
_maxOrphans = maxOrphans;
|
||||
|
||||
return flow;
|
||||
}
|
||||
|
||||
|
||||
CvStereoGCState* cvCreateStereoGCState( int numberOfDisparities, int maxIters )
|
||||
{
|
||||
CvStereoGCState* state = 0;
|
||||
|
||||
state = (CvStereoGCState*)cvAlloc( sizeof(*state) );
|
||||
memset( state, 0, sizeof(*state) );
|
||||
state->minDisparity = 0;
|
||||
state->numberOfDisparities = numberOfDisparities;
|
||||
state->maxIters = maxIters <= 0 ? 3 : maxIters;
|
||||
state->Ithreshold = 5;
|
||||
state->interactionRadius = 1;
|
||||
state->K = state->lambda = state->lambda1 = state->lambda2 = -1.f;
|
||||
state->occlusionCost = OCCLUSION_PENALTY;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void cvReleaseStereoGCState( CvStereoGCState** _state )
|
||||
{
|
||||
CvStereoGCState* state;
|
||||
|
||||
if( !_state && !*_state )
|
||||
return;
|
||||
|
||||
state = *_state;
|
||||
cvReleaseMat( &state->left );
|
||||
cvReleaseMat( &state->right );
|
||||
cvReleaseMat( &state->ptrLeft );
|
||||
cvReleaseMat( &state->ptrRight );
|
||||
cvReleaseMat( &state->vtxBuf );
|
||||
cvReleaseMat( &state->edgeBuf );
|
||||
cvFree( _state );
|
||||
}
|
||||
|
||||
// ||I(x) - J(x')|| =
|
||||
// min(CUTOFF,
|
||||
// min(
|
||||
// max(
|
||||
// max(minJ(x') - I(x), 0),
|
||||
// max(I(x) - maxJ(x'), 0)),
|
||||
// max(
|
||||
// max(minI(x) - J(x'), 0),
|
||||
// max(J(x') - maxI(x), 0)))**2) ==
|
||||
// min(CUTOFF,
|
||||
// min(
|
||||
// max(minJ(x') - I(x), 0) +
|
||||
// max(I(x) - maxJ(x'), 0),
|
||||
//
|
||||
// max(minI(x) - J(x'), 0) +
|
||||
// max(J(x') - maxI(x), 0)))**2)
|
||||
// where (I, minI, maxI) and
|
||||
// (J, minJ, maxJ) are stored as interleaved 3-channel images.
|
||||
// minI, maxI are computed from I,
|
||||
// minJ, maxJ are computed from J - see icvInitGraySubPix.
|
||||
static inline int icvDataCostFuncGraySubpix( const uchar* a, const uchar* b )
|
||||
{
|
||||
int va = a[0], vb = b[0];
|
||||
int da = icvTruncTab[b[1] - va + 255] + icvTruncTab[va - b[2] + 255];
|
||||
int db = icvTruncTab[a[1] - vb + 255] + icvTruncTab[vb - a[2] + 255];
|
||||
return icvCutoffSqrTab[MIN(da,db)];
|
||||
}
|
||||
|
||||
static inline int icvSmoothnessCostFunc( int da, int db, int maxR, const int* stabR, int scale )
|
||||
{
|
||||
return da == db ? 0 : (da == OCCLUDED || db == OCCLUDED ? maxR : stabR[da - db])*scale;
|
||||
}
|
||||
|
||||
static void icvInitGraySubpix( const CvMat* left, const CvMat* right,
|
||||
CvMat* left3, CvMat* right3 )
|
||||
{
|
||||
int k, x, y, rows = left->rows, cols = left->cols;
|
||||
|
||||
for( k = 0; k < 2; k++ )
|
||||
{
|
||||
const CvMat* src = k == 0 ? left : right;
|
||||
CvMat* dst = k == 0 ? left3 : right3;
|
||||
int sstep = src->step;
|
||||
|
||||
for( y = 0; y < rows; y++ )
|
||||
{
|
||||
const uchar* sptr = src->data.ptr + sstep*y;
|
||||
const uchar* sptr_prev = y > 0 ? sptr - sstep : sptr;
|
||||
const uchar* sptr_next = y < rows-1 ? sptr + sstep : sptr;
|
||||
uchar* dptr = dst->data.ptr + dst->step*y;
|
||||
int v_prev = sptr[0];
|
||||
|
||||
for( x = 0; x < cols; x++, dptr += 3 )
|
||||
{
|
||||
int v = sptr[x], v1, minv = v, maxv = v;
|
||||
|
||||
v1 = (v + v_prev)/2;
|
||||
minv = MIN(minv, v1); maxv = MAX(maxv, v1);
|
||||
v1 = (v + sptr_prev[x])/2;
|
||||
minv = MIN(minv, v1); maxv = MAX(maxv, v1);
|
||||
v1 = (v + sptr_next[x])/2;
|
||||
minv = MIN(minv, v1); maxv = MAX(maxv, v1);
|
||||
if( x < cols-1 )
|
||||
{
|
||||
v1 = (v + sptr[x+1])/2;
|
||||
minv = MIN(minv, v1); maxv = MAX(maxv, v1);
|
||||
}
|
||||
v_prev = v;
|
||||
dptr[0] = (uchar)v;
|
||||
dptr[1] = (uchar)minv;
|
||||
dptr[2] = (uchar)maxv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Optimal K is computed as avg_x(k-th-smallest_d(||I(x)-J(x+d)||)),
|
||||
// where k = number_of_disparities*0.25.
|
||||
static float
|
||||
icvComputeK( CvStereoGCState* state )
|
||||
{
|
||||
int x, y, x1, d, i, j, rows = state->left->rows, cols = state->left->cols, n = 0;
|
||||
int mind = state->minDisparity, nd = state->numberOfDisparities, maxd = mind + nd;
|
||||
int k = MIN(MAX((nd + 2)/4, 3), nd);
|
||||
int *arr = (int*)cvStackAlloc(k*sizeof(arr[0])), delta, t, sum = 0;
|
||||
|
||||
for( y = 0; y < rows; y++ )
|
||||
{
|
||||
const uchar* lptr = state->left->data.ptr + state->left->step*y;
|
||||
const uchar* rptr = state->right->data.ptr + state->right->step*y;
|
||||
|
||||
for( x = 0; x < cols; x++ )
|
||||
{
|
||||
for( d = maxd-1, i = 0; d >= mind; d-- )
|
||||
{
|
||||
x1 = x - d;
|
||||
if( (unsigned)x1 >= (unsigned)cols )
|
||||
continue;
|
||||
delta = icvDataCostFuncGraySubpix( lptr + x*3, rptr + x1*3 );
|
||||
if( i < k )
|
||||
arr[i++] = delta;
|
||||
else
|
||||
for( i = 0; i < k; i++ )
|
||||
if( delta < arr[i] )
|
||||
CV_SWAP( arr[i], delta, t );
|
||||
}
|
||||
delta = arr[0];
|
||||
for( j = 1; j < i; j++ )
|
||||
delta = MAX(delta, arr[j]);
|
||||
sum += delta;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
return (float)sum/n;
|
||||
}
|
||||
|
||||
static int64 icvComputeEnergy( const CvStereoGCState* state, const CvStereoGCState2* state2,
|
||||
bool allOccluded )
|
||||
{
|
||||
int x, y, rows = state->left->rows, cols = state->left->cols;
|
||||
int64 E = 0;
|
||||
const int* dtab = state2->dataCostFuncTab;
|
||||
int maxR = state2->interactionRadius;
|
||||
const int* stabR = state2->smoothnessR + CUTOFF;
|
||||
const int* stabI = state2->smoothnessGrayDiff + 255;
|
||||
const uchar* left = state->left->data.ptr;
|
||||
const uchar* right = state->right->data.ptr;
|
||||
short* dleft = state->dispLeft->data.s;
|
||||
short* dright = state->dispRight->data.s;
|
||||
int step = state->left->step;
|
||||
int dstep = (int)(state->dispLeft->step/sizeof(short));
|
||||
|
||||
assert( state->left->step == state->right->step &&
|
||||
state->dispLeft->step == state->dispRight->step );
|
||||
|
||||
if( allOccluded )
|
||||
return (int64)OCCLUSION_PENALTY*rows*cols*2;
|
||||
|
||||
for( y = 0; y < rows; y++, left += step, right += step, dleft += dstep, dright += dstep )
|
||||
{
|
||||
for( x = 0; x < cols; x++ )
|
||||
{
|
||||
int d = dleft[x], x1, d1;
|
||||
if( d == OCCLUDED )
|
||||
E += OCCLUSION_PENALTY;
|
||||
else
|
||||
{
|
||||
x1 = x + d;
|
||||
if( (unsigned)x1 >= (unsigned)cols )
|
||||
continue;
|
||||
d1 = dright[x1];
|
||||
if( d == -d1 )
|
||||
E += dtab[icvDataCostFuncGraySubpix( left + x*3, right + x1*3 )];
|
||||
}
|
||||
|
||||
if( x < cols-1 )
|
||||
{
|
||||
d1 = dleft[x+1];
|
||||
E += icvSmoothnessCostFunc(d, d1, maxR, stabR, stabI[left[x*3] - left[x*3+3]] );
|
||||
}
|
||||
if( y < rows-1 )
|
||||
{
|
||||
d1 = dleft[x+dstep];
|
||||
E += icvSmoothnessCostFunc(d, d1, maxR, stabR, stabI[left[x*3] - left[x*3+step]] );
|
||||
}
|
||||
|
||||
d = dright[x];
|
||||
if( d == OCCLUDED )
|
||||
E += OCCLUSION_PENALTY;
|
||||
|
||||
if( x < cols-1 )
|
||||
{
|
||||
d1 = dright[x+1];
|
||||
E += icvSmoothnessCostFunc(d, d1, maxR, stabR, stabI[right[x*3] - right[x*3+3]] );
|
||||
}
|
||||
if( y < rows-1 )
|
||||
{
|
||||
d1 = dright[x+dstep];
|
||||
E += icvSmoothnessCostFunc(d, d1, maxR, stabR, stabI[right[x*3] - right[x*3+step]] );
|
||||
}
|
||||
assert( E >= 0 );
|
||||
}
|
||||
}
|
||||
|
||||
return E;
|
||||
}
|
||||
|
||||
static inline void icvAddEdge( GCVtx *x, GCVtx* y, GCEdge* edgeBuf, int nedges, int w, int rw )
|
||||
{
|
||||
GCEdge *xy = edgeBuf + nedges, *yx = xy + 1;
|
||||
|
||||
assert( x != 0 && y != 0 );
|
||||
xy->dst = y;
|
||||
xy->next = x->first;
|
||||
xy->weight = (short)w;
|
||||
x->first = nedges;
|
||||
|
||||
yx->dst = x;
|
||||
yx->next = y->first;
|
||||
yx->weight = (short)rw;
|
||||
y->first = nedges+1;
|
||||
}
|
||||
|
||||
static inline int icvAddTWeights( GCVtx* vtx, int sourceWeight, int sinkWeight )
|
||||
{
|
||||
int w = vtx->weight;
|
||||
if( w > 0 )
|
||||
sourceWeight += w;
|
||||
else
|
||||
sinkWeight -= w;
|
||||
vtx->weight = (short)(sourceWeight - sinkWeight);
|
||||
return MIN(sourceWeight, sinkWeight);
|
||||
}
|
||||
|
||||
static inline int icvAddTerm( GCVtx* x, GCVtx* y, int A, int B, int C, int D,
|
||||
GCEdge* edgeBuf, int& nedges )
|
||||
{
|
||||
int dE = 0, w;
|
||||
|
||||
assert(B - A + C - D >= 0);
|
||||
if( B < A )
|
||||
{
|
||||
dE += icvAddTWeights(x, D, B);
|
||||
dE += icvAddTWeights(y, 0, A - B);
|
||||
if( (w = B - A + C - D) != 0 )
|
||||
{
|
||||
icvAddEdge( x, y, edgeBuf, nedges, 0, w );
|
||||
nedges += 2;
|
||||
}
|
||||
}
|
||||
else if( C < D )
|
||||
{
|
||||
dE += icvAddTWeights(x, D, A + D - C);
|
||||
dE += icvAddTWeights(y, 0, C - D);
|
||||
if( (w = B - A + C - D) != 0 )
|
||||
{
|
||||
icvAddEdge( x, y, edgeBuf, nedges, w, 0 );
|
||||
nedges += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dE += icvAddTWeights(x, D, A);
|
||||
if( B != A || C != D )
|
||||
{
|
||||
icvAddEdge( x, y, edgeBuf, nedges, B - A, C - D );
|
||||
nedges += 2;
|
||||
}
|
||||
}
|
||||
return dE;
|
||||
}
|
||||
|
||||
static int64 icvAlphaExpand( int64 Eprev, int alpha, CvStereoGCState* state, CvStereoGCState2* state2 )
|
||||
{
|
||||
GCVtx *var, *var1;
|
||||
int64 E = 0;
|
||||
int delta, E00=0, E0a=0, Ea0=0, Eaa=0;
|
||||
int k, a, d, d1, x, y, x1, y1, rows = state->left->rows, cols = state->left->cols;
|
||||
int nvtx = 0, nedges = 2;
|
||||
GCVtx* vbuf = (GCVtx*)state->vtxBuf->data.ptr;
|
||||
GCEdge* ebuf = (GCEdge*)state->edgeBuf->data.ptr;
|
||||
int maxR = state2->interactionRadius;
|
||||
const int* dtab = state2->dataCostFuncTab;
|
||||
const int* stabR = state2->smoothnessR + CUTOFF;
|
||||
const int* stabI = state2->smoothnessGrayDiff + 255;
|
||||
const uchar* left0 = state->left->data.ptr;
|
||||
const uchar* right0 = state->right->data.ptr;
|
||||
short* dleft0 = state->dispLeft->data.s;
|
||||
short* dright0 = state->dispRight->data.s;
|
||||
GCVtx** pleft0 = (GCVtx**)state->ptrLeft->data.ptr;
|
||||
GCVtx** pright0 = (GCVtx**)state->ptrRight->data.ptr;
|
||||
int step = state->left->step;
|
||||
int dstep = (int)(state->dispLeft->step/sizeof(short));
|
||||
int pstep = (int)(state->ptrLeft->step/sizeof(GCVtx*));
|
||||
int aa[] = { alpha, -alpha };
|
||||
|
||||
//double t = (double)cvGetTickCount();
|
||||
|
||||
assert( state->left->step == state->right->step &&
|
||||
state->dispLeft->step == state->dispRight->step &&
|
||||
state->ptrLeft->step == state->ptrRight->step );
|
||||
for( k = 0; k < 2; k++ )
|
||||
{
|
||||
ebuf[k].dst = 0;
|
||||
ebuf[k].next = 0;
|
||||
ebuf[k].weight = 0;
|
||||
}
|
||||
|
||||
for( y = 0; y < rows; y++ )
|
||||
{
|
||||
const uchar* left = left0 + step*y;
|
||||
const uchar* right = right0 + step*y;
|
||||
const short* dleft = dleft0 + dstep*y;
|
||||
const short* dright = dright0 + dstep*y;
|
||||
GCVtx** pleft = pleft0 + pstep*y;
|
||||
GCVtx** pright = pright0 + pstep*y;
|
||||
const uchar* lr[] = { left, right };
|
||||
const short* dlr[] = { dleft, dright };
|
||||
GCVtx** plr[] = { pleft, pright };
|
||||
|
||||
for( k = 0; k < 2; k++ )
|
||||
{
|
||||
a = aa[k];
|
||||
for( y1 = y+(y>0); y1 <= y+(y<rows-1); y1++ )
|
||||
{
|
||||
const short* disp = (k == 0 ? dleft0 : dright0) + y1*dstep;
|
||||
GCVtx** ptr = (k == 0 ? pleft0 : pright0) + y1*pstep;
|
||||
for( x = 0; x < cols; x++ )
|
||||
{
|
||||
GCVtx* v = ptr[x] = &vbuf[nvtx++];
|
||||
v->first = 0;
|
||||
v->weight = disp[x] == (short)(OCCLUDED ? -OCCLUSION_PENALTY2 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( x = 0; x < cols; x++ )
|
||||
{
|
||||
d = dleft[x];
|
||||
x1 = x + d;
|
||||
var = pleft[x];
|
||||
|
||||
// (left + x, right + x + d)
|
||||
if( d != alpha && d != OCCLUDED && (unsigned)x1 < (unsigned)cols )
|
||||
{
|
||||
var1 = pright[x1];
|
||||
d1 = dright[x1];
|
||||
if( d == -d1 )
|
||||
{
|
||||
assert( var1 != 0 );
|
||||
delta = IS_BLOCKED(alpha, d) ? INFINITY : 0;
|
||||
//add inter edge
|
||||
E += icvAddTerm( var, var1,
|
||||
dtab[icvDataCostFuncGraySubpix( left + x*3, right + x1*3 )],
|
||||
delta, delta, 0, ebuf, nedges );
|
||||
}
|
||||
else if( IS_BLOCKED(alpha, d) )
|
||||
E += icvAddTerm( var, var1, 0, INFINITY, 0, 0, ebuf, nedges );
|
||||
}
|
||||
|
||||
// (left + x, right + x + alpha)
|
||||
x1 = x + alpha;
|
||||
if( (unsigned)x1 < (unsigned)cols )
|
||||
{
|
||||
var1 = pright[x1];
|
||||
d1 = dright[x1];
|
||||
|
||||
E0a = IS_BLOCKED(d, alpha) ? INFINITY : 0;
|
||||
Ea0 = IS_BLOCKED(-d1, alpha) ? INFINITY : 0;
|
||||
Eaa = dtab[icvDataCostFuncGraySubpix( left + x*3, right + x1*3 )];
|
||||
E += icvAddTerm( var, var1, 0, E0a, Ea0, Eaa, ebuf, nedges );
|
||||
}
|
||||
|
||||
// smoothness
|
||||
for( k = 0; k < 2; k++ )
|
||||
{
|
||||
GCVtx** p = plr[k];
|
||||
const short* disp = dlr[k];
|
||||
const uchar* img = lr[k] + x*3;
|
||||
int scale;
|
||||
var = p[x];
|
||||
d = disp[x];
|
||||
a = aa[k];
|
||||
|
||||
if( x < cols - 1 )
|
||||
{
|
||||
var1 = p[x+1];
|
||||
d1 = disp[x+1];
|
||||
scale = stabI[img[0] - img[3]];
|
||||
E0a = icvSmoothnessCostFunc( d, a, maxR, stabR, scale );
|
||||
Ea0 = icvSmoothnessCostFunc( a, d1, maxR, stabR, scale );
|
||||
E00 = icvSmoothnessCostFunc( d, d1, maxR, stabR, scale );
|
||||
E += icvAddTerm( var, var1, E00, E0a, Ea0, 0, ebuf, nedges );
|
||||
}
|
||||
|
||||
if( y < rows - 1 )
|
||||
{
|
||||
var1 = p[x+pstep];
|
||||
d1 = disp[x+dstep];
|
||||
scale = stabI[img[0] - img[step]];
|
||||
E0a = icvSmoothnessCostFunc( d, a, maxR, stabR, scale );
|
||||
Ea0 = icvSmoothnessCostFunc( a, d1, maxR, stabR, scale );
|
||||
E00 = icvSmoothnessCostFunc( d, d1, maxR, stabR, scale );
|
||||
E += icvAddTerm( var, var1, E00, E0a, Ea0, 0, ebuf, nedges );
|
||||
}
|
||||
}
|
||||
|
||||
// visibility term
|
||||
if( d != OCCLUDED && IS_BLOCKED(alpha, -d))
|
||||
{
|
||||
x1 = x + d;
|
||||
if( (unsigned)x1 < (unsigned)cols )
|
||||
{
|
||||
if( d != -dleft[x1] )
|
||||
{
|
||||
var1 = pleft[x1];
|
||||
E += icvAddTerm( var, var1, 0, INFINITY, 0, 0, ebuf, nedges );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//t = (double)cvGetTickCount() - t;
|
||||
ebuf[0].weight = ebuf[1].weight = 0;
|
||||
E += icvGCMaxFlow( vbuf, nvtx, ebuf, state2->orphans, state2->maxOrphans );
|
||||
|
||||
if( E < Eprev )
|
||||
{
|
||||
for( y = 0; y < rows; y++ )
|
||||
{
|
||||
short* dleft = dleft0 + dstep*y;
|
||||
short* dright = dright0 + dstep*y;
|
||||
GCVtx** pleft = pleft0 + pstep*y;
|
||||
GCVtx** pright = pright0 + pstep*y;
|
||||
for( x = 0; x < cols; x++ )
|
||||
{
|
||||
GCVtx* var = pleft[x];
|
||||
if( var && var->parent && var->t )
|
||||
dleft[x] = (short)alpha;
|
||||
|
||||
var = pright[x];
|
||||
if( var && var->parent && var->t )
|
||||
dright[x] = (short)-alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MIN(E, Eprev);
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL void cvFindStereoCorrespondenceGC( const CvArr* _left, const CvArr* _right,
|
||||
CvArr* _dispLeft, CvArr* _dispRight, CvStereoGCState* state, int useDisparityGuess )
|
||||
{
|
||||
CvStereoGCState2 state2;
|
||||
state2.orphans = 0;
|
||||
state2.maxOrphans = 0;
|
||||
|
||||
CvMat lstub, *left = cvGetMat( _left, &lstub );
|
||||
CvMat rstub, *right = cvGetMat( _right, &rstub );
|
||||
CvMat dlstub, *dispLeft = cvGetMat( _dispLeft, &dlstub );
|
||||
CvMat drstub, *dispRight = cvGetMat( _dispRight, &drstub );
|
||||
CvSize size;
|
||||
int iter, i, nZeroExpansions = 0;
|
||||
CvRNG rng = cvRNG(-1);
|
||||
int* disp;
|
||||
CvMat _disp;
|
||||
int64 E;
|
||||
|
||||
CV_Assert( state != 0 );
|
||||
CV_Assert( CV_ARE_SIZES_EQ(left, right) && CV_ARE_TYPES_EQ(left, right) &&
|
||||
CV_MAT_TYPE(left->type) == CV_8UC1 );
|
||||
CV_Assert( !dispLeft ||
|
||||
(CV_ARE_SIZES_EQ(dispLeft, left) && CV_MAT_CN(dispLeft->type) == 1) );
|
||||
CV_Assert( !dispRight ||
|
||||
(CV_ARE_SIZES_EQ(dispRight, left) && CV_MAT_CN(dispRight->type) == 1) );
|
||||
|
||||
size = cvGetSize(left);
|
||||
if( !state->left || state->left->width != size.width || state->left->height != size.height )
|
||||
{
|
||||
int pcn = (int)(sizeof(GCVtx*)/sizeof(int));
|
||||
int vcn = (int)(sizeof(GCVtx)/sizeof(int));
|
||||
int ecn = (int)(sizeof(GCEdge)/sizeof(int));
|
||||
cvReleaseMat( &state->left );
|
||||
cvReleaseMat( &state->right );
|
||||
cvReleaseMat( &state->ptrLeft );
|
||||
cvReleaseMat( &state->ptrRight );
|
||||
cvReleaseMat( &state->dispLeft );
|
||||
cvReleaseMat( &state->dispRight );
|
||||
|
||||
state->left = cvCreateMat( size.height, size.width, CV_8UC3 );
|
||||
state->right = cvCreateMat( size.height, size.width, CV_8UC3 );
|
||||
state->dispLeft = cvCreateMat( size.height, size.width, CV_16SC1 );
|
||||
state->dispRight = cvCreateMat( size.height, size.width, CV_16SC1 );
|
||||
state->ptrLeft = cvCreateMat( size.height, size.width, CV_32SC(pcn) );
|
||||
state->ptrRight = cvCreateMat( size.height, size.width, CV_32SC(pcn) );
|
||||
state->vtxBuf = cvCreateMat( 1, size.height*size.width*2, CV_32SC(vcn) );
|
||||
state->edgeBuf = cvCreateMat( 1, size.height*size.width*12 + 16, CV_32SC(ecn) );
|
||||
}
|
||||
|
||||
if( !useDisparityGuess )
|
||||
{
|
||||
cvSet( state->dispLeft, cvScalarAll(OCCLUDED));
|
||||
cvSet( state->dispRight, cvScalarAll(OCCLUDED));
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( dispLeft && dispRight );
|
||||
cvConvert( dispLeft, state->dispLeft );
|
||||
cvConvert( dispRight, state->dispRight );
|
||||
}
|
||||
|
||||
state2.Ithreshold = state->Ithreshold;
|
||||
state2.interactionRadius = state->interactionRadius;
|
||||
state2.lambda = cvRound(state->lambda*DENOMINATOR);
|
||||
state2.lambda1 = cvRound(state->lambda1*DENOMINATOR);
|
||||
state2.lambda2 = cvRound(state->lambda2*DENOMINATOR);
|
||||
state2.K = cvRound(state->K*DENOMINATOR);
|
||||
|
||||
icvInitStereoConstTabs();
|
||||
icvInitGraySubpix( left, right, state->left, state->right );
|
||||
disp = (int*)cvStackAlloc( state->numberOfDisparities*sizeof(disp[0]) );
|
||||
_disp = cvMat( 1, state->numberOfDisparities, CV_32S, disp );
|
||||
cvRange( &_disp, state->minDisparity, state->minDisparity + state->numberOfDisparities );
|
||||
cvRandShuffle( &_disp, &rng );
|
||||
|
||||
if( state2.lambda < 0 && (state2.K < 0 || state2.lambda1 < 0 || state2.lambda2 < 0) )
|
||||
{
|
||||
float L = icvComputeK(state)*0.2f;
|
||||
state2.lambda = cvRound(L*DENOMINATOR);
|
||||
}
|
||||
|
||||
if( state2.K < 0 )
|
||||
state2.K = state2.lambda*5;
|
||||
if( state2.lambda1 < 0 )
|
||||
state2.lambda1 = state2.lambda*3;
|
||||
if( state2.lambda2 < 0 )
|
||||
state2.lambda2 = state2.lambda;
|
||||
|
||||
icvInitStereoTabs( &state2 );
|
||||
|
||||
E = icvComputeEnergy( state, &state2, !useDisparityGuess );
|
||||
for( iter = 0; iter < state->maxIters; iter++ )
|
||||
{
|
||||
for( i = 0; i < state->numberOfDisparities; i++ )
|
||||
{
|
||||
int alpha = disp[i];
|
||||
int64 Enew = icvAlphaExpand( E, -alpha, state, &state2 );
|
||||
if( Enew < E )
|
||||
{
|
||||
nZeroExpansions = 0;
|
||||
E = Enew;
|
||||
}
|
||||
else if( ++nZeroExpansions >= state->numberOfDisparities )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( dispLeft )
|
||||
cvConvert( state->dispLeft, dispLeft );
|
||||
if( dispRight )
|
||||
cvConvert( state->dispRight, dispRight );
|
||||
|
||||
cvFree( &state2.orphans );
|
||||
}
|
||||
1048
modules/calib3d/src/stereosgbm.cpp
Normal file
1048
modules/calib3d/src/stereosgbm.cpp
Normal file
File diff suppressed because it is too large
Load Diff
405
modules/calib3d/src/triangulate.cpp
Normal file
405
modules/calib3d/src/triangulate.cpp
Normal file
@@ -0,0 +1,405 @@
|
||||
/*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) 2009, Intel Corporation and others, 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"
|
||||
|
||||
// cvCorrectMatches function is Copyright (C) 2009, Jostein Austvik Jacobsen.
|
||||
// cvTriangulatePoints function is derived from icvReconstructPointsFor3View, originally by Valery Mosyagin.
|
||||
|
||||
// HZ, R. Hartley and A. Zisserman, Multiple View Geometry in Computer Vision, Cambridge Univ. Press, 2003.
|
||||
|
||||
|
||||
|
||||
// This method is the same as icvReconstructPointsFor3View, with only a few numbers adjusted for two-view geometry
|
||||
CV_IMPL void
|
||||
cvTriangulatePoints(CvMat* projMatr1, CvMat* projMatr2, CvMat* projPoints1, CvMat* projPoints2, CvMat* points4D)
|
||||
{
|
||||
if( projMatr1 == 0 || projMatr2 == 0 ||
|
||||
projPoints1 == 0 || projPoints2 == 0 ||
|
||||
points4D == 0)
|
||||
CV_Error( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
|
||||
|
||||
if( !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) ||
|
||||
!CV_IS_MAT(projPoints1) || !CV_IS_MAT(projPoints2) ||
|
||||
!CV_IS_MAT(points4D) )
|
||||
CV_Error( CV_StsUnsupportedFormat, "Input parameters must be matrices" );
|
||||
|
||||
int numPoints;
|
||||
numPoints = projPoints1->cols;
|
||||
|
||||
if( numPoints < 1 )
|
||||
CV_Error( CV_StsOutOfRange, "Number of points must be more than zero" );
|
||||
|
||||
if( projPoints2->cols != numPoints || points4D->cols != numPoints )
|
||||
CV_Error( CV_StsUnmatchedSizes, "Number of points must be the same" );
|
||||
|
||||
if( projPoints1->rows != 2 || projPoints2->rows != 2)
|
||||
CV_Error( CV_StsUnmatchedSizes, "Number of proj points coordinates must be == 2" );
|
||||
|
||||
if( points4D->rows != 4 )
|
||||
CV_Error( CV_StsUnmatchedSizes, "Number of world points coordinates must be == 4" );
|
||||
|
||||
if( projMatr1->cols != 4 || projMatr1->rows != 3 ||
|
||||
projMatr2->cols != 4 || projMatr2->rows != 3)
|
||||
CV_Error( CV_StsUnmatchedSizes, "Size of projection matrices must be 3x4" );
|
||||
|
||||
CvMat matrA;
|
||||
double matrA_dat[24];
|
||||
matrA = cvMat(6,4,CV_64F,matrA_dat);
|
||||
|
||||
//CvMat matrU;
|
||||
CvMat matrW;
|
||||
CvMat matrV;
|
||||
//double matrU_dat[9*9];
|
||||
double matrW_dat[6*4];
|
||||
double matrV_dat[4*4];
|
||||
|
||||
//matrU = cvMat(6,6,CV_64F,matrU_dat);
|
||||
matrW = cvMat(6,4,CV_64F,matrW_dat);
|
||||
matrV = cvMat(4,4,CV_64F,matrV_dat);
|
||||
|
||||
CvMat* projPoints[2];
|
||||
CvMat* projMatrs[2];
|
||||
|
||||
projPoints[0] = projPoints1;
|
||||
projPoints[1] = projPoints2;
|
||||
|
||||
projMatrs[0] = projMatr1;
|
||||
projMatrs[1] = projMatr2;
|
||||
|
||||
/* Solve system for each point */
|
||||
int i,j;
|
||||
for( i = 0; i < numPoints; i++ )/* For each point */
|
||||
{
|
||||
/* Fill matrix for current point */
|
||||
for( j = 0; j < 2; j++ )/* For each view */
|
||||
{
|
||||
double x,y;
|
||||
x = cvmGet(projPoints[j],0,i);
|
||||
y = cvmGet(projPoints[j],1,i);
|
||||
for( int k = 0; k < 4; k++ )
|
||||
{
|
||||
cvmSet(&matrA, j*3+0, k, x * cvmGet(projMatrs[j],2,k) - cvmGet(projMatrs[j],0,k) );
|
||||
cvmSet(&matrA, j*3+1, k, y * cvmGet(projMatrs[j],2,k) - cvmGet(projMatrs[j],1,k) );
|
||||
cvmSet(&matrA, j*3+2, k, x * cvmGet(projMatrs[j],1,k) - y * cvmGet(projMatrs[j],0,k) );
|
||||
}
|
||||
}
|
||||
/* Solve system for current point */
|
||||
{
|
||||
cvSVD(&matrA,&matrW,0,&matrV,CV_SVD_V_T);
|
||||
|
||||
/* Copy computed point */
|
||||
cvmSet(points4D,0,i,cvmGet(&matrV,3,0));/* X */
|
||||
cvmSet(points4D,1,i,cvmGet(&matrV,3,1));/* Y */
|
||||
cvmSet(points4D,2,i,cvmGet(&matrV,3,2));/* Z */
|
||||
cvmSet(points4D,3,i,cvmGet(&matrV,3,3));/* W */
|
||||
}
|
||||
}
|
||||
|
||||
/* Points was reconstructed. Try to reproject points */
|
||||
/* We can compute reprojection error if need */
|
||||
{
|
||||
int i;
|
||||
CvMat point3D;
|
||||
double point3D_dat[4];
|
||||
point3D = cvMat(4,1,CV_64F,point3D_dat);
|
||||
|
||||
CvMat point2D;
|
||||
double point2D_dat[3];
|
||||
point2D = cvMat(3,1,CV_64F,point2D_dat);
|
||||
|
||||
for( i = 0; i < numPoints; i++ )
|
||||
{
|
||||
double W = cvmGet(points4D,3,i);
|
||||
|
||||
point3D_dat[0] = cvmGet(points4D,0,i)/W;
|
||||
point3D_dat[1] = cvmGet(points4D,1,i)/W;
|
||||
point3D_dat[2] = cvmGet(points4D,2,i)/W;
|
||||
point3D_dat[3] = 1;
|
||||
|
||||
/* !!! Project this point for each camera */
|
||||
for( int currCamera = 0; currCamera < 2; currCamera++ )
|
||||
{
|
||||
cvMatMul(projMatrs[currCamera], &point3D, &point2D);
|
||||
|
||||
float x,y;
|
||||
float xr,yr,wr;
|
||||
x = (float)cvmGet(projPoints[currCamera],0,i);
|
||||
y = (float)cvmGet(projPoints[currCamera],1,i);
|
||||
|
||||
wr = (float)point2D_dat[2];
|
||||
xr = (float)(point2D_dat[0]/wr);
|
||||
yr = (float)(point2D_dat[1]/wr);
|
||||
|
||||
float deltaX,deltaY;
|
||||
deltaX = (float)fabs(x-xr);
|
||||
deltaY = (float)fabs(y-yr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The Optimal Triangulation Method (see HZ for details)
|
||||
* For each given point correspondence points1[i] <-> points2[i], and a fundamental matrix F,
|
||||
* computes the corrected correspondences new_points1[i] <-> new_points2[i] that minimize the
|
||||
* geometric error d(points1[i],new_points1[i])^2 + d(points2[i],new_points2[i])^2 (where d(a,b)
|
||||
* is the geometric distance between points a and b) subject to the epipolar constraint
|
||||
* new_points2' * F * new_points1 = 0.
|
||||
*
|
||||
* F_ : 3x3 fundamental matrix
|
||||
* points1_ : 2xN matrix containing the first set of points
|
||||
* points2_ : 2xN matrix containing the second set of points
|
||||
* new_points1 : the optimized points1_. if this is NULL, the corrected points are placed back in points1_
|
||||
* new_points2 : the optimized points2_. if this is NULL, the corrected points are placed back in points2_
|
||||
*/
|
||||
CV_IMPL void
|
||||
cvCorrectMatches(CvMat *F_, CvMat *points1_, CvMat *points2_, CvMat *new_points1, CvMat *new_points2)
|
||||
{
|
||||
cv::Ptr<CvMat> tmp33;
|
||||
cv::Ptr<CvMat> tmp31, tmp31_2;
|
||||
cv::Ptr<CvMat> T1i, T2i;
|
||||
cv::Ptr<CvMat> R1, R2;
|
||||
cv::Ptr<CvMat> TFT, TFTt, RTFTR;
|
||||
cv::Ptr<CvMat> U, S, V;
|
||||
cv::Ptr<CvMat> e1, e2;
|
||||
cv::Ptr<CvMat> polynomial;
|
||||
cv::Ptr<CvMat> result;
|
||||
cv::Ptr<CvMat> points1, points2;
|
||||
cv::Ptr<CvMat> F;
|
||||
|
||||
if (!CV_IS_MAT(F_) || !CV_IS_MAT(points1_) || !CV_IS_MAT(points2_) )
|
||||
CV_Error( CV_StsUnsupportedFormat, "Input parameters must be matrices" );
|
||||
if (!( F_->cols == 3 && F_->rows == 3))
|
||||
CV_Error( CV_StsUnmatchedSizes, "The fundamental matrix must be a 3x3 matrix");
|
||||
if (!(((F_->type & CV_MAT_TYPE_MASK) >> 3) == 0 ))
|
||||
CV_Error( CV_StsUnsupportedFormat, "The fundamental matrix must be a single-channel matrix" );
|
||||
if (!(points1_->rows == 1 && points2_->rows == 1 && points1_->cols == points2_->cols))
|
||||
CV_Error( CV_StsUnmatchedSizes, "The point-matrices must have two rows, and an equal number of columns" );
|
||||
if (((points1_->type & CV_MAT_TYPE_MASK) >> 3) != 1 )
|
||||
CV_Error( CV_StsUnmatchedSizes, "The first set of points must contain two channels; one for x and one for y" );
|
||||
if (((points2_->type & CV_MAT_TYPE_MASK) >> 3) != 1 )
|
||||
CV_Error( CV_StsUnmatchedSizes, "The second set of points must contain two channels; one for x and one for y" );
|
||||
if (new_points1 != NULL) {
|
||||
CV_Assert(CV_IS_MAT(new_points1));
|
||||
if (new_points1->cols != points1_->cols || new_points1->rows != 1)
|
||||
CV_Error( CV_StsUnmatchedSizes, "The first output matrix must have the same dimensions as the input matrices" );
|
||||
if (CV_MAT_CN(new_points1->type) != 2)
|
||||
CV_Error( CV_StsUnsupportedFormat, "The first output matrix must have two channels; one for x and one for y" );
|
||||
}
|
||||
if (new_points2 != NULL) {
|
||||
CV_Assert(CV_IS_MAT(new_points2));
|
||||
if (new_points2->cols != points2_->cols || new_points2->rows != 1)
|
||||
CV_Error( CV_StsUnmatchedSizes, "The second output matrix must have the same dimensions as the input matrices" );
|
||||
if (CV_MAT_CN(new_points2->type) != 2)
|
||||
CV_Error( CV_StsUnsupportedFormat, "The second output matrix must have two channels; one for x and one for y" );
|
||||
}
|
||||
|
||||
// Make sure F uses double precision
|
||||
F = cvCreateMat(3,3,CV_64FC1);
|
||||
cvConvert(F_, F);
|
||||
|
||||
// Make sure points1 uses double precision
|
||||
points1 = cvCreateMat(points1_->rows,points1_->cols,CV_64FC2);
|
||||
cvConvert(points1_, points1);
|
||||
|
||||
// Make sure points2 uses double precision
|
||||
points2 = cvCreateMat(points2_->rows,points2_->cols,CV_64FC2);
|
||||
cvConvert(points2_, points2);
|
||||
|
||||
tmp33 = cvCreateMat(3,3,CV_64FC1);
|
||||
tmp31 = cvCreateMat(3,1,CV_64FC1), tmp31_2 = cvCreateMat(3,1,CV_64FC1);
|
||||
T1i = cvCreateMat(3,3,CV_64FC1), T2i = cvCreateMat(3,3,CV_64FC1);
|
||||
R1 = cvCreateMat(3,3,CV_64FC1), R2 = cvCreateMat(3,3,CV_64FC1);
|
||||
TFT = cvCreateMat(3,3,CV_64FC1), TFTt = cvCreateMat(3,3,CV_64FC1), RTFTR = cvCreateMat(3,3,CV_64FC1);
|
||||
U = cvCreateMat(3,3,CV_64FC1);
|
||||
S = cvCreateMat(3,3,CV_64FC1);
|
||||
V = cvCreateMat(3,3,CV_64FC1);
|
||||
e1 = cvCreateMat(3,1,CV_64FC1), e2 = cvCreateMat(3,1,CV_64FC1);
|
||||
|
||||
double x1, y1, x2, y2;
|
||||
double scale;
|
||||
double f1, f2, a, b, c, d;
|
||||
polynomial = cvCreateMat(1,7,CV_64FC1);
|
||||
result = cvCreateMat(1,6,CV_64FC2);
|
||||
double t_min, s_val, t, s;
|
||||
for (int p = 0; p < points1->cols; ++p) {
|
||||
// Replace F by T2-t * F * T1-t
|
||||
x1 = points1->data.db[p*2];
|
||||
y1 = points1->data.db[p*2+1];
|
||||
x2 = points2->data.db[p*2];
|
||||
y2 = points2->data.db[p*2+1];
|
||||
|
||||
cvSetZero(T1i);
|
||||
cvSetReal2D(T1i,0,0,1);
|
||||
cvSetReal2D(T1i,1,1,1);
|
||||
cvSetReal2D(T1i,2,2,1);
|
||||
cvSetReal2D(T1i,0,2,x1);
|
||||
cvSetReal2D(T1i,1,2,y1);
|
||||
cvSetZero(T2i);
|
||||
cvSetReal2D(T2i,0,0,1);
|
||||
cvSetReal2D(T2i,1,1,1);
|
||||
cvSetReal2D(T2i,2,2,1);
|
||||
cvSetReal2D(T2i,0,2,x2);
|
||||
cvSetReal2D(T2i,1,2,y2);
|
||||
cvGEMM(T2i,F,1,0,0,tmp33,CV_GEMM_A_T);
|
||||
cvSetZero(TFT);
|
||||
cvGEMM(tmp33,T1i,1,0,0,TFT);
|
||||
|
||||
// Compute the right epipole e1 from F * e1 = 0
|
||||
cvSetZero(U);
|
||||
cvSetZero(S);
|
||||
cvSetZero(V);
|
||||
cvSVD(TFT,S,U,V);
|
||||
scale = sqrt(cvGetReal2D(V,0,2)*cvGetReal2D(V,0,2) + cvGetReal2D(V,1,2)*cvGetReal2D(V,1,2));
|
||||
cvSetReal2D(e1,0,0,cvGetReal2D(V,0,2)/scale);
|
||||
cvSetReal2D(e1,1,0,cvGetReal2D(V,1,2)/scale);
|
||||
cvSetReal2D(e1,2,0,cvGetReal2D(V,2,2)/scale);
|
||||
if (cvGetReal2D(e1,2,0) < 0) {
|
||||
cvSetReal2D(e1,0,0,-cvGetReal2D(e1,0,0));
|
||||
cvSetReal2D(e1,1,0,-cvGetReal2D(e1,1,0));
|
||||
cvSetReal2D(e1,2,0,-cvGetReal2D(e1,2,0));
|
||||
}
|
||||
|
||||
// Compute the left epipole e2 from e2' * F = 0 => F' * e2 = 0
|
||||
cvSetZero(TFTt);
|
||||
cvTranspose(TFT, TFTt);
|
||||
cvSetZero(U);
|
||||
cvSetZero(S);
|
||||
cvSetZero(V);
|
||||
cvSVD(TFTt,S,U,V);
|
||||
cvSetZero(e2);
|
||||
scale = sqrt(cvGetReal2D(V,0,2)*cvGetReal2D(V,0,2) + cvGetReal2D(V,1,2)*cvGetReal2D(V,1,2));
|
||||
cvSetReal2D(e2,0,0,cvGetReal2D(V,0,2)/scale);
|
||||
cvSetReal2D(e2,1,0,cvGetReal2D(V,1,2)/scale);
|
||||
cvSetReal2D(e2,2,0,cvGetReal2D(V,2,2)/scale);
|
||||
if (cvGetReal2D(e2,2,0) < 0) {
|
||||
cvSetReal2D(e2,0,0,-cvGetReal2D(e2,0,0));
|
||||
cvSetReal2D(e2,1,0,-cvGetReal2D(e2,1,0));
|
||||
cvSetReal2D(e2,2,0,-cvGetReal2D(e2,2,0));
|
||||
}
|
||||
|
||||
// Replace F by R2 * F * R1'
|
||||
cvSetZero(R1);
|
||||
cvSetReal2D(R1,0,0,cvGetReal2D(e1,0,0));
|
||||
cvSetReal2D(R1,0,1,cvGetReal2D(e1,1,0));
|
||||
cvSetReal2D(R1,1,0,-cvGetReal2D(e1,1,0));
|
||||
cvSetReal2D(R1,1,1,cvGetReal2D(e1,0,0));
|
||||
cvSetReal2D(R1,2,2,1);
|
||||
cvSetZero(R2);
|
||||
cvSetReal2D(R2,0,0,cvGetReal2D(e2,0,0));
|
||||
cvSetReal2D(R2,0,1,cvGetReal2D(e2,1,0));
|
||||
cvSetReal2D(R2,1,0,-cvGetReal2D(e2,1,0));
|
||||
cvSetReal2D(R2,1,1,cvGetReal2D(e2,0,0));
|
||||
cvSetReal2D(R2,2,2,1);
|
||||
cvGEMM(R2,TFT,1,0,0,tmp33);
|
||||
cvGEMM(tmp33,R1,1,0,0,RTFTR,CV_GEMM_B_T);
|
||||
|
||||
// Set f1 = e1(3), f2 = e2(3), a = F22, b = F23, c = F32, d = F33
|
||||
f1 = cvGetReal2D(e1,2,0);
|
||||
f2 = cvGetReal2D(e2,2,0);
|
||||
a = cvGetReal2D(RTFTR,1,1);
|
||||
b = cvGetReal2D(RTFTR,1,2);
|
||||
c = cvGetReal2D(RTFTR,2,1);
|
||||
d = cvGetReal2D(RTFTR,2,2);
|
||||
|
||||
// Form the polynomial g(t) = k6*t⁶ + k5*t⁵ + k4*t⁴ + k3*t³ + k2*t² + k1*t + k0
|
||||
// from f1, f2, a, b, c and d
|
||||
cvSetReal2D(polynomial,0,6,( +b*c*c*f1*f1*f1*f1*a-a*a*d*f1*f1*f1*f1*c ));
|
||||
cvSetReal2D(polynomial,0,5,( +f2*f2*f2*f2*c*c*c*c+2*a*a*f2*f2*c*c-a*a*d*d*f1*f1*f1*f1+b*b*c*c*f1*f1*f1*f1+a*a*a*a ));
|
||||
cvSetReal2D(polynomial,0,4,( +4*a*a*a*b+2*b*c*c*f1*f1*a+4*f2*f2*f2*f2*c*c*c*d+4*a*b*f2*f2*c*c+4*a*a*f2*f2*c*d-2*a*a*d*f1*f1*c-a*d*d*f1*f1*f1*f1*b+b*b*c*f1*f1*f1*f1*d ));
|
||||
cvSetReal2D(polynomial,0,3,( +6*a*a*b*b+6*f2*f2*f2*f2*c*c*d*d+2*b*b*f2*f2*c*c+2*a*a*f2*f2*d*d-2*a*a*d*d*f1*f1+2*b*b*c*c*f1*f1+8*a*b*f2*f2*c*d ));
|
||||
cvSetReal2D(polynomial,0,2,( +4*a*b*b*b+4*b*b*f2*f2*c*d+4*f2*f2*f2*f2*c*d*d*d-a*a*d*c+b*c*c*a+4*a*b*f2*f2*d*d-2*a*d*d*f1*f1*b+2*b*b*c*f1*f1*d ));
|
||||
cvSetReal2D(polynomial,0,1,( +f2*f2*f2*f2*d*d*d*d+b*b*b*b+2*b*b*f2*f2*d*d-a*a*d*d+b*b*c*c ));
|
||||
cvSetReal2D(polynomial,0,0,( -a*d*d*b+b*b*c*d ));
|
||||
|
||||
// Solve g(t) for t to get 6 roots
|
||||
cvSetZero(result);
|
||||
cvSolvePoly(polynomial, result, 100, 20);
|
||||
|
||||
// Evaluate the cost function s(t) at the real part of the 6 roots
|
||||
t_min = DBL_MAX;
|
||||
s_val = 1./(f1*f1) + (c*c)/(a*a+f2*f2*c*c);
|
||||
for (int ti = 0; ti < 6; ++ti) {
|
||||
t = result->data.db[2*ti];
|
||||
s = (t*t)/(1 + f1*f1*t*t) + ((c*t + d)*(c*t + d))/((a*t + b)*(a*t + b) + f2*f2*(c*t + d)*(c*t + d));
|
||||
if (s < s_val) {
|
||||
s_val = s;
|
||||
t_min = t;
|
||||
}
|
||||
}
|
||||
|
||||
// find the optimal x1 and y1 as the points on l1 and l2 closest to the origin
|
||||
tmp31->data.db[0] = t_min*t_min*f1;
|
||||
tmp31->data.db[1] = t_min;
|
||||
tmp31->data.db[2] = t_min*t_min*f1*f1+1;
|
||||
tmp31->data.db[0] /= tmp31->data.db[2];
|
||||
tmp31->data.db[1] /= tmp31->data.db[2];
|
||||
tmp31->data.db[2] /= tmp31->data.db[2];
|
||||
cvGEMM(T1i,R1,1,0,0,tmp33,CV_GEMM_B_T);
|
||||
cvGEMM(tmp33,tmp31,1,0,0,tmp31_2);
|
||||
x1 = tmp31_2->data.db[0];
|
||||
y1 = tmp31_2->data.db[1];
|
||||
|
||||
tmp31->data.db[0] = f2*pow(c*t_min+d,2);
|
||||
tmp31->data.db[1] = -(a*t_min+b)*(c*t_min+d);
|
||||
tmp31->data.db[2] = f2*f2*pow(c*t_min+d,2) + pow(a*t_min+b,2);
|
||||
tmp31->data.db[0] /= tmp31->data.db[2];
|
||||
tmp31->data.db[1] /= tmp31->data.db[2];
|
||||
tmp31->data.db[2] /= tmp31->data.db[2];
|
||||
cvGEMM(T2i,R2,1,0,0,tmp33,CV_GEMM_B_T);
|
||||
cvGEMM(tmp33,tmp31,1,0,0,tmp31_2);
|
||||
x2 = tmp31_2->data.db[0];
|
||||
y2 = tmp31_2->data.db[1];
|
||||
|
||||
// Return the points in the matrix format that the user wants
|
||||
points1->data.db[p*2] = x1;
|
||||
points1->data.db[p*2+1] = y1;
|
||||
points2->data.db[p*2] = x2;
|
||||
points2->data.db[p*2+1] = y2;
|
||||
}
|
||||
|
||||
if( new_points1 )
|
||||
cvConvert( points1, new_points1 );
|
||||
if( new_points2 )
|
||||
cvConvert( points2, new_points2 );
|
||||
}
|
||||
410
modules/calib3d/src/undistort.cpp
Normal file
410
modules/calib3d/src/undistort.cpp
Normal file
@@ -0,0 +1,410 @@
|
||||
/*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"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
Mat getDefaultNewCameraMatrix( const Mat& cameraMatrix, Size imgsize,
|
||||
bool centerPrincipalPoint )
|
||||
{
|
||||
if( !centerPrincipalPoint && cameraMatrix.type() == CV_64F )
|
||||
return cameraMatrix;
|
||||
|
||||
Mat newCameraMatrix;
|
||||
cameraMatrix.convertTo(newCameraMatrix, CV_64F);
|
||||
if( centerPrincipalPoint )
|
||||
{
|
||||
((double*)newCameraMatrix.data)[2] = (imgsize.width-1)*0.5;
|
||||
((double*)newCameraMatrix.data)[5] = (imgsize.height-1)*0.5;
|
||||
}
|
||||
return newCameraMatrix;
|
||||
}
|
||||
|
||||
void initUndistortRectifyMap( const Mat& _cameraMatrix, const Mat& _distCoeffs,
|
||||
const Mat& matR, const Mat& _newCameraMatrix,
|
||||
Size size, int m1type, Mat& map1, Mat& map2 )
|
||||
{
|
||||
if( m1type <= 0 )
|
||||
m1type = CV_16SC2;
|
||||
CV_Assert( m1type == CV_16SC2 || m1type == CV_32FC1 || m1type == CV_32FC2 );
|
||||
map1.create( size, m1type );
|
||||
if( m1type != CV_32FC2 )
|
||||
map2.create( size, m1type == CV_16SC2 ? CV_16UC1 : CV_32FC1 );
|
||||
else
|
||||
map2.release();
|
||||
|
||||
Mat_<double> R = Mat_<double>::eye(3, 3), distCoeffs;
|
||||
Mat_<double> A = Mat_<double>(_cameraMatrix), Ar;
|
||||
|
||||
if( _newCameraMatrix.data )
|
||||
Ar = Mat_<double>(_newCameraMatrix);
|
||||
else
|
||||
Ar = getDefaultNewCameraMatrix( A, size, true );
|
||||
|
||||
if( matR.data )
|
||||
R = Mat_<double>(matR);
|
||||
|
||||
if( _distCoeffs.data )
|
||||
distCoeffs = Mat_<double>(_distCoeffs);
|
||||
else
|
||||
{
|
||||
distCoeffs.create(5, 1);
|
||||
distCoeffs = 0.;
|
||||
}
|
||||
|
||||
CV_Assert( A.size() == Size(3,3) && A.size() == R.size() );
|
||||
CV_Assert( Ar.size() == Size(3,3) || Ar.size() == Size(4, 3));
|
||||
Mat_<double> iR = (Ar.colRange(0,3)*R).inv(DECOMP_LU);
|
||||
const double* ir = &iR(0,0);
|
||||
|
||||
double u0 = A(0, 2), v0 = A(1, 2);
|
||||
double fx = A(0, 0), fy = A(1, 1);
|
||||
|
||||
CV_Assert( distCoeffs.size() == Size(1, 4) || distCoeffs.size() == Size(1, 5) ||
|
||||
distCoeffs.size() == Size(4, 1) || distCoeffs.size() == Size(5, 1));
|
||||
|
||||
if( distCoeffs.rows != 1 && !distCoeffs.isContinuous() )
|
||||
distCoeffs = distCoeffs.t();
|
||||
|
||||
double k1 = ((double*)distCoeffs.data)[0];
|
||||
double k2 = ((double*)distCoeffs.data)[1];
|
||||
double p1 = ((double*)distCoeffs.data)[2];
|
||||
double p2 = ((double*)distCoeffs.data)[3];
|
||||
double k3 = distCoeffs.cols + distCoeffs.rows - 1 == 5 ? ((double*)distCoeffs.data)[4] : 0.;
|
||||
|
||||
for( int i = 0; i < size.height; i++ )
|
||||
{
|
||||
float* m1f = (float*)(map1.data + map1.step*i);
|
||||
float* m2f = (float*)(map2.data + map2.step*i);
|
||||
short* m1 = (short*)m1f;
|
||||
ushort* m2 = (ushort*)m2f;
|
||||
double _x = i*ir[1] + ir[2], _y = i*ir[4] + ir[5], _w = i*ir[7] + ir[8];
|
||||
|
||||
for( int j = 0; j < size.width; j++, _x += ir[0], _y += ir[3], _w += ir[6] )
|
||||
{
|
||||
double w = 1./_w, x = _x*w, y = _y*w;
|
||||
double x2 = x*x, y2 = y*y;
|
||||
double r2 = x2 + y2, _2xy = 2*x*y;
|
||||
double kr = 1 + ((k3*r2 + k2)*r2 + k1)*r2;
|
||||
double u = fx*(x*kr + p1*_2xy + p2*(r2 + 2*x2)) + u0;
|
||||
double v = fy*(y*kr + p1*(r2 + 2*y2) + p2*_2xy) + v0;
|
||||
if( m1type == CV_16SC2 )
|
||||
{
|
||||
int iu = saturate_cast<int>(u*INTER_TAB_SIZE);
|
||||
int iv = saturate_cast<int>(v*INTER_TAB_SIZE);
|
||||
m1[j*2] = (short)(iu >> INTER_BITS);
|
||||
m1[j*2+1] = (short)(iv >> INTER_BITS);
|
||||
m2[j] = (ushort)((iv & (INTER_TAB_SIZE-1))*INTER_TAB_SIZE + (iu & (INTER_TAB_SIZE-1)));
|
||||
}
|
||||
else if( m1type == CV_32FC1 )
|
||||
{
|
||||
m1f[j] = (float)u;
|
||||
m2f[j] = (float)v;
|
||||
}
|
||||
else
|
||||
{
|
||||
m1f[j*2] = (float)u;
|
||||
m1f[j*2+1] = (float)v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void undistort( const Mat& src, Mat& dst, const Mat& _cameraMatrix,
|
||||
const Mat& _distCoeffs, const Mat& _newCameraMatrix )
|
||||
{
|
||||
dst.create( src.size(), src.type() );
|
||||
CV_Assert( dst.data != src.data );
|
||||
|
||||
int stripe_size0 = std::min(std::max(1, (1 << 12) / std::max(src.cols, 1)), src.rows);
|
||||
Mat map1(stripe_size0, src.cols, CV_16SC2), map2(stripe_size0, src.cols, CV_16UC1);
|
||||
|
||||
Mat_<double> A, distCoeffs, Ar, I = Mat_<double>::eye(3,3);
|
||||
|
||||
_cameraMatrix.convertTo(A, CV_64F);
|
||||
if( _distCoeffs.data )
|
||||
distCoeffs = Mat_<double>(_distCoeffs);
|
||||
else
|
||||
{
|
||||
distCoeffs.create(5, 1);
|
||||
distCoeffs = 0.;
|
||||
}
|
||||
|
||||
if( _newCameraMatrix.data )
|
||||
_newCameraMatrix.convertTo(Ar, CV_64F);
|
||||
else
|
||||
A.copyTo(Ar);
|
||||
|
||||
double v0 = Ar(1, 2);
|
||||
for( int y = 0; y < src.rows; y += stripe_size0 )
|
||||
{
|
||||
int stripe_size = std::min( stripe_size0, src.rows - y );
|
||||
Ar(1, 2) = v0 - y;
|
||||
Mat map1_part = map1.rowRange(0, stripe_size),
|
||||
map2_part = map2.rowRange(0, stripe_size),
|
||||
dst_part = dst.rowRange(y, y + stripe_size);
|
||||
|
||||
initUndistortRectifyMap( A, distCoeffs, I, Ar, Size(src.cols, stripe_size),
|
||||
map1_part.type(), map1_part, map2_part );
|
||||
remap( src, dst_part, map1_part, map2_part, INTER_LINEAR, BORDER_CONSTANT );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
void cvUndistortPoints( const CvMat* _src, CvMat* _dst, const CvMat* _cameraMatrix,
|
||||
const CvMat* _distCoeffs,
|
||||
const CvMat* matR, const CvMat* matP )
|
||||
{
|
||||
double A[3][3], RR[3][3], k[5]={0,0,0,0,0}, fx, fy, ifx, ify, cx, cy;
|
||||
CvMat matA=cvMat(3, 3, CV_64F, A), _Dk;
|
||||
CvMat _RR=cvMat(3, 3, CV_64F, RR);
|
||||
const CvPoint2D32f* srcf;
|
||||
const CvPoint2D64f* srcd;
|
||||
CvPoint2D32f* dstf;
|
||||
CvPoint2D64f* dstd;
|
||||
int stype, dtype;
|
||||
int sstep, dstep;
|
||||
int i, j, n, iters = 1;
|
||||
|
||||
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( CV_IS_MAT(_cameraMatrix) &&
|
||||
_cameraMatrix->rows == 3 && _cameraMatrix->cols == 3 );
|
||||
|
||||
cvConvert( _cameraMatrix, &matA );
|
||||
|
||||
if( _distCoeffs )
|
||||
{
|
||||
CV_Assert( CV_IS_MAT(_distCoeffs) &&
|
||||
(_distCoeffs->rows == 1 || _distCoeffs->cols == 1) &&
|
||||
(_distCoeffs->rows*_distCoeffs->cols == 4 ||
|
||||
_distCoeffs->rows*_distCoeffs->cols == 5) );
|
||||
|
||||
_Dk = cvMat( _distCoeffs->rows, _distCoeffs->cols,
|
||||
CV_MAKETYPE(CV_64F,CV_MAT_CN(_distCoeffs->type)), k);
|
||||
|
||||
cvConvert( _distCoeffs, &_Dk );
|
||||
iters = 5;
|
||||
}
|
||||
|
||||
if( matR )
|
||||
{
|
||||
CV_Assert( CV_IS_MAT(matR) && matR->rows == 3 && matR->cols == 3 );
|
||||
cvConvert( matR, &_RR );
|
||||
}
|
||||
else
|
||||
cvSetIdentity(&_RR);
|
||||
|
||||
if( matP )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
srcf = (const CvPoint2D32f*)_src->data.ptr;
|
||||
srcd = (const CvPoint2D64f*)_src->data.ptr;
|
||||
dstf = (CvPoint2D32f*)_dst->data.ptr;
|
||||
dstd = (CvPoint2D64f*)_dst->data.ptr;
|
||||
stype = CV_MAT_TYPE(_src->type);
|
||||
dtype = CV_MAT_TYPE(_dst->type);
|
||||
sstep = _src->rows == 1 ? 1 : _src->step/CV_ELEM_SIZE(stype);
|
||||
dstep = _dst->rows == 1 ? 1 : _dst->step/CV_ELEM_SIZE(dtype);
|
||||
|
||||
n = _src->rows + _src->cols - 1;
|
||||
|
||||
fx = A[0][0];
|
||||
fy = A[1][1];
|
||||
ifx = 1./fx;
|
||||
ify = 1./fy;
|
||||
cx = A[0][2];
|
||||
cy = A[1][2];
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
double x, y, x0, y0;
|
||||
if( stype == CV_32FC2 )
|
||||
{
|
||||
x = srcf[i*sstep].x;
|
||||
y = srcf[i*sstep].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = srcd[i*sstep].x;
|
||||
y = srcd[i*sstep].y;
|
||||
}
|
||||
|
||||
x0 = x = (x - cx)*ifx;
|
||||
y0 = y = (y - cy)*ify;
|
||||
|
||||
// compensate distortion iteratively
|
||||
for( j = 0; j < iters; j++ )
|
||||
{
|
||||
double r2 = x*x + y*y;
|
||||
double icdist = 1./(1 + ((k[4]*r2 + k[1])*r2 + k[0])*r2);
|
||||
double deltaX = 2*k[2]*x*y + k[3]*(r2 + 2*x*x);
|
||||
double deltaY = k[2]*(r2 + 2*y*y) + 2*k[3]*x*y;
|
||||
x = (x0 - deltaX)*icdist;
|
||||
y = (y0 - deltaY)*icdist;
|
||||
}
|
||||
|
||||
double xx = RR[0][0]*x + RR[0][1]*y + RR[0][2];
|
||||
double yy = RR[1][0]*x + RR[1][1]*y + RR[1][2];
|
||||
double ww = 1./(RR[2][0]*x + RR[2][1]*y + RR[2][2]);
|
||||
x = xx*ww;
|
||||
y = yy*ww;
|
||||
|
||||
if( dtype == CV_32FC2 )
|
||||
{
|
||||
dstf[i*dstep].x = (float)x;
|
||||
dstf[i*dstep].y = (float)y;
|
||||
}
|
||||
else
|
||||
{
|
||||
dstd[i*dstep].x = x;
|
||||
dstd[i*dstep].y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cv::undistortPoints( const Mat& src, Mat& dst,
|
||||
const Mat& cameraMatrix, const Mat& distCoeffs,
|
||||
const Mat& R, const Mat& P )
|
||||
{
|
||||
CV_Assert( src.isContinuous() && src.depth() == CV_32F &&
|
||||
((src.rows == 1 && src.channels() == 2) || src.cols*src.channels() == 2));
|
||||
|
||||
dst.create(src.size(), src.type());
|
||||
CvMat _src = src, _dst = dst, _cameraMatrix = cameraMatrix;
|
||||
CvMat matR, matP, _distCoeffs, *pR=0, *pP=0, *pD=0;
|
||||
if( R.data )
|
||||
pR = &(matR = R);
|
||||
if( P.data )
|
||||
pP = &(matP = P);
|
||||
if( distCoeffs.data )
|
||||
pD = &(_distCoeffs = distCoeffs);
|
||||
cvUndistortPoints(&_src, &_dst, &_cameraMatrix, pD, pR, pP);
|
||||
}
|
||||
|
||||
void cv::undistortPoints( const Mat& src, std::vector<Point2f>& dst,
|
||||
const Mat& cameraMatrix, const Mat& distCoeffs,
|
||||
const Mat& R, const Mat& P )
|
||||
{
|
||||
size_t sz = src.cols*src.rows*src.channels()/2;
|
||||
CV_Assert( src.isContinuous() && src.depth() == CV_32F &&
|
||||
((src.rows == 1 && src.channels() == 2) || src.cols*src.channels() == 2));
|
||||
|
||||
dst.resize(sz);
|
||||
CvMat _src = src, _dst = Mat(dst), _cameraMatrix = cameraMatrix;
|
||||
CvMat matR, matP, _distCoeffs, *pR=0, *pP=0, *pD=0;
|
||||
if( R.data )
|
||||
pR = &(matR = R);
|
||||
if( P.data )
|
||||
pP = &(matP = P);
|
||||
if( distCoeffs.data )
|
||||
pD = &(_distCoeffs = distCoeffs);
|
||||
cvUndistortPoints(&_src, &_dst, &_cameraMatrix, pD, pR, pP);
|
||||
}
|
||||
|
||||
/* End of file */
|
||||
Reference in New Issue
Block a user