utest.cpp
Go to the documentation of this file.
00001 #include "image_geometry/pinhole_camera_model.h"
00002 #include <sensor_msgs/distortion_models.h>
00003 #include <gtest/gtest.h>
00004 
00010 
00011 class PinholeTest : public testing::Test
00012 {
00013 protected:
00014   virtual void SetUp()
00015   {
00017     // These parameters taken from a real camera calibration
00018     double D[] = {-0.363528858080088, 0.16117037733986861, -8.1109585007538829e-05, -0.00044776712298447841, 0.0};
00019     double K[] = {430.15433020105519,                0.0, 311.71339830549732,
00020                                  0.0, 430.60920415473657, 221.06824942698509,
00021                                  0.0,                0.0,                1.0};
00022     double R[] = {0.99806560714807102, 0.0068562422224214027, 0.061790256276695904,
00023                   -0.0067522959054715113, 0.99997541519165112, -0.0018909025066874664,
00024                   -0.061801701660692349, 0.0014700186639396652, 0.99808736527268516};
00025     double P[] = {295.53402059708782, 0.0, 285.55760765075684, 0.0,
00026                   0.0, 295.53402059708782, 223.29617881774902, 0.0,
00027                   0.0, 0.0, 1.0, 0.0};
00028 
00029     cam_info_.header.frame_id = "tf_frame";
00030     cam_info_.height = 480;
00031     cam_info_.width  = 640;
00032     // No ROI
00033     cam_info_.D.resize(5);
00034     std::copy(D, D+5, cam_info_.D.begin());
00035     std::copy(K, K+9, cam_info_.K.begin());
00036     std::copy(R, R+9, cam_info_.R.begin());
00037     std::copy(P, P+12, cam_info_.P.begin());
00038     cam_info_.distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
00039 
00040     model_.fromCameraInfo(cam_info_);
00041   }
00042   
00043   sensor_msgs::CameraInfo cam_info_;
00044   image_geometry::PinholeCameraModel model_;
00045 };
00046 
00047 TEST_F(PinholeTest, accessorsCorrect)
00048 {
00049   EXPECT_EQ((unsigned)480, model_.height());
00050   EXPECT_EQ((unsigned)640, model_.width());
00051   EXPECT_STREQ("tf_frame", model_.tfFrame().c_str());
00052   EXPECT_EQ(cam_info_.P[0], model_.fx());
00053   EXPECT_EQ(cam_info_.P[5], model_.fy());
00054   EXPECT_EQ(cam_info_.P[2], model_.cx());
00055   EXPECT_EQ(cam_info_.P[6], model_.cy());
00056 }
00057 
00058 TEST_F(PinholeTest, projectPoint)
00059 {
00060   // Spot test an arbitrary point.
00061   {
00062     cv::Point2d uv(100, 100);
00063     cv::Point3d xyz;
00064     model_.projectPixelTo3dRay(uv, xyz);
00065     EXPECT_NEAR(-0.62787224048135637, xyz.x, 1e-8);
00066     EXPECT_NEAR(-0.41719792045817677, xyz.y, 1e-8);
00067     EXPECT_DOUBLE_EQ(1.0, xyz.z);
00068   }
00069 
00070   // Principal point should project straight out.
00071   {
00072     cv::Point2d uv(model_.cx(), model_.cy());
00073     cv::Point3d xyz;
00074     model_.projectPixelTo3dRay(uv, xyz);
00075     EXPECT_DOUBLE_EQ(0.0, xyz.x);
00076     EXPECT_DOUBLE_EQ(0.0, xyz.y);
00077     EXPECT_DOUBLE_EQ(1.0, xyz.z);
00078   }
00079   
00080   // Check projecting to 3d and back over entire image is accurate.
00081   const size_t step = 10;
00082   for (size_t row = 0; row <= cam_info_.height; row += step) {
00083     for (size_t col = 0; col <= cam_info_.width; col += step) {
00084       cv::Point2d uv(row, col), uv_back;
00085       cv::Point3d xyz;
00086       model_.projectPixelTo3dRay(uv, xyz);
00087       model_.project3dToPixel(xyz, uv_back);
00088       // Measured max error at 1.13687e-13
00089       EXPECT_NEAR(uv.x, uv_back.x, 1.14e-13) << "at (" << row << ", " << col << ")";
00090       EXPECT_NEAR(uv.y, uv_back.y, 1.14e-13) << "at (" << row << ", " << col << ")";
00091     }
00092   }
00093 }
00094 
00095 TEST_F(PinholeTest, rectifyPoint)
00096 {
00097   // Spot test an arbitrary point.
00098   {
00099     cv::Point2d uv_raw(100, 100), uv_rect;
00100     model_.rectifyPoint(uv_raw, uv_rect);
00101     EXPECT_DOUBLE_EQ(142.30311584472656, uv_rect.x);
00102     EXPECT_DOUBLE_EQ(132.061065673828, uv_rect.y);
00103   }
00104 
00106 #if 0
00107   // Test rectifyPoint takes (c'x, c'y) [from K] -> (cx, cy) [from P].
00108   double cxp = model_.intrinsicMatrix()(0,2), cyp = model_.intrinsicMatrix()(1,2);
00109   {
00110     cv::Point2d uv_raw(cxp, cyp), uv_rect;
00111     model_.rectifyPoint(uv_raw, uv_rect);
00112     EXPECT_NEAR(uv_rect.x, model_.cx(), 1e-4);
00113     EXPECT_NEAR(uv_rect.y, model_.cy(), 1e-4);
00114   }
00115 
00116   // Test unrectifyPoint takes (cx, cy) [from P] -> (c'x, c'y) [from K].
00117   {
00118     cv::Point2d uv_rect(model_.cx(), model_.cy()), uv_raw;
00119     model_.unrectifyPoint(uv_rect, uv_raw);
00120     EXPECT_NEAR(uv_raw.x, cxp, 1e-4);
00121     EXPECT_NEAR(uv_raw.y, cyp, 1e-4);
00122   }
00123 #endif
00124 
00125   // Check rectifying then unrectifying over most of the image is accurate.
00126   const size_t step = 5;
00127   const size_t border = 65; // Expect bad accuracy far from the center of the image.
00128   for (size_t row = border; row <= cam_info_.height - border; row += step) {
00129     for (size_t col = border; col <= cam_info_.width - border; col += step) {
00130       cv::Point2d uv_raw(row, col), uv_rect, uv_unrect;
00131       model_.rectifyPoint(uv_raw, uv_rect);
00132       model_.unrectifyPoint(uv_rect, uv_unrect);
00133       // Check that we're at least within a pixel...
00134       EXPECT_NEAR(uv_raw.x, uv_unrect.x, 1.0);
00135       EXPECT_NEAR(uv_raw.y, uv_unrect.y, 1.0);
00136     }
00137   }
00138 }
00139 
00140 TEST_F(PinholeTest, getDeltas)
00141 {
00142   double u = 100.0, v = 200.0, du = 17.0, dv = 23.0, Z = 2.0;
00143   cv::Point2d uv0(u, v), uv1(u + du, v + dv);
00144   cv::Point3d xyz0, xyz1;
00145   model_.projectPixelTo3dRay(uv0, xyz0);
00146   xyz0 *= (Z / xyz0.z);
00147   model_.projectPixelTo3dRay(uv1, xyz1);
00148   xyz1 *= (Z / xyz1.z);
00149 
00150   EXPECT_NEAR(model_.getDeltaU(xyz1.x - xyz0.x, Z), du, 1e-4);
00151   EXPECT_NEAR(model_.getDeltaV(xyz1.y - xyz0.y, Z), dv, 1e-4);
00152   EXPECT_NEAR(model_.getDeltaX(du, Z), xyz1.x - xyz0.x, 1e-4);
00153   EXPECT_NEAR(model_.getDeltaY(dv, Z), xyz1.y - xyz0.y, 1e-4);
00154 }
00155 
00156 int main(int argc, char** argv)
00157 {
00158   testing::InitGoogleTest(&argc, argv);
00159   return RUN_ALL_TESTS();
00160 }


image_geometry
Author(s): Patrick Mihelich
autogenerated on Sat Dec 28 2013 17:44:01