Repository for OpenCV's extra modules
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

324 lines
9.7 KiB

/*
* Software License Agreement (BSD License)
*
* Copyright (c) 2009, Willow Garage, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions 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.
* * Neither the name of Willow Garage, Inc. nor the names of its
* contributors may 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
* COPYRIGHT OWNER 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.
*
*/
#include "precomp.hpp"
#if CERES_FOUND
// Eigen
#include <Eigen/Core>
#include <opencv2/core/eigen.hpp>
#include <opencv2/xfeatures2d.hpp>
#include "libmv_capi.h"
using namespace std;
namespace cv
{
namespace sfm
{
/* Parses a given array of 2d points into the libmv tracks structure
*/
static void
parser_2D_tracks( const std::vector<Mat> &points2d, libmv::Tracks &tracks )
{
const int nframes = static_cast<int>(points2d.size());
for (int frame = 0; frame < nframes; ++frame) {
const int ntracks = points2d[frame].cols;
for (int track = 0; track < ntracks; ++track) {
const Vec2d track_pt = points2d[frame].col(track);
if ( track_pt[0] > 0 && track_pt[1] > 0 )
tracks.Insert(frame, track, track_pt[0], track_pt[1]);
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
/* Parses a given set of matches into the libmv tracks structure
*/
static void
parser_2D_tracks( const libmv::Matches &matches, libmv::Tracks &tracks )
{
std::set<Matches::ImageID>::const_iterator iter_image =
matches.get_images().begin();
bool is_first_time = true;
for (; iter_image != matches.get_images().end(); ++iter_image) {
// Exports points
Matches::Features<PointFeature> pfeatures =
matches.InImage<PointFeature>(*iter_image);
while(pfeatures) {
double x = pfeatures.feature()->x(),
y = pfeatures.feature()->y();
// valid marker
if ( x > 0 && y > 0 )
{
tracks.Insert(*iter_image, pfeatures.track(), x, y);
if ( is_first_time )
is_first_time = false;
}
// lost track
else if ( x < 0 && y < 0 )
{
is_first_time = true;
}
pfeatures.operator++();
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
/* Computes the 2d features matches between a given set of images and call the
* reconstruction pipeline.
*/
static libmv_Reconstruction *libmv_solveReconstructionImpl(
const std::vector<String> &images,
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
libmv_ReconstructionOptions* libmv_reconstruction_options)
{
Ptr<Feature2D> edetector = ORB::create(10000);
Ptr<Feature2D> edescriber = xfeatures2d::DAISY::create();
//Ptr<Feature2D> edescriber = xfeatures2d::LATCH::create(64, true, 4);
std::vector<std::string> sImages;
for (int i=0;i<images.size();i++)
sImages.push_back(images[i].c_str());
cout << "Initialize nViewMatcher ... ";
libmv::correspondence::nRobustViewMatching nViewMatcher(edetector, edescriber);
cout << "OK" << endl << "Performing Cross Matching ... ";
nViewMatcher.computeCrossMatch(sImages); cout << "OK" << endl;
// Building tracks
libmv::Tracks tracks;
libmv::Matches matches = nViewMatcher.getMatches();
parser_2D_tracks( matches, tracks );
// Perform reconstruction
return libmv_solveReconstruction(tracks,
libmv_camera_intrinsics_options,
libmv_reconstruction_options);
}
///////////////////////////////////////////////////////////////////////////////////////////////
template <class T>
class SFMLibmvReconstructionImpl : public T
{
public:
SFMLibmvReconstructionImpl(const libmv_CameraIntrinsicsOptions &camera_instrinsic_options,
const libmv_ReconstructionOptions &reconstruction_options) :
libmv_reconstruction_options_(reconstruction_options),
libmv_camera_intrinsics_options_(camera_instrinsic_options) {}
/* Run the pipeline given 2d points
*/
virtual void run(InputArrayOfArrays _points2d)
{
std::vector<Mat> points2d;
_points2d.getMatVector(points2d);
CV_Assert( _points2d.total() >= 2 );
// Parse 2d points to Tracks
Tracks tracks;
parser_2D_tracks(points2d, tracks);
// Set libmv logs level
libmv_initLogging("");
if (libmv_reconstruction_options_.verbosity_level >= 0)
{
libmv_startDebugLogging();
libmv_setLoggingVerbosity(
libmv_reconstruction_options_.verbosity_level);
}
// Perform reconstruction
libmv_reconstruction_ =
*libmv_solveReconstruction(tracks,
&libmv_camera_intrinsics_options_,
&libmv_reconstruction_options_);
}
virtual void run(InputArrayOfArrays points2d, InputOutputArray K, OutputArray Rs,
OutputArray Ts, OutputArray points3d)
{
// Run the pipeline
run(points2d);
// Extract Data
extractLibmvReconstructionData(K, Rs, Ts, points3d);
}
/* Run the pipeline given a set of images
*/
virtual void run(const std::vector <String> &images)
{
// Set libmv logs level
libmv_initLogging("");
if (libmv_reconstruction_options_.verbosity_level >= 0)
{
libmv_startDebugLogging();
libmv_setLoggingVerbosity(
libmv_reconstruction_options_.verbosity_level);
}
// Perform reconstruction
libmv_reconstruction_ =
*libmv_solveReconstructionImpl(images,
&libmv_camera_intrinsics_options_,
&libmv_reconstruction_options_);
}
virtual void run(const std::vector <String> &images, InputOutputArray K, OutputArray Rs,
OutputArray Ts, OutputArray points3d)
{
// Run the pipeline
run(images);
// Extract Data
extractLibmvReconstructionData(K, Rs, Ts, points3d);
}
virtual double getError() const { return libmv_reconstruction_.error; }
virtual void
getPoints(OutputArray points3d) {
const size_t n_points =
libmv_reconstruction_.reconstruction.AllPoints().size();
points3d.create(n_points, 1, CV_64F);
Vec3d point3d;
for ( size_t i = 0; i < n_points; ++i )
{
for ( int j = 0; j < 3; ++j )
point3d[j] =
libmv_reconstruction_.reconstruction.AllPoints()[i].X[j];
Mat(point3d).copyTo(points3d.getMatRef(i));
}
}
virtual cv::Mat getIntrinsics() const {
Mat K;
eigen2cv(libmv_reconstruction_.intrinsics->K(), K);
return K;
}
virtual void
getCameras(OutputArray Rs, OutputArray Ts) {
const size_t n_views =
libmv_reconstruction_.reconstruction.AllCameras().size();
Rs.create(n_views, 1, CV_64F);
Ts.create(n_views, 1, CV_64F);
Matx33d R;
Vec3d t;
for(size_t i = 0; i < n_views; ++i)
{
eigen2cv(libmv_reconstruction_.reconstruction.AllCameras()[i].R, R);
eigen2cv(libmv_reconstruction_.reconstruction.AllCameras()[i].t, t);
Mat(R).copyTo(Rs.getMatRef(i));
Mat(t).copyTo(Ts.getMatRef(i));
}
}
virtual void setReconstructionOptions(
const libmv_ReconstructionOptions &libmv_reconstruction_options) {
libmv_reconstruction_options_ = libmv_reconstruction_options;
}
virtual void setCameraIntrinsicOptions(
const libmv_CameraIntrinsicsOptions &libmv_camera_intrinsics_options) {
libmv_camera_intrinsics_options_ = libmv_camera_intrinsics_options;
}
private:
void
extractLibmvReconstructionData(InputOutputArray K,
OutputArray Rs,
OutputArray Ts,
OutputArray points3d)
{
getCameras(Rs, Ts);
getPoints(points3d);
getIntrinsics().copyTo(K.getMat());
}
libmv_Reconstruction libmv_reconstruction_;
libmv_ReconstructionOptions libmv_reconstruction_options_;
libmv_CameraIntrinsicsOptions libmv_camera_intrinsics_options_;
};
///////////////////////////////////////////////////////////////////////////////////////////////
Ptr<SFMLibmvEuclideanReconstruction>
SFMLibmvEuclideanReconstruction::create(const libmv_CameraIntrinsicsOptions &camera_instrinsic_options,
const libmv_ReconstructionOptions &reconstruction_options)
{
return makePtr<SFMLibmvReconstructionImpl<SFMLibmvEuclideanReconstruction> >(camera_instrinsic_options,reconstruction_options);
}
///////////////////////////////////////////////////////////////////////////////////////////////
} /* namespace cv */
} /* namespace sfm */
#endif
/* End of file. */