//////////////////////////////////////////////////////////////////////////// // File: DataInterface.h // Author: Changchang Wu (ccwu@cs.washington.edu) // Description : data interface, the data format been uploaded to GPU // // Copyright (c) 2011 Changchang Wu (ccwu@cs.washington.edu) // and the University of Washington at Seattle // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public // License as published by the Free Software Foundation; either // Version 3 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // //////////////////////////////////////////////////////////////////////////////// #ifndef DATA_INTERFACE_GPU_H #define DATA_INTERFACE_GPU_H namespace PBA { // ----------------------------WARNING------------------------------ // ----------------------------------------------------------------- // ROTATION CONVERSION: // The internal rotation representation is 3x3 float matrix. Reading // back the rotations as quaternion or Rodrigues's representation will // cause inaccuracy, IF you have wrongly reconstructed cameras with // a very very large focal length (typically also very far away). // In this case, any small change in the rotation matrix, will cause // a large reprojection error. // // --------------------------------------------------------------------- // RADIAL distortion is NOT enabled by default, use parameter "-md", -pd" // or set ConfigBA::__use_radial_distortion to 1 or -1 to enable it. // --------------------------------------------------------------------------- //transfer data type with 4-float alignment #define CameraT CameraT_ #define Point3D Point3D_ template struct CameraT_ { typedef FT float_t; ////////////////////////////////////////////////////// float_t f; // single focal length, K = [f, 0, 0; 0 f 0; 0 0 1] float_t t[3]; // T in P = K[R T], T = - RC float_t m[3][3]; // R in P = K[R T]. float_t radial; // WARNING: BE careful with the radial distortion model. float_t distortion_type; float_t constant_camera; ////////////////////////////////////////////////////////// CameraT_() { radial = 0; distortion_type = 0; constant_camera = 0; } ////////////////////////////////////////////// template void SetCameraT(const CameraX & cam) { f = (float_t)cam.f; t[0] = (float_t)cam.t[0]; t[1] = (float_t)cam.t[1]; t[2] = (float_t)cam.t[2]; for(int i = 0; i < 3; ++i) for(int j = 0; j < 3; ++j) m[i][j] = (float_t)cam.m[i][j]; radial = (float_t)cam.radial; distortion_type = (float_t)cam.distortion_type; constant_camera = (float_t)cam.constant_camera; } ////////////////////////////////////////// enum { CAMERA_VARIABLE = 0, CAMERA_FIXEDINTRINSIC = (1<<0), CAMERA_FIXEDEXTRINSIC = (1<<1), }; void SetVariableCamera() {(int&)constant_camera = CAMERA_VARIABLE;} void SetFixedIntrinsic() {(int&)constant_camera = CAMERA_FIXEDINTRINSIC;} void SetFixedExtrinsic() {(int&)constant_camera = CAMERA_FIXEDEXTRINSIC;} void SetConstantCamera() {(int&)constant_camera = CAMERA_FIXEDINTRINSIC|CAMERA_FIXEDEXTRINSIC;} ////////////////////////////////////// template void SetFocalLength(Float F){ f = (float_t) F; } float_t GetFocalLength() const{return f;} template void SetMeasurementDistortion(Float r) {radial = (float_t) r; distortion_type = -1;} float_t GetMeasurementDistortion() const {return distortion_type == -1 ? radial : 0; } //normalize radial distortion that applies to angle will be (radial * f * f); template void SetNormalizedMeasurementDistortion(Float r) {SetMeasurementDistortion(r / (f * f)); } float_t GetNormalizedMeasurementDistortion() const{return GetMeasurementDistortion() * (f * f); } //use projection distortion template void SetProjectionDistortion(Float r) {radial = float_t(r); distortion_type = 1; } template void SetProjectionDistortion(const Float* r) {SetProjectionDistortion(r[0]); } float_t GetProjectionDistortion() {return distortion_type == 1 ? radial : 0; } template void SetRodriguesRotation(const Float r[3]) { double a = sqrt(r[0]*r[0]+r[1]*r[1]+r[2]*r[2]); double ct = a==0.0?0.5:(1.0-cos(a))/a/a; double st = a==0.0?1:sin(a)/a; m[0][0]=float_t(1.0 - (r[1]*r[1] + r[2]*r[2])*ct); m[0][1]=float_t(r[0]*r[1]*ct - r[2]*st); m[0][2]=float_t(r[2]*r[0]*ct + r[1]*st); m[1][0]=float_t(r[0]*r[1]*ct + r[2]*st); m[1][1]=float_t(1.0 - (r[2]*r[2] + r[0]*r[0])*ct); m[1][2]=float_t(r[1]*r[2]*ct - r[0]*st); m[2][0]=float_t(r[2]*r[0]*ct - r[1]*st); m[2][1]=float_t(r[1]*r[2]*ct + r[0]*st); m[2][2]=float_t(1.0 - (r[0]*r[0] + r[1]*r[1])*ct ); } template void GetRodriguesRotation(Float r[3]) const { double a = (m[0][0]+m[1][1]+m[2][2]-1.0)/2.0; const double epsilon = 0.01; if( fabs(m[0][1] - m[1][0]) < epsilon && fabs(m[1][2] - m[2][1]) < epsilon && fabs(m[0][2] - m[2][0]) < epsilon ) { if( fabs(m[0][1] + m[1][0]) < 0.1 && fabs(m[1][2] + m[2][1]) < 0.1 && fabs(m[0][2] + m[2][0]) < 0.1 && a > 0.9) { r[0] = 0; r[1] = 0; r[2] = 0; } else { const Float ha = Float(sqrt(0.5) * 3.14159265358979323846); double xx = (m[0][0]+1.0)/2.0; double yy = (m[1][1]+1.0)/2.0; double zz = (m[2][2]+1.0)/2.0; double xy = (m[0][1]+m[1][0])/4.0; double xz = (m[0][2]+m[2][0])/4.0; double yz = (m[1][2]+m[2][1])/4.0; if ((xx > yy) && (xx > zz)) { if (xx< epsilon) { r[0] = 0; r[1] = r[2] = ha; } else { double t = sqrt(xx) ; r[0] = Float(t * 3.14159265358979323846); r[1] = Float(xy/t * 3.14159265358979323846); r[2] = Float(xz/t * 3.14159265358979323846); } } else if (yy > zz) { if (yy< epsilon) { r[0] = r[2] = ha; r[1] = 0; } else { double t = sqrt(yy); r[0] = Float(xy/t* 3.14159265358979323846); r[1] = Float( t * 3.14159265358979323846); r[2] = Float(yz/t* 3.14159265358979323846); } } else { if (zz< epsilon) { r[0] = r[1] = ha; r[2] = 0; } else { double t = sqrt(zz); r[0] = Float(xz/ t* 3.14159265358979323846); r[1] = Float(yz/ t* 3.14159265358979323846); r[2] = Float( t * 3.14159265358979323846); } } } } else { a = acos(a); double b = 0.5*a/sin(a); r[0] = Float(b*(m[2][1]-m[1][2])); r[1] = Float(b*(m[0][2]-m[2][0])); r[2] = Float(b*(m[1][0]-m[0][1])); } } //////////////////////// template void SetQuaternionRotation(const Float q[4]) { double qq = sqrt(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3]); double qw, qx, qy, qz; if(qq>0) { qw=q[0]/qq; qx=q[1]/qq; qy=q[2]/qq; qz=q[3]/qq; }else { qw = 1; qx = qy = qz = 0; } m[0][0]=float_t(qw*qw + qx*qx- qz*qz- qy*qy ); m[0][1]=float_t(2*qx*qy -2*qz*qw ); m[0][2]=float_t(2*qy*qw + 2*qz*qx); m[1][0]=float_t(2*qx*qy+ 2*qw*qz); m[1][1]=float_t(qy*qy+ qw*qw - qz*qz- qx*qx); m[1][2]=float_t(2*qz*qy- 2*qx*qw); m[2][0]=float_t(2*qx*qz- 2*qy*qw); m[2][1]=float_t(2*qy*qz + 2*qw*qx ); m[2][2]=float_t(qz*qz+ qw*qw- qy*qy- qx*qx); } template void GetQuaternionRotation(Float q[4]) const { q[0]= 1 + m[0][0] + m[1][1] + m[2][2]; if(q[0]>0.000000001) { q[0] = sqrt(q[0])/2.0; q[1]= (m[2][1] - m[1][2])/( 4.0 *q[0]); q[2]= (m[0][2] - m[2][0])/( 4.0 *q[0]); q[3]= (m[1][0] - m[0][1])/( 4.0 *q[0]); }else { double s; if ( m[0][0] > m[1][1] && m[0][0] > m[2][2] ) { s = 2.0 * sqrt( 1.0 + m[0][0] - m[1][1] - m[2][2]); q[1] = 0.25 * s; q[2] = (m[0][1] + m[1][0] ) / s; q[3] = (m[0][2] + m[2][0] ) / s; q[0] = (m[1][2] - m[2][1] ) / s; } else if (m[1][1] > m[2][2]) { s = 2.0 * sqrt( 1.0 + m[1][1] - m[0][0] - m[2][2]); q[1] = (m[0][1] + m[1][0] ) / s; q[2] = 0.25 * s; q[3] = (m[1][2] + m[2][1] ) / s; q[0] = (m[0][2] - m[2][0] ) / s; } else { s = 2.0 * sqrt( 1.0 + m[2][2] - m[0][0] - m[1][1]); q[1] = (m[0][2] + m[2][0] ) / s; q[2] = (m[1][2] + m[2][1] ) / s; q[3] = 0.25f * s; q[0] = (m[0][1] - m[1][0] ) / s; } } } //////////////////////////////////////////////// template void SetMatrixRotation(const Float * r) { for(int i = 0; i < 9; ++i) m[0][i] = float_t(r[i]); } template void GetMatrixRotation(Float * r) const { for(int i = 0; i < 9; ++i) r[i] = Float(m[0][i]); } float GetRotationMatrixDeterminant()const { return m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1] - m[0][2]*m[1][1]*m[2][0] - m[0][1]*m[1][0]*m[2][2] - m[0][0]*m[1][2]*m[2][1]; } /////////////////////////////////////// template void SetTranslation(const Float T[3]) { t[0] = (float_t)T[0]; t[1] = (float_t)T[1]; t[2] = (float_t)T[2]; } template void GetTranslation(Float T[3]) const { T[0] = (Float)t[0]; T[1] = (Float)t[1]; T[2] = (Float)t[2]; } ///////////////////////////////////////////// template void SetCameraCenterAfterRotation(const Float c[3]) { //t = - R * C for(int j = 0; j < 3; ++j) t[j] = -float_t(double(m[j][0])*double(c[0]) + double(m[j][1])*double(c[1]) + double(m[j][2])*double(c[2])); } template void GetCameraCenter(Float c[3]) const { //C = - R' * t for(int j = 0; j < 3; ++j) c[j] = -Float(double(m[0][j])*double(t[0]) + double(m[1][j])*double(t[1]) + double(m[2][j])*double(t[2])); } //////////////////////////////////////////// template void SetInvertedRT(const Float e[3], const Float T[3]) { SetRodriguesRotation(e); for(int i = 3; i < 9; ++i) m[0][i] = - m[0][i]; SetTranslation(T); t[1] = - t[1]; t[2] = -t[2]; } template void GetInvertedRT (Float e[3], Float T[3]) const { CameraT ci; ci.SetMatrixRotation(m[0]); for(int i = 3; i < 9; ++i) ci.m[0][i] = - ci.m[0][i]; //for(int i = 1; i < 3; ++i) for(int j = 0; j < 3; ++j) ci.m[i][j] = - ci.m[i][j]; ci.GetRodriguesRotation(e); GetTranslation(T); T[1] = - T[1]; T[2] = -T[2]; } template void SetInvertedR9T(const Float e[9], const Float T[3]) { //for(int i = 0; i < 9; ++i) m[0][i] = (i < 3 ? e[i] : - e[i]); //SetTranslation(T); t[1] = - t[1]; t[2] = -t[2]; m[0][0] = e[0]; m[0][1] = e[1]; m[0][2] = e[2]; m[1][0] = -e[3]; m[1][1] = -e[4]; m[1][2] = -e[5]; m[2][0] = -e[6]; m[2][1] = -e[7]; m[2][2] = -e[8]; t[0] = T[0]; t[1] = -T[1]; t[2] = -T[2]; } template void GetInvertedR9T(Float e[9], Float T[3]) const { e[0] = m[0][0]; e[1] = m[0][1]; e[2] = m[0][2]; e[3] = - m[1][0]; e[4] = -m[1][1]; e[5] = -m[1][2]; e[6] = -m[2][0]; e[7] = -m[2][1]; e[8] = -m[2][2] ; T[0] = t[0]; T[1] = -t[1]; T[2] = -t[2]; } }; template struct Point3D { typedef FT float_t; float_t xyz[3]; //3D point location float_t reserved; //alignment //////////////////////////////// template void SetPoint(Float x, Float y, Float z) { xyz[0] = (float_t) x; xyz[1] = (float_t) y; xyz[2] = (float_t) z; reserved = 0; } template void SetPoint(const Float * p) { xyz[0] = (float_t) p[0]; xyz[1] = (float_t) p[1]; xyz[2] = (float_t) p[2]; reserved = 0; } template void GetPoint(Float* p) const { p[0] = (Float) xyz[0]; p[1] = (Float) xyz[1]; p[2] = (Float) xyz[2]; } template void GetPoint(Float&x, Float&y, Float&z) const { x = (Float) xyz[0]; y = (Float) xyz[1]; z = (Float) xyz[2]; } }; #undef CameraT #undef Point3D typedef CameraT_ CameraT; typedef CameraT_ CameraD; typedef Point3D_ Point3D; typedef Point3D_ Point3B; struct Point2D { float x, y; //////////////////////////////////////////////////////// Point2D(){} template Point2D(Float X, Float Y) {SetPoint2D(X, Y); } template void SetPoint2D(Float X, Float Y) { x = (float) X; y = (float) Y; } template void GetPoint2D(Float&X, Float&Y) const { X = (Float) x; Y = (Float) y; } }; } // namespace PBA #endif