00001
00005 #include "reconstruction.hpp"
00006
00007 void summarizeTransformation(const cv::Mat& C, char *summary) {
00008
00009 cv::Mat P, R, Rv, t;
00010 transformationToProjection(C, P);
00011 decomposeTransform(C, R, t);
00012 Rodrigues(R, Rv);
00013
00014 double unitsDist, degreesRot;
00015 unitsDist = getDistanceInUnits(t);
00016 degreesRot = getRotationInDegrees(R);
00017
00018 sprintf(summary, "%f units (%f, %f, %f); %f degrees", unitsDist, t.at<double>(0,0), t.at<double>(1,0), t.at<double>(2,0), degreesRot);
00019
00020 }
00021
00022 int findBestCandidate(const cv::Mat *CX, const cv::Mat& K, const vector<cv::Point2f>& pts1, const vector<cv::Point2f>& pts2, cv::Mat& C) {
00023
00024 int bestScore = 0, bestCandidate = 0;
00025
00026 for (int kkk = 0; kkk < 4; kkk++) {
00027
00028 int validPts = pointsInFront(CX[kkk], K, pts1, pts2);
00029
00030 if (validPts > bestScore) {
00031 bestScore = validPts;
00032 bestCandidate = kkk;
00033 }
00034
00035
00036 }
00037
00038 CX[bestCandidate].copyTo(C);
00039
00040 return bestScore;
00041 }
00042
00043 void reverseTranslation(cv::Mat& C) {
00044
00045 for (unsigned int iii = 0; iii < 3; iii++) {
00046 C.at<double>(iii,3) = -C.at<double>(iii,3);
00047 }
00048
00049 }
00050
00051
00052
00053 void findFeaturesForPoints(vector<featureTrack>& tracks, vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, vector<cv::Point3d>& pts3d, int idx1, int idx2) {
00054
00055
00056 for (unsigned int jjj = 0; jjj < pts3d.size(); jjj++) {
00057
00058
00059
00060 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00061
00062
00063
00064
00065 if (tracks.at(iii).get3dLoc() == pts3d.at(jjj)) {
00066
00067
00068
00069 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size(); kkk++) {
00070
00071
00072
00073 if (((int)tracks.at(iii).locations.at(kkk).imageIndex) == idx1) {
00074
00075 pts1.push_back(tracks.at(iii).locations.at(kkk).featureCoord);
00076
00077 } else if (((int)tracks.at(iii).locations.at(kkk).imageIndex) == idx2) {
00078
00079 pts2.push_back(tracks.at(iii).locations.at(kkk).featureCoord);
00080
00081 }
00082
00083 }
00084
00085 }
00086
00087 }
00088
00089
00090 }
00091
00092 }
00093
00094 int countTriangulatedTracks(const vector<featureTrack>& tracks) {
00095
00096 int triangulatedCount = 0;
00097
00098 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00099
00100 if (tracks.at(iii).isTriangulated) {
00101 triangulatedCount++;
00102 }
00103 }
00104
00105 return triangulatedCount;
00106
00107 }
00108
00109 int countActiveTriangulatedTracks(vector<unsigned int>& indices, vector<featureTrack>& tracks) {
00110
00111 int triangulatedCount = 0;
00112
00113 for (unsigned int iii = 0; iii < indices.size(); iii++) {
00114
00115 if (tracks.at(indices.at(iii)).isTriangulated) {
00116 triangulatedCount++;
00117 }
00118
00119 }
00120
00121 return triangulatedCount;
00122
00123 }
00124
00125 void getIndicesForTriangulation(vector<unsigned int>& dst, vector<unsigned int>& src, vector<unsigned int>& already_triangulated) {
00126
00127 dst.clear();
00128
00129 for (unsigned int iii = 0; iii < src.size(); iii++) {
00130
00131 bool triangulated = false;
00132
00133 for (unsigned int jjj = 0; jjj < already_triangulated.size(); jjj++) {
00134
00135 if (already_triangulated.at(jjj) == src.at(iii)) {
00136 triangulated = true;
00137 continue;
00138 }
00139
00140
00141 }
00142
00143 if (!triangulated) {
00144
00145 dst.push_back(src.at(iii));
00146
00147 }
00148
00149
00150 }
00151
00152 }
00153
00154 void reconstructSubsequence(vector<featureTrack>& tracks, vector<cv::Point3d>& ptCloud, int idx1, int idx2) {
00155
00156 }
00157
00158 void removeShortTracks(vector<featureTrack>& tracks, int idx1, int idx2) {
00159
00160 int minLength = (idx2 - idx1) / 2;
00161
00162 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00163 int trackLength = tracks.at(iii).locations.size();
00164 if (trackLength < minLength) {
00165 int final_image = tracks.at(iii).locations.at(trackLength-1).imageIndex;
00166
00167 if ((final_image >= idx1) && (final_image < idx2)) {
00168 tracks.erase(tracks.begin() + iii);
00169 iii--;
00170 }
00171
00172 }
00173 }
00174
00175 }
00176
00177 void updateSystemTracks(SysSBA& sys, vector<featureTrack>& tracks, unsigned int start_index) {
00178
00179
00180
00181 sys.tracks.clear();
00182
00183
00184 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00185
00186
00187
00188 if (tracks.at(iii).isTriangulated) {
00189
00190
00191
00192
00193 Vector4d temppoint(tracks.at(iii).get3dLoc().x, tracks.at(iii).get3dLoc().y, tracks.at(iii).get3dLoc().z, 1.0);
00194 sys.addPoint(temppoint);
00195
00196
00197
00198
00199
00200
00201
00202 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size(); jjj++) {
00203
00204
00205
00206 if ((((unsigned int) tracks.at(iii).locations.at(jjj).imageIndex) >= start_index) && (((unsigned int) tracks.at(iii).locations.at(jjj).imageIndex) < (start_index+sys.nodes.size()))) {
00207
00208
00209 Vector2d proj;
00210
00211 proj.x() = tracks.at(iii).locations.at(jjj).featureCoord.x;
00212 proj.y() = tracks.at(iii).locations.at(jjj).featureCoord.y;
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 sys.addMonoProj(tracks.at(iii).locations.at(jjj).imageIndex-start_index, sys.tracks.size()-1, proj);
00223
00224
00225
00226
00227 }
00228
00229
00230
00231 }
00232
00233
00234
00235 }
00236
00237 }
00238
00239 }
00240
00241 void updateTriangulatedPoints(vector<featureTrack>& tracks, vector<unsigned int>& indices, vector<cv::Point3d>& cloud) {
00242
00243 if (cloud.size() != indices.size()) {
00244 printf("%s << ERROR! Cloud size and index list size don't match (%d vd %d)\n", __FUNCTION__, ((int)cloud.size()), ((int)indices.size()));
00245 }
00246
00247 for (unsigned int iii = 0; iii < indices.size(); iii++) {
00248
00249 if (tracks.at(indices.at(iii)).isTriangulated) {
00250
00251 }
00252
00253 tracks.at(indices.at(iii)).set3dLoc(cloud.at(iii));
00254
00255
00256
00257 }
00258
00259 }
00260
00261 void reduceActiveToTriangulated(vector<featureTrack>& tracks, vector<unsigned int>& indices, vector<unsigned int>& untriangulated) {
00262
00263 for (unsigned int iii = 0; iii < indices.size(); iii++) {
00264
00265 if (!tracks.at(indices.at(iii)).isTriangulated) {
00266 untriangulated.push_back(indices.at(iii));
00267 indices.erase(indices.begin() + iii);
00268 iii--;
00269 }
00270
00271 }
00272
00273 }
00274
00275 void filterToActivePoints(vector<featureTrack>& tracks, vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, vector<unsigned int>& indices, int idx1, int idx2) {
00276
00277 pts1.clear();
00278 pts2.clear();
00279
00280 for (unsigned int iii = 0; iii < indices.size(); iii++) {
00281
00282 for (unsigned int jjj = 0; jjj < tracks.at(indices.at(iii)).locations.size()-1; jjj++) {
00283
00284 if (((int)tracks.at(indices.at(iii)).locations.at(jjj).imageIndex) == idx1) {
00285
00286 pts1.push_back(tracks.at(indices.at(iii)).locations.at(jjj).featureCoord);
00287
00288 for (unsigned int kkk = jjj+1; kkk < tracks.at(indices.at(iii)).locations.size(); kkk++) {
00289
00290 if (((int)tracks.at(indices.at(iii)).locations.at(kkk).imageIndex) == idx2) {
00291
00292 pts2.push_back(tracks.at(indices.at(iii)).locations.at(kkk).featureCoord);
00293
00294 continue;
00295 }
00296
00297 }
00298
00299 continue;
00300
00301 }
00302
00303 }
00304
00305 }
00306
00307
00308 }
00309
00310 void getActive3dPoints(vector<featureTrack>& tracks, vector<unsigned int>& indices, vector<cv::Point3d>& cloud) {
00311
00312 cloud.clear();
00313
00314 for (unsigned int iii = 0; iii < indices.size(); iii++) {
00315 cloud.push_back(tracks.at(indices.at(iii)).get3dLoc());
00316 }
00317
00318 }
00319
00320 void filterToCompleteTracks(vector<unsigned int>& dst, vector<unsigned int>& src, vector<featureTrack>& tracks, int idx1, int idx2) {
00321
00322 dst.clear();
00323
00324 for (unsigned int iii = 0; iii < src.size(); iii++) {
00325
00326 if (tracks.at(src.at(iii)).locations.size() >= (idx2 - idx1)) {
00327
00328 for (unsigned int jjj = 0; jjj < tracks.at(src.at(iii)).locations.size()-(idx2-idx1); jjj++) {
00329
00330
00331
00332 if (((int)tracks.at(src.at(iii)).locations.at(jjj).imageIndex) == idx1) {
00333
00334
00335
00336 for (unsigned int kkk = jjj+1; kkk < tracks.at(src.at(iii)).locations.size(); kkk++) {
00337
00338
00339
00340 if (((int)tracks.at(src.at(iii)).locations.at(kkk).imageIndex) == idx2) {
00341
00342
00343
00344 dst.push_back(src.at(iii));
00345
00346 }
00347
00348 }
00349
00350 }
00351
00352
00353 }
00354
00355 }
00356
00357 }
00358
00359 }
00360
00361 void getActiveTracks(vector<unsigned int>& indices, vector<featureTrack>& tracks, int idx1, int idx2) {
00362
00363
00364
00365
00366
00367 indices.clear();
00368
00369 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00370
00371
00372
00373 if (tracks.at(iii).locations.size() < 2) {
00374 continue;
00375 }
00376
00377 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size()-1; jjj++) {
00378
00379
00380
00381 if ((((int)tracks.at(iii).locations.at(jjj).imageIndex) >= idx1) && (((int)tracks.at(iii).locations.at(jjj).imageIndex) <= idx2)) {
00382
00383 for (unsigned int kkk = jjj+1; kkk < tracks.at(iii).locations.size(); kkk++) {
00384
00385 if ((((int)tracks.at(iii).locations.at(kkk).imageIndex) >= idx1) && (((int)tracks.at(iii).locations.at(kkk).imageIndex) <= idx2)) {
00386 indices.push_back(iii);
00387 break;
00388 }
00389
00390 }
00391
00392 break;
00393 }
00394
00395
00396 }
00397
00398
00399
00400
00401
00402 }
00403
00404
00405
00406 }
00407
00408 bool estimatePoseFromKnownPoints(cv::Mat& dst, cameraParameters camData, vector<featureTrack>& tracks, unsigned int index, const cv::Mat& guide, unsigned int minAppearances, unsigned int iterCount, double maxReprojErr, double inliersPercentage, double *reprojError, double *pnpInlierProp, bool debug) {
00409
00410 vector<cv::Point3f> points_3d;
00411 vector<cv::Point2f> points_2d;
00412
00413 unsigned int triangulatedCount = 0;
00414 *reprojError = 0.0;
00415 *pnpInlierProp = 0.0;
00416
00417 if (debug) { printf("%s << minAppearances = (%d)\n", __FUNCTION__, minAppearances); }
00418
00419 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00420
00421
00422
00423 if (!tracks.at(iii).isTriangulated) {
00424 continue;
00425 }
00426
00427 triangulatedCount++;
00428
00429 if (tracks.at(iii).locations.size() < minAppearances) {
00430 printf("%s << Error! size() = (%d) < (%d)\n", __FUNCTION__, tracks.at(iii).locations.size(), minAppearances);
00431 continue;
00432 }
00433
00434 bool pointAdded = false;
00435
00436 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size(); jjj++) {
00437
00438
00439
00440 if (tracks.at(iii).locations.at(jjj).imageIndex == index) {
00441
00442 points_2d.push_back(tracks.at(iii).locations.at(jjj).featureCoord);
00443 cv::Point3f tmp_pt = cv::Point3f(((float) tracks.at(iii).get3dLoc().x), ((float) tracks.at(iii).get3dLoc().y), ((float) tracks.at(iii).get3dLoc().z));
00444 points_3d.push_back(tmp_pt);
00445 pointAdded = true;
00446 break;
00447 }
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 }
00461
00462 unsigned int utilizedPointsCount = points_3d.size();
00463
00464 cv::Mat Rvec, R, t;
00465 bool guided = false;
00466
00467 cv::Mat guide_copy;
00468
00469 guide_copy = guide.inv();
00470
00471 if (guide_copy.rows > 0) {
00472 decomposeTransform(guide_copy, R, t);
00473 Rodrigues(R, Rvec);
00474 guided = true;
00475 }
00476
00477
00478 vector<int> inlierPts;
00479
00480 if (points_2d.size() < 8) {
00481 if (debug) { printf("%s << PnP Failed: Insufficient pts: (%d) < (%d) : [%d, %d, %d]\n", __FUNCTION__, ((int)points_2d.size()), 8, utilizedPointsCount, triangulatedCount, ((int)tracks.size())); }
00482 guide.copyTo(dst);
00483 return false;
00484 }
00485
00486 solvePnPRansac(points_3d, points_2d, camData.K, camData.blankCoeffs, Rvec, t, guided, iterCount, maxReprojErr, ((unsigned int) ((double) points_2d.size()) * inliersPercentage), inlierPts, CV_EPNP);
00487
00488
00489
00490 if ( inlierPts.size() < 8 ) {
00491 if (debug) { printf("%s << PnP Failed: Insufficient inliers: (%d) / (%d) : [%d, %d, %d]\n", __FUNCTION__, (int)inlierPts.size(), points_2d.size(), utilizedPointsCount, triangulatedCount, ((int)tracks.size())); }
00492 guide.copyTo(dst);
00493 return false;
00494 }
00495
00496 if (debug) { printf("%s << PnP Succeeded: Inliers: (%d) / (%d) : [%d, %d, %d]\n", __FUNCTION__, (int)inlierPts.size(), points_2d.size(), utilizedPointsCount, triangulatedCount, ((int)tracks.size())); }
00497
00498 *pnpInlierProp = double(inlierPts.size()) / double(points_2d.size());
00499
00500 Rodrigues(Rvec, R);
00501 cv::Mat P;
00502 findP1Matrix(P, R, t);
00503 projectionToTransformation(P, dst);
00504 dst = dst.inv();
00505
00506
00507
00508
00509
00510
00511
00512
00513 cv::vector<cv::Point3f> validPts;
00514 for (unsigned int iii = 0; iii < inlierPts.size(); iii++) {
00515 validPts.push_back(points_3d.at(inlierPts.at(iii)));
00516 }
00517
00518
00519 cv::vector<cv::Point2f> point_2f;
00520 projectPoints(validPts, Rvec, t, camData.K, camData.blankCoeffs, point_2f);
00521
00522
00523
00524 for (unsigned int iii = 0; iii < inlierPts.size(); iii++) {
00525
00526 *reprojError += distBetweenPts2f(points_2d.at(inlierPts.at(iii)), point_2f.at(iii));
00527
00528 }
00529
00530 if (inlierPts.size() > 0) {
00531 *reprojError /= double(inlierPts.size());
00532 } else {
00533 *reprojError = -1.0;
00534 }
00535
00536
00537
00538
00539 return true;
00540
00541 }
00542
00543
00544
00545 void getCorrespondingPoints(vector<featureTrack>& tracks, const vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, int idx0, int idx1) {
00546
00547 printf("%s << Entered X.\n", __FUNCTION__);
00548
00549
00550 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00551
00552 if (tracks.at(iii).locations.size() < 2) {
00553 continue;
00554 }
00555
00556
00557 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size()-1; kkk++) {
00558
00559
00560
00561
00562 if (((int)tracks.at(iii).locations.at(kkk).imageIndex) == idx0) {
00563
00564
00565
00566
00567
00568 for (unsigned int jjj = 0; jjj < pts1.size(); jjj++) {
00569
00570
00571
00572
00573 if ((tracks.at(iii).locations.at(kkk).featureCoord.x == pts1.at(jjj).x) && (tracks.at(iii).locations.at(kkk).featureCoord.y == pts1.at(jjj).y)) {
00574
00575
00576
00577
00578 for (unsigned int ppp = kkk; ppp < tracks.at(iii).locations.size(); ppp++) {
00579
00580
00581
00582
00583 if (((int)tracks.at(iii).locations.at(ppp).imageIndex) == idx1) {
00584
00585
00586
00587
00588 if (jjj != pts2.size()) {
00589 printf("%s << ERROR! Vectors are not syncing (jjj = %d), pts2.size() = %d\n", __FUNCTION__, jjj, ((int)pts2.size()));
00590 } else {
00591 pts2.push_back(tracks.at(iii).locations.at(ppp).featureCoord);
00592 }
00593
00594
00595 }
00596
00597
00598 }
00599
00600 break;
00601 }
00602
00603 }
00604
00605
00606 break;
00607 }
00608
00609 }
00610 }
00611
00612 printf("%s << Exiting.\n", __FUNCTION__);
00613
00614 }
00615
00616 void getTriangulatedFullSpanPoints(vector<featureTrack>& tracks, vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, int idx1, int idx2, vector<cv::Point3f>& points3) {
00617
00618 pts1.clear();
00619 pts2.clear();
00620 points3.clear();
00621
00622 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00623
00624 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size()-1; kkk++) {
00625
00626
00627 if (((int)tracks.at(iii).locations.at(kkk).imageIndex) == idx1) {
00628
00629 for (unsigned int jjj = kkk+1; jjj < tracks.at(iii).locations.size(); jjj++) {
00630
00631 if (((int)tracks.at(iii).locations.at(jjj).imageIndex) == idx2) {
00632
00633 if (tracks.at(iii).isTriangulated) {
00634
00635 pts1.push_back(tracks.at(iii).locations.at(kkk).featureCoord);
00636 pts2.push_back(tracks.at(iii).locations.at(jjj).featureCoord);
00637
00638 points3.push_back(cv::Point3f(((float) tracks.at(iii).get3dLoc().x), ((float) tracks.at(iii).get3dLoc().y), ((float) tracks.at(iii).get3dLoc().z)));
00639
00640 break;
00641 }
00642
00643
00644
00645 }
00646 }
00647
00648 }
00649 }
00650 }
00651
00652 }
00653
00654 void findTriangulatableTracks(vector<featureTrack>& tracks, vector<unsigned int>& indices, vector<unsigned int>& cameras, unsigned int min_length) {
00655
00656 unsigned int insuffAppeared = 0;
00657 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00658
00659 if (tracks.at(iii).locations.size() < min_length) {
00660 continue;
00661 }
00662
00663 unsigned int appearanceCount = 0;
00664 unsigned int progressIndex = 0;
00665
00666 for (unsigned int kkk = 0; kkk < cameras.size(); kkk++) {
00667
00668 while (progressIndex < tracks.at(iii).locations.size()) {
00669 if (tracks.at(iii).locations.at(progressIndex).imageIndex == cameras.at(kkk) ) {
00670 appearanceCount++;
00671 progressIndex++;
00672 break;
00673 }
00674 progressIndex++;
00675 }
00676
00677 }
00678
00679 if (appearanceCount >= min_length) {
00680 indices.push_back(iii);
00681 } else {
00682 insuffAppeared++;
00683
00684 }
00685
00686 }
00687
00688
00689
00690 }
00691
00692 void findTriangulatableTracks3(vector<featureTrack>& tracks, vector<unsigned int>& indices, int latest_index, unsigned int min_length) {
00693
00694 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
00695
00696 if (latest_index == -1) {
00697 if (tracks.at(iii).locations.size() >= min_length) {
00698 indices.push_back(iii);
00699 }
00700 } else {
00701
00702 unsigned int appearanceCount = 0;
00703
00704 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size(); jjj++) {
00705 if (tracks.at(iii).locations.at(jjj).imageIndex <= ((unsigned int) latest_index)) {
00706 appearanceCount++;
00707 }
00708
00709 if (appearanceCount >= min_length) {
00710 indices.push_back(iii);
00711 break;
00712 }
00713 }
00714 }
00715
00716 }
00717
00718 }
00719
00720 void getTranslationBetweenCameras(cv::Mat& C1, cv::Mat& C2, double *translations) {
00721
00722 cv::Mat CD = C2 - C1;
00723
00724 translations[0] = CD.at<double>(0,3);
00725 translations[1] = CD.at<double>(1,3);
00726 translations[2] = CD.at<double>(2,3);
00727
00728 }
00729
00730 int initialTrackTriangulationDummy(vector<featureTrack>& tracks, vector<unsigned int>& indices, cameraParameters& cameraData, geometry_msgs::PoseStamped *keyframePoses, unsigned int keyframeCount, double minSeparation, double maxSeparation, int minEstimates, double maxStandardDev, bool handedness, int xCode) {
00731
00732 int lim = 10;
00733
00734 cv::Point2f dummyPoints1[10], dummyPoints2[10];
00735
00736
00737 if (0) {
00738 dummyPoints1[0].x = 200.5;
00739 dummyPoints1[0].y = 143.5;
00740 dummyPoints2[0].x = 180.5;
00741 dummyPoints2[0].y = 143.5;
00742
00743 } else {
00744
00745 dummyPoints1[0].x = 225.5;
00746 dummyPoints1[0].y = 163.5;
00747 dummyPoints2[0].x = 115.5;
00748 dummyPoints2[0].y = 163.5;
00749
00750 dummyPoints1[1].x = 235.5;
00751 dummyPoints1[1].y = 143.5;
00752 dummyPoints2[1].x = 125.5;
00753 dummyPoints2[1].y = 143.5;
00754
00755 dummyPoints1[2].x = 235.5;
00756 dummyPoints1[2].y = 123.5;
00757 dummyPoints2[2].x = 125.5;
00758 dummyPoints2[2].y = 123.5;
00759
00760 dummyPoints1[3].x = 265.5;
00761 dummyPoints1[3].y = 163.5;
00762 dummyPoints2[3].x = 155.5;
00763 dummyPoints2[3].y = 163.5;
00764
00765 dummyPoints1[4].x = 255.5;
00766 dummyPoints1[4].y = 143.5;
00767 dummyPoints2[4].x = 145.5;
00768 dummyPoints2[4].y = 143.5;
00769
00770 dummyPoints1[5].x = 255.5;
00771 dummyPoints1[5].y = 123.5;
00772 dummyPoints2[5].x = 145.5;
00773 dummyPoints2[5].y = 123.5;
00774
00775
00776 dummyPoints1[6].x = 245.5;
00777 dummyPoints1[6].y = 163.5;
00778 dummyPoints2[6].x = 95.5;
00779 dummyPoints2[6].y = 163.5;
00780
00781 dummyPoints1[7].x = 255.5;
00782 dummyPoints1[7].y = 123.5;
00783 dummyPoints2[7].x = 105.5;
00784 dummyPoints2[7].y = 123.5;
00785
00786 dummyPoints1[8].x = 285.5;
00787 dummyPoints1[8].y = 163.5;
00788 dummyPoints2[8].x = 135.5;
00789 dummyPoints2[8].y = 163.5;
00790
00791 dummyPoints1[9].x = 275.5;
00792 dummyPoints1[9].y = 123.5;
00793 dummyPoints2[9].x = 125.5;
00794 dummyPoints2[9].y = 123.5;
00795 }
00796
00797 vector<cv::Point3f> testPt_3d;
00798 cv::Point3f tmp;
00799 tmp.x = 1.5;
00800 tmp.y = 1.5;
00801 tmp.z = 2.0;
00802 testPt_3d.push_back(tmp);
00803
00804
00805
00806
00807
00808
00809
00810
00811 vector<cv::Point2f> testPts_2d;
00812
00813 cv::Mat rvec, tvec, cameraMatrix, distCoeffs;
00814 tvec = cv::Mat::zeros(3, 1, CV_64FC1);
00815 rvec = cv::Mat::zeros(3, 1, CV_64FC1);
00816 cameraMatrix = cv::Mat::eye(3, 3, CV_64FC1);
00817 distCoeffs = cv::Mat::zeros(5, 1, CV_64FC1);;
00818
00819
00820
00821 tvec.at<double>(0,0) = 0.0;
00822 tvec.at<double>(1,0) = 0.0;
00823 tvec.at<double>(2,0) = 0.0;
00824 projectPoints(testPt_3d, rvec, tvec, cameraMatrix, distCoeffs, testPts_2d);
00825
00826 printf("%s << Point (%f, %f, %f) projected to (%f, %f) for cam (%f, %f, %f)\n", __FUNCTION__, testPt_3d.at(0).x, testPt_3d.at(0).y, testPt_3d.at(0).z, testPts_2d.at(0).x, testPts_2d.at(0).y, tvec.at<double>(0,0), tvec.at<double>(1,0), tvec.at<double>(2,0));
00827
00828 tvec.at<double>(0,0) = -1.5;
00829 tvec.at<double>(1,0) = -1.5;
00830 tvec.at<double>(2,0) = 0.0;
00831
00832 projectPoints(testPt_3d, rvec, tvec, cameraMatrix, distCoeffs, testPts_2d);
00833
00834 printf("%s << Point (%f, %f, %f) projected to (%f, %f) for cam (%f, %f, %f)\n", __FUNCTION__, testPt_3d.at(0).x, testPt_3d.at(0).y, testPt_3d.at(0).z, testPts_2d.at(0).x, testPts_2d.at(0).y, tvec.at<double>(0,0), tvec.at<double>(1,0), tvec.at<double>(2,0));
00835
00836 tvec.at<double>(0,0) = -3.0;
00837 tvec.at<double>(1,0) = -3.0;
00838 tvec.at<double>(2,0) = 0.0;
00839
00840 projectPoints(testPt_3d, rvec, tvec, cameraMatrix, distCoeffs, testPts_2d);
00841
00842 printf("%s << Point (%f, %f, %f) projected to (%f, %f) for cam (%f, %f, %f)\n", __FUNCTION__, testPt_3d.at(0).x, testPt_3d.at(0).y, testPt_3d.at(0).z, testPts_2d.at(0).x, testPts_2d.at(0).y, tvec.at<double>(0,0), tvec.at<double>(1,0), tvec.at<double>(2,0));
00843
00844 tvec.at<double>(0,0) = 0.0;
00845 tvec.at<double>(1,0) = -1.5;
00846 tvec.at<double>(2,0) = 0.0;
00847
00848 projectPoints(testPt_3d, rvec, tvec, cameraMatrix, distCoeffs, testPts_2d);
00849
00850 printf("%s << Point (%f, %f, %f) projected to (%f, %f) for cam (%f, %f, %f)\n", __FUNCTION__, testPt_3d.at(0).x, testPt_3d.at(0).y, testPt_3d.at(0).z, testPts_2d.at(0).x, testPts_2d.at(0).y, tvec.at<double>(0,0), tvec.at<double>(1,0), tvec.at<double>(2,0));
00851
00852 tvec.at<double>(0,0) = -1.5;
00853 tvec.at<double>(1,0) = 0.0;
00854 tvec.at<double>(2,0) = 0.0;
00855
00856 projectPoints(testPt_3d, rvec, tvec, cameraMatrix, distCoeffs, testPts_2d);
00857
00858 printf("%s << Point (%f, %f, %f) projected to (%f, %f) for cam (%f, %f, %f)\n", __FUNCTION__, testPt_3d.at(0).x, testPt_3d.at(0).y, testPt_3d.at(0).z, testPts_2d.at(0).x, testPts_2d.at(0).y, tvec.at<double>(0,0), tvec.at<double>(1,0), tvec.at<double>(2,0));
00859
00860 vector<cv::Point3d> estimatedLocations;
00861 for (int iii = 0; iii < lim; iii++) {
00862
00863 cv::Mat R1, t1, temp_C1, temp_P1;
00864 Quaterniond q1;
00865 Eigen::Vector4d v1;
00866
00867
00868 q1 = Quaterniond(1.0, 0.0, 0.0, 0.0);
00869
00870 v1 = Eigen::Vector4d(1.3, 1.5, 0.0, 1.0);
00871
00872 quaternionToMatrix(q1, R1, handedness);
00873 convertVec4dToMat(v1, t1);
00874 composeTransform(R1, t1, temp_C1);
00875
00876
00877 cv::Mat R2, t2, temp_C2, temp_P2;
00878 Quaterniond q2;
00879 Eigen::Vector4d v2;
00880 q2 = Quaterniond(1.0, 0.0, 0.0, 0.0);
00881
00882 v2 = Eigen::Vector4d(1.7, 1.5, 0.0, 1.0);
00883
00884
00885 quaternionToMatrix(q2, R2, handedness);
00886 convertVec4dToMat(v2, t2);
00887 composeTransform(R2, t2, temp_C2);
00888
00889 cv::Point2f pt1_, pt2_;
00890 cv::Point3d pt3d_;
00891
00892 pt1_ = dummyPoints1[iii];
00893 pt2_ = dummyPoints2[iii];
00894
00895 temp_C1 = temp_C1.inv();
00896 temp_C2 = temp_C2.inv();
00897
00898 cout << "temp_C1 = " << temp_C1 << endl;
00899 cout << "temp_C2 = " << temp_C2 << endl;
00900
00901 Triangulate_1(pt1_, pt2_, cameraData.K, cameraData.K_inv, temp_C1, temp_C2, pt3d_, true);
00902
00903
00904
00905 printf("%s << Triangulated (%f, %f) & (%f, %f) to (%f, %f, %f)\n", __FUNCTION__, pt1_.x, pt1_.y, pt2_.x, pt2_.y, pt3d_.x, pt3d_.y, pt3d_.z);
00906
00907 estimatedLocations.push_back(pt3d_);
00908
00909 tracks.at(indices.at(iii)).set3dLoc(pt3d_);
00910 }
00911
00912 return lim;
00913
00914 }
00915
00916 void filterNearPoints(vector<featureTrack>& featureTrackVector, double x, double y, double z, double limit) {
00917
00918 for (unsigned int iii = 0; iii < featureTrackVector.size(); iii++) {
00919
00920 if (featureTrackVector.at(iii).isTriangulated) {
00921 cv::Point3d pt3d = cv::Point3d(x, y, z);
00922 cv::Point3d pt3d_ = featureTrackVector.at(iii).get3dLoc();
00923 if (distBetweenPts(pt3d, pt3d_) < limit) {
00924 featureTrackVector.at(iii).isTriangulated = false;
00925 }
00926 }
00927
00928 }
00929
00930 }
00931
00932 int initialTrackTriangulation(vector<featureTrack>& tracks, vector<unsigned int>& indices, cameraParameters& cameraData, geometry_msgs::PoseStamped *keyframePoses, unsigned int keyframeCount, double minSeparation, double maxSeparation, int minEstimates, double maxStandardDev, double maxReprojectionDisparity) {
00933
00934 cv::Point3d pt3d, mean3d(0.0, 0.0, 0.0), stddev3d(0.0, 0.0, 0.0);
00935 Quaterniond q0(1.0, 0.0, 0.0, 0.0);
00936
00937 int minProjCount = 0, clusterFail = 0;
00938 vector<int> validPairs, tooClosePairs, tooFarPairs, tooNearPairs, inFrontPairs, withinDisparityPairs;
00939
00940
00941 int triangulatedCounter = 0;
00942
00943 int minProjections_ = minProjections(minEstimates);
00944
00945 for (unsigned int iii = 0; iii < indices.size(); iii++) {
00946
00947 unsigned int ptsBehind = 0, ptsInfront = 0;
00948
00949 int validPairs_ = 0, tooClosePairs_ = 0, tooFarPairs_ = 0, tooNearPairs_ = 0, inFrontPairs_ = 0, withinDisparityPairs_ = 0;
00950
00951 if (tracks.size() <= indices.at(iii)) {
00952 printf("%s << ERROR 1!\n", __FUNCTION__);
00953 continue;
00954 }
00955
00956
00957
00958 if (((int)tracks.at(indices.at(iii)).locations.size()) < minProjections_) {
00959 printf("%s << ERROR 2!\n", __FUNCTION__);
00960 continue;
00961 }
00962
00963
00964
00965 vector<cv::Point3d> estimatedLocations;
00966 vector<double> separationsVector;
00967
00968 pt3d = cv::Point3d(0.0, 0.0, 0.0);
00969
00970 int rrr, sss;
00971
00972
00973 for (unsigned int jjj = 0; jjj < tracks.at(indices.at(iii)).locations.size()-1; jjj++) {
00974
00975
00976
00977
00978 rrr = tracks.at(indices.at(iii)).locations.at(jjj).imageIndex;
00979
00980
00981 int cameraIndex1 = -1;
00982 for (unsigned int kkk = 0; kkk < keyframeCount; kkk++) {
00983 if (((int)keyframePoses[kkk].header.seq) == rrr) {
00984 cameraIndex1 = kkk;
00985 break;
00986 }
00987 }
00988
00989
00990 if (cameraIndex1 == -1) {
00991
00992 continue;
00993 }
00994
00995
00996 cv::Mat R1, t1, temp_C1, temp_P1;
00997 Quaterniond q1;
00998 Eigen::Vector4d v1;
00999
01000 q1 = Quaterniond(keyframePoses[cameraIndex1].pose.orientation.w, keyframePoses[cameraIndex1].pose.orientation.x, keyframePoses[cameraIndex1].pose.orientation.y, keyframePoses[cameraIndex1].pose.orientation.z);
01001 v1 = Eigen::Vector4d(keyframePoses[cameraIndex1].pose.position.x, keyframePoses[cameraIndex1].pose.position.y, keyframePoses[cameraIndex1].pose.position.z, 1.0);
01002
01003 quaternionToMatrix(q1, R1);
01004 convertVec4dToMat(v1, t1);
01005 composeTransform(R1, t1, temp_C1);
01006 temp_C1 = temp_C1.inv();
01007
01008 transformationToProjection(temp_C1, temp_P1);
01009
01010 for (unsigned int kkk = jjj+1; kkk < tracks.at(indices.at(iii)).locations.size(); kkk++) {
01011
01012
01013
01014 sss = tracks.at(indices.at(iii)).locations.at(kkk).imageIndex;
01015
01016
01017 int cameraIndex2 = -1;
01018 for (unsigned int mmm = 0; mmm < keyframeCount; mmm++) {
01019 if (((int)keyframePoses[mmm].header.seq) == sss) {
01020 cameraIndex2 = mmm;
01021 break;
01022 }
01023 }
01024
01025
01026 if (cameraIndex2 == -1) {
01027
01028 continue;
01029 }
01030
01031
01032
01033 validPairs_++;
01034
01035
01036 cv::Mat R2, t2, temp_C2, temp_P2;
01037 Quaterniond q2;
01038 Eigen::Vector4d v2;
01039
01040 q2 = Quaterniond(keyframePoses[cameraIndex2].pose.orientation.w, keyframePoses[cameraIndex2].pose.orientation.x, keyframePoses[cameraIndex2].pose.orientation.y, keyframePoses[cameraIndex2].pose.orientation.z);
01041 v2 = Eigen::Vector4d(keyframePoses[cameraIndex2].pose.position.x, keyframePoses[cameraIndex2].pose.position.y, keyframePoses[cameraIndex2].pose.position.z, 1.0);
01042
01043 quaternionToMatrix(q2, R2);
01044 convertVec4dToMat(v2, t2);
01045 composeTransform(R2, t2, temp_C2);
01046 temp_C2 = temp_C2.inv();
01047 transformationToProjection(temp_C2, temp_P2);
01048
01049
01050 double separation = pow(pow(v1.x() - v2.x(), 2.0) + pow(v1.y() - v2.y(), 2.0) + pow(v1.z() - v2.z(), 2.0), 0.5);
01051
01052 if ( (separation < minSeparation) && (minSeparation != 0.0) ) {
01053
01054 tooClosePairs_++;
01055 continue;
01056 } else if ( (separation > maxSeparation) && (maxSeparation != 0.0) ) {
01057
01058 tooFarPairs_++;
01059 continue;
01060 }
01061
01062 cv::Point2f pt1_, pt2_;
01063 cv::Point3d pt3d_, pt3d_temp;
01064
01065 pt1_ = tracks.at(indices.at(iii)).getCoord(rrr);
01066 pt2_ = tracks.at(indices.at(iii)).getCoord(sss);
01067
01068 Triangulate_1(pt1_, pt2_, cameraData.K, cameraData.K_inv, temp_C1, temp_C2, pt3d_, true);
01069
01070
01071
01072 if (pointIsInFront(temp_C1, pt3d_) && pointIsInFront(temp_C2, pt3d_)) {
01073
01074 inFrontPairs_++;
01075
01076 vector<cv::Point3f> testPt_3d;
01077 testPt_3d.push_back(pt3d_);
01078 cv::Mat distCoeffs = cv::Mat::zeros(5, 1, CV_64FC1);
01079
01080 cv::Mat t1x, r1x, R1_X;
01081 cv::Mat t2x, r2x, R2_X;
01082 decomposeTransform(temp_C1, R1_X, t1x);
01083 decomposeTransform(temp_C2, R2_X, t2x);
01084 Rodrigues(R1_X, r1x);
01085 Rodrigues(R2_X, r2x);
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101 vector<cv::Point2f> testPts_2d_1, testPts_2d_2;
01102
01103 projectPoints(testPt_3d, r1x, t1x, cameraData.K, distCoeffs, testPts_2d_1);
01104 double dist1 = pow(pow(testPts_2d_1.at(0).x - pt1_.x, 2.0) + pow(testPts_2d_1.at(0).y - pt1_.y, 2.0), 0.5);
01105 projectPoints(testPt_3d, r2x, t2x, cameraData.K, distCoeffs, testPts_2d_2);
01106 double dist2 = pow(pow(testPts_2d_2.at(0).x - pt2_.x, 2.0) + pow(testPts_2d_2.at(0).y - pt2_.y, 2.0), 0.5);
01107
01108
01109
01110 if ( ( (dist1 < maxReprojectionDisparity) && (dist2 < maxReprojectionDisparity) ) || (maxReprojectionDisparity == 0.0) ) {
01111 withinDisparityPairs_++;
01112
01113 if ( (pt3d_.x != 0.0) && (pt3d_.y != 0.0) && (pt3d_.z != 0.0)) {
01114
01115 estimatedLocations.push_back(pt3d_);
01116 separationsVector.push_back(separation);
01117 }
01118 }
01119 } else {
01120 ptsBehind++;
01121 }
01122 }
01123 }
01124
01125
01126
01127 validPairs.push_back(validPairs_);
01128 tooClosePairs.push_back(tooClosePairs_);
01129 tooFarPairs.push_back(tooFarPairs_);
01130 tooNearPairs.push_back(tooNearPairs_);
01131 inFrontPairs.push_back(inFrontPairs_);
01132 withinDisparityPairs.push_back(withinDisparityPairs_);
01133
01134
01135
01136 if (((int)estimatedLocations.size()) < minEstimates) {
01137
01138 minProjCount++;
01139 continue;
01140 } else {
01141
01142 }
01143
01144 int mode = CLUSTER_MEAN_MODE;
01145 bool validResult = findClusterMean(estimatedLocations, pt3d, mode, minEstimates, maxStandardDev);
01146
01147 if (validResult) {
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162 tracks.at(indices.at(iii)).set3dLoc(pt3d);
01163 triangulatedCounter++;
01164
01165 } else {
01166 clusterFail++;
01167
01168 }
01169
01170 }
01171
01172 double validPairs_ave = 0.0, tooClosePairs_ave = 0.0, tooFarPairs_ave = 0.0, tooNearPairs_ave = 0.0, inFrontPairs_ave = 0.0, withinDisparityPairs_ave = 0.0;
01173
01174 for (unsigned int iii = 0; iii < validPairs.size(); iii++) {
01175 validPairs_ave += validPairs.at(iii);
01176 tooClosePairs_ave += tooClosePairs.at(iii);
01177 tooFarPairs_ave += tooFarPairs.at(iii);
01178 tooNearPairs_ave += tooNearPairs.at(iii);
01179 inFrontPairs_ave += inFrontPairs.at(iii);
01180 withinDisparityPairs_ave += withinDisparityPairs.at(iii);
01181 }
01182
01183 validPairs_ave /= double(validPairs.size());
01184 tooClosePairs_ave /= double(validPairs.size());
01185 tooFarPairs_ave /= double(validPairs.size());
01186 tooNearPairs_ave /= double(validPairs.size());
01187 inFrontPairs_ave /= double(validPairs.size());
01188 withinDisparityPairs_ave /= double(validPairs.size());
01189
01190
01191
01192
01193
01194 return triangulatedCounter;
01195
01196 }
01197
01198 bool findClusterMean(const vector<cv::Point3d>& pts, cv::Point3d& pt3d, int mode, int minEstimates, double maxStandardDev) {
01199
01200 cv::Point3d mean3d = cv::Point3d(0.0, 0.0, 0.0);
01201 cv::Point3d stddev3d = cv::Point3d(0.0, 0.0, 0.0);
01202
01203 vector<cv::Point3d> estimatedLocations;
01204 estimatedLocations.insert(estimatedLocations.end(), pts.begin(), pts.end());
01205 vector<int> clusterCount;
01206
01207 double outlierLimit = 3.0;
01208
01209 if (mode == CLUSTER_MEAN_MODE) {
01210
01211
01212 for (unsigned int iii = 0; iii < estimatedLocations.size(); iii++) {
01213 clusterCount.push_back(1);
01214
01215 }
01216
01217 for (unsigned int iii = 0; iii < estimatedLocations.size()-1; iii++) {
01218
01219 cv::Point3d basePt = estimatedLocations.at(iii);
01220
01221
01222
01223 for (unsigned int jjj = iii+1; jjj < estimatedLocations.size(); jjj++) {
01224
01225 double separation = pow(pow(basePt.x - estimatedLocations.at(jjj).x, 2.0) + pow(basePt.y - estimatedLocations.at(jjj).y, 2.0) + pow(basePt.z - estimatedLocations.at(jjj).z, 2.0), 0.5);
01226
01227 if ( (separation < maxStandardDev) || (maxStandardDev == 0.0) ) {
01228
01229 estimatedLocations.at(iii) *= double(clusterCount.at(iii));
01230 clusterCount.at(iii)++;
01231 estimatedLocations.at(iii) += estimatedLocations.at(jjj);
01232 estimatedLocations.at(iii).x /= double(clusterCount.at(iii));
01233 estimatedLocations.at(iii).y /= double(clusterCount.at(iii));
01234 estimatedLocations.at(iii).z /= double(clusterCount.at(iii));
01235
01236 estimatedLocations.erase(estimatedLocations.begin() + jjj);
01237 clusterCount.erase(clusterCount.begin() + jjj);
01238 jjj--;
01239
01240 }
01241
01242 }
01243 }
01244
01245 int maxClusterSize = 0, maxClusterIndex = -1;
01246
01247 for (unsigned int iii = 0; iii < estimatedLocations.size(); iii++) {
01248
01249 if (clusterCount.at(iii) >= maxClusterSize) {
01250 maxClusterSize = clusterCount.at(iii);
01251 maxClusterIndex = iii;
01252 }
01253
01254
01255 }
01256
01257 if (maxClusterSize >= minEstimates) {
01258 pt3d = estimatedLocations.at(maxClusterIndex);
01259 } else {
01260 return false;
01261 }
01262
01263 } else {
01264
01265
01266 for (unsigned int qqq = 0; qqq < estimatedLocations.size(); qqq++) {
01267
01268
01269
01270 mean3d.x += (estimatedLocations.at(qqq).x / ((double) estimatedLocations.size()));
01271 mean3d.y += (estimatedLocations.at(qqq).y / ((double) estimatedLocations.size()));
01272 mean3d.z += (estimatedLocations.at(qqq).z / ((double) estimatedLocations.size()));
01273
01274 }
01275
01276
01277
01278
01279
01280
01281 for (unsigned int qqq = 0; qqq < estimatedLocations.size(); qqq++) {
01282
01283 stddev3d.x += (pow((estimatedLocations.at(qqq).x - mean3d.x), 2.0) / ((double) estimatedLocations.size()));
01284 stddev3d.y += (pow((estimatedLocations.at(qqq).y - mean3d.y), 2.0) / ((double) estimatedLocations.size()));
01285 stddev3d.z += (pow((estimatedLocations.at(qqq).z - mean3d.z), 2.0) / ((double) estimatedLocations.size()));
01286
01287 }
01288
01289 stddev3d.x = pow(stddev3d.x, 0.5);
01290 stddev3d.y = pow(stddev3d.y, 0.5);
01291 stddev3d.z = pow(stddev3d.z, 0.5);
01292
01293
01294
01295
01296
01297
01298 for (int qqq = estimatedLocations.size()-1; qqq >= 0; qqq--) {
01299
01300 double abs_diff_x = abs(estimatedLocations.at(qqq).x - mean3d.x);
01301 double abs_diff_y = abs(estimatedLocations.at(qqq).y - mean3d.y);
01302 double abs_diff_z = abs(estimatedLocations.at(qqq).z - mean3d.z);
01303
01304 if ((abs_diff_x > outlierLimit*stddev3d.x) || (abs_diff_y > outlierLimit*stddev3d.y) || (abs_diff_z > outlierLimit*stddev3d.z)) {
01305 estimatedLocations.erase(estimatedLocations.begin() + qqq);
01306 }
01307
01308 }
01309
01310
01311
01312
01313 stddev3d.x = 0.0;
01314 stddev3d.y = 0.0;
01315 stddev3d.z = 0.0;
01316
01317 for (unsigned int qqq = 0; qqq < estimatedLocations.size(); qqq++) {
01318
01319 stddev3d.x += (pow((estimatedLocations.at(qqq).x - mean3d.x), 2.0) / ((double) estimatedLocations.size()));
01320 stddev3d.y += (pow((estimatedLocations.at(qqq).y - mean3d.y), 2.0) / ((double) estimatedLocations.size()));
01321 stddev3d.z += (pow((estimatedLocations.at(qqq).z - mean3d.z), 2.0) / ((double) estimatedLocations.size()));
01322
01323 }
01324
01325 stddev3d.x = pow(stddev3d.x, 0.5);
01326 stddev3d.y = pow(stddev3d.y, 0.5);
01327 stddev3d.z = pow(stddev3d.z, 0.5);
01328
01329
01330
01331
01332 if ( ((stddev3d.x > maxStandardDev) || (stddev3d.y > maxStandardDev) || (stddev3d.z > maxStandardDev) || (((int)estimatedLocations.size()) < minEstimates)) && (maxStandardDev != 0.0) ) {
01333 return false;
01334 }
01335
01336
01337
01338
01339 pt3d.x = 0.0;
01340 pt3d.y = 0.0;
01341 pt3d.z = 0.0;
01342
01343 for (unsigned int qqq = 0; qqq < estimatedLocations.size(); qqq++) {
01344
01345 pt3d.x += (estimatedLocations.at(qqq).x / ((double) estimatedLocations.size()));
01346 pt3d.y += (estimatedLocations.at(qqq).y / ((double) estimatedLocations.size()));
01347 pt3d.z += (estimatedLocations.at(qqq).z / ((double) estimatedLocations.size()));
01348
01349 }
01350 }
01351
01352 return true;
01353 }
01354
01355 void triangulateTracks(vector<featureTrack>& tracks, vector<unsigned int>& indices, cameraParameters& cameraData, cv::Mat *cameras, unsigned int earliest_index, unsigned int latest_index) {
01356
01357
01358
01359
01360
01361 unsigned int minPairs = 10;
01362
01363
01364
01365
01366 unsigned int pair_width = latest_index - earliest_index + 1;
01367 cv::Mat validFramePairs = cv::Mat::zeros(pair_width, pair_width, CV_8UC1);
01368
01369 double translations[3];
01370
01371 for (unsigned int iii = earliest_index; iii < latest_index; iii++) {
01372 for (unsigned int jjj = iii+1; jjj <= latest_index; jjj++) {
01373
01374 if (cameras[iii].rows != 4) {
01375 continue;
01376 }
01377
01378 if (cameras[jjj].rows != 4) {
01379 continue;
01380 }
01381
01382 getTranslationBetweenCameras(cameras[iii], cameras[jjj], translations);
01383
01384
01385
01386
01387
01388
01389
01390
01391 if ((abs(translations[0] > 0.2)) || (abs(translations[1] > 0.2))) {
01392 validFramePairs.at<unsigned char>(iii-earliest_index,jjj-earliest_index) = 1;
01393 }
01394 }
01395 }
01396
01397 unsigned int validCount = countNonZero(validFramePairs);
01398
01399
01400
01401 if (validCount < minPairs) {
01402 return;
01403 }
01404
01405
01406
01407 vector<cv::Point3d> estimatedLocations;
01408
01409 cv::Point3d pt3d(0.0, 0.0, 0.0);
01410 cv::Point3d mean3d(0.0, 0.0, 0.0);
01411 cv::Point3d stddev3d(0.0, 0.0, 0.0);
01412
01413
01414
01415 for (unsigned int iii = 0; iii < indices.size(); iii++) {
01416
01417
01418
01419 if (tracks.size() <= indices.at(iii)) {
01420 return;
01421 }
01422
01423 if (tracks.at(indices.at(iii)).locations.size() < 2) {
01424 continue;
01425 }
01426
01427 if (tracks.at(indices.at(iii)).isTriangulated) {
01428 continue;
01429 }
01430
01431
01432
01433 estimatedLocations.clear();
01434
01435 pt3d = cv::Point3d(0.0, 0.0, 0.0);
01436 mean3d = cv::Point3d(0.0, 0.0, 0.0);
01437 stddev3d = cv::Point3d(0.0, 0.0, 0.0);
01438
01439 unsigned int rrr, sss;
01440
01441 for (unsigned int jjj = 0; jjj < tracks.at(indices.at(iii)).locations.size()-1; jjj++) {
01442
01443
01444
01445 rrr = tracks.at(indices.at(iii)).locations.at(jjj).imageIndex;
01446
01447 if ((rrr >= earliest_index) && (rrr <= latest_index)) {
01448
01449
01450
01451 if (cameras[rrr].rows != 4) {
01452
01453 continue;
01454 }
01455
01456
01457
01458
01459
01460 cv::Mat temp_C0;
01461 cameras[rrr].copyTo(temp_C0);
01462
01463 for (unsigned int kkk = jjj+1; kkk < tracks.at(indices.at(iii)).locations.size(); kkk++) {
01464
01465
01466
01467 sss = tracks.at(indices.at(iii)).locations.at(kkk).imageIndex;
01468
01469 if ((sss >= earliest_index) && (sss <= latest_index)) {
01470
01471
01472
01473
01474
01475 if (validFramePairs.at<unsigned char>(rrr-earliest_index,sss-earliest_index) == 0) {
01476 continue;
01477 }
01478
01479 if (cameras[sss].rows != 4) {
01480
01481 continue;
01482 }
01483
01484
01485
01486
01487 cv::Mat temp_C1;
01488 cameras[sss].copyTo(temp_C1);
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498 cv::Point2f pt1_, pt2_;
01499 cv::Point3d pt3d_;
01500
01501 pt1_ = tracks.at(indices.at(iii)).getCoord(rrr);
01502 pt2_ = tracks.at(indices.at(iii)).getCoord(sss);
01503
01504 Triangulate(pt1_, pt2_, cameraData.K, cameraData.K_inv, temp_C0, temp_C1, pt3d_, false);
01505
01506
01507
01508 estimatedLocations.push_back(pt3d_);
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518 if (jjj == 0) {
01519
01520 }
01521 }
01522 }
01523 }
01524
01525 }
01526
01527
01528
01529 if (estimatedLocations.size() >= minPairs) {
01530
01531
01532
01533
01534
01535 for (unsigned int qqq = 0; qqq < estimatedLocations.size(); qqq++) {
01536
01537 mean3d.x += (estimatedLocations.at(qqq).x / ((double) estimatedLocations.size()));
01538 mean3d.y += (estimatedLocations.at(qqq).y / ((double) estimatedLocations.size()));
01539 mean3d.z += (estimatedLocations.at(qqq).z / ((double) estimatedLocations.size()));
01540
01541 }
01542
01543
01544
01545 for (unsigned int qqq = 0; qqq < estimatedLocations.size(); qqq++) {
01546
01547 stddev3d.x += (pow((estimatedLocations.at(qqq).x - mean3d.x), 2.0) / ((double) estimatedLocations.size()));
01548 stddev3d.y += (pow((estimatedLocations.at(qqq).y - mean3d.y), 2.0) / ((double) estimatedLocations.size()));
01549 stddev3d.z += (pow((estimatedLocations.at(qqq).z - mean3d.z), 2.0) / ((double) estimatedLocations.size()));
01550
01551 }
01552
01553 stddev3d.x = pow(stddev3d.x, 0.5);
01554 stddev3d.y = pow(stddev3d.y, 0.5);
01555 stddev3d.z = pow(stddev3d.z, 0.5);
01556
01557
01558
01559 for (int qqq = estimatedLocations.size()-1; qqq >= 0; qqq--) {
01560
01561
01562
01563 double abs_diff_x = abs(estimatedLocations.at(qqq).x - mean3d.x);
01564 double abs_diff_y = abs(estimatedLocations.at(qqq).y - mean3d.y);
01565 double abs_diff_z = abs(estimatedLocations.at(qqq).z - mean3d.z);
01566
01567 if ((abs_diff_x > 2*stddev3d.x) || (abs_diff_y > 2*stddev3d.y) || (abs_diff_z > 2*stddev3d.z)) {
01568 estimatedLocations.erase(estimatedLocations.begin() + qqq);
01569 }
01570
01571 }
01572
01573
01574
01575
01576
01577
01578 if (estimatedLocations.size() >= minPairs) {
01579
01580
01581 for (unsigned int qqq = 0; qqq < estimatedLocations.size(); qqq++) {
01582
01583
01584
01585 pt3d.x += (estimatedLocations.at(qqq).x / ((double) estimatedLocations.size()));
01586 pt3d.y += (estimatedLocations.at(qqq).y / ((double) estimatedLocations.size()));
01587 pt3d.z += (estimatedLocations.at(qqq).z / ((double) estimatedLocations.size()));
01588
01589 }
01590
01591 tracks.at(indices.at(iii)).set3dLoc(pt3d);
01592
01593
01594
01595 }
01596
01597
01598
01599
01600 }
01601
01602
01603 }
01604
01605
01606 }
01607
01608 unsigned int addNewPoints(vector<featureTrack>& tracks, vector<unsigned int>& indices, cameraParameters& cameraData, cv::Mat *cameras, unsigned int earliest_index, unsigned int latest_index) {
01609
01610 unsigned int totalTriangulatedPoints = 0;
01611
01612 for (unsigned int iii = 0; iii < indices.size(); iii++) {
01613 if (tracks.size() < indices.at(iii)) {
01614 continue;
01615 }
01616
01617 if (tracks.at(indices.at(iii)).locations.size() < 2) {
01618 continue;
01619 }
01620
01621 for (unsigned int jjj = 0; jjj < tracks.at(indices.at(iii)).locations.size()-1; jjj++) {
01622
01623
01624
01625 if (tracks.at(indices.at(iii)).isTriangulated) {
01626 continue;
01627 }
01628
01629
01630
01631 unsigned int contribCount = 0;
01632 cv::Point3d pt3d(0.0, 0.0, 0.0);
01633
01634 unsigned int rrr = tracks.at(indices.at(iii)).locations.at(jjj).imageIndex;
01635
01636
01637
01638
01639 if (rrr == earliest_index) {
01640
01641 if (cameras[rrr].rows != 4) {
01642 printf("%s << Breaking rrr (%d)...\n", __FUNCTION__, rrr);
01643 continue;
01644 }
01645
01646
01647
01648 cv::Mat temp_C0;
01649 cameras[rrr].copyTo(temp_C0);
01650
01651 for (unsigned int kkk = jjj+1; kkk < tracks.at(indices.at(iii)).locations.size(); kkk++) {
01652
01653 unsigned int sss = tracks.at(indices.at(iii)).locations.at(kkk).imageIndex;
01654
01655
01656
01657
01658
01659 if (sss == latest_index) {
01660
01661 if (cameras[sss].rows != 4) {
01662 printf("%s << Breaking sss (%d)...\n", __FUNCTION__, sss);
01663 continue;
01664 }
01665
01666
01667
01668 cv::Mat temp_C1;
01669 cameras[sss].copyTo(temp_C1);
01670
01671
01672
01673 cv::Point2f pt1_, pt2_;
01674 cv::Point3d pt3d_;
01675
01676 pt1_ = tracks.at(indices.at(iii)).getCoord(rrr);
01677 pt2_ = tracks.at(indices.at(iii)).getCoord(sss);
01678
01679
01680
01681
01682
01683
01684
01685
01686 Triangulate(pt1_, pt2_, cameraData.K, cameraData.K_inv, temp_C0, temp_C1, pt3d_, false);
01687
01688
01689 pt3d.x += pt3d_.x;
01690 pt3d.y += pt3d_.y;
01691 pt3d.z += pt3d_.z;
01692 contribCount++;
01693
01694 }
01695 }
01696 }
01697
01698 if (contribCount > 0) {
01699
01700
01701
01702 pt3d.x /= ((double) contribCount);
01703 pt3d.y /= ((double) contribCount);
01704 pt3d.z /= ((double) contribCount);
01705
01706 tracks.at(indices.at(iii)).set3dLoc(pt3d);
01707 }
01708
01709
01710
01711 }
01712
01713 }
01714
01715 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
01716 if (tracks.at(iii).isTriangulated) {
01717 totalTriangulatedPoints++;
01718 }
01719 }
01720
01721 return totalTriangulatedPoints;
01722
01723 }
01724
01725 unsigned int putativelyTriangulateNewTracks(vector<featureTrack>& tracks, vector<unsigned int>& indices, cameraParameters& cameraData, cv::Mat *cameras, unsigned int earliest_index, unsigned int latest_index) {
01726
01727
01728
01729 unsigned int totalTriangulatedPoints = 0;
01730
01731 for (unsigned int iii = 0; iii < indices.size(); iii++) {
01732
01733
01734
01735 if (tracks.size() < indices.at(iii)) {
01736 continue;
01737 }
01738
01739 if (tracks.at(indices.at(iii)).locations.size() < 2) {
01740 continue;
01741 }
01742
01743 for (unsigned int jjj = 0; jjj < tracks.at(indices.at(iii)).locations.size()-1; jjj++) {
01744
01745
01746
01747 if (tracks.at(indices.at(iii)).isTriangulated) {
01748 continue;
01749 }
01750
01751
01752
01753 unsigned int contribCount = 0;
01754 cv::Point3d pt3d(0.0, 0.0, 0.0);
01755
01756 unsigned int rrr = tracks.at(indices.at(iii)).locations.at(jjj).imageIndex;
01757
01758 if (cameras[rrr].rows != 4) {
01759 continue;
01760 }
01761
01762 if ((rrr >= earliest_index) && (rrr <= latest_index)) {
01763
01764
01765
01766 cv::Mat temp_C0;
01767 cameras[rrr].copyTo(temp_C0);
01768
01769 for (unsigned int kkk = jjj+1; kkk < tracks.at(indices.at(iii)).locations.size(); kkk++) {
01770
01771 unsigned int sss = tracks.at(indices.at(iii)).locations.at(kkk).imageIndex;
01772
01773 if (cameras[sss].rows != 4) {
01774 continue;
01775 }
01776
01777
01778
01779 if ((sss >= earliest_index) && (sss <= latest_index)) {
01780
01781
01782
01783 cv::Mat temp_C1;
01784 cameras[sss].copyTo(temp_C1);
01785
01786
01787
01788 cv::Point2f pt1_, pt2_;
01789 cv::Point3d pt3d_;
01790
01791 pt1_ = tracks.at(indices.at(iii)).getCoord(rrr);
01792 pt2_ = tracks.at(indices.at(iii)).getCoord(sss);
01793
01794
01795
01796
01797
01798
01799
01800
01801 Triangulate(pt1_, pt2_, cameraData.K, cameraData.K_inv, temp_C0, temp_C1, pt3d_, false);
01802
01803
01804 pt3d.x += pt3d_.x;
01805 pt3d.y += pt3d_.y;
01806 pt3d.z += pt3d_.z;
01807 contribCount++;
01808
01809 }
01810 }
01811 }
01812
01813 if (contribCount > 0) {
01814
01815
01816
01817 pt3d.x /= ((double) contribCount);
01818 pt3d.y /= ((double) contribCount);
01819 pt3d.z /= ((double) contribCount);
01820
01821 tracks.at(indices.at(iii)).set3dLoc(pt3d);
01822 }
01823
01824
01825
01826 }
01827
01828 }
01829
01830 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
01831 if (tracks.at(iii).isTriangulated) {
01832 totalTriangulatedPoints++;
01833 }
01834 }
01835
01836 return totalTriangulatedPoints;
01837
01838 }
01839
01840 void getPointsFromTracks(vector<featureTrack>& tracks, vector<cv::Point2f>& pts1, vector<cv::Point2f>& pts2, int idx1, int idx2) {
01841
01842
01843
01844
01845
01846
01847 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
01848
01849
01850
01851 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size(); kkk++) {
01852
01853
01854
01855
01856
01857
01858
01859
01860 if (((int)tracks.at(iii).locations.at(kkk).imageIndex) == idx1) {
01861
01862
01863
01864 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size(); jjj++) {
01865
01866
01867
01868 if (((int)tracks.at(iii).locations.at(jjj).imageIndex) == idx2) {
01869
01870
01871
01872 pts1.push_back(tracks.at(iii).locations.at(kkk).featureCoord);
01873 pts2.push_back(tracks.at(iii).locations.at(jjj).featureCoord);
01874 break;
01875 }
01876 }
01877
01878 }
01879 }
01880 }
01881 }
01882
01883 void obtainAppropriateBaseTransformation(cv::Mat& C0, vector<featureTrack>& tracks) {
01884
01885 cv::Point3d centroid, deviations;
01886
01887 int numTriangulatedPts = 0;
01888
01889 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
01890 if (tracks.at(iii).isTriangulated) {
01891
01892 numTriangulatedPts += 1;
01893
01894 }
01895 }
01896
01897 if (numTriangulatedPts == 0) {
01898 C0 = cv::Mat::eye(4, 4, CV_64FC1);
01899 } else {
01900
01901 findCentroidAndSpread(tracks, centroid, deviations);
01902
01903
01904 cv::Mat t(4, 1, CV_64FC1), R;
01905
01906 R = cv::Mat::eye(3, 3, CV_64FC1);
01907
01908 t.at<double>(0,0) = centroid.x + 3.0 * deviations.x;
01909 t.at<double>(0,0) = centroid.y + 3.0 * deviations.y;
01910 t.at<double>(0,0) = centroid.z + 3.0 * deviations.z;
01911 t.at<double>(3,0) = 1.0;
01912
01913 composeTransform(R, t, C0);
01914 }
01915 }
01916
01917 void findCentroidAndSpread(vector<featureTrack>& tracks, cv::Point3d& centroid, cv::Point3d& deviations) {
01918
01919 centroid = cv::Point3d(0.0, 0.0, 0.0);
01920 deviations = cv::Point3d(0.0, 0.0, 0.0);
01921
01922 double numPoints = 0.00;
01923
01924 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
01925 if (tracks.at(iii).isTriangulated) {
01926
01927 numPoints += 1.00;
01928
01929 }
01930 }
01931
01932 if (numPoints == 0.00) {
01933 return;
01934 }
01935
01936 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
01937
01938 if (tracks.at(iii).isTriangulated) {
01939
01940 cv::Point3d tmpPt;
01941 tmpPt = tracks.at(iii).get3dLoc();
01942 centroid.x += (tmpPt.x / numPoints);
01943 centroid.y += (tmpPt.y / numPoints);
01944 centroid.z += (tmpPt.z / numPoints);
01945
01946 }
01947
01948 }
01949
01950 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
01951
01952 if (tracks.at(iii).isTriangulated) {
01953 cv::Point3d tmpPt;
01954 tmpPt = tracks.at(iii).get3dLoc();
01955 deviations.x += (pow((tmpPt.x - centroid.x), 2.0) / numPoints);
01956 deviations.y += (pow((tmpPt.y - centroid.y), 2.0) / numPoints);
01957 deviations.z += (pow((tmpPt.z - centroid.z), 2.0) / numPoints);
01958 }
01959
01960 }
01961
01962 deviations.x = pow(deviations.x, 0.5);
01963 deviations.y = pow(deviations.y, 0.5);
01964 deviations.z = pow(deviations.z, 0.5);
01965 }
01966
01967 void getPoints3dFromTracks(vector<featureTrack>& tracks, vector<cv::Point3d>& cloud, int idx1, int idx2) {
01968
01969 cloud.clear();
01970
01971 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
01972
01973 if (!tracks.at(iii).isTriangulated) {
01974 continue;
01975 }
01976
01977 if (tracks.at(iii).locations.size() == 0) {
01978 continue;
01979 }
01980
01981 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size(); kkk++) {
01982
01983 bool addedPoint = false;
01984
01985 if ((((int)tracks.at(iii).locations.at(kkk).imageIndex) == idx1) || (idx1 == -1)) {
01986
01987 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size(); jjj++) {
01988
01989 if ((((int)tracks.at(iii).locations.at(jjj).imageIndex) == idx2) || (idx2 == -1)) {
01990 cloud.push_back(tracks.at(iii).get3dLoc());
01991 addedPoint = true;
01992 break;
01993 }
01994 }
01995
01996 }
01997
01998 if (addedPoint) {
01999 break;
02000 }
02001
02002 }
02003
02004
02005
02006 }
02007
02008 }
02009
02010
02011 void findFourTransformations(cv::Mat *C, const cv::Mat& E, const cv::Mat& K, const vector<cv::Point2f>& pts1, const vector<cv::Point2f>& pts2) {
02012
02013
02014 cv::Mat I, negI, t33, W, Winv, Z, Kinv, zeroTrans, R, t, Rvec;
02015
02016 Kinv = K.inv();
02017 zeroTrans = cv::Mat::zeros(3, 1, CV_64FC1);
02018 I = cv::Mat::eye(3, 3, CV_64FC1);
02019 negI = -I;
02020
02021 getWandZ(W, Winv, Z);
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037 cv::Mat c;
02038
02039
02040
02041
02042 cv::Mat u_transposePos, u_transposeNeg;
02043 cv::SVD svdPos, svdNeg;
02044
02045 svdPos = cv::SVD(E);
02046 svdNeg = cv::SVD(-E);
02047
02048 transpose(svdPos.u, u_transposePos);
02049 transpose(svdNeg.u, u_transposeNeg);
02050
02051 double detVal;
02052
02053 for (unsigned int zzz = 0; zzz < 4; zzz++) {
02054
02055
02056
02057 switch (zzz) {
02058 case 0:
02059
02060 t33 = svdPos.u * Z * u_transposePos;
02061 R = svdPos.u * Winv * svdPos.vt;
02062 detVal = determinant(R);
02063 if (detVal < 0) {
02064 t33 = svdNeg.u * Z * u_transposeNeg;
02065 R = svdNeg.u * Winv * svdNeg.vt;
02066 }
02067 break;
02068 case 1:
02069
02070 t33 = negI * svdPos.u * Z * u_transposePos;
02071 R = svdPos.u * Winv * svdPos.vt;
02072 detVal = determinant(R);
02073 if (detVal < 0) {
02074 t33 = negI * svdNeg.u * Z * u_transposeNeg;
02075 R = svdNeg.u * Winv * svdNeg.vt;
02076 }
02077 break;
02078 case 2:
02079
02080 t33 = svdPos.u * Z * u_transposePos;
02081 R = svdPos.u * W * svdPos.vt;
02082 detVal = determinant(R);
02083 if (detVal < 0) {
02084 t33 = svdNeg.u * Z * u_transposeNeg;
02085 R = svdNeg.u * W * svdNeg.vt;
02086 }
02087 break;
02088 case 3:
02089
02090 t33 = negI * svdPos.u * Z * u_transposePos;
02091 R = svdPos.u * W * svdPos.vt;
02092 detVal = determinant(R);
02093 if (detVal < 0) {
02094 t33 = negI * svdNeg.u * Z * u_transposeNeg;
02095 R = svdNeg.u * W * svdNeg.vt;
02096 }
02097 break;
02098 default:
02099 break;
02100 }
02101
02102
02103 t = cv::Mat::zeros(3, 1, CV_64F);
02104 t.at<double>(0,0) = -t33.at<double>(1,2);
02105 t.at<double>(1,0) = t33.at<double>(0,2);
02106 t.at<double>(2,0) = -t33.at<double>(0,1);
02107
02108
02109
02110 if (abs(1.0 - detVal) > 0.01) {
02111
02112 } else {
02113
02114 }
02115
02116
02117
02118 composeTransform(R, t, c);
02119
02120
02121
02122
02123
02124
02125
02126 c.copyTo(C[zzz]);
02127
02128
02129
02130 }
02131
02132 }
02133
02134
02135
02136 bool pointIsInFront(const cv::Mat& C, const cv::Point3d& pt) {
02137
02138 cv::Point3d p1;
02139
02140 transfer3dPoint(pt, p1, C);
02141
02142 if (p1.z > 0) {
02143 return true;
02144 } else {
02145
02146 return false;
02147
02148 }
02149
02150
02151 }
02152
02153
02154 int pointsInFront(const cv::Mat& C1, const cv::Mat& C2, const vector<cv::Point3d>& pts) {
02155 int retVal = 0;
02156
02157 vector<cv::Point3d> pts1, pts2;
02158
02159 cv::Mat R1, t1, R2, t2;
02160 decomposeTransform(C1, R1, t1);
02161 decomposeTransform(C2, R2, t2);
02162
02163 double rot1, rot2;
02164 rot1 = getRotationInDegrees(R1);
02165 rot2 = getRotationInDegrees(R2);
02166
02167 printf("%s << Two rotations = (%f, %f)\n", __FUNCTION__, rot1, rot2);
02168
02169
02170
02171
02172 transfer3DPoints(pts, pts1, C1);
02173 transfer3DPoints(pts, pts2, C2);
02174
02175 for (unsigned int iii = 0; iii < pts.size(); iii++) {
02176
02177
02178
02179 if ((pts1.at(iii).z > 0) && (pts2.at(iii).z > 0)) {
02180
02181 if (retVal < 5) {
02182 printf("%s << Point location is (%f, %f, %f)\n", __FUNCTION__, pts.at(iii).x, pts.at(iii).y, pts.at(iii).z);
02183 printf("%s << Rel #1 is (%f, %f, %f)\n", __FUNCTION__, pts1.at(iii).x, pts1.at(iii).y, pts1.at(iii).z);
02184 printf("%s << Rel #2 is (%f, %f, %f)\n", __FUNCTION__, pts2.at(iii).x, pts2.at(iii).y, pts2.at(iii).z);
02185 }
02186
02187 retVal++;
02188 }
02189 }
02190
02191 return retVal;
02192 }
02193
02194
02195 int pointsInFront(const cv::Mat& C1, const cv::Mat& K, const vector<cv::Point2f>& pts1, const vector<cv::Point2f>& pts2) {
02196
02197 int retVal = 0;
02198
02199 cv::Mat Kinv;
02200 Kinv = K.inv();
02201
02202
02203 cv::Mat P0, C0;
02204 initializeP0(P0);
02205 projectionToTransformation(P0, C0);
02206
02207
02208 cv::Mat P1;
02209 transformationToProjection(C1, P1);
02210
02211
02212 vector<cv::Point3d> pc1, pc2;
02213 vector<cv::Point2f> correspImg1Pt, correspImg2Pt;
02214
02215
02216 TriangulatePoints(pts1, pts2, K, Kinv, P0, P1, pc1, correspImg1Pt);
02217
02218
02219 cv::Mat C1inv;
02220 C1inv = C1.inv();
02221
02222
02223 transfer3DPoints(pc1, pc2, C1);
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245 int inFront1 = 0, inFront2 = 0;
02246
02247 for (unsigned int iii = 0; iii < pc1.size(); iii++) {
02248
02249
02250
02251
02252
02253 if (pc1.at(iii).z > 0) {
02254 inFront1++;
02255 }
02256
02257 if (pc2.at(iii).z > 0) {
02258 inFront2++;
02259 }
02260
02261 if ((pc1.at(iii).z > 0) && (pc2.at(iii).z > 0)) {
02262 retVal++;
02263 }
02264
02265 }
02266
02267
02268
02269 return retVal;
02270
02271 }
02272
02273 void convertPoint3dToMat(const cv::Point3d& src, cv::Mat& dst) {
02274 dst = cv::Mat::zeros(4, 1, CV_64FC1);
02275
02276 dst.at<double>(3, 0) = 1.0;
02277
02278 dst.at<double>(0,0) = src.x;
02279 dst.at<double>(1,0) = src.y;
02280 dst.at<double>(2,0) = src.z;
02281 }
02282
02283 void transfer3dPoint(const cv::Point3d& src, cv::Point3d& dst, const cv::Mat& C) {
02284
02285 cv::Mat pt1, pt2;
02286
02287 pt1 = cv::Mat::zeros(4, 1, CV_64FC1);
02288 pt2 = cv::Mat::zeros(4, 1, CV_64FC1);
02289
02290 pt1.at<double>(3, 0) = 1.0;
02291 pt2.at<double>(3, 0) = 1.0;
02292
02293
02294 pt1.at<double>(0,0) = src.x;
02295 pt1.at<double>(1,0) = src.y;
02296 pt1.at<double>(2,0) = src.z;
02297
02298 pt2 = C * pt1;
02299
02300 dst = cv::Point3d(pt2.at<double>(0,0), pt2.at<double>(1,0), pt2.at<double>(2,0));
02301
02302 }
02303
02304 void transfer3DPoints(const vector<cv::Point3d>& src, vector<cv::Point3d>& dst, const cv::Mat& C) {
02305
02306 cv::Mat pt1, pt2;
02307
02308 pt1 = cv::Mat::zeros(4, 1, CV_64FC1);
02309 pt2 = cv::Mat::zeros(4, 1, CV_64FC1);
02310
02311 pt1.at<double>(3, 0) = 1.0;
02312 pt2.at<double>(3, 0) = 1.0;
02313
02314 cv::Point3d shiftedPoint;
02315
02316 for (unsigned int iii = 0; iii < src.size(); iii++) {
02317 pt1.at<double>(0,0) = src.at(iii).x;
02318 pt1.at<double>(1,0) = src.at(iii).y;
02319 pt1.at<double>(2,0) = src.at(iii).z;
02320
02321 pt2 = C * pt1;
02322
02323
02324
02325 shiftedPoint.x = pt2.at<double>(0,0);
02326 shiftedPoint.y = pt2.at<double>(1,0);
02327 shiftedPoint.z = pt2.at<double>(2,0);
02328
02329 dst.push_back(shiftedPoint);
02330 }
02331
02332
02333
02334 }
02335
02336
02337
02338 double calcInlierGeometryDistance(vector<cv::Point2f>& points1, vector<cv::Point2f>& points2, cv::Mat& mat, cv::Mat& mask, int distMethod) {
02339
02340 double error = 0.0;
02341
02342 int inlierCounter = 0;
02343
02344 for (unsigned int iii = 0; iii < points1.size(); iii++) {
02345 if (mask.at<char>(iii, 0) > 0) {
02346
02347 error += calcGeometryDistance(points1.at(iii), points2.at(iii), mat, distMethod);
02348
02349 inlierCounter++;
02350 }
02351 }
02352
02353 error /= (double) inlierCounter;
02354
02355 return error;
02356 }
02357
02358 double calcGeometryScore(vector<cv::Point2f>& points1, vector<cv::Point2f>& points2, cv::Mat& F, cv::Mat& Fmask, cv::Mat& H, cv::Mat& Hmask) {
02359 double gScore = 0.0;
02360
02361 int inliers_H = 0, inliers_F = 0;
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375 inliers_H = countNonZero(Hmask);
02376 inliers_F = countNonZero(Fmask);
02377
02378 printf("%s << Inliers: %d (H), %d (F)\n", __FUNCTION__, inliers_H, inliers_F);
02379
02380 double sampson_H, sampson_F;
02381
02382 sampson_H = calcSampsonError(points1, points2, H, Hmask);
02383 sampson_F = calcSampsonError(points1, points2, F, Fmask);
02384
02385 double sampson_H2 = 0.0, sampson_F2 = 0.0;
02386
02387 printf("%s << Sampson errors: %f (H), %f (F)\n", __FUNCTION__, sampson_H, sampson_F);
02388
02389 for (unsigned int iii = 0; iii < points1.size(); iii++) {
02390 sampson_H2 += calcSampsonDistance(points1.at(iii), points2.at(iii), H) / (double)points1.size();
02391 sampson_F2 += calcSampsonDistance(points1.at(iii), points2.at(iii), F) / (double)points1.size();
02392 }
02393
02394 printf("%s << Sampson errors2: %f (H), %f (F)\n", __FUNCTION__, sampson_H2, sampson_F2);
02395
02396
02397 gScore = (((double) inliers_F) / ((double) inliers_H)) * ( sampson_H / pow(sampson_F, 0.5));
02398
02399 printf("%s << gScore = %f\n", __FUNCTION__, gScore);
02400
02401 return gScore;
02402 }
02403
02404 double calcFrameScore(double geomScore, int numFeatures, int numTracks) {
02405
02406 double frameScore;
02407
02408 frameScore = geomScore * ((double) numTracks) / ((double) numFeatures);
02409
02410 return frameScore;
02411 }
02412
02413 double calcSampsonError(vector<cv::Point2f>& points1, vector<cv::Point2f>& points2, cv::Mat& H, cv::Mat& Hmask) {
02414 double sampsonError = 0.0;
02415
02416 int inlierCounter = 0;
02417
02418
02419 for (unsigned int iii = 0; iii < points1.size(); iii++) {
02420 if (Hmask.at<char>(iii, 0) > 0) {
02421
02422 sampsonError += lourakisSampsonError(points1.at(iii), points2.at(iii), H);
02423
02424 inlierCounter++;
02425 }
02426 }
02427
02428 sampsonError /= (double) inlierCounter;
02429
02430 return sampsonError;
02431
02432 }
02433
02434
02435 double calcSampsonDistance(cv::Point2f& pt1, cv::Point2f& pt2, cv::Mat& F) {
02436
02437 double dist;
02438
02439 cv::Mat point1(1, 3, CV_64FC1), point2(1, 3, CV_64FC1);
02440
02441 point1.at<double>(0, 0) = (double) pt1.x;
02442 point1.at<double>(0, 1) = (double) pt1.y;
02443 point1.at<double>(0, 2) = 1.0;
02444
02445 cv::Mat t1;
02446 transpose(point1, t1);
02447
02448 point2.at<double>(0, 0) = (double) pt2.x;
02449 point2.at<double>(0, 1) = (double) pt2.y;
02450 point2.at<double>(0, 2) = 1.0;
02451
02452 cv::Mat a, b, c;
02453
02454 a = point2 * F * t1;
02455 b = F * t1;
02456 c = point2 * F;
02457
02458 double val1 = pow(a.at<double>(0, 0), 2.0);
02459 double val2 = 1.0 / ((pow(b.at<double>(0, 0), 2.0)) + (pow(b.at<double>(1, 0), 2.0)));
02460 double val3 = 1.0 / ((pow(c.at<double>(0, 0), 2.0)) + (pow(c.at<double>(1, 0), 2.0)));
02461
02462 dist = val1 * (val2 + val3);
02463
02464 return dist;
02465
02466 }
02467
02468 double calcGeometryScore(int numInliers_H, int numInliers_F, double sampsonError_H, double sampsonError_F) {
02469 double geometryScore = 0.0;
02470
02471 geometryScore = ((double) numInliers_F / (double) numInliers_H) * sampsonError_H / pow(sampsonError_F, 0.5);
02472
02473 return geometryScore;
02474 }
02475
02476 void assignIntrinsicsToP0(cv::Mat& P0, const cv::Mat& K) {
02477 P0 = cv::Mat::zeros(3, 4, CV_64FC1);
02478
02479 for (int iii = 0; iii < 3; iii++) {
02480 for (int jjj = 0; jjj < 3; jjj++) {
02481 P0.at<double>(iii,jjj) = K.at<double>(iii,jjj);
02482 }
02483 }
02484
02485 }
02486
02487 double getQuaternionAngle(const Quaterniond& q1, const Quaterniond& q2) {
02488 double angle, dot_prod;
02489
02490 dot_prod = dotProduct(q1, q2);
02491
02492 angle = 2.0 * acos(abs(dot_prod));
02493
02494 return angle;
02495 }
02496
02497 double dotProduct(const Quaterniond& q1, const Quaterniond& q2) {
02498 double prod;
02499
02500 prod = q1.x()*q2.x() + q1.y()*q2.y() + q1.z()*q2.z() + q1.w()*q2.w();
02501
02502 return prod;
02503 }
02504
02505 void combineTransforms(cv::Mat& CN, const cv::Mat& C0, const cv::Mat& C1) {
02506 CN = cv::Mat::eye(4, 4, CV_64FC1);
02507
02508 CN = C0 * C1;
02509 }
02510
02511 double dotProduct(const cv::Mat& vec1, const cv::Mat& vec2) {
02512 double prod;
02513
02514 prod = vec1.at<double>(0,0)*vec2.at<double>(0,0) + vec1.at<double>(0,0)*vec2.at<double>(0,0) + vec1.at<double>(0,0)*vec2.at<double>(0,0);
02515
02516 return prod;
02517
02518 }
02519
02520 double getRotationInDegrees(const cv::Mat& R) {
02521 Quaterniond rotation;
02522 matrixToQuaternion(R, rotation);
02523 Quaterniond dq = defaultQuaternion();
02524 double qa = getQuaternionAngle(rotation, dq) * 180.0 / M_PI;
02525
02526 return qa;
02527
02528 }
02529
02530 double getDistanceInUnits(const cv::Mat& t) {
02531 double retVal = 0.0;
02532
02533 retVal += pow(t.at<double>(0,0), 2.0);
02534 retVal += pow(t.at<double>(1,0), 2.0);
02535 retVal += pow(t.at<double>(2,0), 2.0);
02536 retVal = pow(retVal, 0.5);
02537
02538 return retVal;
02539 }
02540
02541
02542
02543 void addFixedCamera(SysSBA& sys, cameraParameters& cameraData, const cv::Mat& C) {
02544 addBlankCamera(sys, cameraData, true);
02545 updateCameraNode_2(sys, C, sys.nodes.size()-1);
02546 }
02547
02548 void addNewCamera(SysSBA& sys, cameraParameters& cameraData, const cv::Mat& C) {
02549 addBlankCamera(sys, cameraData, false);
02550 updateCameraNode_2(sys, C, sys.nodes.size()-1);
02551 }
02552
02553 void convertVec4dToMat(const Vector4d& vec4, cv::Mat& mat) {
02554 mat = cv::Mat::zeros(3, 1, CV_64FC1);
02555
02556 mat.at<double>(0,0) = vec4.x();
02557 mat.at<double>(1,0) = vec4.y();
02558 mat.at<double>(2,0) = vec4.z();
02559
02560 }
02561
02562 void updateTracks(vector<featureTrack>& trackVector, const SysSBA& sys) {
02563 cv::Point3d tmpPt;
02564 for (unsigned int iii = 0; iii < sys.tracks.size(); iii++) {
02565 if (iii < trackVector.size()) {
02566 tmpPt.x = sys.tracks[iii].point.x();
02567 tmpPt.y = sys.tracks[iii].point.y();
02568 tmpPt.z = sys.tracks[iii].point.z();
02569 trackVector.at(iii).set3dLoc(tmpPt);
02570 }
02571
02572 }
02573 }
02574
02575 void retrieveAllPoints(vector<cv::Point3d>& pts, const SysSBA& sys) {
02576
02577 cv::Point3d point_3;
02578
02579 for (unsigned int iii = 0; iii < sys.tracks.size(); iii++) {
02580 point_3.x = sys.tracks[iii].point.x();
02581 point_3.y = sys.tracks[iii].point.y();
02582 point_3.z = sys.tracks[iii].point.z();
02583
02584 pts.push_back(point_3);
02585 }
02586 }
02587
02588 void retrieveCameraPose(const SysSBA& sys, unsigned int idx, cv::Mat& camera) {
02589
02590 cv::Mat R, t;
02591 quaternionToMatrix(sys.nodes[idx].qrot, R);
02592 convertVec4dToMat(sys.nodes[idx].trans, t);
02593 composeTransform(R, t, camera);
02594
02595 }
02596
02597 double retrieveCameraPose(const SysSBA& sys, unsigned int idx, geometry_msgs::Pose& pose) {
02598
02599 cv::Point3d sysPt(sys.nodes[idx].trans(0), sys.nodes[idx].trans(1), sys.nodes[idx].trans(2));
02600 cv::Point3d posePt(pose.position.x, pose.position.y, pose.position.z);
02601
02602 double dist = distBetweenPts(sysPt, posePt);
02603
02604
02605 pose.orientation.w = sys.nodes[idx].qrot.w();
02606 pose.orientation.x = sys.nodes[idx].qrot.x();
02607 pose.orientation.y = sys.nodes[idx].qrot.y();
02608 pose.orientation.z = sys.nodes[idx].qrot.z();
02609
02610 pose.position.x = sys.nodes[idx].trans(0);
02611 pose.position.y = sys.nodes[idx].trans(1);
02612 pose.position.z = sys.nodes[idx].trans(2);
02613
02614 return dist;
02615
02616 }
02617
02618
02619 void retrieveAllCameras(cv::Mat *allCameraPoses, const SysSBA& sys) {
02620
02621 for (unsigned int iii = 0; iii < sys.nodes.size(); iii++) {
02622
02623
02624 retrieveCameraPose(sys, iii, allCameraPoses[iii]);
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635 }
02636 }
02637
02638 void assignTracksToSBA(SysSBA& sys, vector<featureTrack>& trackVector, int maxIndex) {
02639
02640 sys.tracks.clear();
02641
02642
02643 sys.connMat.clear();
02644
02645
02646
02647
02648
02649
02650 for (unsigned int iii = 0; iii < trackVector.size(); iii++) {
02651
02652
02653 if (((int)trackVector.at(iii).locations.at(0).imageIndex) < maxIndex) {
02654 cv::Point3d tmp3dPt = trackVector.at(iii).get3dLoc();
02655 Vector4d temppoint(tmp3dPt.x, tmp3dPt.y, tmp3dPt.z, 1.0);
02656 sys.addPoint(temppoint);
02657 }
02658
02659 }
02660
02661
02662 for (unsigned int iii = 0; iii < trackVector.size(); iii++) {
02663 Vector2d proj;
02664
02665
02666 if (((int)trackVector.at(iii).locations.at(0).imageIndex) < maxIndex) {
02667
02668
02669 for (unsigned int jjj = 0; jjj < trackVector.at(iii).locations.size(); jjj++) {
02670
02671
02672 if (trackVector.at(iii).locations.at(jjj).imageIndex < (maxIndex+1)) {
02673 proj.x() = trackVector.at(iii).locations.at(jjj).featureCoord.x;
02674 proj.y() = trackVector.at(iii).locations.at(jjj).featureCoord.y;
02675
02676 sys.addMonoProj(trackVector.at(iii).locations.at(jjj).imageIndex, iii, proj);
02677 }
02678
02679
02680 }
02681 }
02682
02683
02684 }
02685
02686 }
02687
02688 void estimateNewPose(vector<featureTrack>& tracks, cv::Mat& K, int idx, cv::Mat& pose) {
02689
02690
02691
02692 vector<cv::Point3d> worldPoints;
02693 vector<cv::Point2f> imagePoints1, imagePoints2;
02694
02695 cv::Mat blankCoeffs = cv::Mat::zeros(1, 8, CV_64FC1);
02696
02697 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
02698 if (tracks.at(iii).locations.size() >= 2) {
02699
02700 int finalIndex = tracks.at(iii).locations.size()-1;
02701
02702 if (((int)tracks.at(iii).locations.at(finalIndex).imageIndex) == idx) {
02703
02704 worldPoints.push_back(tracks.at(iii).get3dLoc());
02705 cv::Point2f tmpPt2(tracks.at(iii).locations.at(finalIndex-1).featureCoord.x, tracks.at(iii).locations.at(finalIndex-1).featureCoord.y);
02706 imagePoints1.push_back(tmpPt2);
02707 tmpPt2 = cv::Point2f(tracks.at(iii).locations.at(finalIndex).featureCoord.x, tracks.at(iii).locations.at(finalIndex).featureCoord.y);
02708 imagePoints2.push_back(tmpPt2);
02709 }
02710
02711 }
02712 }
02713
02714
02715 cv::Mat Rvec, R, t;
02716
02717 vector<cv::Point3f> objectPoints;
02718 cv::Point3f tmpPt;
02719
02720 for (unsigned int jjj = 0; jjj < worldPoints.size(); jjj++) {
02721 tmpPt = cv::Point3f((float) worldPoints.at(jjj).x, (float) worldPoints.at(jjj).y, (float) worldPoints.at(jjj).z);
02722 objectPoints.push_back(tmpPt);
02723 }
02724
02725
02726 solvePnPRansac(objectPoints, imagePoints2, K, blankCoeffs, Rvec, t);
02727 Rodrigues(Rvec, R);
02728
02729
02730 composeTransform(R, t, pose);
02731 }
02732
02733 void addNewPoints(SysSBA& sys, const vector<cv::Point3d>& pc) {
02734
02735 Vector2d proj;
02736
02737 proj.x() = 0.0;
02738 proj.y() = 0.0;
02739
02740 for (unsigned int iii = 0; iii < pc.size(); iii++) {
02741 Vector4d temppoint(pc.at(iii).x, pc.at(iii).y, pc.at(iii).z, 1.0);
02742
02743 sys.addPoint(temppoint);
02744
02745 sys.addMonoProj(0, iii, proj);
02746 }
02747 }
02748
02749 int addToTracks(SysSBA& sys, int im1, vector<cv::Point2f>& pts1, int im2, vector<cv::Point2f>& pts2) {
02750
02751
02752
02753
02754
02755 Vector2d proj;
02756
02757
02758
02759
02760 for (unsigned int iii = 0; iii < pts1.size(); iii++) {
02761
02762 bool pointInTracks = false;
02763
02764
02765
02766 for (unsigned int ttt = 0; ttt < sys.tracks.size(); ttt++) {
02767
02768
02769
02770 int finalIndex = sys.tracks.at(ttt).projections.size() - 1;
02771
02772
02773
02774 if (finalIndex > -1) {
02775
02776
02777
02778 printf("%s << Attempting [%d][%d][%d][%d]\n", __FUNCTION__, im1, im2, iii, ttt);
02779 printf("%s << ndi(%d / %d) = \n", __FUNCTION__, finalIndex, ((int)sys.tracks.at(ttt).projections.size()));
02780
02781 printf("%s << sizeof() %d\n", __FUNCTION__, int(sizeof(sys.tracks.at(ttt).projections)));
02782
02783 if (finalIndex > 0) {
02784 printf("%s << (-1) %d\n", __FUNCTION__, sys.tracks.at(ttt).projections.at(finalIndex-1).ndi);
02785 }
02786
02787 printf("%s << %d\n", __FUNCTION__, sys.tracks.at(ttt).projections.at(finalIndex).ndi);
02788
02789 if ((im1 == 2) && (im2 == 3) && (iii == 16) && (ttt == 68)) {
02790
02791 }
02792
02793
02794
02795
02796
02797 if (sys.tracks.at(ttt).projections.at(finalIndex).ndi == im1) {
02798
02799
02800
02801 if ((sys.tracks.at(ttt).projections.at(finalIndex).kp.x() == pts1.at(iii).x) && (sys.tracks.at(ttt).projections.at(finalIndex).kp.y() == pts1.at(iii).y)) {
02802
02803
02804
02805
02806
02807 pointInTracks = true;
02808
02809 proj.x() = pts2.at(iii).x;
02810 proj.y() = pts2.at(iii).y;
02811
02812 if (!sys.addMonoProj(im2, ttt, proj)) {
02813 printf("%s << Adding point failed!\n", __FUNCTION__);
02814 }
02815
02816
02817
02818 break;
02819
02820 }
02821
02822
02823 }
02824
02825
02826 }
02827
02828
02829
02830 }
02831
02832 if (!pointInTracks) {
02833
02834
02835
02836 int newTrackNum = sys.tracks.size();
02837
02838 Vector4d temppoint(0.0, 0.0, 0.0, 1.0);
02839
02840
02841
02842
02843 sys.addPoint(temppoint);
02844
02845
02846
02847
02848 proj.x() = pts1.at(iii).x;
02849 proj.y() = pts1.at(iii).y;
02850
02851 if (!sys.addMonoProj(im1, newTrackNum, proj)) {
02852 printf("%s << Adding point failed!\n", __FUNCTION__);
02853 }
02854
02855 proj.x() = pts2.at(iii).x;
02856 proj.y() = pts2.at(iii).y;
02857
02858 if (!sys.addMonoProj(im2, newTrackNum, proj)) {
02859 printf("%s << Adding point failed!\n", __FUNCTION__);
02860 }
02861
02862
02863 } else {
02864
02865 }
02866
02867
02868 }
02869
02870 return sys.tracks.size();
02871 }
02872
02873 void addBlankCamera(SysSBA& sys, cameraParameters& cameraData, bool isFixed) {
02874
02875 frame_common::CamParams cam_params;
02876
02877
02878 cam_params.fx = cameraData.K.at<double>(0, 0);
02879 cam_params.fy = cameraData.K.at<double>(1, 1);
02880
02881 cam_params.cx = cameraData.K.at<double>(0, 2);
02882 cam_params.cy = cameraData.K.at<double>(1, 2);
02883 cam_params.tx = 0;
02884
02885
02886
02887 Vector4d trans(0, 0, 0, 1);
02888
02889
02890 Quaterniond rot(1, 0, 0, 0);
02891 rot.normalize();
02892
02893
02894
02895
02896 sys.addNode(trans, rot, cam_params, isFixed);
02897
02898 sys.nodes.at(sys.nodes.size()-1).setDr(true);
02899
02900 if (isFixed) {
02901
02902 }
02903
02904
02905
02906
02907
02908
02909
02910
02911 }
02912
02913 void printSystemSummary(SysSBA& sys) {
02914 printf("%s << sys.nodes.size() = %d\n", __FUNCTION__, ((int)sys.nodes.size()));
02915 printf("%s << sys.tracks.size() = %d\n", __FUNCTION__, ((int)sys.tracks.size()));
02916 }
02917
02918 Quaterniond defaultQuaternion() {
02919 Quaterniond defQuaternion(1, 0, 0, 0);
02920
02921 return defQuaternion;
02922 }
02923
02924 void updateCameraNode_2(SysSBA& sys, const cv::Mat& C, int image_index) {
02925 cv::Mat R, t;
02926
02927 cv::Mat Cnew;
02928
02929 if (C.rows == 4) {
02930 C.copyTo(Cnew);
02931 } else {
02932 Cnew = cv::Mat(4, 4, CV_64FC1);
02933 for (unsigned int iii = 0; iii < 3; iii++) {
02934 for (unsigned int jjj = 0; jjj < 4; jjj++) {
02935 Cnew.at<double>(iii,jjj) = C.at<double>(iii,jjj);
02936
02937 }
02938 }
02939
02940 Cnew.at<double>(3,0) = 0.0;
02941 Cnew.at<double>(3,1) = 0.0;
02942 Cnew.at<double>(3,2) = 0.0;
02943 Cnew.at<double>(3,3) = 1.0;
02944 }
02945
02946 cv::Mat C_inv = Cnew.inv();
02947
02948 decomposeTransform(C, R, t);
02949
02950 for (unsigned int iii = 0; iii < 3; iii++) {
02951 for (unsigned int jjj = 0; jjj < 4; jjj++) {
02952 sys.nodes.at(image_index).w2n(iii,jjj) = C.at<double>(iii,jjj);
02953 }
02954 }
02955
02956 updateCameraNode_2(sys, R, t, image_index);
02957 }
02958
02959 void updateCameraNode_2(SysSBA& sys, const cv::Mat& R, const cv::Mat& t, int image_index) {
02960 Vector4d translation;
02961 Quaterniond rotation;
02962
02963
02964
02965 translation.x() = t.at<double>(0,0);
02966 translation.y() = t.at<double>(1,0);
02967 translation.z() = t.at<double>(2,0);
02968
02969
02970
02971 matrixToQuaternion(R, rotation);
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987 sys.nodes[image_index].trans = translation;
02988 sys.nodes[image_index].qrot = rotation;
02989
02990 }
02991
02992 void convertProjectionMatCVToEigen(const cv::Mat& mat, Eigen::Matrix< double, 3, 4 > m) {
02993
02994 m(0,0) = mat.at<double>(0,0);
02995 m(0,1) = mat.at<double>(0,1);
02996 m(0,2) = mat.at<double>(0,2);
02997 m(0,3) = mat.at<double>(0,3);
02998
02999 m(1,0) = mat.at<double>(1,0);
03000 m(1,1) = mat.at<double>(1,1);
03001 m(1,2) = mat.at<double>(1,2);
03002 m(1,3) = mat.at<double>(1,3);
03003
03004 m(2,0) = mat.at<double>(2,0);
03005 m(2,1) = mat.at<double>(2,1);
03006 m(2,2) = mat.at<double>(2,2);
03007 m(2,3) = mat.at<double>(2,3);
03008
03009 }
03010
03011 void convertProjectionMatEigenToCV(const Eigen::Matrix< double, 3, 4 > m, cv::Mat& mat) {
03012
03013 mat = cv::Mat::zeros(3, 4, CV_64FC1);
03014
03015 mat.at<double>(0,0) = m(0,0);
03016 mat.at<double>(0,1) = m(0,1);
03017 mat.at<double>(0,2) = m(0,2);
03018 mat.at<double>(0,3) = m(0,3);
03019
03020 mat.at<double>(1,0) = m(1,0);
03021 mat.at<double>(1,1) = m(1,1);
03022 mat.at<double>(1,2) = m(1,2);
03023 mat.at<double>(1,3) = m(1,3);
03024
03025 mat.at<double>(2,0) = m(2,0);
03026 mat.at<double>(2,1) = m(2,1);
03027 mat.at<double>(2,2) = m(2,2);
03028 mat.at<double>(2,3) = m(2,3);
03029
03030 }
03031
03032
03033
03034
03035 float ReciprocalSqrt( float x ) {
03036 long i;
03037 float y, r;
03038
03039 y = x * 0.5f;
03040 i = *(long *)( &x );
03041 i = 0x5f3759df - ( i >> 1 );
03042 r = *(float *)( &i );
03043 r = r * ( 1.5f - r * r * y );
03044 return r;
03045 }
03046
03047
03048 void updateCameraNode(SysSBA& sys, cv::Mat R, cv::Mat t, int img1, int img2) {
03049
03050 cv::Mat full_R;
03051
03052 Rodrigues(R, full_R);
03053
03054 printf("%s << Trying to determine position of camera node (%d, %d)...\n", __FUNCTION__, img1, img2);
03055
03056 cout << "R = " << R << endl;
03057 cout << "t = " << t << endl;
03058
03059
03060 Vector4d temptrans = sys.nodes[img1].trans;
03061 Quaterniond tempqrot = sys.nodes[img1].qrot;
03062
03063
03064
03065
03066
03067
03068
03069
03070 Vector4d temptrans_N;
03071 Quaterniond tempqrot_N;
03072 temptrans_N.x() = -temptrans.x();
03073 temptrans_N.y() = -temptrans.y();
03074 temptrans_N.z() = -temptrans.z();
03075 tempqrot_N.x() = tempqrot.x();
03076 tempqrot_N.y() = tempqrot.y();
03077 tempqrot_N.z() = tempqrot.z();
03078 tempqrot_N.w() = -tempqrot.w();
03079 tempqrot_N.normalize();
03080
03081 sba::Node negativeOrigin;
03082 negativeOrigin.trans = temptrans_N;
03083 negativeOrigin.qrot = tempqrot_N;
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102 Vector4d temptrans_B;
03103 Quaterniond tempqrot_B;
03104 temptrans_B.x() = t.at<double>(0,0);
03105 temptrans_B.y() = t.at<double>(1,0);
03106 temptrans_B.z() = t.at<double>(2,0);
03107
03108 matrixToQuaternion(full_R, tempqrot_B);
03109
03110
03111
03112
03113
03114
03115
03116 tempqrot_B.normalize();
03117
03118 sba::Node secondNode;
03119 secondNode.trans = temptrans_B;
03120 secondNode.qrot = tempqrot_B;
03121
03122
03123
03124
03125
03126 Eigen::Matrix< double, 4, 1 > transformationMat;
03127 Eigen::Quaternion< double > quaternionVec;
03128
03129 sba::transformN2N(transformationMat, quaternionVec, negativeOrigin, secondNode);
03130
03131
03132
03133
03134
03135 temptrans.x() = transformationMat(0,0);
03136 temptrans.y() = transformationMat(1,0);
03137 temptrans.z() = transformationMat(2,0);
03138
03139 tempqrot.x() = quaternionVec.x();
03140 tempqrot.y() = quaternionVec.y();
03141 tempqrot.z() = quaternionVec.z();
03142 tempqrot.normalize();
03143
03144 sys.nodes[img2].trans = temptrans;
03145 sys.nodes[img2].qrot = tempqrot;
03146
03147 sys.nodes[img2].normRot();
03148 sys.nodes[img2].setTransform();
03149 sys.nodes[img2].setProjection();
03150 sys.nodes[img2].setDr(true);
03151
03152
03153
03154 return;
03155
03156
03157
03158
03159
03160 temptrans.x() += t.at<double>(0,0);
03161 temptrans.y() += t.at<double>(1,0);
03162 temptrans.z() += t.at<double>(2,0);
03163
03164
03165
03166 tempqrot.x() += R.at<double>(0,0);
03167 tempqrot.y() += R.at<double>(1,0);
03168 tempqrot.z() += R.at<double>(2,0);
03169 tempqrot.normalize();
03170
03171 sys.nodes[img2].trans = temptrans;
03172 sys.nodes[img2].qrot = tempqrot;
03173
03174
03175
03176 sys.nodes[img2].normRot();
03177 sys.nodes[img2].setTransform();
03178 sys.nodes[img2].setProjection();
03179 sys.nodes[img2].setDr(true);
03180
03181 }
03182
03183 void constrainDodgyPoints(SysSBA& sys) {
03184
03185 for (unsigned int iii = 0; iii < sys.nodes.size(); iii++) {
03186 if ((abs(sys.nodes[iii].trans.x()) > POSITION_LIMIT) || (abs(sys.nodes[iii].trans.y()) > POSITION_LIMIT) || (abs(sys.nodes[iii].trans.z()) > POSITION_LIMIT)) {
03187 sys.nodes[iii].trans.x() = 0.0;
03188 sys.nodes[iii].trans.y() = 0.0;
03189 sys.nodes[iii].trans.z() = 0.0;
03190 }
03191 }
03192
03193 for (unsigned int iii = 0; iii < sys.tracks.size(); iii++) {
03194 if ((abs(sys.tracks[iii].point.x()) > POSITION_LIMIT) || (abs(sys.tracks[iii].point.y()) > POSITION_LIMIT) || (abs(sys.tracks[iii].point.z()) > POSITION_LIMIT)) {
03195 sys.tracks[iii].point.x() = 0.0;
03196 sys.tracks[iii].point.y() = 0.0;
03197 sys.tracks[iii].point.z() = 0.0;
03198 }
03199 }
03200 }
03201
03202 int TriangulateNewTracks(vector<featureTrack>& trackVector, const int index1, const int index2, const cv::Mat& K, const cv::Mat& K_inv, const cv::Mat& P0, const cv::Mat& P1, bool initializeOnFocalPlane) {
03203
03204 cv::Mat coordinateTransform;
03205
03206 int tracksTriangulated = 0;
03207
03208
03209 for (unsigned int iii = 0; iii < trackVector.size(); iii++) {
03210
03211 for (unsigned int jjj = 0; jjj < trackVector.at(iii).locations.size()-1; jjj++) {
03212
03213 int trInd1 = trackVector.at(iii).locations.at(jjj).imageIndex;
03214
03215 if (trInd1 == index1) {
03216
03217 for (unsigned int kkk = jjj+1; kkk < trackVector.at(iii).locations.size(); kkk++) {
03218
03219 int trInd2 = trackVector.at(iii).locations.at(kkk).imageIndex;
03220
03221 if (trInd2 == index2) {
03222
03223 cv::Point2f loc1 = trackVector.at(iii).locations.at(jjj).featureCoord;
03224 cv::Point2f loc2 = trackVector.at(iii).locations.at(kkk).featureCoord;
03225
03226 cv::Point3d xyzPoint;
03227
03228
03229 if (initializeOnFocalPlane) {
03230 xyzPoint.x = loc1.x;
03231 xyzPoint.y = loc1.y;
03232 xyzPoint.z = 1.0;
03233 } else {
03234 Triangulate(loc1, loc2, K, K_inv, P0, P1, xyzPoint);
03235 }
03236
03237
03238
03239
03240
03241 trackVector.at(iii).set3dLoc(xyzPoint);
03242
03243
03244
03245
03246
03247
03248 tracksTriangulated++;
03249
03250 }
03251
03252 }
03253
03254 }
03255
03256
03257 }
03258
03259
03260
03261
03262 }
03263
03264 return tracksTriangulated;
03265
03266 }
03267
03268 void ExtractPointCloud(vector<cv::Point3d>& cloud, vector<featureTrack>& trackVector) {
03269
03270
03271 for (unsigned int iii = 0; iii < trackVector.size(); iii++) {
03272
03273 cloud.push_back(trackVector.at(iii).get3dLoc());
03274 }
03275
03276
03277 }
03278
03279
03280
03281 void reduceVectorsToTrackedPoints(const vector<cv::Point2f>& points1, vector<cv::Point2f>& trackedPoints1, const vector<cv::Point2f>& points2, vector<cv::Point2f>& trackedPoints2, vector<uchar>& statusVec) {
03282
03283 trackedPoints1.clear();
03284 trackedPoints2.clear();
03285
03286 for (unsigned int iii = 0; iii < statusVec.size(); iii++) {
03287
03288 if (statusVec.at(iii) > 0) {
03289
03290 trackedPoints1.push_back(points1.at(iii));
03291 trackedPoints2.push_back(points2.at(iii));
03292 } else {
03293
03294 }
03295 }
03296
03297 }
03298
03299 bool findBestReconstruction(const cv::Mat& P0, cv::Mat& P1, cv::Mat& R, cv::Mat& t, const cv::SVD& svd, const cv::Mat& K, const vector<cv::Point2f>& pts1, const vector<cv::Point2f>& pts2, bool useDefault) {
03300
03301 bool validity = false;
03302
03303
03304
03305 if (pts1.size() != pts2.size()) {
03306 printf("%s << ERROR! Point vector size mismatch.\n", __FUNCTION__);
03307 }
03308
03309 int bestIndex = 0, bestScore = -1;
03310 cv::Mat t33, t_tmp[4], R_tmp[4], W, Z, Winv, I, negI, P1_tmp[4];
03311 cv::Mat Kinv;
03312
03313
03314 Kinv = K.inv();
03315
03316
03317
03318 cv::Mat zeroTrans;
03319 zeroTrans = cv::Mat::zeros(3, 1, CV_64F);
03320
03321 I = cv::Mat::eye(3, 3, CV_64FC1);
03322 negI = -I;
03323 getWandZ(W, Winv, Z);
03324
03325
03326
03327 cv::Mat u_transpose;
03328 transpose(svd.u, u_transpose);
03329
03330 cv::Mat rotation1;
03331 Rodrigues(I, rotation1);
03332
03333
03334
03335
03336
03337 float sig = rotation1.at<double>(0,1);
03338 float phi = rotation1.at<double>(0,2);
03339
03340
03341
03342 cv::Point3d unitVec1(1.0*sin(sig)*cos(phi), 1.0*sin(sig)*cos(phi), 1.0*cos(sig));
03343
03344
03345
03346 cv::Mat uv1(unitVec1);
03347
03348
03349
03350
03351 for (int zzz = 0; zzz < 4; zzz++) {
03352
03353
03354
03355 switch (zzz) {
03356 case 0:
03357
03358 t33 = svd.u * Z * u_transpose;
03359 R_tmp[zzz] = svd.u * Winv * svd.vt;
03360 break;
03361 case 1:
03362
03363 t33 = negI * svd.u * Z * u_transpose;
03364 R_tmp[zzz] = svd.u * Winv * svd.vt;
03365 break;
03366 case 2:
03367
03368 t33 = svd.u * Z * u_transpose;
03369 R_tmp[zzz] = svd.u * W * svd.vt;
03370 break;
03371 case 3:
03372
03373 t33 = negI * svd.u * Z * u_transpose;
03374 R_tmp[zzz] = svd.u * W * svd.vt;
03375 break;
03376 default:
03377 break;
03378 }
03379
03380
03381 t_tmp[zzz] = cv::Mat::zeros(3, 1, CV_64F);
03382 t_tmp[zzz].at<double>(0,0) = -t33.at<double>(1,2);
03383 t_tmp[zzz].at<double>(1,0) = t33.at<double>(0,2);
03384 t_tmp[zzz].at<double>(2,0) = -t33.at<double>(0,1);
03385
03386
03387 findP1Matrix(P1_tmp[zzz], R_tmp[zzz], t_tmp[zzz]);
03388
03389
03390 cv::Mat rotation2;
03391 Rodrigues(R_tmp[zzz], rotation2);
03392
03393
03394
03395 sig = rotation2.at<double>(0,1);
03396 phi = rotation2.at<double>(0,2);
03397
03398
03399
03400 cv::Point3d unitVec2(1.0*sin(sig)*cos(phi), 1.0*sin(sig)*cos(phi), 1.0*cos(sig));
03401
03402 cv::Mat uv2(unitVec2);
03403
03404
03405
03406 int badCount = 0;
03407
03408 vector<cv::Point3d> pointcloud;
03409 vector<cv::Point2f> correspImg1Pt;
03410
03411
03412
03413 TriangulatePoints(pts1, pts2, K, Kinv, P0, P1_tmp[zzz], pointcloud, correspImg1Pt);
03414
03415
03416
03417 cv::Mat Rs_k[2], ts_k[2];
03418
03419
03420 for (unsigned int kkk = 0; kkk < pointcloud.size(); kkk++) {
03421
03422
03423
03424
03425
03426 cv::Point3d rayVec1, rayVec2;
03427
03428 Rs_k[0] = I;
03429 Rs_k[1] = R_tmp[zzz];
03430
03431 ts_k[0] = zeroTrans;
03432 ts_k[1] = t_tmp[zzz];
03433
03434
03435
03436
03437
03438
03439
03440
03441 rayVec1.x = pointcloud.at(kkk).x - ts_k[0].at<double>(0,0);
03442 rayVec1.y = pointcloud.at(kkk).y - ts_k[0].at<double>(1,0);
03443 rayVec1.z = pointcloud.at(kkk).z - ts_k[0].at<double>(2,0);
03444
03445 rayVec2.x = pointcloud.at(kkk).x - ts_k[1].at<double>(0,0);
03446 rayVec2.y = pointcloud.at(kkk).y - ts_k[1].at<double>(1,0);
03447 rayVec2.z = pointcloud.at(kkk).z - ts_k[1].at<double>(2,0);
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464 double dot1, dot2;
03465
03466 cv::Mat rv1(rayVec1), rv2(rayVec2);
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476 dot1 = uv1.dot(rv1);
03477 dot2 = uv2.dot(rv2);
03478
03479
03480
03481
03482
03483 double mag1 = pow(pow(rayVec1.x, 2) + pow(rayVec1.y, 2) + pow(rayVec1.z, 2), 0.5);
03484 double mag2 = pow(pow(rayVec2.x, 2) + pow(rayVec2.y, 2) + pow(rayVec2.z, 2), 0.5);
03485
03486
03487
03488 double ang1 = fmod(acos(dot1 / mag1), 2*M_PI);
03489 double ang2 = fmod(acos(dot2 / mag2), 2*M_PI);
03490
03491
03492
03493
03494
03495
03496
03497 if ((abs(ang1) < M_PI/2 ) || (abs(ang2) < M_PI/2)) {
03498
03499
03500 validity = false;
03501 badCount++;
03502 }
03503
03504 if (rayVec1.z < 0) {
03505
03506
03507 } else {
03508
03509
03510 }
03511
03512
03513
03514 }
03515
03516 printf("%s << badCount[%d] = %d\n", __FUNCTION__, zzz, badCount);
03517
03518 if (zzz == 0) {
03519 bestScore = badCount;
03520 } else {
03521 if (badCount < bestScore) {
03522 bestScore = badCount;
03523 bestIndex = zzz;
03524 }
03525 }
03526
03527
03528 }
03529
03530 if (bestScore == 0) {
03531 validity = true;
03532 }
03533
03534
03535 if (useDefault) {
03536 bestIndex = 2;
03537 printf("%s << Defaulting to model #%d\n", __FUNCTION__, bestIndex);
03538 }
03539
03540 findP1Matrix(P1, R_tmp[bestIndex], t_tmp[bestIndex]);
03541
03542 R_tmp[bestIndex].copyTo(R);
03543 t_tmp[bestIndex].copyTo(t);
03544
03545 return validity;
03546 }
03547
03548 void initializeP0(cv::Mat& P) {
03549 P = cv::Mat::zeros(3, 4, CV_64FC1);
03550 P.at<double>(0,0) = 1.0;
03551 P.at<double>(0,1) = 0.0;
03552 P.at<double>(0,2) = 0.0;
03553 P.at<double>(0,3) = 0.0;
03554 P.at<double>(1,0) = 0.0;
03555 P.at<double>(1,1) = 1.0;
03556 P.at<double>(1,2) = 0.0;
03557 P.at<double>(1,3) = 0.0;
03558 P.at<double>(2,0) = 0.0;
03559 P.at<double>(2,1) = 0.0;
03560 P.at<double>(2,2) = 1.0;
03561 P.at<double>(2,3) = 0.0;
03562 }
03563
03564 void LinearLSTriangulation(cv::Mat& dst, const cv::Point3d& u1, const cv::Mat& P1, const cv::Point3d& u2, const cv::Mat& P2) {
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577 cv::Mat A(4, 3, CV_64FC1);
03578
03579 A.at<double>(0,0) = u1.x * P1.at<double>(2,0) - P1.at<double>(0,0);
03580 A.at<double>(0,1) = u1.x * P1.at<double>(2,1) - P1.at<double>(0,1);
03581 A.at<double>(0,2) = u1.x * P1.at<double>(2,2) - P1.at<double>(0,2);
03582
03583 A.at<double>(1,0) = u1.y * P1.at<double>(2,0) - P1.at<double>(1,0);
03584 A.at<double>(1,1) = u1.y * P1.at<double>(2,1) - P1.at<double>(1,1);
03585 A.at<double>(1,2) = u1.y * P1.at<double>(2,2) - P1.at<double>(1,2);
03586
03587 A.at<double>(2,0) = u2.x * P2.at<double>(2,0) - P2.at<double>(0,0);
03588 A.at<double>(2,1) = u2.x * P2.at<double>(2,1) - P2.at<double>(0,1);
03589 A.at<double>(2,2) = u2.x * P2.at<double>(2,2) - P2.at<double>(0,2);
03590
03591 A.at<double>(3,0) = u2.y * P2.at<double>(2,0) - P2.at<double>(1,0);
03592 A.at<double>(3,1) = u2.y * P2.at<double>(2,1) - P2.at<double>(1,1);
03593 A.at<double>(3,2) = u2.y * P2.at<double>(2,2) - P2.at<double>(1,2);
03594
03595
03596
03597
03598
03599 cv::Mat B(4, 1, CV_64FC1);
03600
03601 B.at<double>(0,0) = -((double) u1.x * P1.at<double>(2,3) - P1.at<double>(0,3));
03602 B.at<double>(0,1) = -((double) u1.y * P1.at<double>(2,3) - P1.at<double>(1,3));
03603 B.at<double>(0,2) = -((double) u2.x * P2.at<double>(2,3) - P2.at<double>(0,3));
03604 B.at<double>(0,3) = -((double) u2.y * P2.at<double>(2,3) - P2.at<double>(1,3));
03605
03606 cv::solve(A, B, dst, cv::DECOMP_SVD);
03607
03608 }
03609
03610 void Triangulate_1(const cv::Point2d& pt1, const cv::Point2d& pt2, const cv::Mat& K, const cv::Mat& Kinv, const cv::Mat& P1, const cv::Mat& P2, cv::Point3d& xyzPoint, bool iterate) {
03611
03612 cv::Mat C1, C2;
03613 projectionToTransformation(P1, C1);
03614 projectionToTransformation(P2, C2);
03615
03616 cv::Mat U1(3, 1, CV_64FC1);
03617 U1.at<double>(0,0) = pt1.x;
03618 U1.at<double>(1,0) = pt1.y;
03619 U1.at<double>(2,0) = 1.0;
03620 cv::Mat UM1 = Kinv * U1;
03621
03622 cv::Point3d u1(UM1.at<double>(0,0), UM1.at<double>(1,0), UM1.at<double>(2,0));
03623
03624 cv::Mat U2(3, 1, CV_64FC1);
03625 U2.at<double>(0,0) = pt2.x;
03626 U2.at<double>(1,0) = pt2.y;
03627 U2.at<double>(2,0) = 1.0;
03628 cv::Mat UM2 = Kinv * U2;
03629
03630 cv::Point3d u2(UM2.at<double>(0,0), UM2.at<double>(1,0), UM2.at<double>(2,0));
03631
03632
03633
03634 cv::Mat X;
03635
03636 if (iterate) {
03637 IterativeLinearLSTriangulation(X, u1, C1, u2, C2);
03638
03639
03640
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653
03654 } else {
03655 LinearLSTriangulation(X, u1, C1, u2, C2);
03656 }
03657
03658
03659 xyzPoint = cv::Point3d(X.at<double>(0,0), X.at<double>(1,0), X.at<double>(2,0));
03660
03661
03662
03663 }
03664
03665 void IterativeLinearLSTriangulation(cv::Mat& dst, const cv::Point3d& u1, const cv::Mat& P1, const cv::Point3d& u2, const cv::Mat& P2) {
03666
03667 int maxIterations = 10;
03668
03669 cv::Mat X(4, 1, CV_64FC1), XA;
03670
03671
03672
03673 LinearLSTriangulation(XA, u1, P1, u2, P2);
03674
03675
03676 X.at<double>(0,0) = XA.at<double>(0,0);
03677 X.at<double>(1,0) = XA.at<double>(1,0);
03678 X.at<double>(2,0) = XA.at<double>(2,0);
03679 X.at<double>(3,0) = 1.0;
03680
03681 double wi1 = 1.0, wi2 = 1.0;
03682
03683 for (int i = 0; i < maxIterations; i++) {
03684
03685
03686 cv::Mat P1X = P1.row(2) * X;
03687 double p1a = P1X.at<double>(0, 0);
03688
03689 cv::Mat P2X = P2.row(2) * X;
03690 double p2a = P2X.at<double>(0, 0);
03691
03692
03693 if ((fabsf(wi1 - p1a) <= EPSILON) && (fabsf(wi2 - p2a) <= EPSILON)) {
03694 break;
03695 }
03696
03697 wi1 = p1a;
03698 wi2 = p2a;
03699
03700
03701 cv::Mat A(4, 3, CV_64FC1);
03702
03703 A.at<double>(0,0) = (u1.x * P1.at<double>(2,0) - P1.at<double>(0,0)) / wi1;
03704 A.at<double>(0,1) = (u1.x * P1.at<double>(2,1) - P1.at<double>(0,1)) / wi1;
03705 A.at<double>(0,2) = (u1.x * P1.at<double>(2,2) - P1.at<double>(0,2)) / wi1;
03706
03707 A.at<double>(1,0) = (u1.y * P1.at<double>(2,0) - P1.at<double>(1,0)) / wi1;
03708 A.at<double>(1,1) = (u1.y * P1.at<double>(2,1) - P1.at<double>(1,1)) / wi1;
03709 A.at<double>(1,2) = (u1.y * P1.at<double>(2,2) - P1.at<double>(1,2)) / wi1;
03710
03711 A.at<double>(2,0) = (u2.x * P2.at<double>(2,0) - P2.at<double>(0,0)) / wi2;
03712 A.at<double>(2,1) = (u2.x * P2.at<double>(2,1) - P2.at<double>(0,1)) / wi2;
03713 A.at<double>(2,2) = (u2.x * P2.at<double>(2,2) - P2.at<double>(0,2)) / wi2;
03714
03715 A.at<double>(3,0) = (u2.y * P2.at<double>(2,0) - P2.at<double>(1,0)) / wi2;
03716 A.at<double>(3,1) = (u2.y * P2.at<double>(2,1) - P2.at<double>(1,1)) / wi2;
03717 A.at<double>(3,2) = (u2.y * P2.at<double>(2,2) - P2.at<double>(1,2)) / wi2;
03718
03719 cv::Mat B(4, 1, CV_64FC1);
03720
03721 B.at<double>(0,0) = -(u1.x * P1.at<double>(2,3) - P1.at<double>(0,3)) / wi1;
03722 B.at<double>(1,0) = -(u1.y * P1.at<double>(2,3) - P1.at<double>(1,3)) / wi1;
03723 B.at<double>(2,0) = -(u2.x * P2.at<double>(2,3) - P2.at<double>(0,3)) / wi2;
03724 B.at<double>(3,0) = -(u2.y * P2.at<double>(2,3) - P2.at<double>(1,3)) / wi2;
03725
03726 cv::solve(A, B, XA, cv::DECOMP_SVD);
03727
03728 X.at<double>(0,0) = XA.at<double>(0,0);
03729 X.at<double>(1,0) = XA.at<double>(1,0);
03730 X.at<double>(2,0) = XA.at<double>(2,0);
03731 X.at<double>(3,0) = 1.0;
03732
03733 }
03734
03735 X.copyTo(dst);
03736
03737 }
03738
03739 void getWandZ(cv::Mat& W, cv::Mat& Winv, cv::Mat& Z) {
03740 W = cv::Mat::zeros(3, 3, CV_64FC1);
03741
03742 W.at<double>(0,0) = 0.0;
03743 W.at<double>(0,1) = -1.0;
03744 W.at<double>(0,2) = 0.0;
03745
03746 W.at<double>(1,0) = 1.0;
03747 W.at<double>(1,1) = 0.0;
03748 W.at<double>(1,2) = 0.0;
03749
03750 W.at<double>(2,0) = 0.0;
03751 W.at<double>(2,1) = 0.0;
03752 W.at<double>(2,2) = 1.0;
03753
03754 Winv = cv::Mat::zeros(3, 3, CV_64FC1);
03755
03756 Winv.at<double>(0,0) = 0.0;
03757 Winv.at<double>(0,1) = 1.0;
03758 Winv.at<double>(0,2) = 0.0;
03759
03760 Winv.at<double>(1,0) = -1.0;
03761 Winv.at<double>(1,1) = 0.0;
03762 Winv.at<double>(1,2) = 0.0;
03763
03764 Winv.at<double>(2,0) = 0.0;
03765 Winv.at<double>(2,1) = 0.0;
03766 Winv.at<double>(2,2) = 1.0;
03767
03768 Z = cv::Mat::zeros(3, 3, CV_64FC1);
03769
03770 Z.at<double>(0,1) = 1.0;
03771 Z.at<double>(1,0) = -1.0;
03772 }
03773
03774 void findP1Matrix(cv::Mat& P1, const cv::Mat& R, const cv::Mat& t) {
03775
03776
03777
03778
03779
03780
03781
03782
03783 P1 = cv::Mat(3, 4, CV_64FC1);
03784
03785 P1.at<double>(0,0) = R.at<double>(0,0);
03786 P1.at<double>(0,1) = R.at<double>(0,1);
03787 P1.at<double>(0,2) = R.at<double>(0,2);
03788 P1.at<double>(0,3) = t.at<double>(0,0);
03789
03790 P1.at<double>(1,0) = R.at<double>(1,0);
03791 P1.at<double>(1,1) = R.at<double>(1,1);
03792 P1.at<double>(1,2) = R.at<double>(1,2);
03793 P1.at<double>(1,3) = t.at<double>(1,0);
03794
03795 P1.at<double>(2,0) = R.at<double>(2,0);
03796 P1.at<double>(2,1) = R.at<double>(2,1);
03797 P1.at<double>(2,2) = R.at<double>(2,2);
03798 P1.at<double>(2,3) = t.at<double>(2,0);
03799 }
03800
03801 void Triangulate(const cv::Point2f& pt1, const cv::Point2f& pt2, const cv::Mat& K, const cv::Mat& Kinv, const cv::Mat& P1, const cv::Mat& P2, cv::Point3d& xyzPoint, bool debug) {
03802
03803 cv::Mat C1, C2;
03804 projectionToTransformation(P1, C1);
03805 projectionToTransformation(P2, C2);
03806
03807
03808 cv::Mat P0, PR, C0, CR;
03809 initializeP0(P0);
03810 projectionToTransformation(P0, C0);
03811 CR = C2 * C1.inv();
03812 transformationToProjection(CR, PR);
03813
03814 cv::Point3d xyzPoint_R;
03815
03816
03817
03818
03819 cv::Point3d u_1(pt1.x, pt1.y, 1.0);
03820 cv::Mat umx1 = Kinv * cv::Mat(u_1);
03821
03822 u_1.x = umx1.at<double>(0, 0);
03823 u_1.y = umx1.at<double>(1, 0);
03824 u_1.z = umx1.at<double>(2, 0);
03825
03826
03827 cv::Point3d u_2(pt2.x, pt2.y,1.0);
03828 cv::Mat umx2 = Kinv * cv::Mat(u_2);
03829
03830 u_2.x = umx2.at<double>(0, 0);
03831 u_2.y = umx2.at<double>(1, 0);
03832 u_2.z = umx2.at<double>(2, 0);
03833
03834
03835
03836 cv::Mat X;
03837
03838 IterativeLinearLSTriangulation(X, u_1, P0, u_2, PR);
03839
03840 xyzPoint_R = cv::Point3d( X.at<double>(0, 0), X.at<double>(1, 0), X.at<double>(2, 0) );
03841
03842 cv::Mat A(4, 1, CV_64FC1), B(4, 1, CV_64FC1);
03843
03844 A.at<double>(0,0) = xyzPoint_R.x;
03845 A.at<double>(1,0) = xyzPoint_R.y;
03846 A.at<double>(2,0) = xyzPoint_R.z;
03847 A.at<double>(3,0) = 1.0;
03848
03849
03850 B = C1 * A;
03851
03852 xyzPoint.x = B.at<double>(0,0) / B.at<double>(3,0);
03853 xyzPoint.y = B.at<double>(1,0) / B.at<double>(3,0);
03854 xyzPoint.z = B.at<double>(2,0) / B.at<double>(3,0);
03855
03856 if (debug) {
03857
03858 printf("%s << DEBUG SUMMARY:\n", __FUNCTION__);
03859
03860
03861 cout << endl << "P1 = " << P1 << endl;
03862 cout << "P2 = " << P2 << endl;
03863 cout << "P0 = " << P0 << endl;
03864 cout << "PR = " << PR << endl;
03865 cout << "C1 = " << C1 << endl << endl;
03866
03867 printf("pt1 -> u_1 = (%f, %f), (%f, %f, %f)\n", pt1.x, pt1.y, u_1.x, u_1.y, u_1.z);
03868 printf("pt2 -> u_2 = (%f, %f), (%f, %f, %f)\n\n", pt2.x, pt2.y, u_2.x, u_2.y, u_2.z);
03869
03870 printf("xyzPoint_R = (%f, %f, %f)\n", xyzPoint_R.x, xyzPoint_R.y, xyzPoint_R.z);
03871 printf("xyzPoint = (%f, %f, %f)\n\n", xyzPoint.x, xyzPoint.y, xyzPoint.z);
03872
03873 cin.get();
03874 }
03875
03876
03877 }
03878
03879 void TriangulatePoints(const vector<cv::Point2f>& pt_set1,
03880 const vector<cv::Point2f>& pt_set2,
03881 const cv::Mat& K,
03882 const cv::Mat& Kinv,
03883 const cv::Mat& P,
03884 const cv::Mat& P1,
03885 vector<cv::Point3d>& pointcloud,
03886 vector<cv::Point2f>& correspImg1Pt)
03887 {
03888
03889 pointcloud.clear();
03890 correspImg1Pt.clear();
03891
03892 cv::Point3d point_3;
03893
03894 for (unsigned int iii = 0; iii < pt_set1.size(); iii++) {
03895
03896 Triangulate(pt_set1.at(iii), pt_set2.at(iii), K, Kinv, P, P1, point_3, false);
03897
03898 pointcloud.push_back(point_3);
03899 correspImg1Pt.push_back(pt_set1[iii]);
03900 }
03901 }
03902
03903 void findCentroid(vector<featureTrack>& tracks, cv::Point3d& centroid, cv::Point3d& stdDeviation) {
03904
03905 unsigned int triangulatedPoints = 0;
03906
03907 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
03908 if (tracks.at(iii).isTriangulated) {
03909 triangulatedPoints++;
03910 }
03911 }
03912
03913 printf("%s << triangulatedPoints = %d\n", __FUNCTION__, triangulatedPoints);
03914
03915 centroid = cv::Point3d(0.0, 0.0, 0.0);
03916 stdDeviation = cv::Point3d(0.0, 0.0, 0.0);
03917
03918 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
03919 if (tracks.at(iii).isTriangulated) {
03920 centroid.x += (tracks.at(iii).get3dLoc().x / ((double) triangulatedPoints));
03921 centroid.y += (tracks.at(iii).get3dLoc().y / ((double) triangulatedPoints));
03922 centroid.z += (tracks.at(iii).get3dLoc().z / ((double) triangulatedPoints));
03923 }
03924 }
03925
03926 for (unsigned int iii = 0; iii < tracks.size(); iii++) {
03927 if (tracks.at(iii).isTriangulated) {
03928 stdDeviation.x += (pow((tracks.at(iii).get3dLoc().x - centroid.x), 2.0) / ((double) triangulatedPoints));
03929 stdDeviation.y += (pow((tracks.at(iii).get3dLoc().y - centroid.y), 2.0) / ((double) triangulatedPoints));
03930 stdDeviation.z += (pow((tracks.at(iii).get3dLoc().z - centroid.z), 2.0) / ((double) triangulatedPoints));
03931 }
03932
03933 }
03934
03935 stdDeviation.x = pow(stdDeviation.x, 0.5);
03936 stdDeviation.y = pow(stdDeviation.y, 0.5);
03937 stdDeviation.z = pow(stdDeviation.z, 0.5);
03938
03939 }
03940