00001
00002 #ifndef vpgl_camera_convert_cxx_
00003 #define vpgl_camera_convert_cxx_
00004
00005 #include "vpgl_camera_convert.h"
00006
00007
00008 #include <vcl_iostream.h>
00009 #include <vcl_cassert.h>
00010 #include <vcl_cstdlib.h>
00011 #include <vcl_cmath.h>
00012 #include <vnl/vnl_numeric_traits.h>
00013 #include <vnl/vnl_det.h>
00014 #include <vnl/vnl_vector_fixed.h>
00015 #include <vnl/vnl_matrix_fixed.h>
00016 #include <vnl/algo/vnl_svd.h>
00017 #include <vnl/algo/vnl_qr.h>
00018 #include <vgl/algo/vgl_rotation_3d.h>
00019 #include <vgl/algo/vgl_h_matrix_3d.h>
00020 #include <vgl/vgl_homg_point_3d.h>
00021 #include <vpgl/algo/vpgl_ortho_procrustes.h>
00022 #include <vpgl/algo/vpgl_optimize_camera.h>
00023 #include <vpgl/algo/vpgl_camera_compute.h>
00024 #include <vgl/vgl_point_2d.h>
00025 #include <vgl/vgl_point_3d.h>
00026 #include <vgl/vgl_box_3d.h>
00027 #include <vgl/vgl_homg_point_2d.h>
00028 #include <vgl/vgl_ray_3d.h>
00029 #include <vgl/vgl_plane_3d.h>
00030 #include <vbl/vbl_array_2d.h>
00031 #include <vpgl/vpgl_lvcs.h>
00032 #include <vpgl/algo/vpgl_backproject.h>
00033
00034
00035 static vcl_vector<double>
00036 pvector(const double x, const double y, const double z)
00037 {
00038
00039 vcl_vector<double> pv(20);
00040 pv[0]= x*x*x;
00041 pv[1]= x*x*y;
00042 pv[2]= x*x*z;
00043 pv[3]= x*x;
00044 pv[4]= x*y*y;
00045 pv[5]= x*y*z;
00046 pv[6]= x*y;
00047 pv[7]= x*z*z;
00048 pv[8]= x*z;
00049 pv[9]= x;
00050 pv[10]= y*y*y;
00051 pv[11]= y*y*z;
00052 pv[12]= y*y;
00053 pv[13]= y*z*z;
00054 pv[14]= y*z;
00055 pv[15]= y;
00056 pv[16]= z*z*z;
00057 pv[17]= z*z;
00058 pv[18]= z;
00059 pv[19]= 1;
00060 return pv;
00061 }
00062
00063 static vcl_vector<double>
00064 power_vector_dx(const double x, const double y, const double z)
00065 {
00066
00067 vcl_vector<double> pv(20, 0.0);
00068 pv[0]= 3*x*x;
00069 pv[1]= 2*x*y;
00070 pv[2]= 2*x*z;
00071 pv[3]= 2*x;
00072 pv[4]= y*y;
00073 pv[5]= y*z;
00074 pv[6]= y;
00075 pv[7]= z*z;
00076 pv[8]= z;
00077 pv[9]= 1;
00078 return pv;
00079 }
00080
00081 static vcl_vector<double>
00082 power_vector_dy(const double x, const double y, const double z)
00083 {
00084
00085 vcl_vector<double> pv(20, 0.0);
00086 pv[1]= x*x;
00087 pv[4]= 2*x*y;
00088 pv[5]= x*z;
00089 pv[6]= x;
00090 pv[10]= 3*y*y;
00091 pv[11]= 2*y*z;
00092 pv[12]= 2*y;
00093 pv[13]= z*z;
00094 pv[14]= z;
00095 pv[15]= 1;
00096 return pv;
00097 }
00098
00099 static vcl_vector<double>
00100 power_vector_dz(const double x, const double y, const double z)
00101 {
00102
00103 vcl_vector<double> pv(20, 0.0);
00104 pv[2]= x*x;
00105 pv[5]= x*y;
00106 pv[7]= 2*x*z;
00107 pv[8]= x;
00108 pv[11]= y*y;
00109 pv[13]= 2*y*z;
00110 pv[14]= y;
00111 pv[16]= 3*z*z;
00112 pv[17]= 2*z;
00113 pv[18]= 1;
00114 return pv;
00115 }
00116
00117
00118 static double pval(vcl_vector<double> const& pv, vcl_vector<double>const& coef)
00119 {
00120 double sum = 0.0;
00121 for (unsigned i = 0; i<20; ++i)
00122 sum += pv[i]*coef[i];
00123 return sum;
00124 }
00125
00126
00127
00128 bool vpgl_proj_camera_convert::
00129 convert( vpgl_rational_camera<double> const& rat_cam,
00130 vgl_point_3d<double> const& world_center,
00131 vpgl_proj_camera<double>& camera)
00132 {
00133 double x0 = world_center.x(), y0 = world_center.y(), z0 = world_center.z();
00134
00135 double nx0 =
00136 rat_cam.scl_off(vpgl_rational_camera<double>::X_INDX).normalize(x0);
00137 double ny0 =
00138 rat_cam.scl_off(vpgl_rational_camera<double>::Y_INDX).normalize(y0);
00139 double nz0 =
00140 rat_cam.scl_off(vpgl_rational_camera<double>::Z_INDX).normalize(z0);
00141
00142
00143 vcl_vector<vcl_vector<double> > coeffs = rat_cam.coefficients();
00144 vcl_vector<double> neu_u = coeffs[0];
00145 vcl_vector<double> den_u = coeffs[1];
00146 vcl_vector<double> neu_v = coeffs[2];
00147 vcl_vector<double> den_v = coeffs[3];
00148
00149
00150 double nmax_u = -vnl_numeric_traits<double>::maxval;
00151 double dmax_u = nmax_u, nmax_v = nmax_u,dmax_v = nmax_u;
00152 for (unsigned i = 0; i<20; ++i)
00153 {
00154 if (vcl_fabs(neu_u[i])>nmax_u)
00155 nmax_u=vcl_fabs(neu_u[i]);
00156 if (vcl_fabs(den_u[i])>dmax_u)
00157 dmax_u=vcl_fabs(den_u[i]);
00158 if (vcl_fabs(neu_v[i])>nmax_v)
00159 nmax_v=vcl_fabs(neu_v[i]);
00160 if (vcl_fabs(den_v[i])>dmax_v)
00161 dmax_v=vcl_fabs(den_v[i]);
00162 }
00163
00164 double norm_u = nmax_u, norm_v = nmax_v;
00165 if (norm_u<dmax_u) norm_u = dmax_u;
00166 if (norm_v<dmax_v) norm_v = dmax_v;
00167 for (unsigned i = 0; i<20; ++i)
00168 {
00169 neu_u[i] /= norm_u; den_u[i] /= norm_u;
00170 neu_v[i] /= norm_v; den_v[i] /= norm_v;
00171 }
00172
00173
00174
00175 vcl_vector<double> pv0 = pvector(nx0,ny0,nz0);
00176 double neu_u_0 = pval(pv0,neu_u), den_u_0 = pval(pv0,den_u);
00177 double neu_v_0 = pval(pv0,neu_v), den_v_0 = pval(pv0,den_v);
00178 vcl_vector<double> pv_dx0 = power_vector_dx(nx0,ny0,nz0);
00179 double neu_u_dx0 = pval(pv_dx0,neu_u), den_u_dx0 = pval(pv_dx0,den_u);
00180 double neu_v_dx0 = pval(pv_dx0,neu_v), den_v_dx0 = pval(pv_dx0,den_v);
00181 vcl_vector<double> pv_dy0 = power_vector_dy(nx0,ny0,nz0);
00182 double neu_u_dy0 = pval(pv_dy0,neu_u), den_u_dy0 = pval(pv_dy0,den_u);
00183 double neu_v_dy0 = pval(pv_dy0,neu_v), den_v_dy0 = pval(pv_dy0,den_v);
00184 vcl_vector<double> pv_dz0 = power_vector_dz(nx0,ny0,nz0);
00185 double neu_u_dz0 = pval(pv_dz0,neu_u), den_u_dz0 = pval(pv_dz0,den_u);
00186 double neu_v_dz0 = pval(pv_dz0,neu_v), den_v_dz0 = pval(pv_dz0,den_v);
00187
00188
00189 vnl_matrix<double> C(4,4);
00190 C[0][0]=neu_u_dx0; C[0][1]=neu_u_dy0; C[0][2]=neu_u_dz0; C[0][3]=neu_u_0;
00191 C[1][0]=den_u_dx0; C[1][1]=den_u_dy0; C[1][2]=den_u_dz0; C[1][3]=den_u_0;
00192 C[2][0]=neu_v_dx0; C[2][1]=neu_v_dy0; C[2][2]=neu_v_dz0; C[2][3]=neu_v_0;
00193 C[3][0]=den_v_dx0; C[3][1]=den_v_dy0; C[3][2]=den_v_dz0; C[3][3]=den_v_0;
00194
00195 vnl_svd<double> svd(C);
00196 vnl_vector<double> nv = svd.nullvector();
00197
00198 nv/=nv[3];
00199 #if 1
00200 vcl_cout << "Center of projection\n" << nv << '\n'
00201 << "Residual\n" << C*nv << '\n';
00202 #endif
00203
00204 double ndu = vcl_sqrt(den_u_dx0*den_u_dx0 + den_u_dy0*den_u_dy0 +
00205 den_u_dz0*den_u_dz0);
00206 double ndv = vcl_sqrt(den_v_dx0*den_v_dx0 + den_v_dy0*den_v_dy0 +
00207 den_v_dz0*den_v_dz0);
00208
00209
00210 if (ndu/vcl_fabs(den_u_0)<1.0e-10||ndv/vcl_fabs(den_v_0)<1.0e-10)
00211 {
00212 vcl_cout << "Camera is nearly affine - approximation not implemented!\n";
00213 return false;
00214 }
00215
00216 vnl_matrix_fixed<double, 3, 3> M;
00217 for (unsigned i = 0; i<3; ++i)
00218 {
00219 M[0][i]=C[0][i]/ndu;
00220 M[1][i]=C[2][i]/ndv;
00221 M[2][i]=(C[1][i]/ndu + C[3][i]/ndv)/2;
00222 }
00223 #if 1
00224 vcl_cout << "M matrix\n" << M << '\n';
00225
00226 vnl_matrix_fixed<double,3,3> Mf;
00227 for ( int i = 0; i < 3; ++i )
00228 for ( int j = 0; j < 3; ++j )
00229 Mf(i,j) = M(2-j,2-i);
00230 vnl_qr<double> QR( Mf.as_ref() );
00231 vnl_matrix_fixed<double,3,3> q,r,Qf,Rf, uq,ur;
00232 q = QR.Q();
00233 r = QR.R();
00234 for ( int i = 0; i < 3; ++i ) {
00235 for ( int j = 0; j < 3; ++j ) {
00236 Qf(i,j) = q(2-j,2-i);
00237 Rf(i,j) = r(2-j,2-i);
00238 }
00239 }
00240 vcl_cout << "Flipped Rotation\n" << Qf << '\n'
00241 << "Flipped Upper Triangular\n" << Rf << '\n';
00242 vnl_qr<double> uqr(M.as_ref());
00243 uq = uqr.Q();
00244 ur = uqr.R();
00245 vcl_cout << "UnFlipped Rotation\n" << uq << '\n'
00246 << "UnFlipped Upper Triangular\n" << ur << '\n'
00247 << "Det uq " << vnl_det<double>(uq) << '\n';
00248
00249 vnl_vector<double> c1(3), c3(3);
00250 for (unsigned i = 0; i<3; ++i) {
00251 c1[i]=C[1][i]/ndu;
00252 c3[i]=C[3][i]/ndv;
00253 }
00254
00255 vcl_cout << "Denominators\n"
00256 << "C1 " << c1
00257 << "C3 " << c3;
00258 #endif
00259
00260 vnl_vector_fixed<double, 3> c;
00261 for (unsigned i = 0; i<3; ++i)
00262 c[i]=nv[i];
00263 vnl_vector_fixed<double, 3> p3 = -M*c;
00264
00265 vnl_matrix_fixed<double, 3, 4> pmatrix;
00266 for (unsigned r = 0; r<3; ++r)
00267 for (unsigned c = 0; c<3; ++c)
00268 pmatrix[r][c] = M[r][c];
00269 for (unsigned r = 0; r<3; ++r)
00270 pmatrix[r][3] = p3[r];
00271
00272 double uscale = rat_cam.scale(vpgl_rational_camera<double>::U_INDX);
00273 double uoff = rat_cam.offset(vpgl_rational_camera<double>::U_INDX);
00274 double vscale = rat_cam.scale(vpgl_rational_camera<double>::V_INDX);
00275 double voff = rat_cam.offset(vpgl_rational_camera<double>::V_INDX);
00276 vnl_matrix_fixed<double, 3, 3> Kr;
00277 Kr.fill(0.0);
00278 Kr[0][0]=uscale; Kr[0][2]=uoff;
00279 Kr[1][1]=vscale; Kr[1][2]=voff;
00280 Kr[2][2]=1.0;
00281 #if 1
00282 vcl_cout << "Kr\n" << Kr << '\n';
00283 vnl_matrix_fixed<double,3,3> KRf, KR=Kr*uq;
00284 for ( int i = 0; i < 3; ++i )
00285 for ( int j = 0; j < 3; ++j )
00286 KRf(i,j) = KR(2-j,2-i);
00287 vnl_qr<double> krQR( KRf.as_ref() );
00288 vnl_matrix_fixed<double,3,3> krq,krr,krQf,krRf;
00289 krq = krQR.Q();
00290 krr = krQR.R();
00291 for ( int i = 0; i < 3; ++i ) {
00292 for ( int j = 0; j < 3; ++j ) {
00293 krQf(i,j) = krq(2-j,2-i);
00294 krRf(i,j) = krr(2-j,2-i);
00295 }
00296 }
00297 vcl_cout << "Flipped Rotation (KR)\n" << krQf << '\n'
00298 << "Flipped Upper Triangular (KR)\n" << krRf << '\n';
00299
00300 int r0pos = krRf(0,0) > 0 ? 1 : -1;
00301 int r1pos = krRf(1,1) > 0 ? 1 : -1;
00302 int r2pos = krRf(2,2) > 0 ? 1 : -1;
00303 int diag[3] = { r0pos, r1pos, r2pos };
00304 vnl_matrix_fixed<double,3,3> K1,R1;
00305 for ( int i = 0; i < 3; ++i ) {
00306 for ( int j = 0; j < 3; ++j ) {
00307 K1(i,j) = diag[j]*krRf(i,j);
00308 R1(i,j) = diag[i]*krQf(i,j);
00309 }
00310 }
00311 K1 = K1/K1(2,2);
00312 vcl_cout << "K1\n" << K1 <<'\n'
00313 << "R1\n" << R1 << '\n'
00314 << "Det R1 " << vnl_det<double>(R1) << '\n';
00315 #endif
00316
00317
00318 vnl_matrix_fixed<double, 4, 4> T;
00319 T.fill(0.0);
00320 T[0][0]=1.0; T[1][1]=1.0; T[2][2]=1.0; T[3][3]=1.0;
00321 T[0][3] = -nx0; T[1][3]= -ny0; T[2][3]=-nz0;
00322 pmatrix = Kr*pmatrix*T;
00323 #if 0
00324 vcl_cout << "P Matrix\n" << pmatrix << '\n';
00325 #endif
00326 camera.set_matrix(pmatrix);
00327 return true;
00328 }
00329
00330
00331
00332
00333 vgl_h_matrix_3d<double>
00334 vpgl_proj_camera_convert::norm_trans(vpgl_rational_camera<double> const& rat_cam)
00335 {
00336 double xscale = rat_cam.scale(vpgl_rational_camera<double>::X_INDX);
00337 double xoff = rat_cam.offset(vpgl_rational_camera<double>::X_INDX);
00338 double yscale = rat_cam.scale(vpgl_rational_camera<double>::Y_INDX);
00339 double yoff = rat_cam.offset(vpgl_rational_camera<double>::Y_INDX);
00340 double zscale = rat_cam.scale(vpgl_rational_camera<double>::Z_INDX);
00341 double zoff = rat_cam.offset(vpgl_rational_camera<double>::Z_INDX);
00342 vgl_h_matrix_3d<double> T;
00343 T.set_identity();
00344 T.set(0,0,1/xscale); T.set(1,1,1/yscale); T.set(2,2,1/zscale);
00345 T.set(0,3, -xoff/xscale); T.set(1,3, -yoff/yscale);
00346 T.set(2,3, -zoff/zscale);
00347 return T;
00348 }
00349
00350
00351 bool vpgl_perspective_camera_convert::
00352 convert( vpgl_rational_camera<double> const& rat_cam,
00353 vgl_box_3d<double> const& approximation_volume,
00354 vpgl_perspective_camera<double>& camera,
00355 vgl_h_matrix_3d<double>& norm_trans)
00356 {
00357 vpgl_scale_offset<double> sou =
00358 rat_cam.scl_off(vpgl_rational_camera<double>::U_INDX);
00359 vpgl_scale_offset<double> sov =
00360 rat_cam.scl_off(vpgl_rational_camera<double>::V_INDX);
00361 vpgl_scale_offset<double> sox =
00362 rat_cam.scl_off(vpgl_rational_camera<double>::X_INDX);
00363 vpgl_scale_offset<double> soy =
00364 rat_cam.scl_off(vpgl_rational_camera<double>::Y_INDX);
00365 vpgl_scale_offset<double> soz =
00366 rat_cam.scl_off(vpgl_rational_camera<double>::Z_INDX);
00367 unsigned ni = static_cast<unsigned>(2*sou.scale());
00368 unsigned nj = static_cast<unsigned>(2*sov.scale());
00369 norm_trans.set_identity();
00370 norm_trans.set(0,0,1/sox.scale()); norm_trans.set(1,1,1/soy.scale());
00371 norm_trans.set(2,2,1/soz.scale());
00372 norm_trans.set(0,3, -sox.offset()/sox.scale());
00373 norm_trans.set(1,3, -soy.offset()/soy.scale());
00374 norm_trans.set(2,3, -soz.offset()/soz.scale());
00375
00376 vgl_point_3d<double> minp = approximation_volume.min_point();
00377 vgl_point_3d<double> maxp = approximation_volume.max_point();
00378 double xmin = minp.x(), ymin = minp.y(), zmin = minp.z();
00379 double xrange = maxp.x()-xmin, yrange = maxp.y()-ymin,
00380 zrange = maxp.z()-zmin;
00381 if (xrange<0||yrange<0||zrange<0)
00382 return false;
00383
00384 unsigned n = 100;
00385 vcl_vector<vgl_point_3d<double> > world_pts;
00386 unsigned count = 0, ntrials = 0;
00387 while (count<n)
00388 {
00389 ntrials++;
00390 double rx = xrange*(vcl_rand()/(RAND_MAX+1.0));
00391 double ry = yrange*(vcl_rand()/(RAND_MAX+1.0));
00392 double rz = zrange*(vcl_rand()/(RAND_MAX+1.0));
00393 vgl_point_3d<double> wp(xmin+rx, ymin+ry, zmin+rz);
00394 vgl_point_2d<double> ip = rat_cam.project(wp);
00395 if (ip.x()<0||ip.x()>ni||ip.y()<0||ip.y()>nj)
00396 continue;
00397 world_pts.push_back(wp);
00398 count++;
00399 }
00400 vcl_cout << "Ntrials " << ntrials << '\n';
00401
00402
00403 vcl_vector<vgl_point_3d<double> > norm_world_pts;
00404 vcl_vector<vgl_point_2d<double> > image_pts, norm_image_pts;
00405 unsigned N = world_pts.size();
00406 for (unsigned i = 0; i<N; ++i)
00407 {
00408 vgl_point_3d<double> wp = world_pts[i];
00409 vgl_point_2d<double> ip = rat_cam.project(wp);
00410 image_pts.push_back(ip);
00411 vgl_point_2d<double> nip(sou.normalize(ip.x()), sov.normalize(ip.y()));
00412 norm_image_pts.push_back(nip);
00413 vgl_point_3d<double> nwp(sox.normalize(wp.x()),
00414 soy.normalize(wp.y()),
00415 soz.normalize(wp.z()));
00416 norm_world_pts.push_back(nwp);
00417 }
00418
00419
00420 vnl_matrix_fixed<double, 3, 3> kk;
00421 kk.fill(0);
00422 kk[0][0]= 1.0;
00423 kk[1][1]= 1.0;
00424 kk[2][2]=1.0;
00425
00426
00427 vpgl_calibration_matrix<double> K(kk);
00428 if (! vpgl_perspective_camera_compute::compute(norm_image_pts,
00429 norm_world_pts,
00430 K, camera))
00431 return false;
00432 vcl_cout << camera << '\n';
00433
00434 vpgl_calibration_matrix<double> Kmin = camera.get_calibration();
00435 vnl_matrix_fixed<double, 3, 3> kk_min;
00436 kk_min = Kmin.get_matrix();
00437 kk[0][0]= sou.scale(); kk[0][2]= sou.offset();
00438 kk[1][1]= sov.scale(); kk[1][2]= sov.offset();
00439 kk *= kk_min;
00440 camera.set_calibration(kk);
00441
00442
00443 double err_max = 0, err_min = 1e10;
00444 vgl_point_3d<double> min_pt, max_pt;
00445 for (unsigned i = 0; i<N; ++i)
00446 {
00447 vgl_point_3d<double> nwp = norm_world_pts[i];
00448 double U ,V;
00449 camera.project(nwp.x(), nwp.y(), nwp.z(), U, V);
00450 vgl_point_2d<double> ip = image_pts[i];
00451 double error = vcl_sqrt((ip.x()-U)*(ip.x()-U) + (ip.y()-V)*(ip.y()-V));
00452 if ( error > err_max )
00453 {
00454 err_max = error;
00455 max_pt = world_pts[i];
00456 }
00457 if (error < err_min)
00458 {
00459 err_min = error;
00460 min_pt = world_pts[i];
00461 }
00462 }
00463 vcl_cout << "Max Error = " << err_max << " at " << max_pt << '\n'
00464 << "Min Error = " << err_min << " at " << min_pt << '\n'
00465 << "final cam\n" << camera << '\n';
00466 return true;
00467 }
00468
00469
00470 bool vpgl_perspective_camera_convert::
00471 convert_local( vpgl_rational_camera<double> const& rat_cam,
00472 vgl_box_3d<double> const& approximation_volume,
00473 vpgl_perspective_camera<double>& camera,
00474 vgl_h_matrix_3d<double>& norm_trans)
00475 {
00476
00477 double lon_low = approximation_volume.min_x();
00478 double lat_low = approximation_volume.min_y();
00479 #ifdef DEBUG
00480 double lon_high = approximation_volume.max_x();
00481 double lat_high = approximation_volume.max_y();
00482 assert( lat_low < lat_high && lon_low < lon_high );
00483 #endif
00484 vpgl_lvcs lvcs_converter( lat_low, lon_low,
00485 .5*(approximation_volume.min_z()+approximation_volume.max_z()),
00486 vpgl_lvcs::wgs84, vpgl_lvcs::DEG );
00487
00488
00489 double min_lx=1e99, min_ly=1e99, min_lz=1e99, max_lx=0, max_ly=0, max_lz=0;
00490 for ( int cx = 0; cx < 2; ++cx ) {
00491 for ( int cy = 0; cy < 2; ++cy ) {
00492 for ( int cz = 0; cz < 2; ++cz ) {
00493 vgl_point_3d<double> wc(approximation_volume.min_x()*cx + approximation_volume.max_x()*(1-cx),
00494 approximation_volume.min_y()*cy + approximation_volume.max_y()*(1-cy),
00495 approximation_volume.min_z()*cz + approximation_volume.max_z()*(1-cz) );
00496 double lcx, lcy, lcz;
00497 lvcs_converter.global_to_local(wc.x(), wc.y(), wc.z(), vpgl_lvcs::wgs84, lcx, lcy, lcz );
00498 vgl_point_3d<double> wc_loc( lcx, lcy, lcz );
00499 if ( cx == 0 && cy == 0 && cz == 0 ) {
00500 min_lx = wc_loc.x(); max_lx = wc_loc.x();
00501 min_ly = wc_loc.y(); max_ly = wc_loc.y();
00502 min_lz = wc_loc.z(); max_lz = wc_loc.z();
00503 continue;
00504 }
00505 if ( wc_loc.x() < min_lx ) min_lx = wc_loc.x();
00506 if ( wc_loc.y() < min_ly ) min_ly = wc_loc.y();
00507 if ( wc_loc.z() < min_lz ) min_lz = wc_loc.z();
00508 if ( wc_loc.x() > max_lx ) max_lx = wc_loc.x();
00509 if ( wc_loc.y() > max_ly ) max_ly = wc_loc.y();
00510 if ( wc_loc.z() > max_lz ) max_lz = wc_loc.z();
00511 }
00512 }
00513 }
00514 double dlx = max_lx-min_lx, dly = max_ly-min_ly, dlz = max_lz-min_lz;
00515
00516 norm_trans.set_identity();
00517 norm_trans.set(0,0,2/dlx); norm_trans.set(1,1,2/dly); norm_trans.set(2,2,2/dlz);
00518 norm_trans.set(0,3, -1-2*min_lx/dlx );
00519 norm_trans.set(1,3, -1-2*min_ly/dly);
00520 norm_trans.set(2,3, -1-2*min_lz/dlz);
00521
00522 vpgl_scale_offset<double> sou =
00523 rat_cam.scl_off(vpgl_rational_camera<double>::U_INDX);
00524 vpgl_scale_offset<double> sov =
00525 rat_cam.scl_off(vpgl_rational_camera<double>::V_INDX);
00526 vpgl_scale_offset<double> sox =
00527 rat_cam.scl_off(vpgl_rational_camera<double>::X_INDX);
00528 vpgl_scale_offset<double> soy =
00529 rat_cam.scl_off(vpgl_rational_camera<double>::Y_INDX);
00530 vpgl_scale_offset<double> soz =
00531 rat_cam.scl_off(vpgl_rational_camera<double>::Z_INDX);
00532 unsigned ni = static_cast<unsigned>(2*sou.scale());
00533 unsigned nj = static_cast<unsigned>(2*sov.scale());
00534
00535 vgl_point_3d<double> minp = approximation_volume.min_point();
00536 vgl_point_3d<double> maxp = approximation_volume.max_point();
00537 double xmin = minp.x(), ymin = minp.y(), zmin = minp.z();
00538 double xrange = maxp.x()-xmin,
00539 yrange = maxp.y()-ymin,
00540 zrange = maxp.z()-zmin;
00541 if (xrange<0||yrange<0||zrange<0)
00542 return false;
00543
00544 unsigned n = 100;
00545 vcl_vector<vgl_point_3d<double> > world_pts;
00546 unsigned count = 0, ntrials = 0;
00547 while (count<n)
00548 {
00549 ++ntrials;
00550 double rx = xrange*(vcl_rand()/(RAND_MAX+1.0));
00551 double ry = yrange*(vcl_rand()/(RAND_MAX+1.0));
00552 double rz = zrange*(vcl_rand()/(RAND_MAX+1.0));
00553 vgl_point_3d<double> wp(xmin+rx, ymin+ry, zmin+rz);
00554 vgl_point_2d<double> ip = rat_cam.project(wp);
00555 if (ip.x()<0||ip.x()>ni||ip.y()<0||ip.y()>nj)
00556 continue;
00557 world_pts.push_back(wp);
00558 count++;
00559 }
00560 vcl_cout << "Ntrials " << ntrials << '\n';
00561
00562
00563 vcl_vector<vgl_point_3d<double> > norm_world_pts;
00564 vcl_vector<vgl_point_2d<double> > image_pts, norm_image_pts;
00565 unsigned N = world_pts.size();
00566 for (unsigned i = 0; i<N; ++i)
00567 {
00568 vgl_point_3d<double> wp = world_pts[i];
00569 vgl_point_2d<double> ip = rat_cam.project(wp);
00570 image_pts.push_back(ip);
00571 vgl_point_2d<double> nip(sou.normalize(ip.x()), sov.normalize(ip.y()));
00572 norm_image_pts.push_back(nip);
00573
00574
00575 double lcx, lcy, lcz;
00576 lvcs_converter.global_to_local(wp.x(), wp.y(), wp.z(), vpgl_lvcs::wgs84, lcx, lcy, lcz );
00577 vgl_homg_point_3d<double> wp_loc( lcx, lcy, lcz );
00578
00579 vgl_homg_point_3d<double> nwp = norm_trans*wp_loc;
00580 assert( vcl_fabs(nwp.x()) <= 1
00581 && vcl_fabs(nwp.y()) <= 1
00582 && vcl_fabs(nwp.z()) <= 1 );
00583 norm_world_pts.push_back(vgl_point_3d<double>(nwp) );
00584 }
00585
00586
00587 vnl_matrix_fixed<double, 3, 3> kk;
00588 kk.fill(0);
00589 kk[0][0]= 1.0;
00590 kk[1][1]= 1.0;
00591 kk[2][2]=1.0;
00592
00593
00594 vpgl_calibration_matrix<double> K(kk);
00595 if (! vpgl_perspective_camera_compute::compute(norm_image_pts,
00596 norm_world_pts,
00597 K, camera))
00598 return false;
00599 vcl_cout << camera << '\n';
00600
00601 vpgl_calibration_matrix<double> Kmin = camera.get_calibration();
00602 vnl_matrix_fixed<double, 3, 3> kk_min;
00603 kk_min = Kmin.get_matrix();
00604 kk[0][0]= sou.scale(); kk[0][2]= sou.offset();
00605 kk[1][1]= sov.scale(); kk[1][2]= sov.offset();
00606 kk *= kk_min;
00607 camera.set_calibration(kk);
00608
00609
00610 double err_max = 0, err_min = 1e10;
00611 vgl_point_3d<double> min_pt, max_pt;
00612 for (unsigned i = 0; i<N; ++i)
00613 {
00614 vgl_point_3d<double> nwp = norm_world_pts[i];
00615 double U ,V;
00616 camera.project(nwp.x(), nwp.y(), nwp.z(), U, V);
00617 vgl_point_2d<double> ip = image_pts[i];
00618 double error = vcl_sqrt((ip.x()-U)*(ip.x()-U) + (ip.y()-V)*(ip.y()-V));
00619 if ( error > err_max )
00620 {
00621 err_max = error;
00622 max_pt = world_pts[i];
00623 }
00624 if (error < err_min)
00625 {
00626 err_min = error;
00627 min_pt = world_pts[i];
00628 }
00629 }
00630 vcl_cout << "Max Error = " << err_max << " at " << max_pt << '\n'
00631 << "Min Error = " << err_min << " at " << min_pt << '\n'
00632 << "final cam\n" << camera << '\n';
00633 return true;
00634 }
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 static bool interp_ray(vcl_vector<vgl_ray_3d<double> > const& ray_nbrs,
00646 vgl_ray_3d<double> & intrp_ray)
00647 {
00648 unsigned nrays = ray_nbrs.size();
00649 if (nrays!=4) return false;
00650 vgl_ray_3d<double> r0 = ray_nbrs[0], r1 = ray_nbrs[1];
00651 vgl_ray_3d<double> r2 = ray_nbrs[2], r3 = ray_nbrs[3];
00652 vgl_point_3d<double> org0 = r0.origin(), org1 = r1.origin();
00653 vgl_point_3d<double> org2 = r2.origin(), org3 = r3.origin();
00654 vgl_vector_3d<double> dir0 = r0.direction(), dir1 = r1.direction();
00655 vgl_vector_3d<double> dir2 = r2.direction(), dir3 = r3.direction();
00656
00657 vgl_vector_3d<double> dodu = 0.5*(org2-org1);
00658 vgl_vector_3d<double> dodv = 0.5*(org3-org0);
00659 vgl_vector_3d<double> dddu = 0.5*(dir2-dir1);
00660 vgl_vector_3d<double> dddv = 0.5*(dir3-dir0);
00661 vgl_point_3d<double> temp = org1 + dodu + dodv;
00662 double ox = 0.5*(org0.x()+ temp.x());
00663 double oy = 0.5*(org0.y()+ temp.y());
00664 double oz = 0.5*(org0.z()+ temp.z());
00665 vgl_point_3d<double> iorg(ox, oy, oz);
00666 vgl_vector_3d<double> idir = 0.5*(dir1 + dddu + dir0 + dddv);
00667 intrp_ray.set(iorg, idir);
00668 return true;
00669 }
00670
00671
00672 static bool ray_tol(vpgl_local_rational_camera<double> const& rat_cam,
00673 double mid_u, double mid_v,
00674 vgl_plane_3d<double> const& high,
00675 vgl_point_3d<double> const& high_guess,
00676 vgl_plane_3d<double> const& low,
00677 vgl_point_3d<double> const& low_guess,
00678 double& org_tol, double& dir_tol)
00679 {
00680 vgl_point_2d<double> ip(mid_u,mid_v);
00681 vgl_point_3d<double> high_pt, low_pt, low_pt_pix;
00682 if (!vpgl_backproject::bproj_plane(&rat_cam, ip, high, high_guess, high_pt))
00683 return false;
00684 if (!vpgl_backproject::bproj_plane(&rat_cam, ip, low, low_guess, low_pt))
00685 return false;
00686
00687 ip.set(mid_u+1.0, mid_v+1.0);
00688 if (!vpgl_backproject::bproj_plane(&rat_cam, ip, low, low_pt, low_pt_pix))
00689 return false;
00690
00691 double gsd = (low_pt-low_pt_pix).length();
00692
00693 double tfact = 0.001;
00694 org_tol = tfact*gsd;
00695 vgl_vector_3d<double> dir0 = low_pt-high_pt;
00696 vgl_vector_3d<double> dir1 = low_pt_pix-high_pt;
00697 double ang = angle(dir0, dir1);
00698 dir_tol = tfact*ang;
00699 return true;
00700 }
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716 bool vpgl_generic_camera_convert::
00717 upsample_rays(vcl_vector<vgl_ray_3d<double> > const& ray_nbrs,
00718 vgl_ray_3d<double> const& ray,
00719 vcl_vector<vgl_ray_3d<double> >& interp_rays)
00720 {
00721 unsigned nrays = ray_nbrs.size();
00722 if (nrays!=4) return false;
00723 vgl_ray_3d<double> r00 = ray_nbrs[0],
00724 r01 = ray_nbrs[1];
00725 vgl_ray_3d<double> r10 = ray_nbrs[2],
00726 r11 = ray_nbrs[3];
00727 vgl_point_3d<double> org = ray.origin();
00728 vgl_vector_3d<double> dir = ray.direction();
00729 vgl_point_3d<double> org00 = r00.origin(),
00730 org01 = r01.origin();
00731 vgl_point_3d<double> org10 = r10.origin(),
00732 org11 = r11.origin();
00733 vgl_vector_3d<double> dir00 = r00.direction(), dir01 = r01.direction();
00734 vgl_vector_3d<double> dir10 = r10.direction(), dir11 = r11.direction();
00735
00736
00737 interp_rays[0] = ray;
00738
00739
00740 vgl_point_3d<double> iorg = org00+ (org01-org00)*0.5;
00741 vgl_vector_3d<double> idir = dir00*0.5 + dir01*0.5;
00742 interp_rays[1].set(iorg, idir);
00743
00744
00745 iorg = org00+ (org10-org00)*0.5;
00746 idir = 0.5*dir00 + 0.5*dir10;
00747 interp_rays[2].set(iorg, idir);
00748
00749
00750 iorg = org00+0.25*(org01-org00) + 0.25*(org10-org00)+ 0.25*(org11-org00);
00751 idir = 0.25*dir00 + 0.25*dir01+ 0.25*dir10+0.25*dir11;
00752 interp_rays[3].set(iorg, idir);
00753
00754 return true;
00755 }
00756
00757
00758
00759 vgl_ray_3d<double>
00760 vpgl_generic_camera_convert::interp_pair(vgl_ray_3d<double> const& r0,
00761 vgl_ray_3d<double> const& r1,
00762 double n_grid)
00763 {
00764 vgl_vector_3d<double> v01 = r1.origin()-r0.origin();
00765 vgl_point_3d<double> intp_org = r1.origin()+ n_grid*v01;
00766 vgl_vector_3d<double> d01 = r1.direction()-r0.direction();
00767 vgl_vector_3d<double> intp_dir = r1.direction()+ n_grid*d01;
00768 return vgl_ray_3d<double>(intp_org, intp_dir);
00769 }
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780 bool vpgl_generic_camera_convert::
00781 convert( vpgl_local_rational_camera<double> const& rat_cam,
00782 int ni, int nj, vpgl_generic_camera<double> & gen_cam, unsigned level)
00783 {
00784
00785 double zoff = rat_cam.offset(vpgl_rational_camera<double>::Z_INDX);
00786 double zscl = rat_cam.scale(vpgl_rational_camera<double>::Z_INDX);
00787
00788
00789
00790
00791
00792 double el_low = zoff-zscl/2;
00793 double el_high = zoff+zscl/2;
00794 double lon = rat_cam.offset(vpgl_rational_camera<double>::X_INDX);
00795 double lat = rat_cam.offset(vpgl_rational_camera<double>::Y_INDX);
00796 double x,y, z_low, z_high;
00797
00798 rat_cam.lvcs().global_to_local(lon,lat,el_low,vpgl_lvcs::wgs84,x,y,z_low,vpgl_lvcs::DEG);
00799 rat_cam.lvcs().global_to_local(lon,lat,el_high,vpgl_lvcs::wgs84,x,y,z_high,vpgl_lvcs::DEG);
00800
00801 return convert(rat_cam, ni, nj, gen_cam, z_low, z_high, level);
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813 bool vpgl_generic_camera_convert::
00814 convert( vpgl_local_rational_camera<double> const& rat_cam,
00815 int ni, int nj, vpgl_generic_camera<double> & gen_cam,
00816 double local_z_min, double local_z_max, unsigned level)
00817 {
00818 vgl_plane_3d<double> high(0.0, 0.0, 1.0, -local_z_max);
00819 vgl_plane_3d<double> low(0.0, 0.0, 1.0, -local_z_min);
00820
00821
00822 vgl_point_3d<double> org(0.0, 0.0, local_z_max), endpt(0.0, 0.0, local_z_min);
00823
00824
00825
00826 double dim = ni;
00827 if (nj<ni)
00828 dim = nj;
00829 double lv = vcl_log(dim)/vcl_log(2.0);
00830 int n_levels = static_cast<int>(lv+1.0);
00831 if (dim*vcl_pow(0.5, static_cast<double>(n_levels-1)) < 3.0) n_levels--;
00832
00833
00834 vcl_vector<int> nr(n_levels,0), nc(n_levels,0);
00835
00836 vcl_vector<double> scl(n_levels,1.0);
00837 vcl_vector<vbl_array_2d<vgl_ray_3d<double> > > ray_pyr(n_levels);
00838 ray_pyr[0].resize(nj, ni);
00839 ray_pyr[0].fill(vgl_ray_3d<double>(vgl_point_3d<double>(0,0,0),vgl_vector_3d<double>(0,0,1)));
00840 nr[0]=nj; nc[0]=ni; scl[0]=1.0;
00841 int di = (ni+1)/2+1,
00842 dj = (nj+1)/2+1;
00843
00844 for (int i=1; i<n_levels; ++i)
00845 {
00846 ray_pyr[i].resize(dj,di);
00847 ray_pyr[i].fill(vgl_ray_3d<double>(vgl_point_3d<double>(0,0,0),
00848 vgl_vector_3d<double>(0,0,1)));
00849 nr[i]=dj;
00850 nc[i]=di;
00851 scl[i]=2.0*scl[i-1];
00852 di = (di+1)/2+1;
00853 dj = (dj+1)/2+1;
00854 }
00855
00856 double org_tol = 0.0;
00857 double ang_tol = 0.0;
00858 double max_org_err = 0.0, max_ang_err = 0.0;
00859 if (!ray_tol(rat_cam, ni/2.0, nj/2.0, high,
00860 org, low, endpt, org_tol, ang_tol))
00861 return false;
00862 bool need_interp = true;
00863 int lev = n_levels-1;
00864 for (; lev>=0&&need_interp; --lev) {
00865
00866 for (int j =0; j<nr[lev]; ++j) {
00867 int sj = static_cast<int>(scl[lev]*j);
00868
00869 for (int i =0;i<nc[lev]; ++i)
00870 {
00871 int si = static_cast<int>(scl[lev]*i);
00872
00873 vgl_point_2d<double> ip(si,sj);
00874 #if 1 // use result from previous pyramid level to initialize guess
00875 vgl_point_3d<double> prev_org(0.0,0.0,local_z_max);
00876 vgl_point_3d<double> prev_endpt(0.0, 0.0, local_z_min);
00877
00878 if (lev < n_levels-1) {
00879 double rel_scale = scl[lev]/scl[lev+1];
00880 int i_above = static_cast<int>(rel_scale * i);
00881 int j_above = static_cast<int>(rel_scale * j);
00882
00883 prev_org = ray_pyr[lev+1][j_above][i_above].origin();
00884 vgl_vector_3d<double> prev_dir = ray_pyr[lev+1][j_above][i_above].direction();
00885
00886 double ray_len = (local_z_min - prev_org.z()) / prev_dir.z();
00887 prev_endpt = prev_org + (prev_dir * ray_len);
00888 }
00889 const double error_tol = 0.25;
00890 if (!vpgl_backproject::bproj_plane(&rat_cam, ip, high, prev_org, org, error_tol))
00891 return false;
00892 if (!vpgl_backproject::bproj_plane(&rat_cam, ip, low, prev_endpt, endpt, error_tol))
00893 return false;
00894 #else // 0
00895 if (!vpgl_backproject::bproj_plane(&rat_cam, ip, high, vgl_point_3d<double>(0.0,0.0,0.0), org))
00896 return false;
00897 if (!vpgl_backproject::bproj_plane(&rat_cam, ip, low, vgl_point_3d<double>(0.0,0.0,0.0), endpt))
00898 return false;
00899 #endif
00900 vgl_vector_3d<double> dir = endpt-org;
00901 ray_pyr[lev][j][i].set(org, dir);
00902 }
00903 }
00904
00905
00906
00907
00908 need_interp = false;
00909 max_org_err = 0.0; max_ang_err = 0.0;
00910 vcl_vector<vgl_ray_3d<double> > ray_nbrs(4);
00911 for (int j =1; j<(nr[lev]-1)&&!need_interp; ++j) {
00912 for (int i =1;(i<nc[lev]-1)&&!need_interp; ++i) {
00913 vgl_ray_3d<double> ray = ray_pyr[lev][j][i];
00914
00915
00916
00917
00918
00919
00920
00921 ray_nbrs[0]=ray_pyr[lev][j-1][i];
00922 ray_nbrs[1]=ray_pyr[lev][j][i-1];
00923 ray_nbrs[2]=ray_pyr[lev][j][i+1];
00924 ray_nbrs[3]=ray_pyr[lev][j+1][i];
00925
00926 vgl_ray_3d<double> intp_ray;
00927 if (!interp_ray(ray_nbrs, intp_ray))
00928 return false;
00929 double dorg = (ray.origin()-intp_ray.origin()).length();
00930 double dang = angle(ray.direction(), intp_ray.direction());
00931 if (dorg>max_org_err) max_org_err = dorg;
00932 if (dang>max_ang_err) max_ang_err = dang;
00933 need_interp = max_org_err>org_tol || max_ang_err>ang_tol;
00934 }
00935 }
00936 }
00937
00938
00939 for (++lev; lev>0; --lev) {
00940 unsigned int ncr = nc[lev];
00941 unsigned int nrb = nr[lev];
00942 vbl_array_2d<vgl_ray_3d<double> >& clev = ray_pyr[lev];
00943 vbl_array_2d<vgl_ray_3d<double> >& nlev = ray_pyr[lev-1];
00944 vcl_vector<vgl_ray_3d<double> > ray_nbrs(4);
00945 vcl_vector<vgl_ray_3d<double> > interp_rays(4);
00946 for (unsigned int j = 0; j<nrb; ++j)
00947 for (unsigned int i = 0; i<ncr; ++i) {
00948 ray_nbrs[0] = clev[j][i];
00949 ray_nbrs[1] = clev[j][i];
00950 ray_nbrs[2] = clev[j][i];
00951 ray_nbrs[3] = clev[j][i];
00952 if (i+1<ncr) ray_nbrs[1] = clev[j][i+1];
00953 if (j+1<nrb) ray_nbrs[2] = clev[j+1][i];
00954 if (i+1<ncr && j+1<nrb) ray_nbrs[3] = clev[j+1][i+1];
00955 if (!upsample_rays(ray_nbrs, clev[j][i], interp_rays))
00956 return false;
00957 if (2*i<nlev.cols() && 2*j<nlev.rows())
00958 {
00959 nlev[2*j][2*i] =interp_rays[0];
00960 if (2*i+1<nlev.cols()) nlev[2*j][2*i+1] =interp_rays[1];
00961 if (2*j+1<nlev.rows()) nlev[2*j+1][2*i] =interp_rays[2];
00962 if (2*i+1<nlev.cols() && 2*j+1<nlev.rows()) nlev[2*j+1][2*i+1]=interp_rays[3];
00963 }
00964 }
00965 }
00966 if ((int)level < n_levels) {
00967 gen_cam = vpgl_generic_camera<double>(ray_pyr[level]);
00968 return true;
00969 }
00970 else
00971 return false;
00972 }
00973
00974 bool vpgl_generic_camera_convert::
00975 convert( vpgl_proj_camera<double> const& prj_cam, int ni, int nj,
00976 vpgl_generic_camera<double> & gen_cam, unsigned level)
00977 {
00978 vbl_array_2d<vgl_ray_3d<double> > rays(nj, ni);
00979 vgl_ray_3d<double> ray;
00980 vgl_homg_point_2d<double> ipt;
00981 double scale = (level < 32) ? double(1L<<level) : vcl_pow(2.0,static_cast<double>(level));
00982 for (int j = 0; j<nj; ++j)
00983 for (int i = 0; i<ni; ++i) {
00984 ipt.set(i*scale, j*scale, 1.0);
00985 ray = prj_cam.backproject_ray(ipt);
00986 rays[j][i]=ray;
00987 }
00988 gen_cam = vpgl_generic_camera<double>(rays);
00989 return true;
00990 }
00991
00992 bool vpgl_generic_camera_convert::
00993 convert( vpgl_perspective_camera<double> const& per_cam, int ni, int nj,
00994 vpgl_generic_camera<double> & gen_cam, unsigned level)
00995 {
00996 vbl_array_2d<vgl_ray_3d<double> > rays(nj, ni);
00997 vgl_ray_3d<double> ray;
00998 vgl_homg_point_2d<double> ipt;
00999 double scale = (level < 32) ? double(1L<<level) : vcl_pow(2.0,static_cast<double>(level));
01000 for (int j = 0; j<nj; ++j)
01001 for (int i = 0; i<ni; ++i) {
01002 ipt.set(i*scale, j*scale, 1.0);
01003 ray = per_cam.backproject_ray(ipt);
01004 rays[j][i]=ray;
01005 }
01006 gen_cam = vpgl_generic_camera<double>(rays);
01007 return true;
01008 }
01009
01010 bool vpgl_generic_camera_convert::
01011 convert_with_margin( vpgl_perspective_camera<double> const& per_cam, int ni, int nj,
01012 vpgl_generic_camera<double> & gen_cam, int margin, unsigned level)
01013 {
01014 vbl_array_2d<vgl_ray_3d<double> > rays(nj+2*margin, ni+2*margin);
01015 vgl_ray_3d<double> ray;
01016 vgl_homg_point_2d<double> ipt;
01017 double scale = (level < 32) ? double(1L<<level) : vcl_pow(2.0,static_cast<double>(level));
01018 for (int j = -margin; j<nj+margin; ++j)
01019 for (int i = -margin; i<ni+margin; ++i) {
01020 ipt.set(i*scale, j*scale, 1.0);
01021 ray = per_cam.backproject_ray(ipt);
01022 rays[j+margin][i+margin]=ray;
01023 }
01024 gen_cam = vpgl_generic_camera<double>(rays);
01025 return true;
01026 }
01027
01028
01029
01030
01031
01032
01033 bool vpgl_generic_camera_convert::
01034 convert( vpgl_affine_camera<double> const& aff_cam, int ni, int nj,
01035 vpgl_generic_camera<double> & gen_cam, unsigned level)
01036 {
01037 double scale = (level < 32) ? double(1L<<level) : vcl_pow(2.0,static_cast<double>(level));
01038
01039 vgl_homg_point_3d<double> cent = aff_cam.camera_center();
01040 vgl_vector_3d<double> dir(cent.x(), cent.y(), cent.z());
01041 vbl_array_2d<vgl_ray_3d<double> > rays(nj, ni);
01042 vgl_homg_point_3d<double> horg;
01043 vgl_point_3d<double> org;
01044 vgl_homg_point_2d<double> ipt;
01045 vgl_homg_line_3d_2_points<double> hline;
01046 for (int j = 0; j<nj; ++j)
01047 for (int i = 0; i<ni; ++i) {
01048 ipt.set(i*scale, j*scale, 1.0);
01049 hline = aff_cam.backproject(ipt);
01050 horg = hline.point_finite();
01051 org.set(horg.x()/horg.w(), horg.y()/horg.w(), horg.z()/horg.w());
01052 rays[j][i].set(org, dir);
01053 }
01054 gen_cam = vpgl_generic_camera<double>(rays);
01055 return true;
01056 }
01057
01058 bool vpgl_generic_camera_convert::
01059 convert( vpgl_camera_double_sptr const& camera, int ni, int nj,
01060 vpgl_generic_camera<double> & gen_cam, unsigned level)
01061 {
01062 if (vpgl_local_rational_camera<double>* cam =
01063 dynamic_cast<vpgl_local_rational_camera<double>*>(camera.ptr()))
01064 return vpgl_generic_camera_convert::convert(*cam, ni, nj, gen_cam, level);
01065
01066 if (vpgl_perspective_camera<double>* cam =
01067 dynamic_cast<vpgl_perspective_camera<double>*>(camera.ptr())) {
01068 return vpgl_generic_camera_convert::convert(*cam, ni, nj, gen_cam, level);
01069 }
01070
01071 if (vpgl_proj_camera<double>* cam =
01072 dynamic_cast<vpgl_proj_camera<double>*>(camera.ptr())) {
01073 return vpgl_generic_camera_convert::convert(*cam, ni, nj, gen_cam, level);
01074 }
01075
01076 if (vpgl_affine_camera<double>* cam =
01077 dynamic_cast<vpgl_affine_camera<double>*>(camera.ptr()))
01078 return vpgl_generic_camera_convert::convert(*cam, ni, nj, gen_cam, level);
01079
01080 return false;
01081 }
01082
01083
01084 bool vpgl_generic_camera_convert::convert( vpgl_geo_camera& geocam, int ni, int nj, double height,
01085 vpgl_generic_camera<double> & gen_cam, unsigned level)
01086 {
01087 double scale = (level < 32) ? double(1L<<level) : vcl_pow(2.0,static_cast<double>(level));
01088
01089
01090 vgl_vector_3d<double> dir(0.0, 0.0, -1.0);
01091
01092 vbl_array_2d<vgl_ray_3d<double> > rays(nj, ni);
01093 vgl_point_3d<double> org;
01094
01095 for (int j = 0; j<nj; ++j)
01096 for (int i = 0; i<ni; ++i) {
01097 double x,y,z;
01098 geocam.backproject(i*scale, j*scale,x,y,z);
01099 org.set(x, y, height);
01100 rays[j][i].set(org, dir);
01101 }
01102 gen_cam = vpgl_generic_camera<double>(rays);
01103 return true;
01104 }
01105
01106
01107 #endif // vpgl_camera_convert_cxx_