00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "HMatrix2DAffineCompute.h"
00009
00010 #include <vcl_vector.h>
00011 #include <vcl_cassert.h>
00012 #include <vnl/vnl_matrix.h>
00013 #include <mvl/HMatrix2D.h>
00014 #include <mvl/HomgPoint2D.h>
00015 #include <vnl/vnl_matops.h>
00016 #include <vnl/vnl_double_2.h>
00017 #include <vnl/vnl_double_2x2.h>
00018 #include <vnl/vnl_double_3x3.h>
00019 #include <vnl/algo/vnl_svd.h>
00020 #include <vnl/vnl_inverse.h>
00021
00022 #include <mvl/PairMatchSetCorner.h>
00023
00024
00025
00026 static bool tmp_fun(vcl_vector<vgl_homg_point_2d<double> > const& pts1,
00027 vcl_vector<vgl_homg_point_2d<double> > const& pts2,
00028 HMatrix2D& H)
00029 {
00030
00031
00032
00033
00034 assert(pts1.size() == pts2.size());
00035
00036 NonHomg p1(pts1);
00037 NonHomg p2(pts2);
00038 vnl_double_2 mn1 = mean2(p1);
00039 vnl_double_2 mn2 = mean2(p2);
00040 sub_rows(p1,mn1);
00041 sub_rows(p2,mn2);
00042
00043 #if 0
00044 vnl_matrix<double> joint = vnl_matops().cat(p1,p2);
00045 #else
00046 vnl_matrix<double> joint(pts1.size(),2+2);
00047 joint.update(p1,0,0);
00048 joint.update(p2,0,2);
00049 #endif
00050
00051 vnl_svd<double> svd(joint);
00052
00053 vnl_double_2x2 N = (svd.V().extract(2,2,0,2)).transpose();
00054 vnl_double_2x2 M = (svd.V().extract(2,2,2,2)).transpose();
00055
00056 vnl_double_2x2 Aff = - vnl_inverse(M) * N;
00057 vnl_double_2 t = mn2 - Aff*mn1;
00058
00059 vnl_double_3x3 T;
00060 T.set_identity();
00061 T.update(Aff.as_ref());
00062 T(0,2) = t[0];
00063 T(1,2) = t[1];
00064 H.set(T);
00065 return true;
00066 }
00067
00068 static bool tmp_fun(vcl_vector<HomgPoint2D> const& pts1,
00069 vcl_vector<HomgPoint2D> const& pts2,
00070 HMatrix2D& H)
00071 {
00072
00073
00074
00075
00076 assert(pts1.size() == pts2.size());
00077
00078 NonHomg p1(pts1);
00079 NonHomg p2(pts2);
00080 vnl_double_2 mn1 = mean2(p1);
00081 vnl_double_2 mn2 = mean2(p2);
00082 sub_rows(p1,mn1);
00083 sub_rows(p2,mn2);
00084
00085 #if 0
00086 vnl_matrix<double> joint = vnl_matops().cat(p1,p2);
00087 #else
00088 vnl_matrix<double> joint(pts1.size(),2+2);
00089 joint.update(p1,0,0);
00090 joint.update(p2,0,2);
00091 #endif
00092
00093 vnl_svd<double> svd(joint);
00094
00095 vnl_double_2x2 N = (svd.V().extract(2,2,0,2)).transpose();
00096 vnl_double_2x2 M = (svd.V().extract(2,2,2,2)).transpose();
00097
00098 vnl_double_2x2 Aff = - vnl_inverse(M) * N;
00099 vnl_double_2 t = mn2 - Aff*mn1;
00100
00101 vnl_double_3x3 T;
00102 T.set_identity();
00103 T.update(Aff.as_ref());
00104 T(0,2) = t[0];
00105 T(1,2) = t[1];
00106 H.set(T);
00107 return true;
00108 }
00109
00110 HMatrix2D
00111 HMatrix2DAffineCompute::compute(const PairMatchSetCorner &matches)
00112 {
00113 vcl_vector<HomgPoint2D> pts1(matches.count());
00114 vcl_vector<HomgPoint2D> pts2(matches.count());
00115 matches.extract_matches(pts1, pts2);
00116 HMatrix2D H;
00117 tmp_fun(pts1,pts2,H);
00118 return H;
00119 }
00120
00121 HMatrix2D
00122 HMatrix2DAffineCompute::compute(const vcl_vector<vgl_homg_point_2d<double> >&p1,
00123 const vcl_vector<vgl_homg_point_2d<double> >&p2)
00124 {
00125 HMatrix2D H;
00126 tmp_fun(p1,p2,H);
00127 return H;
00128 }
00129
00130 HMatrix2D
00131 HMatrix2DAffineCompute::compute(const vcl_vector<HomgPoint2D>&p1,
00132 const vcl_vector<HomgPoint2D>&p2)
00133 {
00134 HMatrix2D H;
00135 tmp_fun(p1,p2,H);
00136 return H;
00137 }
00138
00139 bool
00140 HMatrix2DAffineCompute::compute_p(const vcl_vector<HomgPoint2D> &pts1,
00141 const vcl_vector<HomgPoint2D> &pts2,
00142 HMatrix2D *H)
00143 {
00144 return tmp_fun(pts1,pts2,*H);
00145 }
00146
00147
00148
00149 NonHomg::NonHomg(vcl_vector<vgl_homg_point_2d<double> > const& A)
00150 : vnl_matrix<double>(A.size(),2)
00151 {
00152 vnl_matrix<double> &X = *this;
00153 int n = rows();
00154 for (int i=0; i<n; ++i)
00155 X(i,0) = A[i].x()/A[i].w(),
00156 X(i,1) = A[i].y()/A[i].w();
00157 }
00158
00159 NonHomg::NonHomg(const vcl_vector<HomgPoint2D> &A)
00160 : vnl_matrix<double>(A.size(),2)
00161 {
00162 vnl_matrix<double> &X = *this;
00163 int n = rows();
00164 for (int i=0; i<n; ++i)
00165 A[i].get_nonhomogeneous(X(i,0),X(i,1));
00166 }
00167
00168 vnl_double_2 mean2(const vnl_matrix<double> &A)
00169 {
00170 assert(A.columns() == 2);
00171 vnl_double_2 mean(0,0);
00172 int n = A.rows();
00173 for (int j=0; j<2; ++j) {
00174 for (int k=0; k<n; ++k)
00175 mean[j] += A(k,j);
00176 }
00177 mean *= (1.0/n);
00178 return mean;
00179 }
00180
00181 vnl_matrix<double>& sub_rows(vnl_matrix<double> &A, const vnl_double_2 a)
00182 {
00183 unsigned c = A.columns();
00184 unsigned r = A.rows();
00185 assert(c == a.size());
00186 for (unsigned j=0; j < c; ++j)
00187 for (unsigned i=0; i < r; ++i)
00188 A(i,j) -= a[j];
00189
00190 return A;
00191 }