This page is meant to coordinate our community efforts to implement full support for 3D Reconstruction in OpenCV.

Roadmap

Checklist

  1. (./) Camera Calibration

  2. Triangulation

    • The simple linear method exists already in cvaux/src/cvtrifocal.cpp: icvReconstructPointsFor3View. The method can be easily adapted to two views. Someone interested in implementing the optimal algorithm 12.1 in Multiple View Geometry (2.ed) ?

Todo

Some preliminary notes

There are a lot of functions for 3D reconstuction in the cvaux folder that are not available yet but seem to work or need some small changes. For example a function for computing the projection matrices for three views and N points. From the camera matrices it is possible the define a trifocal tensor. This function uses a bundle adjustement method and functions for calculating camera matrices from point correspondences and homogeneous 4D points from camera matrices and 2D points. All this functions are not declared extern so you can not use them. To make this work you have to put the definitions in the cvaux.h. So for the mentioned function this would be:

/* Computes projection matrices for 6 points */
CVAPI(int) icvComputeProjectMatrices6Points(CvMat *points1, CvMat *points2, CvMat *points3, CvMat *projMatr1, CvMat *projMatr2, CvMat *projMatr3);

/* Computes projection matrices for N points */
/*
@param  (input)         CvMat *points1          3xN matrix for image 1
@param  (input)         CvMat *points2          3xN matrix for image 2
@param  (input)         CvMat *points3          3xN matrix for image 3
@param  (output)        CvMat *projMatr1        3x4 matrix for image 1
@param  (output)        CvMat *projMatr2        3x4 matrix for image 2
@param  (output)        CvMat *projMatr3        3x4 matrix for image 3
@param  (input)         double threshold        threshold for good point
@param  (input)         double probability      probability of good result
@param  (output)        CvMat *status           1xN matrix status of points (good or bad)
@param  (output)        CvMat *points4D         4xN matrix of reconstructed points
@result: 0 => did not find projection matrices, 1 => found projection matrices
*/
CVAPI(int) icvComputeProjectMatricesNPoints(CvMat *points1, CvMat *points2, CvMat *points3, CvMat *projMatr1, CvMat *projMatr2, CvMat *projMatr3, double threshold, double p, CvMat *status, CvMat *points4D);

Unfortunately there is a bug (I (StefanHafeneger) think they changed some code after they wrote this functions). To fix this you have to change three lines in cvtrifocal.cpp:

line 1571: change double result_dat[2*3]; to double result_dat[3];
line 1573: change result = cvMat(2,3,CV_64F,result_dat); to result = cvMat(1,3,CV_64F,result_dat);
line 1589: change if( fabs(cvmGet(&result,1,i)) < 1e-8 ) to if( 1 == 1 )

There seem to be a lot of functions described in Multiple View Geometry in Computer Graphic by Hartley and Zisserman. So I think the work would be to debug the functions and them add the declaration in the cvaux.h.

Bugs

I (StefanHafeneger) now tried to use icvComputeProjectMatricesNPoints() for a set of tracked points. There seems to be a bug in the Bundle Adjustment. I get an assert() in cvSolveCubic(). I haven't had time yet to figure out what's going wrong there. So if someone wants to help please let me know.

Results

After applying code changes mentioned above by Stefan:
The results of icvComputeProjectMatricesNPoints() in trifocal.cpp are correct for the following synthetic test:
The test used only translation and no rotation between cameras. With this configuration the plane at infinity is determined in an easy way and hence upgrading to a metric reconstruction is possible. (Note: The first camera returned is not the canonical one. So one has to transform the cameras to apply results of the auto-calibration chapter in Multiple View Geometry.) The metric reconstruction gave little numerical error after similarity alignment to the original 3D points.
Note: There was no noise included within this test.
Further tests should include rotation between cameras and analysis of the error depending on noise.

what is in openCV

I (SebastianHoefle) start here with documentation of functions in cvcorrimages. Note, that this is primarily a documentation and I have not tested the correctness of the functions (although they look quite fine). The box at the end indicates the status of the method. So, work has to be done ...

cvaux/src/cvcorrimages.cpp

This file contains functions which track points over images and compute projection matrices for these tracked points. icvAddNewImageToPrevious adds an new image to an initial projective reconstruction and returns the projection matrix for the new image. The initial projective reconstruction can be retrieved e.g. from icvComputeProjectMatricesNPoints (in cvtrifocal.cpp) from N > 6 correspondend points in three images. (Note: In principal you could get a projective reconstruction also from two images.)

CreateFeaturePoints

This method calls cvGoodFeaturesToTrack to detect feature points.

int icvCreateFeaturePoints(IplImage *image, CvMat *points, CvMat *status)
image

source image

points

found feature points (type must be CV_32F or CV_64F). The desired number of features to be found is points->col.

status

mask array for feature points (must have same number of cols than points). If the number of found features is less than points->col found, than status is zero for these points [number of foundFeatures+1, points->col]

working

FindCorrForGivenPoints

Finds correspondend feature points with optical flow.

int icvFindCorrForGivenPoints( IplImage *image1,/* Image 1 */
                                IplImage *image2,/* Image 2 */
                                CvMat *points1, 
                                CvMat *pntStatus1,
                                CvMat *points2,
                                CvMat *pntStatus2,
                                int useFilter,/*Use fundamental matrix to filter points */
                                double threshold);

For given points1 (with pntStatus) on image1 finds corresponding points2 on image2 and set pntStatus2 for them. The method uses optical flow ( cvCalcOpticalFlowPyrLK ) and optionally the fundamental matrix to filter the found points. The output status2 (mask mat (single channel, 8 bit)) specifies found/not found points.

Returns number of corresponding points.

working

GrowPointsAndStatus

Add to existing points and status arrays new points or just grow.

int icvGrowPointsAndStatus(CvMat **oldPoints,CvMat **oldStatus,CvMat *addPoints,CvMat *addStatus,int addCreateNum);

All points of addPoints will be added to oldPoints, in such a way that oldPoints dereferenced will point to the new allocated joined CvMat. The same for the status points. Optionally one could create more elements with argument addCreateNum (without copying, so addPoints and addStatus can be 0).

not tested

RemoveDoublePoins

Removes points which are near.

int icvRemoveDoublePoins(   CvMat *oldPoints,/* Points on prev image */
                            CvMat *newPoints,/* New points */
                            CvMat *oldStatus,/* Status for old points */
                            CvMat *newStatus,
                            CvMat *origStatus,
                            float threshold);

Removes Points which are near ( |p - q| < threshold ) or more precisely sets origStatus to zero for the case that an old point is near to a new point. The method uses delaunay division to find nearest points between oldPoints and newPoints.

not tested

ComputeProjectMatrixStatus

Wrapper to call icvComputeProjectMatrix of cvtrifocal.cpp with the points with good status.

void icvComputeProjectMatrixStatus(CvMat *objPoints4D,CvMat *points2,CvMat *status, CvMat *projMatr)
icvComputeProjectMatrix works,  and as this method copies just points with good status, this should also work.

AddNewImageToPrevious

The method adds finds new points and a projection matrix for a new image using already reconstructed 4D points.

void icvAddNewImageToPrevious____(
                                    IplImage *newImage,//Image to add
                                    IplImage *oldImage,//Previous image
                                    CvMat *oldPoints,// previous 2D points on prev image (some points may be not visible)
                                    CvMat *oldPntStatus,//Status for each point on prev image
                                    CvMat *objPoints4D,//prev 4D points
                                    CvMat *newPoints,  //Points on new image corr for prev
                                    CvMat *newPntStatus,// New point status for new image
                                    CvMat *newFPoints2D1,//new feature points on prev image
                                    CvMat *newFPoints2D2,//new feature points on new image
                                    CvMat *newFPointsStatus,
                                    CvMat *newProjMatr,
                                    int useFilter,
                                    double threshold)
 

This method puts things together:

not tested

DeleteSparsInPoints

Delete Points which could not be tracked.

int icvDeleteSparsInPoints(  int numImages,
                             CvMat **points,
                             CvMat **status,
                             CvMat *wasStatus)

This method deletes feature points, if in no image pair the correspondence could be found, i.e. the points was never found (status == 0 in all images). All points with a status of 1 in any of the images are copied to the front of the matrix and the status is set to one. The status of the remaining elements at the end is set to zero.

not tested

Outcommented methods

These outcommented functions seem to be earlier versions of the functions above described.

New Methods

These are some new methods to support 3D reconstruction.

cv/src/cvgeometry.cpp

Compute RQ Decomposition of 3x3 matrices

/* Computes RQ decomposition for 3x3 matrices */
/*
@param  (input)         CvMat *matrixM                  3x3 matrix M
@param  (output)        CvMat *matrixR                  3x3 upper-triangular matrix R
@param  (output)        CvMat *matrixQ                  3x3 orthogonal matrix Q
@param  (output)        CvMat *matrixQx                 3x3 rotation matrix Qx (optional)
@param  (output)        CvMat *matrixQy                 3x3 rotation matrix Qy (optional)
@param  (output)        CvMat *matrixQz                 3x3 rotation matrix Qz (optional)
@param  (output)        CvPoint3D64f *eulerAngles       Euler angles of rotation (optional)
*/
void cvRQDecomp3x3(const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ, CvMat *matrixQx = NULL, CvMat *matrixQy = NULL, CvMat *matrixQz = NULL), CvPoint3D64f *eulerAngles CV_DEFAULT(NULL));

This function computes a RQ decomposition using Givens rotations. This function is used to decompose the left 3x3 submatrix of a projection matrix into a calibration and a rotation matrix. It optionally returns three rotation matrices, one for each axis, and the three Euler angles (for OpenGL etc.).

working

Compute projection matrix decomposition

/* Computes projection matrix decomposition */
/*
@param  (input)         CvMat *projMatr                 3x4 projection matrix
@param  (output)        CvMat *calibMatr                3x3 internal calibration matrix
@param  (output)        CvMat *rotMatr                  3x3 external rotation matrix
@param  (output)        CvMat *posVect                  4x1 external position vector
@param  (output)        CvMat *rotMatrX                 3x3 x-axis rotation matrix (optional)
@param  (output)        CvMat *rotMatrY                 3x3 y-axis rotation matrix (optional)
@param  (output)        CvMat *rotMatrZ                 3x3 z-axis rotation matrix (optional)
@param  (output)        CvPoint3D64f *eulerAngles       Euler angles of rotation (optional)
*/
void cvDecomposeProjectionMatrix(const CvMat *projMatr, CvMat *calibMatr, CvMat *rotMatr, CvMat *posVect, CvMat *rotMatrX = NULL, CvMat *rotMatrY = NULL, CvMat *rotMatrZ = NULL, CvPoint3D64f *eulerAngles = NULL);

This function computes a decomposition of a projection matrix into a calibration and a rotation matrix and the position of the camera. It optionally returns three rotation matrices, one for each axis, and the three Euler angles (for OpenGL etc.).

working, implementation of infinite cameras could be added

EffortFor3dReconstruction (last edited 2008-04-10 18:51:19 by StefanHafeneger)

SourceForge.net Logo