projection.cpp 5.41 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
/*
 * 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"

// Eigen
#include <Eigen/Core>

// OpenCV
#include <opencv2/core/eigen.hpp>
#include <opencv2/sfm/numeric.hpp>
#include <opencv2/sfm/projection.hpp>

// libmv headers
#include "libmv/multiview/projection.h"

#include <iostream>

namespace cv
{
namespace sfm
{

template<typename T>
void
58
homogeneousToEuclidean(const Mat & X_, Mat & x_)
59
{
60
  int d = X_.rows - 1;
61

62 63
  const Mat_<T> & X_rows = X_.rowRange(0,d);
  const Mat_<T> h = X_.row(d);
64 65 66

  const T * h_ptr = h[0], *h_ptr_end = h_ptr + h.cols;
  const T * X_ptr = X_rows[0];
67
  T * x_ptr = x_.ptr<T>(0);
68 69 70
  for (; h_ptr != h_ptr_end; ++h_ptr, ++X_ptr, ++x_ptr)
  {
    const T * X_col_ptr = X_ptr;
71 72
    T * x_col_ptr = x_ptr, *x_col_ptr_end = x_col_ptr + d * x_.step1();
    for (; x_col_ptr != x_col_ptr_end; X_col_ptr+=X_rows.step1(), x_col_ptr+=x_.step1() )
73 74 75 76 77
      *x_col_ptr = (*X_col_ptr) / (*h_ptr);
  }
}

void
78
homogeneousToEuclidean(InputArray X_, OutputArray x_)
79 80
{
  // src
81
  const Mat X = X_.getMat();
82 83

  // dst
84 85
   x_.create(X.rows-1, X.cols, X.type());
  Mat x = x_.getMat();
86 87 88 89 90 91 92 93 94 95 96 97 98

  // type
  if( X.depth() == CV_32F )
  {
    homogeneousToEuclidean<float>(X,x);
  }
  else
  {
    homogeneousToEuclidean<double>(X,x);
  }
}

void
99
euclideanToHomogeneous(InputArray x_, OutputArray X_)
100
{
101
  const Mat x = x_.getMat();
102
  const Mat last_row = Mat::ones(1, x.cols, x.type());
103
  vconcat(x, last_row, X_);
104 105 106 107 108 109 110 111 112 113
}

template<typename T>
void
projectionFromKRt(const Mat_<T> &K, const Mat_<T> &R, const Mat_<T> &t, Mat_<T> P)
{
  hconcat( K*R, K*t, P );
}

void
114
projectionFromKRt(InputArray K_, InputArray R_, InputArray t_, OutputArray P_)
115
{
116
  const Mat K = K_.getMat(), R = R_.getMat(), t = t_.getMat();
117 118 119 120
  const int depth = K.depth();
  CV_Assert((K.cols == 3 && K.rows == 3) && (t.cols == 1 && t.rows == 3) && (K.size() == R.size()));
  CV_Assert((depth == CV_32F || depth == CV_64F) && depth == R.depth() && depth == t.depth());

121
  P_.create(3, 4, depth);
122

123
  Mat P = P_.getMat();
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

  // type
  if( depth == CV_32F )
  {
    projectionFromKRt<float>(K, R, t, P);
  }
  else
  {
    projectionFromKRt<double>(K, R, t, P);
  }

}

template<typename T>
void
139
KRtFromProjection( const Mat_<T> &P_, Mat_<T> K_, Mat_<T> R_, Mat_<T> t_ )
140 141 142 143 144
{
  libmv::Mat34 P;
  libmv::Mat3 K, R;
  libmv::Vec3 t;

145
  cv2eigen( P_, P );
146 147 148

  libmv::KRt_From_P( P, &K, &R, &t );

149 150 151
  eigen2cv( K, K_ );
  eigen2cv( R, R_ );
  eigen2cv( t, t_ );
152 153 154
}

void
155
KRtFromProjection( InputArray P_, OutputArray K_, OutputArray R_, OutputArray t_ )
156
{
157
  const Mat P = P_.getMat();
158 159 160
  const int depth = P.depth();
  CV_Assert((P.cols == 4 && P.rows == 3) && (depth == CV_32F || depth == CV_64F));

161 162 163
  K_.create(3, 3, depth);
  R_.create(3, 3, depth);
  t_.create(3, 1, depth);
164

165
  Mat K = K_.getMat(), R = R_.getMat(), t = t_.getMat();
166 167 168 169 170 171 172 173 174 175 176 177 178 179

  // type
  if( depth == CV_32F )
  {
    KRtFromProjection<float>(P, K, R, t);
  }
  else
  {
    KRtFromProjection<double>(P, K, R, t);
  }
}

template<typename T>
T
180
depthValue( const Mat_<T> &R_, const Mat_<T> &t_, const Mat_<T> &X_ )
181
{
182 183
  Matx<T,3,3> R(R_);
  Vec<T,3> t(t_);
184

185
  if ( X_.rows == 3)
186
  {
187
    Vec<T,3> X(X_);
188 189 190 191
    return (R*X)(2) + t(2);
  }
  else
  {
192
    Vec<T,4> X(X_);
193 194 195 196 197 198 199
    Vec<T,3> Xe;
    homogeneousToEuclidean(X,Xe);
    return depthValue<T>( Mat(R), Mat(t), Mat(Xe) );
  }
}

double
200
depth( InputArray R_, InputArray t_, InputArray X_)
201
{
202
  const Mat R = R_.getMat(), t = t_.getMat(), X = X_.getMat();
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
  const int depth = R.depth();
  CV_Assert( R.rows == 3 && R.cols == 3 && t.rows == 3 && t.cols == 1 );
  CV_Assert( (X.rows == 3 && X.cols == 1) || (X.rows == 4 && X.cols == 1) );
  CV_Assert( depth == CV_32F || depth == CV_64F );

  double depth_value = 0.0;

  if ( depth == CV_32F )
  {
    depth_value = static_cast<double>(depthValue<float>(R, t, X));
  }
  else
  {
    depth_value = depthValue<double>(R, t, X);
  }

  return depth_value;
}

} /* namespace sfm */
} /* namespace cv */