[Bf-blender-cvs] [e183da7] soc-2016-multiview: add intersect and resect

Tianwei Shen noreply at git.blender.org
Thu Jun 23 09:01:55 CEST 2016


Commit: e183da7db99a93cfd28cff3967ec5218e3a310f8
Author: Tianwei Shen
Date:   Thu Jun 23 15:01:41 2016 +0800
Branches: soc-2016-multiview
https://developer.blender.org/rBe183da7db99a93cfd28cff3967ec5218e3a310f8

add intersect and resect

===================================================================

M	intern/libmv/CMakeLists.txt
M	intern/libmv/intern/reconstructionN.cc
M	intern/libmv/libmv/autotrack/bundle.cc
M	intern/libmv/libmv/autotrack/bundle.h
A	intern/libmv/libmv/autotrack/intersect.cc
A	intern/libmv/libmv/autotrack/intersect.h
A	intern/libmv/libmv/autotrack/pipeline.cc
A	intern/libmv/libmv/autotrack/pipeline.h
M	intern/libmv/libmv/autotrack/reconstruction.h
A	intern/libmv/libmv/autotrack/resect.cc
A	intern/libmv/libmv/autotrack/resect.h

===================================================================

diff --git a/intern/libmv/CMakeLists.txt b/intern/libmv/CMakeLists.txt
index d88f0f4..f1cc270 100644
--- a/intern/libmv/CMakeLists.txt
+++ b/intern/libmv/CMakeLists.txt
@@ -76,8 +76,11 @@ if(WITH_LIBMV)
 		intern/tracksN.cc
 		libmv/autotrack/autotrack.cc
 		libmv/autotrack/bundle.cc
+		libmv/autotrack/intersect.cc
+		libmv/autotrack/pipeline.cc
 		libmv/autotrack/predict_tracks.cc
 		libmv/autotrack/reconstruction.cc
+		libmv/autotrack/resect.cc
 		libmv/autotrack/tracks.cc
 		libmv/base/aligned_malloc.cc
 		libmv/image/array_nd.cc
@@ -130,12 +133,15 @@ if(WITH_LIBMV)
 		libmv/autotrack/bundle.h
 		libmv/autotrack/callbacks.h
 		libmv/autotrack/frame_accessor.h
+		libmv/autotrack/intersect.h
 		libmv/autotrack/marker.h
 		libmv/autotrack/model.h
+		libmv/autotrack/pipeline.h
 		libmv/autotrack/predict_tracks.h
 		libmv/autotrack/quad.h
 		libmv/autotrack/reconstruction.h
 		libmv/autotrack/region.h
+		libmv/autotrack/resect.h
 		libmv/autotrack/tracks.h
 		libmv/base/aligned_malloc.h
 		libmv/base/id_generator.h
diff --git a/intern/libmv/intern/reconstructionN.cc b/intern/libmv/intern/reconstructionN.cc
index 8f1cfe0..3f59b3e 100644
--- a/intern/libmv/intern/reconstructionN.cc
+++ b/intern/libmv/intern/reconstructionN.cc
@@ -35,6 +35,7 @@
 #include "libmv/autotrack/frame_accessor.h"
 #include "libmv/autotrack/marker.h"
 #include "libmv/autotrack/model.h"
+#include "libmv/autotrack/pipeline.h"
 #include "libmv/autotrack/predict_tracks.h"
 #include "libmv/autotrack/quad.h"
 #include "libmv/autotrack/reconstruction.h"
@@ -184,21 +185,19 @@ libmv_ReconstructionN** libmv_solveMultiviewReconstruction(
 	update_callback.invoke(0, "Initial reconstruction");
 
 	// reconstruct two views from the main clip
-	if(!mv::ReconstructTwoFrames(keyframe_markers, 0, *(all_libmv_reconstruction[0]->intrinsics), &reconstruction))
-	{
+	if(!mv::ReconstructTwoFrames(keyframe_markers, 0, *(all_libmv_reconstruction[0]->intrinsics), &reconstruction)) {
 		printf("mv::ReconstrucTwoFrames failed\n");
 		all_libmv_reconstruction[0]->is_valid = false;
 		return all_libmv_reconstruction;
 	}
 	// bundle the two-view initial reconstruction
-	if(!mv::EuclideanBundleAll(all_normalized_tracks, &reconstruction))
-	{
+	// (it is redundant for now since now 3d point is added at this stage)
+	if(!mv::EuclideanBundleAll(all_normalized_tracks, &reconstruction)) {
 		printf("mv::EuclideanBundleAll failed\n");
 		all_libmv_reconstruction[0]->is_valid = false;
 		return all_libmv_reconstruction;
 	}
-	if(!mv::EuclideanReconstructionComplete(all_normalized_tracks, &reconstruction, &update_callback))
-	{
+	if(!mv::EuclideanCompleteMultiviewReconstruction(all_normalized_tracks, &reconstruction, &update_callback)) {
 		printf("mv::EuclideanReconstructionComplete failed\n");
 		all_libmv_reconstruction[0]->is_valid = false;
 		return all_libmv_reconstruction;
diff --git a/intern/libmv/libmv/autotrack/bundle.cc b/intern/libmv/libmv/autotrack/bundle.cc
index 257f06d..1113e7b 100644
--- a/intern/libmv/libmv/autotrack/bundle.cc
+++ b/intern/libmv/libmv/autotrack/bundle.cc
@@ -682,10 +682,4 @@ bool EuclideanBundleAll(const Tracks &tracks,
 	return true;
 }
 
-bool EuclideanReconstructionComplete(const Tracks &tracks,
-                                     Reconstruction *reconstruction,
-                                     libmv::ProgressUpdateCallback *update_callback) {
-	return true;
-}
-
 }  // namespace mv
diff --git a/intern/libmv/libmv/autotrack/bundle.h b/intern/libmv/libmv/autotrack/bundle.h
index 4755bea..c367802 100644
--- a/intern/libmv/libmv/autotrack/bundle.h
+++ b/intern/libmv/libmv/autotrack/bundle.h
@@ -23,8 +23,8 @@
 // This is a autotrack equivalent bundle set, adapted from simple_pipeline,
 // which replaces libmv with mv, includeing tracks and markers
 
-#ifndef LIBMV_SIMPLE_PIPELINE_BUNDLE_H
-#define LIBMV_SIMPLE_PIPELINE_BUNDLE_H
+#ifndef LIBMV_AUTOTRACK_BUNDLE_H
+#define LIBMV_AUTOTRACK_BUNDLE_H
 
 #include "libmv/numeric/numeric.h"
 #include "libmv/autotrack/tracks.h"
@@ -132,10 +132,6 @@ void EuclideanBundleCommonIntrinsics(
 bool EuclideanBundleAll(const Tracks &tracks,
                         Reconstruction *reconstruction);
 
-bool EuclideanReconstructionComplete(const Tracks &tracks,
-                                     Reconstruction *reconstruction,
-                                     libmv::ProgressUpdateCallback *update_callback);
 }  // namespace mv
 
-#endif   // LIBMV_SIMPLE_PIPELINE_BUNDLE_H
-
+#endif   // LIBMV_AUTOTRACK_BUNDLE_H
diff --git a/intern/libmv/libmv/autotrack/intersect.cc b/intern/libmv/libmv/autotrack/intersect.cc
new file mode 100644
index 0000000..59f0820
--- /dev/null
+++ b/intern/libmv/libmv/autotrack/intersect.cc
@@ -0,0 +1,262 @@
+// Copyright (c) 2016 libmv authors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//
+// Author: Tianwei Shen <shentianweipku at gmail.com>
+
+#include "libmv/autotrack/intersect.h"
+
+#include "libmv/base/vector.h"
+#include "libmv/logging/logging.h"
+#include "libmv/multiview/projection.h"
+#include "libmv/multiview/triangulation.h"
+#include "libmv/multiview/nviewtriangulation.h"
+#include "libmv/numeric/numeric.h"
+#include "libmv/numeric/levenberg_marquardt.h"
+#include "libmv/autotrack/reconstruction.h"
+#include "libmv/autotrack/tracks.h"
+
+#include "ceres/ceres.h"
+
+using libmv::Mat;
+using libmv::Mat34;
+using libmv::Mat2X;
+using libmv::Vec4;
+
+namespace mv {
+
+namespace {
+
+class EuclideanIntersectCostFunctor {
+ public:
+  EuclideanIntersectCostFunctor(const Marker &marker,
+                                const CameraPose &camera)
+      : marker_(marker), camera_(camera) {}
+
+  template<typename T>
+  bool operator()(const T *X, T *residuals) const {
+    typedef Eigen::Matrix<T, 3, 3> Mat3;
+    typedef Eigen::Matrix<T, 3, 1> Vec3;
+
+    Vec3 x(X);
+    Mat3 R(camera_.R.cast<T>());
+    Vec3 t(camera_.t.cast<T>());
+
+    Vec3 projected = R * x + t;
+    projected /= projected(2);
+
+    residuals[0] = (T(projected(0)) - T(marker_.center[0])) * T(marker_.weight);
+    residuals[1] = (T(projected(1)) - T(marker_.center[1])) * T(marker_.weight);
+
+    return true;
+  }
+
+  const Marker &marker_;
+  const CameraPose &camera_;
+};
+
+}  // namespace
+
+bool EuclideanIntersect(const vector<Marker> &markers,
+                        Reconstruction *reconstruction) {
+  if (markers.size() < 2) {
+    return false;
+  }
+
+  // Compute projective camera matrices for the cameras the intersection is
+  // going to use.
+  Mat3 K = Mat3::Identity();
+  vector<Mat34> cameras;
+  Mat34 P;
+  for (int i = 0; i < markers.size(); ++i) {
+    CameraPose *camera = reconstruction->CameraPoseForFrame(markers[i].clip, markers[i].frame);
+    libmv::P_From_KRt(K, camera->R, camera->t, &P);
+    cameras.push_back(P);
+  }
+
+  // Stack the 2D coordinates together as required by NViewTriangulate.
+  Mat2X points(2, markers.size());
+  for (int i = 0; i < markers.size(); ++i) {
+    points(0, i) = markers[i].center[0];
+    points(1, i) = markers[i].center[1];
+  }
+
+  Vec4 Xp;
+  LG << "Intersecting with " << markers.size() << " markers.";
+  libmv::NViewTriangulateAlgebraic(points, cameras, &Xp);
+
+  // Get euclidean version of the homogeneous point.
+  Xp /= Xp(3);
+  Vec3 X = Xp.head<3>();
+
+  ceres::Problem problem;
+
+  // Add residual blocks to the problem.
+  int num_residuals = 0;
+  for (int i = 0; i < markers.size(); ++i) {
+    const Marker &marker = markers[i];
+    if (marker.weight != 0.0) {
+      const CameraPose &camera =
+          *reconstruction->CameraPoseForFrame(marker.clip, marker.frame);
+
+      problem.AddResidualBlock(
+          new ceres::AutoDiffCostFunction<
+              EuclideanIntersectCostFunctor,
+              2, /* num_residuals */
+              3>(new EuclideanIntersectCostFunctor(marker, camera)),
+          NULL,
+          &X(0));
+	  num_residuals++;
+    }
+  }
+
+  // TODO(sergey): Once we'll update Ceres to the next version
+  // we wouldn't need this check anymore -- Ceres will deal with
+  // zero-sized problems nicely.
+  LG << "Number of residuals: " << num_residuals;
+  if (!num_residuals) {
+    LG << "Skipping running minimizer with zero residuals";
+
+	// We still add 3D point for the track regardless it was
+	// optimized or not. If track is a constant zero it'll use
+	// algebraic intersection result as a 3D coordinate.
+
+    Vec3 point = X.head<3>();
+	Point mv_point(markers[0].track, point);
+	reconstruction->AddPoint(mv_point);
+
+    return true;
+  }
+
+  // Configure the solve.
+  ceres::Solver::Options solver_options;
+  solver_options.linear_solver_type = ceres::DENSE_QR;
+  solver_options.max_num_iterations = 50;
+  solver_options.update_state_every_iteration = true;
+  solver_options.parameter_tolerance = 1e-16;
+  solver_options.function_tolerance = 1e-16;
+
+  // Run the solve.
+  ceres::Solver::Summary summary;
+  ceres::Solve(solver_options, &problem, &summary);
+
+  VLOG(1) << "Summary:\n" << summary.FullReport();
+
+  // Try projecting the point; make sure it's in front of everyone.
+  for (int i = 0; i < cameras.size(); ++i) {
+    const CameraPose &camera =
+        *reconstruction->CameraPoseForFrame(ma

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list