32 #include <Base/Common/CompareFloatingPoint.hh>
33 #include <Geometry/CoordinateTransform3D.hh>
34 #include <Geometry/ProjectionParametersBase.hh>
35 #include <Geometry/ProjectionParametersBufferedRay.hh>
36 #include <Geometry/ProjectionParametersCylindric.hh>
37 #include <Geometry/ProjectionParametersFactory.hh>
38 #include <Geometry/ProjectionParametersGreatCircles.hh>
39 #include <Geometry/ProjectionParametersIO.hh>
40 #include <Geometry/ProjectionParametersPerspective.hh>
41 #include <Geometry/ProjectionParametersPerspectiveDepth.hh>
42 #include <Geometry/ProjectionParametersSpherical.hh>
43 #include <Geometry/ProjectionParametersSphericalSimple.hh>
44 #include <Geometry/ProjectionParametersZoom.hh>
45 #include <Base/Image/Image.hh>
46 #include <Base/Image/ImageIO.hh>
47 #include <Base/Math/Random.hh>
52 #include <Base/Common/XMLIO.hh>
60 #define MAX_COORDS_3D 100.0
65 int main(
int argc,
char *argv[])
68 const unsigned int width = 1000;
69 const unsigned int height = 1000;
70 const unsigned int radius = min(width,height);
71 const double phi = M_PI;
72 const double theta = M_PI;
76 pp_persp.SetSimplePerspective(0.5*phi, width, height);
79 pp_sph_smp(-0.5*phi, 0, phi/(
double)radius,
80 theta/(
double)radius, width, height);
82 pp_cyl(-10.0, 10.0, -0.5*phi, 0.5*phi, width, height);
85 pp_gr_circ.SetInternals(-0.5*phi, 0.5*phi, 0, theta, width, height);
87 std::vector<ProjectionParametersBase*> projections;
88 std::vector<std::string> names;
89 projections.push_back(&pp_persp);
90 names.push_back(
"ProjectionParametersPerspective");
91 projections.push_back(&pp_sph);
92 names.push_back(
"ProjectionParametersSpherical");
93 projections.push_back(&pp_sph_smp);
94 names.push_back(
"ProjectionParametersSphericalSimple");
95 projections.push_back(&pp_cyl);
96 names.push_back(
"ProjectionParametersCylindric");
97 projections.push_back(&pp_buf_ray);
98 names.push_back(
"ProjectionParametersBufferedRay");
99 projections.push_back(&pp_gr_circ);
100 names.push_back(
"ProjectionParametersGreatCircles");
101 projections.push_back(&pp_zoom);
102 names.push_back(
"ProjectionParametersZoom");
103 const unsigned int projs_num = projections.size();
104 BIASASSERT(projections.size() == names.size());
110 cout <<
"Start pose interface tests...\n";
111 for (
unsigned int proj_id = 0; proj_id < projs_num; proj_id++)
113 cout <<
"- Testing " << names[proj_id] <<
"... ";
114 if (verbose) cout << endl;
123 for (
unsigned int k = 0; k < 3; k++)
124 C[k] = random.GetUniformDistributed (-MAX_C, MAX_C);
125 for (
unsigned int k = 0; k < 3; k++)
126 rad[k] = random.GetUniformDistributed (-M_PI, M_PI);
127 q.SetXYZ(rad[0], rad[1], rad[2]);
129 if (verbose) cout <<
" - created random pose C = " << C <<
", q = "
130 << q <<
", R = " << R << endl;
134 cout << names[proj_id] <<
" pose should be initially invalid!\n";
141 cout << names[proj_id] <<
" CValid() failed after setting position!\n";
145 cout << names[proj_id] <<
" pose should stay invalid after setting "
146 <<
"position only, but is valid!\n";
153 cout << names[proj_id] <<
" QValid() failed after setting orientation!\n";
157 cout << names[proj_id] <<
" pose should be valid after setting position "
158 <<
"and orientation, but is invalid!\n";
165 cout << names[proj_id] <<
" pose should be invalid after Invalidate()!\n";
170 cout << names[proj_id] <<
" pose should be valid after Validate()!\n";
180 if (verbose) cout <<
" GetC() : " << C <<
", GetQ() : " << q
181 <<
", GetR() : " << R << endl;
183 cout << names[proj_id] <<
" position differs after Set()/Get()!\n";
184 cout <<
"expected C = " << C <<
"\tfound C = " << test_C << endl;
189 cout << names[proj_id] <<
" orientation differs after Set()/Get()!\n";
190 cout <<
"expected q = +-" << q <<
"\tfound q = " << test_q << endl;
193 if (!
BIAS::Equal((R-test_R).NormL2(), 0.0, EPSILON)) {
194 cout << names[proj_id] <<
" rotation matrix differs after Set()/Get()!\n";
195 cout <<
"expected R = " << R <<
"\tfound R = " << test_R << endl;
201 if (verbose) cout <<
" - GetPoseParametrization() : " << pose << endl;
206 cout << names[proj_id] <<
" position differs from pose parametrization!\n";
207 cout <<
"expected C = " << C <<
"\tfound C = " << test_C << endl;
212 cout << names[proj_id] <<
" orientation differs from pose parametrization!\n";
213 cout <<
"expected q = +-" << q <<
"\tfound q = " << test_q << endl;
219 if (verbose) cout <<
" - GetExternals() : " << T << endl;
224 cout << names[proj_id] <<
" position differs from externals!\n";
225 cout <<
"expected C = " << C <<
"\tfound C = " << test_C << endl;
228 if (!
BIAS::Equal((R-test_R).NormL2(), 0.0, EPSILON)) {
229 cout << names[proj_id] <<
" rotation matrix differs from externals!\n";
230 cout <<
"expected R = " << R <<
"\tfound R = " << test_R << endl;
235 if (ppb->ProjectionParametersBase::DoIntrinsicsDiffer(ppb)) {
236 cout << names[proj_id] <<
" intrinsics differ from themselves!\n";
240 cout << names[proj_id] <<
" extrinsics differ from themselves!\n";
246 if (ppb->ProjectionParametersBase::DoIntrinsicsDiffer(ppb_copy)) {
247 cout << names[proj_id] <<
" intrinsics differ after Clone()!\n";
251 cout << names[proj_id] <<
" extrinsics differ after Clone()!\n";
256 if (verbose) cout <<
" -> "; cout <<
"OK\n";
259 #ifdef BIAS_HAVE_XML2
261 cout <<
"Start XML input/output tests...\n";
263 for (
unsigned int proj_id = 0; proj_id < projs_num; proj_id++)
265 cout <<
"- Testing " << names[proj_id] <<
"... ";
266 if (verbose) cout << endl;
272 std::string filename =
"Test";
273 filename.append(names[proj_id]);
274 filename.append(
".xml");
279 xmlNodePtr xmlNode = xmlIO.
create(xmlName);
281 if (ppb->
XMLOut(xmlNode, xmlIO) != 0) {
282 cout << names[proj_id] <<
" failed to export XML node with XMLOut()!\n";
285 if (xmlIO.
write(filename) != 0) {
286 cout << names[proj_id] <<
" failed to write XML to " << filename <<
"!\n";
291 xmlNode = xmlIO.
read(filename);
292 if (xmlNode == NULL) {
293 cout << names[proj_id] <<
" failed to read XML from " << filename <<
"!\n";
296 if (ppb_copy->
XMLIn(xmlNode, xmlIO) != 0) {
297 cout << names[proj_id] <<
" failed to import XML node with XMLIn()!\n";
302 if (ppb->ProjectionParametersBase::DoIntrinsicsDiffer(ppb_copy)) {
303 cout << names[proj_id] <<
" intrinsics differ after importing XML!\n";
307 cout << names[proj_id] <<
" extrinsics differ after importing XML!\n";
312 if (verbose) cout <<
" -> "; cout <<
"OK\n";
317 cout <<
"Start projection tests...\n";
319 const unsigned int points_num = 100;
320 for (
unsigned int proj_id = 0; proj_id < projs_num; proj_id++)
322 cout <<
"- Testing " << names[proj_id] <<
"... ";
323 if (verbose) cout << endl;
328 if (ppb == &pp_buf_ray || ppb == &pp_zoom) {
329 if (verbose) cout <<
" -> "; cout <<
"Skipped\n";
349 std::vector<HomgPoint2D> points2D;
350 std::vector<HomgPoint3D> points3D;
355 if (verbose) cout <<
"C = " << C << endl;
356 for (
unsigned int i = 0; i < points_num; i++)
358 for (
unsigned int k = 0; k < 3; k++)
360 random.GetUniformDistributed(C[k]-MAX_COORDS_3D, C[k]+MAX_COORDS_3D);
361 points3D.push_back(point3D);
362 point2D = ppb->
Project(point3D);
363 if (BIAS_ISNAN(point2D[0]) || BIAS_ISNAN(point2D[1]) || BIAS_ISNAN(point2D[2]))
365 points2D.push_back(point2D);
367 cout <<
"[" << i <<
"] " << points2D[i] <<
" <-> " << points3D[i] << endl;
373 unsigned int invisible_num = 0;
374 for (
unsigned int i = 0; i < points_num; i++)
377 point2D = points2D[i];
384 eucl3D = points3D[i].GetEuclidean();
385 depth = C.Dist(eucl3D);
388 diff = point3D.
Dist(points3D[i]);
390 cout << names[proj_id] <<
" unprojection yield inconsistent results!\n";
391 cout <<
"3D point " << points3D[i] <<
" -> 2D point " << point2D
392 <<
" -> 3D point " << point3D <<
" (difference = "
393 << diff <<
")" << endl;
398 diff = ray3D.
Dist((eucl3D-C).GetNormalized());
400 cout << names[proj_id] <<
" unprojection yield inconsistent results!\n";
401 cout <<
"3D ray " << (eucl3D-C).GetNormalized() <<
" -> 2D point "
402 << point2D <<
" -> 3D ray " << ray3D <<
" (difference = "
403 << diff <<
")" << endl;
421 if (verbose) cout <<
" -> ";
422 cout <<
"OK (" << invisible_num <<
" not visible)\n";
426 cout <<
"Create debug images...\n";
428 for (
unsigned int proj_id = 0; proj_id < projs_num; proj_id++)
430 cout <<
"- Save debug image for " << names[proj_id] <<
"... ";
438 unsigned char *ptr = image.GetImageData();
439 for (
unsigned int y = 0; y < height; y++) {
441 for (
unsigned int x = 0; x < width; x++) {
446 for (
unsigned int k = 0; k < 3; k++)
447 *(ptr++) = (
unsigned char)rint(255.0*fabs(ray3D[k]));
452 std::string filename =
"Test";
453 filename.append(names[proj_id]);
454 filename.append(
".png");
virtual BIAS::Vector3< double > GetC() const
Get projection center.
void addAttribute(const xmlNodePtr Node, const std::string &AttributeName, bool AttributeValue)
Add an attribute to a node.
This class maps image coords to rays which are buffered for fast lookup.
void Multiply(const T &scalar, Vector4< T > &dest) const
Multiplication with a scalar, storing results in destionation vector.
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
int write(const std::string &Filename, bool AutoAddCompressionSuffix=true) const
Write the whole tree that was constructed in memory to disk.
xmlNodePtr read(const std::string &Filename)
Read and parse an XML file from disk, DtD validation is not yet implemented.
virtual int XMLOut(const xmlNodePtr Node, XMLIO &XMLObject) const
Specialization of XML write function.
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
virtual HomgPoint3D UnProjectToPoint(const HomgPoint2D &pos, double depth, bool IgnoreDistortion=false) const
calculates a 3D point in the global (not the rig) coordinate system, which belongs to the image posit...
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
virtual BIAS::Matrix3x4< double > GetExternals() const
Return cached 3x4 representation of external matrix [R|C].
virtual ProjectionParametersBase * Clone() const =0
Covariant virtual copy constructor used in BIAS::Projection.
xmlNodePtr create(const std::string &RootNodeName)
Create the base of a new XML-Tree in memory, already with a one and only root node.
Vector< T > GetCol(const int &col) const
return a copy of column "col", zero based counting
int SetFromQuaternion(const Quaternion< ROTATION_MATRIX_TYPE > &q)
Set rotation matrix from a quaternion.
Slim class bundeling pose parametrization and associated covariance matrix.
virtual void UnProjectToRay(const HomgPoint2D &pos, Vector3< double > &origin, Vector3< double > &direction, bool ignoreDistortion=false) const
Calculates the view ray, which belongs to the given position on the image plane, in global coordinate...
virtual int XMLIn(const xmlNodePtr Node, XMLIO &XMLObject)
Specialization of XML read function.
spherical camera that samples along big circles containig the H vector.
virtual HomgPoint2D Project(const HomgPoint3D &X, bool IgnoreDistortion=false) const
calculates the projection of a point in the world coordinate system to a pixel in the image plane of ...
double Dist(const Vector3< T > &vec) const
Return the euclidean distance of 2 vectors.
virtual void SetQ(const BIAS::Quaternion< double > &Q)
Set orientation from unit quaternion Q.
Wrapper class for reading and writing XML files based on the XML library libxml2. ...
void Mult(const Vector3< T > &argvec, Vector3< T > &destvec) const
matrix - vector multiplicate this matrix with Vector3, storing the result in destvec calculates: dest...
virtual bool PoseValid() const
Check if current pose is valid.
void SetFromRowVectors(const BIAS::Vector3< T > &v0, const BIAS::Vector3< T > &v1, const BIAS::Vector3< T > &v2)
set this matrix from 3 vectors, each representating a row
virtual BIAS::PoseParametrization GetPoseParametrization() const
Return copy of pose parametrization object.
virtual bool QValid() const
Check if current orientation is valid.
virtual BIAS::RMatrix GetR() const
Get orientation as rotation matrix R.
virtual Vector3< double > UnProjectToPointLocal(const HomgPoint2D &pos, const double &depth, bool IgnoreDistortion=false) const
calculates a 3D point in the local camera coordinate system, which belongs to the image position pos ...
double Dist(const Vector4< T > &vec) const
Return the euclidean distance of 2 vectors.
virtual bool CValid() const
Check of current projection center is valid.
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
bool Equal(const T left, const T right, const T eps)
comparison function for floating point values See http://www.boost.org/libs/test/doc/components/test_...
Vector3< PP_TYPE > GetPosition() const
returns the position (first 3 entries) part of the pose parametrization vector
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
void MultIP(const T &scalar)
virtual const bool DoExtrinsicsDiffer(const ProjectionParametersBase *p) const
virtual void ValidatePose()
Validate currently set pose.
virtual int XMLGetClassName(std::string &TopLevelTag, double &Version) const
Specialization of XML block name function.
Quaternion< PP_TYPE > GetOrientation() const
returns the quaternion (last 4 entries) part of the pose parametrization vector
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
void Set(const HOMGPOINT2D_TYPE &x, const HOMGPOINT2D_TYPE &y)
set elementwise with given 2 euclidean scalar values.
virtual BIAS::Quaternion< double > GetQ() const
Get orientation as unit quaternion.
virtual void SetC(const BIAS::Vector3< double > &C)
Set projection center.
Vector3< T > & Normalize()
normalize this vector to length 1
class for producing random numbers from different distributions
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
virtual void InvalidatePose()
Invalidate currently set pose.