00001
00034 #include <opencv/cv.h>
00035 #include <vector>
00036 #include "ObjectDetectorMethod.h"
00037 #include "ObjectModel.h"
00038 #include "CameraBridge.h"
00039
00040 #include "DUtilsCV.h"
00041 #include "DVision.h"
00042 #include "epnp.h"
00043 #include "NonLinearLS.h"
00044 #include <iostream>
00045
00046 using namespace std;
00047
00048 typedef DVision::PMVS::PLYFile::PLYPoint PLYPoint;
00049
00050
00051
00052 void ObjectDetectorMethod::calculatePose(const ObjectModel::Face &face,
00053 const std::vector<int> &face_indices, const DVision::SurfSet &scene_surfset,
00054 const std::vector<int> &scene_indices, const CameraBridge &camera,
00055 cv::Mat &cTo) const
00056 {
00057 const unsigned int N = face_indices.size();
00058 const cv::Mat &A = camera.GetIntrinsicParameters();
00059
00060 epnp PnP;
00061 PnP.set_maximum_number_of_correspondences(N);
00062 PnP.set_internal_parameters(
00063 A.at<float>(0, 2), A.at<float>(1, 2), A.at<float>(0, 0), A.at<float>(1, 1));
00064
00065 PnP.reset_correspondences();
00066
00067 for(unsigned int i = 0; i < N; ++i)
00068 {
00069 const PLYPoint &p3d = face.plypoints[ face_indices[i] ];
00070 const cv::KeyPoint &kp = scene_surfset.keys[ scene_indices[i] ];
00071 PnP.add_correspondence(p3d.x, p3d.y, p3d.z, kp.pt.x, kp.pt.y);
00072 }
00073
00074 double cRo_r[3][3], cto_r[3];
00075 PnP.compute_pose(cRo_r, cto_r);
00076
00077
00078
00079 OptimizationData dat;
00080 const cv::Mat &K=camera.GetIntrinsicParameters();
00081 const cv::Mat &dis=camera.GetDistortionParameters();
00082 dat.cal[0]=K.at<float>(0, 2);
00083 dat.cal[1]=K.at<float>(1, 2);
00084 dat.cal[2]=K.at<float>(0, 0);
00085 dat.cal[3]=K.at<float>(1, 1);
00086 dat.cal[4]=0.0;
00087 dat.cal[5]=0.0;
00088 dat.cam(0,0)=cRo_r[0][0]; dat.cam(0,1)=cRo_r[0][1]; dat.cam(0,2)=cRo_r[0][2];
00089 dat.cam(1,0)=cRo_r[1][0]; dat.cam(1,1)=cRo_r[1][1]; dat.cam(1,2)=cRo_r[1][2];
00090 dat.cam(2,0)=cRo_r[2][0]; dat.cam(2,1)=cRo_r[2][1]; dat.cam(2,2)=cRo_r[2][2];
00091
00092 dat.cam(3,0)=0; dat.cam(3,1)=0; dat.cam(3,2)=0; dat.cam(3,3)=1;
00093 dat.cam(0,3)=cto_r[0];
00094 dat.cam(1,3)=cto_r[1];
00095 dat.cam(2,3)=cto_r[2];
00096
00097 Vector2 pto2;
00098 Vector3 pto3;
00099 for(unsigned int i = 0; i < N; ++i)
00100 {
00101 const PLYPoint &p3d = face.plypoints[ face_indices[i] ];
00102 pto3[0]=p3d.x;
00103 pto3[1]=p3d.y;
00104 pto3[2]=p3d.z;
00105 dat.pto3D.push_back(pto3);
00106 const cv::KeyPoint &kp = scene_surfset.keys[ scene_indices[i] ];
00107 pto2[0]=kp.pt.x;
00108 pto2[1]=kp.pt.y;
00109 dat.pto2D.push_back(pto2);
00110 }
00111
00112
00113
00114 poseOptimization(dat);
00115
00116 cRo_r[0][0]=dat.cam(0,0); cRo_r[0][1]=dat.cam(0,1); cRo_r[0][2]=dat.cam(0,2);
00117 cRo_r[1][0]=dat.cam(1,0); cRo_r[1][1]=dat.cam(1,1); cRo_r[1][2]=dat.cam(1,2);
00118 cRo_r[2][0]=dat.cam(2,0); cRo_r[2][1]=dat.cam(2,1); cRo_r[2][2]=dat.cam(2,2);
00119 cto_r[0]=dat.cam(0,3);cto_r[1]=dat.cam(1,3);cto_r[2]=dat.cam(2,3);
00120
00121
00122 cv::Mat cRo(3, 3, CV_64F, cRo_r);
00123 cv::Mat cto(3, 1, CV_64F, cto_r);
00124
00125 cTo = DUtilsCV::Transformations::composeRt(cRo, cto);
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 }
00152
00153
00154
00155 void ObjectDetectorMethod::convertPose(const cv::Mat &T,
00156 geometry_msgs::Pose &pose) const
00157 {
00158 if(T.type() == CV_64F)
00159 {
00160 pose.position.x = T.at<double>(0, 3) / T.at<double>(3, 3);
00161 pose.position.y = T.at<double>(1, 3) / T.at<double>(3, 3);
00162 pose.position.z = T.at<double>(2, 3) / T.at<double>(3, 3);
00163 }
00164 else
00165 {
00166 pose.position.x = T.at<float>(0, 3) / T.at<float>(3, 3);
00167 pose.position.y = T.at<float>(1, 3) / T.at<float>(3, 3);
00168 pose.position.z = T.at<float>(2, 3) / T.at<float>(3, 3);
00169 }
00170
00171
00172 geometry_msgs::Quaternion &q = pose.orientation;
00173
00174 double a[3][3];
00175
00176 if(T.type() == CV_64F)
00177 {
00178 for(int i = 0; i < 3; ++i)
00179 for(int j = 0; j < 3; ++j)
00180 a[i][j] = T.at<double>(j,i);
00181 }
00182 else
00183 {
00184 for(int i = 0; i < 3; ++i)
00185 for(int j = 0; j < 3; ++j)
00186 a[i][j] = T.at<float>(j,i);
00187 }
00188
00189 double trace= a[0][0] + a[1][1] + a[2][2];
00190
00191 if (trace > 0){
00192 double sqtrp1 = sqrt( trace + 1.0 );
00193
00194 q.w = 0.5*sqtrp1;
00195 q.x = (a[1][2] - a[2][1])/(2.0*sqtrp1);
00196 q.y = (a[2][0] - a[0][2])/(2.0*sqtrp1);
00197 q.z = (a[0][1] - a[1][0])/(2.0*sqtrp1);
00198 }else{
00199 if ( (a[1][1] > a[0][0]) && (a[1][1] > a[2][2])){
00200 double sqdip1 = sqrt(a[1][1] - a[0][0] - a[2][2] + 1.0 );
00201
00202 q.y = 0.5*sqdip1;
00203
00204 if ( sqdip1 != 0 ) sqdip1 = 0.5/sqdip1;
00205
00206 q.w = (a[2][0] - a[0][2])*sqdip1;
00207 q.x = (a[0][1] + a[1][0])*sqdip1;
00208 q.z = (a[1][2] + a[2][1])*sqdip1;
00209 }else if (a[2][2] > a[0][0]){
00210 double sqdip1 = sqrt(a[2][2] - a[0][0] - a[1][1] + 1.0 );
00211
00212 q.z = 0.5*sqdip1;
00213
00214 if ( sqdip1 != 0 ) sqdip1 = 0.5/sqdip1;
00215
00216 q.w = (a[0][1] - a[1][0])*sqdip1;
00217 q.x = (a[2][0] + a[0][2])*sqdip1;
00218 q.y = (a[1][2] + a[2][1])*sqdip1;
00219 }else{
00220 double sqdip1 = sqrt(a[0][0] - a[1][1] - a[2][2] + 1.0 );
00221
00222 q.x = 0.5*sqdip1;
00223
00224 if ( sqdip1 != 0 ) sqdip1 = 0.5/sqdip1;
00225
00226 q.w = (a[1][2] - a[2][1])*sqdip1;
00227 q.y = (a[0][1] + a[1][0])*sqdip1;
00228 q.z = (a[2][0] + a[0][2])*sqdip1;
00229 }
00230 }
00231 }
00232
00233
00234
00235 void ObjectDetectorMethod::convert3DPoints(const ObjectModel::Face &face,
00236 const std::vector<int> &indices,
00237 const cv::Mat &cTo,
00238 std::vector<geometry_msgs::Point> &points3d) const
00239 {
00240 assert(cTo.type() == CV_64F);
00241
00242 cv::Mat oP(4, indices.size(), CV_64F);
00243
00244 for(unsigned int i = 0; i < indices.size(); ++i)
00245 {
00246 const PLYPoint &ply = face.plypoints[indices[i]];
00247 oP.at<double>(0, i) = ply.x;
00248 oP.at<double>(1, i) = ply.y;
00249 oP.at<double>(2, i) = ply.z;
00250 oP.at<double>(3, i) = 1;
00251 }
00252
00253 cv::Mat cP = cTo * oP;
00254 points3d.resize(indices.size());
00255
00256 for(unsigned int i = 0; i < indices.size(); ++i)
00257 {
00258 points3d[i].x = cP.at<double>(0, i) / cP.at<double>(3, i);
00259 points3d[i].y = cP.at<double>(1, i) / cP.at<double>(3, i);
00260 points3d[i].z = cP.at<double>(2, i) / cP.at<double>(3, i);
00261
00262 }
00263
00264 }
00265
00266
00267
00268 void ObjectDetectorMethod::convert3DPoints(const ObjectModel::Face &face,
00269 const cv::Mat &cTo,
00270 std::vector<geometry_msgs::Point> &points3d) const
00271 {
00272 assert(cTo.type() == CV_64F);
00273
00274 const unsigned int N = face.plypoints.size();
00275
00276 cv::Mat oP(4, N, CV_64F);
00277
00278 for(unsigned int i = 0; i < N; ++i)
00279 {
00280 const PLYPoint &ply = face.plypoints[i];
00281 oP.at<double>(0, i) = ply.x;
00282 oP.at<double>(1, i) = ply.y;
00283 oP.at<double>(2, i) = ply.z;
00284 oP.at<double>(3, i) = 1;
00285 }
00286
00287 cv::Mat cP = cTo * oP;
00288
00289 points3d.resize(N);
00290 for(unsigned int i = 0; i < N; ++i)
00291 {
00292 points3d[i].x = cP.at<double>(0, i) / cP.at<double>(3, i);
00293 points3d[i].y = cP.at<double>(1, i) / cP.at<double>(3, i);
00294 points3d[i].z = cP.at<double>(2, i) / cP.at<double>(3, i);
00295 }
00296
00297 }
00298
00299
00300
00301 void ObjectDetectorMethod::get3DModelPoints(const ObjectModel::Face &face,
00302 std::vector<geometry_msgs::Point> &points3d) const
00303 {
00304 const unsigned int N = face.plypoints.size();
00305 points3d.resize(N);
00306
00307 for(unsigned int i = 0; i < N; ++i)
00308 {
00309 const PLYPoint &ply = face.plypoints[i];
00310
00311 points3d[i].x = ply.x;
00312 points3d[i].y = ply.y;
00313 points3d[i].z = ply.z;
00314 }
00315 }
00316
00317
00318
00319 void ObjectDetectorMethod::get3DModelPoints(const ObjectModel::Face &face,
00320 const std::vector<int> &indices,
00321 std::vector<geometry_msgs::Point> &points3d) const
00322 {
00323 const unsigned int N =indices.size();
00324 points3d.resize(N);
00325
00326 for(unsigned int i = 0; i < N ; ++i)
00327 {
00328 const PLYPoint &ply = face.plypoints[indices[i]];
00329 points3d[i].x = ply.x;
00330 points3d[i].y = ply.y;
00331 points3d[i].z = ply.z;
00332 }
00333
00334 }
00335
00336
00337 void ObjectDetectorMethod::getPointsOctave(const ObjectModel::Face &face,
00338 const std::vector<int> &indices,
00339 std::vector<int> &octave) const
00340 {
00341 const unsigned int N =indices.size();
00342 octave.clear();
00343
00344 for(unsigned int i = 0; i < N; ++i)
00345 {
00346 const cv::KeyPoint &kp = face.surf.keys[indices[i]];
00347 octave.push_back(kp.octave);
00348 }
00349
00350 }
00351
00352 void ObjectDetectorMethod::getPointsOctave(const ObjectModel::Face &face,
00353 std::vector<int> &octave) const
00354 {
00355 for(unsigned int i = 0; i < face.surf.keys.size(); ++i)
00356 {
00357 const cv::KeyPoint &kp = face.surf.keys[i];
00358 octave.push_back(kp.octave);
00359 }
00360
00361 }
00362
00363
00364
00365 void ObjectDetectorMethod::project2DPoints(const ObjectModel::Face &face,
00366 const cv::Mat &cTo, const CameraBridge &camera,
00367 std::vector<re_msgs::Pixel> &points2d) const
00368 {
00369 const unsigned int N = face.plypoints.size();
00370
00371 cv::Mat oP(4, N, CV_64F);
00372
00373 for(unsigned int i = 0; i < N; ++i)
00374 {
00375 const PLYPoint &ply = face.plypoints[i];
00376 oP.at<double>(0, i) = ply.x;
00377 oP.at<double>(1, i) = ply.y;
00378 oP.at<double>(2, i) = ply.z;
00379 oP.at<double>(3, i) = 1;
00380 }
00381
00382 cv::Mat cP = cTo * oP;
00383
00384 cv::Mat oP_4x3(oP.cols, 3, CV_32F);
00385 for(int c = 0; c < oP.cols; ++c)
00386 for(int r = 0; r < 3; ++r)
00387 oP_4x3.at<float>(c, r) = oP.at<double>(r, c) / oP.at<double>(3, c);
00388
00389 cv::Mat cRo;
00390 cv::Mat cto(3, 1, CV_64F);
00391 DUtilsCV::Transformations::decomposeRt(cTo, cRo, cto);
00392
00393 vector<cv::Point2f> cam_pixels;
00394 cv::projectPoints(oP_4x3, cRo, cto, camera.GetIntrinsicParameters(),
00395 cv::Mat::zeros(4,1,CV_32F), cam_pixels);
00396
00397
00398 points2d.resize(N);
00399 for(unsigned int i = 0; i < N; ++i)
00400 {
00401 points2d[i].x = cam_pixels[i].x;
00402 points2d[i].y = cam_pixels[i].y;
00403 }
00404
00405 }
00406
00407
00408 void ObjectDetectorMethod::project2DPoints(const ObjectModel::Face &face,
00409 const cv::Mat &cTo, const CameraBridge &camera,
00410 const std::vector<int> &indices,
00411 std::vector<re_msgs::Pixel> &points2d) const
00412 {
00413 const unsigned int N = indices.size();
00414
00415 cv::Mat oP(4, N, CV_64F);
00416
00417 for(unsigned int i = 0; i < N; ++i)
00418 {
00419 const PLYPoint &ply = face.plypoints[indices[i]];
00420 oP.at<double>(0, i) = ply.x;
00421 oP.at<double>(1, i) = ply.y;
00422 oP.at<double>(2, i) = ply.z;
00423 oP.at<double>(3, i) = 1;
00424 }
00425
00426 cv::Mat cP = cTo * oP;
00427
00428 cv::Mat oP_4x3(oP.cols, 3, CV_32F);
00429 for(int c = 0; c < oP.cols; ++c)
00430 for(int r = 0; r < 3; ++r)
00431 oP_4x3.at<float>(c, r) = oP.at<double>(r, c) / oP.at<double>(3, c);
00432
00433 cv::Mat cRo;
00434 cv::Mat cto(3, 1, CV_64F);
00435 DUtilsCV::Transformations::decomposeRt(cTo, cRo, cto);
00436
00437 vector<cv::Point2f> cam_pixels;
00438 cv::projectPoints(oP_4x3, cRo, cto, camera.GetIntrinsicParameters(),
00439 cv::Mat::zeros(4,1,CV_32F), cam_pixels);
00440
00441
00442 points2d.resize(N);
00443 for(unsigned int i = 0; i < N; ++i)
00444 {
00445 points2d[i].x = cam_pixels[i].x;
00446 points2d[i].y = cam_pixels[i].y;
00447 }
00448
00449 }
00450
00451
00452 void ObjectDetectorMethod::changeOrientation(const cv::Mat &cTo, cv::Mat &rTo)
00453 const
00454 {
00455
00456
00457
00458
00459
00460 if(cTo.type() == CV_32F)
00461 {
00462 rTo = (cv::Mat_<float>(4, 4) <<
00463 cTo.at<float>(2,0), cTo.at<float>(2,1), cTo.at<float>(2,2), cTo.at<float>(2,3),
00464 -cTo.at<float>(0,0), -cTo.at<float>(0,1), -cTo.at<float>(0,2), -cTo.at<float>(0,3),
00465 -cTo.at<float>(1,0), -cTo.at<float>(1,1), -cTo.at<float>(1,2), -cTo.at<float>(1,3),
00466 cTo.at<float>(3,0), cTo.at<float>(3,1), cTo.at<float>(3,2), cTo.at<float>(3,3));
00467 }
00468 else
00469 {
00470 rTo = (cv::Mat_<double>(4, 4) <<
00471 cTo.at<double>(2,0), cTo.at<double>(2,1), cTo.at<double>(2,2), cTo.at<double>(2,3),
00472 -cTo.at<double>(0,0), -cTo.at<double>(0,1), -cTo.at<double>(0,2), -cTo.at<double>(0,3),
00473 -cTo.at<double>(1,0), -cTo.at<double>(1,1), -cTo.at<double>(1,2), -cTo.at<double>(1,3),
00474 cTo.at<double>(3,0), cTo.at<double>(3,1), cTo.at<double>(3,2), cTo.at<double>(3,3));
00475 }
00476 }
00477
00478
00479
00480