$search
00001 00005 #include "reconstruction.hpp" 00006 00007 void summarizeTransformation(const Mat& C, char *summary) { 00008 00009 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 Mat *CX, const Mat& K, const vector<Point2f>& pts1, const vector<Point2f>& pts2, 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 //printf("%s << validPts(%d) = %d\n", __FUNCTION__, kkk, validPts); 00036 } 00037 00038 CX[bestCandidate].copyTo(C); 00039 00040 return bestScore; 00041 } 00042 00043 void reverseTranslation(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<Point2f>& pts1, vector<Point2f>& pts2, vector<Point3d>& pts3d, int idx1, int idx2) { 00054 00055 // For each 3d point, find the track that contains it, then find the projections... 00056 for (unsigned int jjj = 0; jjj < pts3d.size(); jjj++) { 00057 00058 //printf("%s << jjj = %d (%f, %f, %f)\n", __FUNCTION__, jjj, pts3d.at(jjj).x, pts3d.at(jjj).y, pts3d.at(jjj).z); 00059 00060 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 00061 00062 //printf("%s << iii = %d\n", __FUNCTION__, iii); 00063 00064 // MONKEY!! 00065 if (tracks.at(iii).get3dLoc() == pts3d.at(jjj)) { 00066 00067 //printf("%s << MATCH! (%d, %d)\n", __FUNCTION__, jjj, iii); 00068 00069 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size(); kkk++) { 00070 00071 //printf("%s << kkk = %d (%d, %d)\n", __FUNCTION__, kkk, tracks.at(iii).locations.at(kkk).imageIndex, tracks.at(iii).locations.at(kkk).imageIndex); 00072 00073 if (tracks.at(iii).locations.at(kkk).imageIndex == idx1) { 00074 00075 pts1.push_back(tracks.at(iii).locations.at(kkk).featureCoord); 00076 00077 } else if (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 countActiveTriangulatedTracks(vector<unsigned int>& indices, vector<featureTrack>& tracks) { 00095 00096 int triangulatedCount = 0; 00097 00098 for (unsigned int iii = 0; iii < indices.size(); iii++) { 00099 00100 if (tracks.at(indices.at(iii)).isTriangulated) { 00101 triangulatedCount++; 00102 } 00103 00104 } 00105 00106 return triangulatedCount; 00107 00108 } 00109 00110 void getIndicesForTriangulation(vector<unsigned int>& dst, vector<unsigned int>& src, vector<unsigned int>& already_triangulated) { 00111 00112 dst.clear(); 00113 00114 for (unsigned int iii = 0; iii < src.size(); iii++) { 00115 00116 bool triangulated = false; 00117 00118 for (unsigned int jjj = 0; jjj < already_triangulated.size(); jjj++) { 00119 00120 if (already_triangulated.at(jjj) == src.at(iii)) { 00121 triangulated = true; 00122 continue; 00123 } 00124 00125 00126 } 00127 00128 if (!triangulated) { 00129 00130 dst.push_back(src.at(iii)); 00131 00132 } 00133 00134 00135 } 00136 00137 } 00138 00139 void reconstructSubsequence(vector<featureTrack>& tracks, vector<Point3d>& ptCloud, int idx1, int idx2) { 00140 00141 } 00142 00143 void removeShortTracks(vector<featureTrack>& tracks, int idx1, int idx2) { 00144 00145 int minLength = (idx2 - idx1) / 2; 00146 00147 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 00148 int trackLength = tracks.at(iii).locations.size(); 00149 if (trackLength < minLength) { 00150 int final_image = tracks.at(iii).locations.at(trackLength-1).imageIndex; 00151 00152 if ((final_image >= idx1) && (final_image < idx2)) { 00153 tracks.erase(tracks.begin() + iii); 00154 iii--; 00155 } 00156 00157 } 00158 } 00159 00160 } 00161 00162 void updateSystemTracks(SysSBA& sys, vector<featureTrack>& tracks, unsigned int start_index) { 00163 00164 //sys = SysSBA(); 00165 00166 sys.tracks.clear(); 00167 00168 00169 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 00170 00171 //printf("%s << Checking track (%d) (size = %d)\n", __FUNCTION__, iii, tracks.at(iii).locations.size()); 00172 00173 if (tracks.at(iii).isTriangulated) { 00174 00175 00176 //printf("%s << Track is triangulated\n", __FUNCTION__); 00177 00178 Vector4d temppoint(tracks.at(iii).get3dLoc().x, tracks.at(iii).get3dLoc().y, tracks.at(iii).get3dLoc().z, 1.0); 00179 sys.addPoint(temppoint); 00180 00181 //printf("%s << Point added; nodes = %d\n", __FUNCTION__, sys.nodes.size()); 00182 //printf("%s << sys.tracks.size() = %d\n", __FUNCTION__, sys.tracks.size()); 00183 00184 // sys.tracks.size()-1 00185 00186 00187 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size(); jjj++) { 00188 00189 // Only want to add projections for active nodes 00190 00191 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()))) { 00192 //printf("%s << Assembling projection (%d)(%d)\n", __FUNCTION__, iii, jjj); 00193 00194 Vector2d proj; 00195 00196 proj.x() = tracks.at(iii).locations.at(jjj).featureCoord.x; 00197 proj.y() = tracks.at(iii).locations.at(jjj).featureCoord.y; 00198 00199 //printf("%s << Adding projection (track: %d)(loc: %d) node #: [%d]\n", __FUNCTION__, iii, jjj, tracks.at(iii).locations.at(jjj).imageIndex); 00200 00201 //printf("%s << vec size (tracks: %d, nodes for this track: %d)\n", __FUNCTION__, tracks.size(), tracks.at(iii).locations.size()); 00202 //printf("%s << sys size (tracks: %d, nodes: %d)\n", __FUNCTION__, sys.tracks.size(), sys.nodes.size()); 00203 00204 // If you only have 30 nodes, then how are you adding a track that has an image index of 53? 00205 00206 //printf("%s << Adding mono projection: (cam: %d / %d, track: %d / %d) = (%f, %f)\n", __FUNCTION__, tracks.at(iii).locations.at(jjj).imageIndex, sys.nodes.size(), sys.tracks.size()-1, sys.tracks.size(), proj.x(), proj.y()); 00207 sys.addMonoProj(tracks.at(iii).locations.at(jjj).imageIndex-start_index, sys.tracks.size()-1, proj); 00208 00209 //printf("%s << Added.\n", __FUNCTION__); 00210 00211 // 0, 53, proj 00212 } 00213 00214 00215 00216 } 00217 00218 //printf("%s << Projections added\n", __FUNCTION__); 00219 00220 } 00221 00222 } 00223 00224 } 00225 00226 void updateTriangulatedPoints(vector<featureTrack>& tracks, vector<unsigned int>& indices, vector<Point3d>& cloud) { 00227 00228 if (cloud.size() != indices.size()) { 00229 printf("%s << ERROR! Cloud size and index list size don't match (%d vd %d)\n", __FUNCTION__, cloud.size(), indices.size()); 00230 } 00231 00232 for (unsigned int iii = 0; iii < indices.size(); iii++) { 00233 00234 if (tracks.at(indices.at(iii)).isTriangulated) { 00235 //printf("%s << (%d) is triangulated; moving from (%f, %f, %f) to (%f, %f, %f)\n", __FUNCTION__, iii, tracks.at(indices.at(iii)).get3dLoc().x, tracks.at(indices.at(iii)).get3dLoc().y, tracks.at(indices.at(iii)).get3dLoc().z, cloud.at(iii).x, cloud.at(iii).y, cloud.at(iii).z); 00236 } 00237 00238 tracks.at(indices.at(iii)).set3dLoc(cloud.at(iii)); 00239 00240 00241 00242 } 00243 00244 } 00245 00246 void reduceActiveToTriangulated(vector<featureTrack>& tracks, vector<unsigned int>& indices, vector<unsigned int>& untriangulated) { 00247 00248 for (unsigned int iii = 0; iii < indices.size(); iii++) { 00249 00250 if (!tracks.at(indices.at(iii)).isTriangulated) { 00251 untriangulated.push_back(indices.at(iii)); 00252 indices.erase(indices.begin() + iii); 00253 iii--; 00254 } 00255 00256 } 00257 00258 } 00259 00260 void filterToActivePoints(vector<featureTrack>& tracks, vector<Point2f>& pts1, vector<Point2f>& pts2, vector<unsigned int>& indices, int idx1, int idx2) { 00261 00262 pts1.clear(); 00263 pts2.clear(); 00264 00265 for (unsigned int iii = 0; iii < indices.size(); iii++) { 00266 00267 for (unsigned int jjj = 0; jjj < tracks.at(indices.at(iii)).locations.size()-1; jjj++) { 00268 00269 if (tracks.at(indices.at(iii)).locations.at(jjj).imageIndex == idx1) { 00270 00271 pts1.push_back(tracks.at(indices.at(iii)).locations.at(jjj).featureCoord); 00272 00273 for (unsigned int kkk = jjj+1; kkk < tracks.at(indices.at(iii)).locations.size(); kkk++) { 00274 00275 if (tracks.at(indices.at(iii)).locations.at(kkk).imageIndex == idx2) { 00276 00277 pts2.push_back(tracks.at(indices.at(iii)).locations.at(kkk).featureCoord); 00278 00279 continue; 00280 } 00281 00282 } 00283 00284 continue; 00285 00286 } 00287 00288 } 00289 00290 } 00291 00292 00293 } 00294 00295 void getActive3dPoints(vector<featureTrack>& tracks, vector<unsigned int>& indices, vector<Point3d>& cloud) { 00296 00297 cloud.clear(); 00298 00299 for (unsigned int iii = 0; iii < indices.size(); iii++) { 00300 cloud.push_back(tracks.at(indices.at(iii)).get3dLoc()); 00301 } 00302 00303 } 00304 00305 void filterToCompleteTracks(vector<unsigned int>& dst, vector<unsigned int>& src, vector<featureTrack>& tracks, int idx1, int idx2) { 00306 00307 dst.clear(); 00308 00309 for (unsigned int iii = 0; iii < src.size(); iii++) { 00310 00311 if (tracks.at(src.at(iii)).locations.size() >= (idx2 - idx1)) { 00312 00313 for (unsigned int jjj = 0; jjj < tracks.at(src.at(iii)).locations.size()-(idx2-idx1); jjj++) { 00314 00315 //printf("%s << DEBUG [%d][%d]\n", __FUNCTION__, iii, jjj); 00316 00317 if (tracks.at(src.at(iii)).locations.at(jjj).imageIndex == idx1) { 00318 00319 //printf("%s << DEBUG [%d][%d] X\n", __FUNCTION__, iii, jjj); 00320 00321 for (unsigned int kkk = jjj+1; kkk < tracks.at(src.at(iii)).locations.size(); kkk++) { 00322 00323 //printf("%s << DEBUG [%d][%d][%d]\n", __FUNCTION__, iii, jjj, kkk); 00324 00325 if (tracks.at(src.at(iii)).locations.at(kkk).imageIndex == idx2) { 00326 00327 //printf("%s << DEBUG [%d][%d][%d] X\n", __FUNCTION__, iii, jjj, kkk); 00328 00329 dst.push_back(src.at(iii)); 00330 00331 } 00332 00333 } 00334 00335 } 00336 00337 00338 } 00339 00340 } 00341 00342 } 00343 00344 } 00345 00346 void getActiveTracks(vector<unsigned int>& indices, vector<featureTrack>& tracks, int idx1, int idx2) { 00347 00348 printf("%s << Entered.\n", __FUNCTION__); 00349 00350 // Should only consider a track active if it contains at least two projections in the subsequence 00351 00352 indices.clear(); 00353 00354 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 00355 00356 //printf("%s << DEBUG [%d]\n", __FUNCTION__, iii); 00357 00358 if (tracks.at(iii).locations.size() < 2) { 00359 continue; 00360 } 00361 00362 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size()-1; jjj++) { 00363 00364 //printf("%s << DEBUG [%d][%d]\n", __FUNCTION__, iii, jjj); 00365 00366 if ((tracks.at(iii).locations.at(jjj).imageIndex >= idx1) && (tracks.at(iii).locations.at(jjj).imageIndex <= idx2)) { 00367 00368 for (unsigned int kkk = jjj+1; kkk < tracks.at(iii).locations.size(); kkk++) { 00369 00370 if ((tracks.at(iii).locations.at(kkk).imageIndex >= idx1) && (tracks.at(iii).locations.at(kkk).imageIndex <= idx2)) { 00371 indices.push_back(iii); 00372 break; 00373 } 00374 00375 } 00376 00377 break; 00378 } 00379 00380 00381 } 00382 00383 00384 00385 00386 00387 } 00388 00389 printf("%s << Exiting.\n", __FUNCTION__); 00390 00391 } 00392 00393 bool estimatePoseFromKnownPoints(Mat& dst, cameraParameters camData, vector<featureTrack>& tracks, unsigned int index, const Mat& guide) { 00394 00395 vector<Point3f> points_3d; 00396 vector<Point2f> points_2d; 00397 00398 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 00399 00400 //printf("%s << DEBUG [%d]\n", __FUNCTION__, iii); 00401 00402 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size(); jjj++) { 00403 00404 //printf("%s << DEBUG [%d][%d]\n", __FUNCTION__, iii, jjj); 00405 00406 if (tracks.at(iii).locations.at(jjj).imageIndex == index) { 00407 00408 /* 00409 if ((index >= 224) && (index <= 226)) { 00410 printf("%s << Found track (%d) in image (%d)\n", __FUNCTION__, iii, index); 00411 } 00412 */ 00413 00414 if (tracks.at(iii).isTriangulated) { 00415 points_2d.push_back(tracks.at(iii).locations.at(jjj).featureCoord); 00416 Point3f tmp_pt = Point3f(((float) tracks.at(iii).get3dLoc().x), ((float) tracks.at(iii).get3dLoc().y), ((float) tracks.at(iii).get3dLoc().z)); 00417 points_3d.push_back(tmp_pt); 00418 00419 } 00420 00421 00422 break; 00423 } 00424 00425 00426 } 00427 00428 00429 } 00430 00431 Mat Rvec, R, t; 00432 bool guided = false; 00433 00434 if (guide.rows > 0) { 00435 decomposeTransform(guide, R, t); 00436 Rodrigues(R, Rvec); 00437 guided = true; 00438 } 00439 00440 Mat inlierPts; 00441 00442 00443 if (points_2d.size() < 8) { 00444 printf("%s << Insufficient pts (%d) in frame (%d)\n", __FUNCTION__, points_2d.size(), index); 00445 guide.copyTo(dst); 00446 00447 //while (1) {} 00448 return false; 00449 } 00450 00451 //printf("%s << About to solve PnP to estimate pose; (%d) pts\n", __FUNCTION__, points_2d.size()); 00452 00453 // ORIGINAL 00454 //solvePnPRansac(points_3d, points_2d, camData.K, camData.blankCoeffs, Rvec, t, guided, 300, 6.0, ((unsigned int) ((double) points_2d.size()) * 0.9), inlierPts); 00455 00456 // DIDNT WORK 00457 //solvePnPRansac(points_3d, points_2d, camData.K, camData.blankCoeffs, Rvec, t, guided, 100, 8.0, ((unsigned int) ((double) points_2d.size()) * 0.9), inlierPts); 00458 00459 // WORKED WELL! 00460 // solvePnPRansac(points_3d, points_2d, camData.K, camData.blankCoeffs, Rvec, t, guided, 100, 6.0, ((unsigned int) ((double) points_2d.size()) * 0.9), inlierPts); 00461 00462 // SEEMS TO WORK... 00463 //solvePnPRansac(points_3d, points_2d, camData.K, camData.blankCoeffs, Rvec, t, guided, 100, 5.0, ((unsigned int) ((double) points_2d.size()) * 0.9), inlierPts); 00464 00465 solvePnPRansac(points_3d, points_2d, camData.K, camData.blankCoeffs, Rvec, t, guided, 100, 4.0, ((unsigned int) ((double) points_2d.size()) * 0.9), inlierPts); 00466 00467 Rodrigues(Rvec, R); 00468 00469 Mat P; 00470 00471 findP1Matrix(P, R, t); 00472 00473 projectionToTransformation(P, dst); 00474 00475 dst = dst.inv(); 00476 00477 return true; 00478 00479 } 00480 00481 00482 00483 void getCorrespondingPoints(vector<featureTrack>& tracks, const vector<Point2f>& pts1, vector<Point2f>& pts2, int idx0, int idx1) { 00484 00485 printf("%s << Entered X.\n", __FUNCTION__); 00486 00487 // For each track 00488 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 00489 00490 if (tracks.at(iii).locations.size() < 2) { 00491 continue; 00492 } 00493 //printf("%s << Debug (%d)\n", __FUNCTION__, iii); 00494 // For each projection in the track 00495 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size()-1; kkk++) { 00496 00497 //printf("%s << Debug (%d)(%d)\n", __FUNCTION__, iii, kkk); 00498 00499 // If the camera of the projection matches the aim (idx0) 00500 if (tracks.at(iii).locations.at(kkk).imageIndex == idx0) { 00501 // Found a feature that exists in the first image 00502 00503 //printf("%s << Debug (%d)(%d) 2\n", __FUNCTION__, iii, kkk); 00504 00505 // For each of the first set of points 00506 for (unsigned int jjj = 0; jjj < pts1.size(); jjj++) { 00507 00508 //printf("%s << Debug (%d)(%d)(%d)\n", __FUNCTION__, iii, kkk, jjj); 00509 00510 // If the projection location matches the first point at this point 00511 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)) { 00512 00513 //printf("%s << Debug (%d)(%d)(%d) 2\n", __FUNCTION__, iii, kkk, jjj); 00514 00515 // For each of the later projections on that track 00516 for (unsigned int ppp = kkk; ppp < tracks.at(iii).locations.size(); ppp++) { 00517 00518 //printf("%s << Debug (%d)(%d)(%d)(%d)\n", __FUNCTION__, iii, kkk, jjj, ppp); 00519 00520 // If this later projection matches the second aimed index 00521 if (tracks.at(iii).locations.at(ppp).imageIndex == idx1) { 00522 00523 //printf("%s << Debug (%d)(%d)(%d)(%d) 2\n", __FUNCTION__, iii, kkk, jjj, ppp); 00524 00525 // If the first projec....? 00526 if (jjj != pts2.size()) { 00527 printf("%s << ERROR! Vectors are not syncing (jjj = %d), pts2.size() = %d\n", __FUNCTION__, jjj, pts2.size()); 00528 } else { 00529 pts2.push_back(tracks.at(iii).locations.at(ppp).featureCoord); 00530 } 00531 00532 00533 } 00534 00535 00536 } 00537 00538 break; 00539 } 00540 00541 } 00542 00543 00544 break; 00545 } 00546 00547 } 00548 } 00549 00550 printf("%s << Exiting.\n", __FUNCTION__); 00551 00552 } 00553 00554 void getTriangulatedFullSpanPoints(vector<featureTrack>& tracks, vector<Point2f>& pts1, vector<Point2f>& pts2, int idx1, int idx2, vector<Point3f>& points3) { 00555 00556 pts1.clear(); 00557 pts2.clear(); 00558 points3.clear(); 00559 00560 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 00561 00562 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size()-1; kkk++) { 00563 00564 // If the track extends between the two images of interest 00565 if (tracks.at(iii).locations.at(kkk).imageIndex == idx1) { 00566 00567 for (unsigned int jjj = kkk+1; jjj < tracks.at(iii).locations.size(); jjj++) { 00568 00569 if (tracks.at(iii).locations.at(jjj).imageIndex == idx2) { 00570 00571 if (tracks.at(iii).isTriangulated) { 00572 00573 pts1.push_back(tracks.at(iii).locations.at(kkk).featureCoord); 00574 pts2.push_back(tracks.at(iii).locations.at(jjj).featureCoord); 00575 00576 points3.push_back(Point3f(((float) tracks.at(iii).get3dLoc().x), ((float) tracks.at(iii).get3dLoc().y), ((float) tracks.at(iii).get3dLoc().z))); 00577 00578 break; 00579 } 00580 00581 00582 00583 } 00584 } 00585 00586 } 00587 } 00588 } 00589 00590 } 00591 00592 void findTriangulatableTracks(vector<featureTrack>& tracks, vector<unsigned int>& indices, unsigned int latest_index, unsigned int min_length) { 00593 00594 //int earliest_index = ((int) latest_index) - ((int) min_length); 00595 00596 /* 00597 if (earliest_index < 0) { 00598 return; 00599 } 00600 */ 00601 00602 //printf("%s << Searching up to camera (%d)\n", __FUNCTION__, latest_index); 00603 00604 bool trackAdded; 00605 00606 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 00607 00608 trackAdded = false; 00609 00610 if (tracks.at(iii).locations.size() > 0) { 00611 //printf("%s << Track (%d) spans from (%d) to (%d) and is triangulated? (%d)\n", __FUNCTION__, iii, tracks.at(iii).locations.at(0).imageIndex, tracks.at(iii).locations.at(tracks.at(iii).locations.size()-1).imageIndex, tracks.at(iii).isTriangulated); 00612 } else { 00613 continue; 00614 } 00615 00616 00617 if ((!tracks.at(iii).isTriangulated) && (tracks.at(iii).locations.size() >= min_length)) { 00618 00619 unsigned int appearanceCount = 0; 00620 00621 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size(); jjj++) { 00622 if (tracks.at(iii).locations.at(jjj).imageIndex <= latest_index) { 00623 appearanceCount++; 00624 00625 00626 } 00627 00628 00629 if (appearanceCount >= min_length) { 00630 indices.push_back(iii); 00631 break; 00632 } 00633 } 00634 00635 /* 00636 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size()-min_length; jjj++) { 00637 if (tracks.at(iii).locations.at(jjj).imageIndex == earliest_index) { 00638 00639 for (unsigned int kkk = jjj+min_length-1; kkk < tracks.at(iii).locations.size(); kkk++) { 00640 00641 if (tracks.at(iii).locations.at(kkk).imageIndex == latest_index) { 00642 indices.push_back(iii); 00643 trackAdded = true; 00644 break; 00645 } 00646 00647 } 00648 00649 } 00650 00651 if (trackAdded) { 00652 break; 00653 } 00654 } 00655 * */ 00656 00657 //printf("%s << And (%d) was not added...\n", __FUNCTION__, iii); 00658 } 00659 } 00660 00661 } 00662 00663 void getTranslationBetweenCameras(Mat& C1, Mat& C2, double *translations) { 00664 00665 Mat CD = C2 - C1; 00666 00667 translations[0] = CD.at<double>(0,3); 00668 translations[1] = CD.at<double>(1,3); 00669 translations[2] = CD.at<double>(2,3); 00670 00671 } 00672 00673 void triangulateTracks(vector<featureTrack>& tracks, vector<unsigned int>& indices, cameraParameters& cameraData, Mat *cameras, unsigned int earliest_index, unsigned int latest_index) { 00674 00675 //return; 00676 00677 //printf("%s << Entered.\n", __FUNCTION__); 00678 00679 unsigned int minPairs = 10; 00680 00681 // Should first check through camera pairs to see which ones can achive valid triangulations: 00682 00683 //printf("%s << latest_index/earliest_index = (%d/%d)\n", __FUNCTION__, latest_index, earliest_index); 00684 unsigned int pair_width = latest_index - earliest_index + 1; 00685 Mat validFramePairs = Mat::zeros(pair_width, pair_width, CV_8UC1); 00686 00687 double translations[3]; 00688 00689 for (unsigned int iii = earliest_index; iii < latest_index; iii++) { 00690 for (unsigned int jjj = iii+1; jjj <= latest_index; jjj++) { 00691 00692 if (cameras[iii].rows != 4) { 00693 continue; 00694 } 00695 00696 if (cameras[jjj].rows != 4) { 00697 continue; 00698 } 00699 00700 getTranslationBetweenCameras(cameras[iii], cameras[jjj], translations); 00701 00702 //printf("%s << translations = (%f, %f, %f)\n", __FUNCTION__, translations[0], translations[1], translations[2]); 00703 00704 //if ((abs(translations[0]) + abs(translations[1])) < 2.0*abs(translations[2])) { 00705 00706 00707 00708 // Conditions for validity as a camera pair 00709 if ((abs(translations[0] > 0.2)) || (abs(translations[1] > 0.2))) { // || (abs(translations[2] > 1.0)) 00710 validFramePairs.at<unsigned char>(iii-earliest_index,jjj-earliest_index) = 1; 00711 } 00712 } 00713 } 00714 00715 unsigned int validCount = countNonZero(validFramePairs); 00716 00717 //printf("%s << validCount = %d\n", __FUNCTION__, validCount); 00718 00719 if (validCount < minPairs) { 00720 return; 00721 } 00722 00723 //printf("%s << Continuing.\n", __FUNCTION__); 00724 00725 vector<Point3d> estimatedLocations; 00726 00727 unsigned int contribCount = 0; 00728 Point3d pt3d(0.0, 0.0, 0.0); 00729 Point3d mean3d(0.0, 0.0, 0.0); 00730 Point3d stddev3d(0.0, 0.0, 0.0); 00731 00732 00733 00734 for (unsigned int iii = 0; iii < indices.size(); iii++) { 00735 00736 //printf("%s << Track (%d) ...\n", __FUNCTION__, indices.at(iii)); 00737 00738 if (tracks.size() <= indices.at(iii)) { 00739 return; 00740 } 00741 00742 if (tracks.at(indices.at(iii)).locations.size() < 2) { 00743 continue; 00744 } 00745 00746 if (tracks.at(indices.at(iii)).isTriangulated) { 00747 continue; 00748 } 00749 00750 //printf("%s << Track (%d) DEBUG [%d]\n", __FUNCTION__, indices.at(iii), 0); 00751 00752 estimatedLocations.clear(); 00753 00754 contribCount = 0; 00755 pt3d = Point3d(0.0, 0.0, 0.0); 00756 mean3d = Point3d(0.0, 0.0, 0.0); 00757 stddev3d = Point3d(0.0, 0.0, 0.0); 00758 00759 unsigned int rrr, sss; 00760 00761 for (unsigned int jjj = 0; jjj < tracks.at(indices.at(iii)).locations.size()-1; jjj++) { 00762 00763 //printf("%s << Track (%d) jjj [%d]\n", __FUNCTION__, indices.at(iii), jjj); 00764 00765 int rrr = tracks.at(indices.at(iii)).locations.at(jjj).imageIndex; 00766 00767 if ((rrr >= earliest_index) && (rrr <= latest_index)) { 00768 00769 //printf("%s << Track (%d) jjj [%d] debug [%d]\n", __FUNCTION__, indices.at(iii), jjj, 0); 00770 00771 if (cameras[rrr].rows != 4) { 00772 //printf("%s << Breaking rrr (%d)...\n", __FUNCTION__, rrr); 00773 continue; 00774 } 00775 00776 //printf("%s << Track (%d) jjj [%d] debug [%d]\n", __FUNCTION__, indices.at(iii), jjj, 1); 00777 00778 //printf("%s << rrr = %d\n", __FUNCTION__, rrr); 00779 00780 Mat temp_C0; 00781 cameras[rrr].copyTo(temp_C0); 00782 00783 for (unsigned int kkk = jjj+1; kkk < tracks.at(indices.at(iii)).locations.size(); kkk++) { 00784 00785 //printf("%s << Track (%d) kkk [%d]\n", __FUNCTION__, indices.at(iii), kkk); 00786 00787 sss = tracks.at(indices.at(iii)).locations.at(kkk).imageIndex; 00788 00789 if ((sss >= earliest_index) && (sss <= latest_index)) { 00790 00791 //printf("%s << Track (%d) kkk [%d] debug [%d]\n", __FUNCTION__, indices.at(iii), kkk, 0); 00792 00793 //printf("%s << testing 00794 00795 if (validFramePairs.at<unsigned char>(rrr-earliest_index,sss-earliest_index) == 0) { 00796 continue; 00797 } 00798 00799 if (cameras[sss].rows != 4) { 00800 //printf("%s << Breaking sss (%d)...\n", __FUNCTION__, sss); 00801 continue; 00802 } 00803 00804 //printf("%s << Track (%d) kkk [%d] debug [%d]\n", __FUNCTION__, indices.at(iii), kkk, 1); 00805 00806 00807 Mat temp_C1; 00808 cameras[sss].copyTo(temp_C1); 00809 00810 // This should be a valid pair of projections to triangulate from for this point.. 00811 00812 // Check that the projections have enough translation: 00813 00814 00815 00816 //} 00817 00818 Point2f pt1_, pt2_; 00819 Point3d pt3d_; 00820 00821 pt1_ = tracks.at(indices.at(iii)).getCoord(rrr); 00822 pt2_ = tracks.at(indices.at(iii)).getCoord(sss); 00823 00824 Triangulate(pt1_, pt2_, cameraData.K, cameraData.K_inv, temp_C1, temp_C0, pt3d_, false); 00825 00826 //if ((pointIsInFront(temp_C0, pt3d_)) && (pointIsInFront(temp_C1, pt3d_))) { 00827 00828 estimatedLocations.push_back(pt3d_); 00829 00830 /* 00831 pt3d.x += pt3d_.x; 00832 pt3d.y += pt3d_.y; 00833 pt3d.z += pt3d_.z; 00834 contribCount++; 00835 */ 00836 //} 00837 00838 if (jjj == 0) { 00839 //printf("%s << Adding triangulation: (%f, %f, %f)\n", __FUNCTION__, pt3d_.x, pt3d_.y, pt3d_.z); 00840 } 00841 } 00842 } 00843 } 00844 00845 } 00846 00847 //printf("%s << Track (%d) : estimatedLocations.size() = %d\n", __FUNCTION__, indices.at(iii), estimatedLocations.size()); 00848 00849 if (estimatedLocations.size() >= minPairs) { 00850 00851 //printf("%s << Assigning (%d)\n", __FUNCTION__, indices.at(iii)); 00852 00853 //printf("%s << Calculating means..\n", __FUNCTION__); 00854 00855 for (unsigned int qqq = 0; qqq < estimatedLocations.size(); qqq++) { 00856 00857 mean3d.x += (estimatedLocations.at(qqq).x / ((double) estimatedLocations.size())); 00858 mean3d.y += (estimatedLocations.at(qqq).y / ((double) estimatedLocations.size())); 00859 mean3d.z += (estimatedLocations.at(qqq).z / ((double) estimatedLocations.size())); 00860 00861 } 00862 00863 //printf("%s << Calculating deviations..\n", __FUNCTION__); 00864 00865 for (unsigned int qqq = 0; qqq < estimatedLocations.size(); qqq++) { 00866 00867 stddev3d.x += (pow((estimatedLocations.at(qqq).x - mean3d.x), 2.0) / ((double) estimatedLocations.size())); 00868 stddev3d.y += (pow((estimatedLocations.at(qqq).y - mean3d.y), 2.0) / ((double) estimatedLocations.size())); 00869 stddev3d.z += (pow((estimatedLocations.at(qqq).z - mean3d.z), 2.0) / ((double) estimatedLocations.size())); 00870 00871 } 00872 00873 stddev3d.x = pow(stddev3d.x, 0.5); 00874 stddev3d.y = pow(stddev3d.y, 0.5); 00875 stddev3d.z = pow(stddev3d.z, 0.5); 00876 00877 //printf("%s << Erasing outliers..\n", __FUNCTION__); 00878 00879 for (int qqq = estimatedLocations.size()-1; qqq >= 0; qqq--) { 00880 00881 //printf("%s << qqq = %d\n", __FUNCTION__, qqq); 00882 00883 double abs_diff_x = abs(estimatedLocations.at(qqq).x - mean3d.x); 00884 double abs_diff_y = abs(estimatedLocations.at(qqq).y - mean3d.y); 00885 double abs_diff_z = abs(estimatedLocations.at(qqq).z - mean3d.z); 00886 00887 if ((abs_diff_x > 2*stddev3d.x) || (abs_diff_y > 2*stddev3d.y) || (abs_diff_z > 2*stddev3d.z)) { 00888 estimatedLocations.erase(estimatedLocations.begin() + qqq); 00889 } 00890 00891 } 00892 00893 00894 //printf("%s << Mean: (%f, %f, %f)\n", __FUNCTION__, mean3d.x, mean3d.y, mean3d.z); 00895 //printf("%s << Std deviation: (%f, %f, %f)\n", __FUNCTION__, stddev3d.x, stddev3d.y, stddev3d.z); 00896 00897 00898 if (estimatedLocations.size() >= minPairs) { 00899 //printf("%s << Re-calculating mean..\n", __FUNCTION__); 00900 00901 for (int qqq = 0; qqq < estimatedLocations.size(); qqq++) { 00902 00903 //printf("%s << qqq = %d\n", __FUNCTION__, qqq); 00904 00905 pt3d.x += (estimatedLocations.at(qqq).x / ((double) estimatedLocations.size())); 00906 pt3d.y += (estimatedLocations.at(qqq).y / ((double) estimatedLocations.size())); 00907 pt3d.z += (estimatedLocations.at(qqq).z / ((double) estimatedLocations.size())); 00908 00909 } 00910 00911 tracks.at(indices.at(iii)).set3dLoc(pt3d); 00912 00913 //printf("%s << Adding contribution: (%f, %f, %f)\n", __FUNCTION__, pt3d.x, pt3d.y, pt3d.z); 00914 00915 } 00916 00917 00918 00919 00920 } 00921 00922 // printf("%s << Track (%d) : DONE!\n", __FUNCTION__, indices.at(iii)); 00923 } 00924 00925 //printf("%s << Exiting.\n", __FUNCTION__); 00926 } 00927 00928 unsigned int addNewPoints(vector<featureTrack>& tracks, vector<unsigned int>& indices, cameraParameters& cameraData, Mat *cameras, unsigned int earliest_index, unsigned int latest_index) { 00929 00930 unsigned int totalTriangulatedPoints = 0; 00931 00932 for (unsigned int iii = 0; iii < indices.size(); iii++) { 00933 if (tracks.size() < indices.at(iii)) { 00934 continue; 00935 } 00936 00937 if (tracks.at(indices.at(iii)).locations.size() < 2) { 00938 continue; 00939 } 00940 00941 for (unsigned int jjj = 0; jjj < tracks.at(indices.at(iii)).locations.size()-1; jjj++) { 00942 00943 //printf("%s << jjj = %d\n", __FUNCTION__, jjj); 00944 00945 if (tracks.at(indices.at(iii)).isTriangulated) { 00946 continue; 00947 } 00948 00949 //printf("%s << jjj (continuing)\n", __FUNCTION__, jjj); 00950 00951 unsigned int contribCount = 0; 00952 Point3d pt3d(0.0, 0.0, 0.0); 00953 00954 unsigned int rrr = tracks.at(indices.at(iii)).locations.at(jjj).imageIndex; 00955 00956 00957 00958 00959 if (rrr == earliest_index) { 00960 00961 if (cameras[rrr].rows != 4) { 00962 printf("%s << Breaking rrr (%d)...\n", __FUNCTION__, rrr); 00963 continue; 00964 } 00965 00966 //printf("%s << rrr = %d\n", __FUNCTION__, rrr); 00967 00968 Mat temp_C0; 00969 cameras[rrr].copyTo(temp_C0); 00970 00971 for (unsigned int kkk = jjj+1; kkk < tracks.at(indices.at(iii)).locations.size(); kkk++) { 00972 00973 unsigned int sss = tracks.at(indices.at(iii)).locations.at(kkk).imageIndex; 00974 00975 00976 00977 //printf("%s << sss = %d\n", __FUNCTION__, sss); 00978 00979 if (sss == latest_index) { 00980 00981 if (cameras[sss].rows != 4) { 00982 printf("%s << Breaking sss (%d)...\n", __FUNCTION__, sss); 00983 continue; 00984 } 00985 00986 //printf("%s << sss = %d\n", __FUNCTION__, sss); 00987 00988 Mat temp_C1; 00989 cameras[sss].copyTo(temp_C1); 00990 00991 // This should be a valid pair of projections to triangulate from for this point.. 00992 00993 Point2f pt1_, pt2_; 00994 Point3d pt3d_; 00995 00996 pt1_ = tracks.at(indices.at(iii)).getCoord(rrr); 00997 pt2_ = tracks.at(indices.at(iii)).getCoord(sss); 00998 00999 //printf("%s << Triangulating...\n", __FUNCTION__); 01000 //printf("%s << pts = (%f, %f) & (%f, %f)\n", __FUNCTION__, pt1_.x, pt1_.y, pt2_.x, pt2_.y); 01001 //cout << cameraData.K << endl; 01002 //cout << cameraData.K_inv << endl; 01003 //cout << temp_C1 << endl; 01004 //cout << temp_C0 << endl; 01005 01006 Triangulate(pt1_, pt2_, cameraData.K, cameraData.K_inv, temp_C1, temp_C0, pt3d_, false); 01007 01008 //if ((pointIsInFront(temp_C0, pt3d_)) && (pointIsInFront(temp_C1, pt3d_))) { 01009 pt3d.x += pt3d_.x; 01010 pt3d.y += pt3d_.y; 01011 pt3d.z += pt3d_.z; 01012 contribCount++; 01013 //} 01014 } 01015 } 01016 } 01017 01018 if (contribCount > 0) { 01019 01020 //printf("%s << Assigning (%d)\n", __FUNCTION__, indices.at(iii)); 01021 01022 pt3d.x /= ((double) contribCount); 01023 pt3d.y /= ((double) contribCount); 01024 pt3d.z /= ((double) contribCount); 01025 01026 tracks.at(indices.at(iii)).set3dLoc(pt3d); 01027 } 01028 01029 01030 01031 } 01032 01033 } 01034 01035 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 01036 if (tracks.at(iii).isTriangulated) { 01037 totalTriangulatedPoints++; 01038 } 01039 } 01040 01041 return totalTriangulatedPoints; 01042 01043 } 01044 01045 unsigned int putativelyTriangulateNewTracks(vector<featureTrack>& tracks, vector<unsigned int>& indices, cameraParameters& cameraData, Mat *cameras, unsigned int earliest_index, unsigned int latest_index) { 01046 01047 //printf("%s << Entered: (%d, %d, %d, %d)\n", __FUNCTION__, tracks.size(), indices.size(), earliest_index, latest_index); 01048 01049 unsigned int totalTriangulatedPoints = 0; 01050 01051 for (unsigned int iii = 0; iii < indices.size(); iii++) { 01052 01053 //printf("%s << iii = %d\n", __FUNCTION__, iii); 01054 01055 if (tracks.size() < indices.at(iii)) { 01056 continue; 01057 } 01058 01059 if (tracks.at(indices.at(iii)).locations.size() < 2) { 01060 continue; 01061 } 01062 01063 for (unsigned int jjj = 0; jjj < tracks.at(indices.at(iii)).locations.size()-1; jjj++) { 01064 01065 //printf("%s << jjj = %d\n", __FUNCTION__, jjj); 01066 01067 if (tracks.at(indices.at(iii)).isTriangulated) { 01068 continue; 01069 } 01070 01071 //printf("%s << jjj (continuing)\n", __FUNCTION__, jjj); 01072 01073 unsigned int contribCount = 0; 01074 Point3d pt3d(0.0, 0.0, 0.0); 01075 01076 unsigned int rrr = tracks.at(indices.at(iii)).locations.at(jjj).imageIndex; 01077 01078 if (cameras[rrr].rows != 4) { 01079 continue; 01080 } 01081 01082 if ((rrr >= earliest_index) && (rrr <= latest_index)) { 01083 01084 //printf("%s << rrr = %d\n", __FUNCTION__, rrr); 01085 01086 Mat temp_C0; 01087 cameras[rrr].copyTo(temp_C0); 01088 01089 for (unsigned int kkk = jjj+1; kkk < tracks.at(indices.at(iii)).locations.size(); kkk++) { 01090 01091 unsigned int sss = tracks.at(indices.at(iii)).locations.at(kkk).imageIndex; 01092 01093 if (cameras[sss].rows != 4) { 01094 continue; 01095 } 01096 01097 //printf("%s << sss = %d\n", __FUNCTION__, sss); 01098 01099 if ((sss >= earliest_index) && (sss <= latest_index)) { 01100 01101 //printf("%s << sss = %d\n", __FUNCTION__, sss); 01102 01103 Mat temp_C1; 01104 cameras[sss].copyTo(temp_C1); 01105 01106 // This should be a valid pair of projections to triangulate from for this point.. 01107 01108 Point2f pt1_, pt2_; 01109 Point3d pt3d_; 01110 01111 pt1_ = tracks.at(indices.at(iii)).getCoord(rrr); 01112 pt2_ = tracks.at(indices.at(iii)).getCoord(sss); 01113 01114 //printf("%s << Triangulating...\n", __FUNCTION__); 01115 //printf("%s << pts = (%f, %f) & (%f, %f)\n", __FUNCTION__, pt1_.x, pt1_.y, pt2_.x, pt2_.y); 01116 //cout << cameraData.K << endl; 01117 //cout << cameraData.K_inv << endl; 01118 //cout << temp_C1 << endl; 01119 //cout << temp_C0 << endl; 01120 01121 Triangulate(pt1_, pt2_, cameraData.K, cameraData.K_inv, temp_C1, temp_C0, pt3d_, false); 01122 01123 //if ((pointIsInFront(temp_C0, pt3d_)) && (pointIsInFront(temp_C1, pt3d_))) { 01124 pt3d.x += pt3d_.x; 01125 pt3d.y += pt3d_.y; 01126 pt3d.z += pt3d_.z; 01127 contribCount++; 01128 //} 01129 } 01130 } 01131 } 01132 01133 if (contribCount > 0) { 01134 01135 //printf("%s << Assigning (%d)\n", __FUNCTION__, indices.at(iii)); 01136 01137 pt3d.x /= ((double) contribCount); 01138 pt3d.y /= ((double) contribCount); 01139 pt3d.z /= ((double) contribCount); 01140 01141 tracks.at(indices.at(iii)).set3dLoc(pt3d); 01142 } 01143 01144 01145 01146 } 01147 01148 } 01149 01150 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 01151 if (tracks.at(iii).isTriangulated) { 01152 totalTriangulatedPoints++; 01153 } 01154 } 01155 01156 return totalTriangulatedPoints; 01157 01158 } 01159 01160 void getPointsFromTracks(vector<featureTrack>& tracks, vector<Point2f>& pts1, vector<Point2f>& pts2, int idx1, int idx2) { 01161 01162 // Could make more efficient by only testing tracks that are long enough, but 01163 // If there are missing frames (acceptable?) then the simple way of achieving this won't work) 01164 01165 //printf("%s << searching for indices (%d) & (%d) [tracks.size() = (%d)]\n", __FUNCTION__, idx1, idx2, tracks.size()); 01166 01167 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 01168 01169 //printf("%s << Searching track (%d)...\n", __FUNCTION__, iii); 01170 01171 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size(); kkk++) { 01172 01173 //printf("%s << Searching element (%d) ; (%d)\n", __FUNCTION__, kkk, tracks.at(iii).locations.at(kkk).imageIndex); 01174 01175 //if (tracks.at(iii).locations.at(kkk).imageIndex == 0) { 01176 //printf("%s << FOUND A ZERO TRACK!!!\n", __FUNCTION__); 01177 //} 01178 01179 // If the track extends between the two images of interest 01180 if (tracks.at(iii).locations.at(kkk).imageIndex == idx1) { 01181 01182 //printf("%s << Found index A (%d)...\n", __FUNCTION__, idx1); 01183 01184 for (unsigned int jjj = 0; jjj < tracks.at(iii).locations.size(); jjj++) { 01185 01186 //printf("%s << Searching element (%d)...\n", __FUNCTION__, jjj); 01187 01188 if (tracks.at(iii).locations.at(jjj).imageIndex == idx2) { 01189 01190 //printf("%s << Found match!\n", __FUNCTION__); 01191 01192 pts1.push_back(tracks.at(iii).locations.at(kkk).featureCoord); 01193 pts2.push_back(tracks.at(iii).locations.at(jjj).featureCoord); 01194 break; 01195 } 01196 } 01197 01198 } 01199 } 01200 } 01201 } 01202 01203 void obtainAppropriateBaseTransformation(Mat& C0, vector<featureTrack>& tracks) { 01204 01205 Point3d centroid, deviations; 01206 01207 int numTriangulatedPts = 0; 01208 01209 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 01210 if (tracks.at(iii).isTriangulated) { 01211 01212 numTriangulatedPts += 1; 01213 01214 } 01215 } 01216 01217 if (numTriangulatedPts == 0) { 01218 C0 = Mat::eye(4, 4, CV_64FC1); 01219 } else { 01220 // Find centroid and standard deviations of points 01221 findCentroidAndSpread(tracks, centroid, deviations); 01222 01223 // Create transformation matrix with a centroid that is distance 01224 Mat t(4, 1, CV_64FC1), R; 01225 01226 R = Mat::eye(3, 3, CV_64FC1); 01227 01228 t.at<double>(0,0) = centroid.x + 3.0 * deviations.x; 01229 t.at<double>(0,0) = centroid.y + 3.0 * deviations.y; 01230 t.at<double>(0,0) = centroid.z + 3.0 * deviations.z; 01231 t.at<double>(3,0) = 1.0; 01232 01233 compileTransform(C0, R, t); 01234 } 01235 } 01236 01237 void findCentroidAndSpread(vector<featureTrack>& tracks, Point3d& centroid, Point3d& deviations) { 01238 01239 centroid = Point3d(0.0, 0.0, 0.0); 01240 deviations = Point3d(0.0, 0.0, 0.0); 01241 01242 double numPoints = 0.00; 01243 01244 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 01245 if (tracks.at(iii).isTriangulated) { 01246 01247 numPoints += 1.00; 01248 01249 } 01250 } 01251 01252 if (numPoints == 0.00) { 01253 return; 01254 } 01255 01256 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 01257 01258 if (tracks.at(iii).isTriangulated) { 01259 01260 Point3d tmpPt; 01261 tmpPt = tracks.at(iii).get3dLoc(); 01262 centroid.x += (tmpPt.x / numPoints); 01263 centroid.y += (tmpPt.y / numPoints); 01264 centroid.z += (tmpPt.z / numPoints); 01265 01266 } 01267 01268 } 01269 01270 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 01271 01272 if (tracks.at(iii).isTriangulated) { 01273 Point3d tmpPt; 01274 tmpPt = tracks.at(iii).get3dLoc(); 01275 deviations.x += (pow((tmpPt.x - centroid.x), 2.0) / numPoints); 01276 deviations.y += (pow((tmpPt.y - centroid.y), 2.0) / numPoints); 01277 deviations.z += (pow((tmpPt.z - centroid.z), 2.0) / numPoints); 01278 } 01279 01280 } 01281 01282 deviations.x = pow(deviations.x, 0.5); 01283 deviations.y = pow(deviations.y, 0.5); 01284 deviations.z = pow(deviations.z, 0.5); 01285 } 01286 01287 void getPoints3dFromTracks(vector<featureTrack>& tracks, vector<Point3d>& cloud, int idx1, int idx2) { 01288 01289 cloud.clear(); 01290 01291 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 01292 01293 for (unsigned int kkk = 0; kkk < tracks.at(iii).locations.size()-1; kkk++) { 01294 // If the track extends between the two images of interest 01295 if (tracks.at(iii).locations.at(kkk).imageIndex == idx1) { 01296 01297 for (unsigned int jjj = kkk+1; jjj < tracks.at(iii).locations.size(); jjj++) { 01298 01299 if (tracks.at(iii).locations.at(jjj).imageIndex == idx2) { 01300 cloud.push_back(tracks.at(iii).get3dLoc()); 01301 break; 01302 } 01303 } 01304 01305 } 01306 } 01307 01308 01309 01310 } 01311 01312 } 01313 01314 01315 void findFourTransformations(Mat *C, const Mat& E, const Mat& K, const vector<Point2f>& pts1, const vector<Point2f>& pts2) { 01316 01317 01318 Mat I, negI, t33, W, Winv, Z, Kinv, zeroTrans, R, t, Rvec; 01319 01320 Kinv = K.inv(); 01321 zeroTrans = Mat::zeros(3, 1, CV_64FC1); 01322 I = Mat::eye(3, 3, CV_64FC1); 01323 negI = -I; 01324 01325 getWandZ(W, Winv, Z); 01326 01327 //cout << __FUNCTION__ << " << W = " << W << endl; 01328 //cout << __FUNCTION__ << " << Winv = " << Winv << endl; 01329 01330 //R = svd.u * W * svd.vt; 01331 //t = svd.u.col(2); 01332 01333 //cout << __FUNCTION__ << " << R = " << R << endl; 01334 01335 //Rodrigues(R, Rvec); 01336 01337 //cout << __FUNCTION__ << " << Rvec = " << Rvec << endl; 01338 01339 //cout << __FUNCTION__ << " << t = " << t << endl; 01340 01341 Mat c; 01342 //compileTransform(c, R, t); 01343 01344 //cout << __FUNCTION__ << " << c = " << c << endl; 01345 01346 Mat u_transposePos, u_transposeNeg; 01347 SVD svdPos, svdNeg; 01348 01349 svdPos = SVD(E); 01350 svdNeg = SVD(-E); 01351 01352 transpose(svdPos.u, u_transposePos); 01353 transpose(svdNeg.u, u_transposeNeg); 01354 01355 double detVal; 01356 01357 for (unsigned int zzz = 0; zzz < 4; zzz++) { 01358 01359 //printf("%s << Loop [%d]\n", __FUNCTION__, zzz); 01360 01361 switch (zzz) { 01362 case 0: 01363 //t33 = v * W * SIGMA * vt; 01364 t33 = svdPos.u * Z * u_transposePos; 01365 R = svdPos.u * Winv * svdPos.vt; 01366 detVal = determinant(R); 01367 if (detVal < 0) { 01368 t33 = svdNeg.u * Z * u_transposeNeg; 01369 R = svdNeg.u * Winv * svdNeg.vt; 01370 } 01371 break; 01372 case 1: 01373 //t33 = v * W_inv * SIGMA * vt; 01374 t33 = negI * svdPos.u * Z * u_transposePos; 01375 R = svdPos.u * Winv * svdPos.vt; 01376 detVal = determinant(R); 01377 if (detVal < 0) { 01378 t33 = negI * svdNeg.u * Z * u_transposeNeg; 01379 R = svdNeg.u * Winv * svdNeg.vt; 01380 } 01381 break; 01382 case 2: 01383 //t33 = v * W * SIGMA * vt; 01384 t33 = svdPos.u * Z * u_transposePos; 01385 R = svdPos.u * W * svdPos.vt; 01386 detVal = determinant(R); 01387 if (detVal < 0) { 01388 t33 = svdNeg.u * Z * u_transposeNeg; 01389 R = svdNeg.u * W * svdNeg.vt; 01390 } 01391 break; 01392 case 3: 01393 //t33 = v * W_inv * SIGMA * vt; 01394 t33 = negI * svdPos.u * Z * u_transposePos; 01395 R = svdPos.u * W * svdPos.vt; 01396 detVal = determinant(R); 01397 if (detVal < 0) { 01398 t33 = negI * svdNeg.u * Z * u_transposeNeg; 01399 R = svdNeg.u * W * svdNeg.vt; 01400 } 01401 break; 01402 default: 01403 break; 01404 } 01405 01406 // Converting 3x3 t mat to vector 01407 t = Mat::zeros(3, 1, CV_64F); 01408 t.at<double>(0,0) = -t33.at<double>(1,2); // originally had -ve 01409 t.at<double>(1,0) = t33.at<double>(0,2); // originall had a +ve 01410 t.at<double>(2,0) = -t33.at<double>(0,1); // originally had -ve 01411 01412 //cout << __FUNCTION__ << " << t[" << zzz << "] = " << t << endl; 01413 01414 if (abs(1.0 - detVal) > 0.01) { 01415 //printf("%s << Solution [%d] is invalid - det(R) = %f\n", __FUNCTION__, zzz, detVal); 01416 } else { 01417 //printf("%s << Solution [%d] det(R) = %f\n", __FUNCTION__, zzz, detVal); 01418 } 01419 01420 //compileTransform(c, R, -R*t); 01421 compileTransform(c, R, t); 01422 01423 //char printSummary[256]; 01424 //summarizeTransformation(c, printSummary); 01425 //printf("%s << Original c[%d] = %s\n", __FUNCTION__, zzz, printSummary); 01426 01427 //c = c.inv(); 01428 01429 c.copyTo(C[zzz]); 01430 01431 //cout << __FUNCTION__ << " << Czzz = " << C[zzz] << endl; 01432 01433 } 01434 01435 } 01436 01437 void projectionToTransformation(const Mat& proj, Mat& trans) { 01438 trans = Mat::eye(4, 4, CV_64FC1); 01439 01440 trans.at<double>(0,0) = proj.at<double>(0,0); 01441 trans.at<double>(0,1) = proj.at<double>(0,1); 01442 trans.at<double>(0,2) = proj.at<double>(0,2); 01443 trans.at<double>(0,3) = proj.at<double>(0,3); 01444 01445 trans.at<double>(1,0) = proj.at<double>(1,0); 01446 trans.at<double>(1,1) = proj.at<double>(1,1); 01447 trans.at<double>(1,2) = proj.at<double>(1,2); 01448 trans.at<double>(1,3) = proj.at<double>(1,3); 01449 01450 trans.at<double>(2,0) = proj.at<double>(2,0); 01451 trans.at<double>(2,1) = proj.at<double>(2,1); 01452 trans.at<double>(2,2) = proj.at<double>(2,2); 01453 trans.at<double>(2,3) = proj.at<double>(2,3); 01454 } 01455 01456 void transformationToProjection(const Mat& trans, Mat& proj) { 01457 proj = Mat::zeros(3, 4, CV_64FC1); 01458 01459 proj.at<double>(0,0) = trans.at<double>(0,0); 01460 proj.at<double>(0,1) = trans.at<double>(0,1); 01461 proj.at<double>(0,2) = trans.at<double>(0,2); 01462 proj.at<double>(0,3) = trans.at<double>(0,3); 01463 01464 proj.at<double>(1,0) = trans.at<double>(1,0); 01465 proj.at<double>(1,1) = trans.at<double>(1,1); 01466 proj.at<double>(1,2) = trans.at<double>(1,2); 01467 proj.at<double>(1,3) = trans.at<double>(1,3); 01468 01469 proj.at<double>(2,0) = trans.at<double>(2,0); 01470 proj.at<double>(2,1) = trans.at<double>(2,1); 01471 proj.at<double>(2,2) = trans.at<double>(2,2); 01472 proj.at<double>(2,3) = trans.at<double>(2,3); 01473 01474 } 01475 01476 bool pointIsInFront(const Mat& C, const Point3d& pt) { 01477 01478 Point3d p1; 01479 01480 transfer3dPoint(pt, p1, C); 01481 01482 if (p1.z > 0) { 01483 return true; 01484 } else { 01485 01486 return false; 01487 01488 } 01489 01490 01491 } 01492 01493 // This function is when you have the 3D points and both transformation matrices 01494 int pointsInFront(const Mat& C1, const Mat& C2, const vector<Point3d>& pts) { 01495 int retVal = 0; 01496 01497 vector<Point3d> pts1, pts2; 01498 01499 Mat R1, t1, R2, t2; 01500 decomposeTransform(C1, R1, t1); 01501 decomposeTransform(C2, R2, t2); 01502 01503 double rot1, rot2; 01504 rot1 = getRotationInDegrees(R1); 01505 rot2 = getRotationInDegrees(R2); 01506 01507 printf("%s << Two rotations = (%f, %f)\n", __FUNCTION__, rot1, rot2); 01508 01509 // maybe something to do with intrinsics matrix.... 01510 01511 // want to transfer the 3D point locations into the co-ordinate system of each camera 01512 transfer3DPoints(pts, pts1, C1); 01513 transfer3DPoints(pts, pts2, C2); 01514 01515 for (unsigned int iii = 0; iii < pts.size(); iii++) { 01516 01517 //printf("%s << [%d](%f, %f, %f)-(%f, %f, %f)\n", __FUNCTION__, iii, pts1.at(iii).x, pts1.at(iii).y, pts1.at(iii).z, pts2.at(iii).x, pts2.at(iii).y, pts2.at(iii).z); 01518 01519 if ((pts1.at(iii).z > 0) && (pts2.at(iii).z > 0)) { 01520 01521 if (retVal < 5) { 01522 printf("%s << Point location is (%f, %f, %f)\n", __FUNCTION__, pts.at(iii).x, pts.at(iii).y, pts.at(iii).z); 01523 printf("%s << Rel #1 is (%f, %f, %f)\n", __FUNCTION__, pts1.at(iii).x, pts1.at(iii).y, pts1.at(iii).z); 01524 printf("%s << Rel #2 is (%f, %f, %f)\n", __FUNCTION__, pts2.at(iii).x, pts2.at(iii).y, pts2.at(iii).z); 01525 } 01526 01527 retVal++; 01528 } 01529 } 01530 01531 return retVal; 01532 } 01533 01534 // This function is when you have the relative transformation matrix, cam matrix, and 2D locations of points.. 01535 int pointsInFront(const Mat& C1, const Mat& K, const vector<Point2f>& pts1, const vector<Point2f>& pts2) { 01536 01537 int retVal = 0; 01538 01539 Mat Kinv; 01540 Kinv = K.inv(); 01541 01542 // Representing initial camera relative to itself 01543 Mat P0, C0; 01544 initializeP0(P0); 01545 projectionToTransformation(P0, C0); 01546 01547 // Representing second camera relative to first camera 01548 Mat P1; 01549 transformationToProjection(C1, P1); 01550 01551 01552 vector<Point3d> pc1, pc2; 01553 vector<Point2f> correspImg1Pt, correspImg2Pt; 01554 01555 // Get 3D locations of points relative to first camera 01556 TriangulatePoints(pts1, pts2, K, Kinv, P0, P1, pc1, correspImg1Pt); 01557 01558 // Transfer 3D locations so that they are relative to second camera 01559 Mat C1inv; 01560 C1inv = C1.inv(); 01561 01562 // src, dst, transform : if C1 represents transform from world to cam 1... 01563 transfer3DPoints(pc1, pc2, C1); // trying C1inv... 01564 01565 //Mat R1, t1; 01566 //decomposeTransform(C, R1, t1); 01567 //double deg1 = getRotationInDegrees(R1); 01568 //printf("%s << Forwards rotation = %f\n", __FUNCTION__, deg1); 01569 01570 01571 //printf("%s << DEBUG %d\n", __FUNCTION__, 2); 01572 //Cinv = C.inv(); 01573 //transformationToProjection(Cinv, P1b); 01574 01575 //Mat R2, t2; 01576 //decomposeTransform(Cinv, R2, t2); 01577 //double deg2 = getRotationInDegrees(R2); 01578 //printf("%s << Backwards rotation = %f\n", __FUNCTION__, deg2); 01579 01580 //printf("%s << DEBUG %d\n", __FUNCTION__, 3); 01581 //TriangulatePoints(pts2, pts1, K, Kinv, P0, P1b, pc2, correspImg2Pt); 01582 01583 //printf("%s << DEBUG %d\n", __FUNCTION__, 4); 01584 01585 int inFront1 = 0, inFront2 = 0; 01586 01587 for (unsigned int iii = 0; iii < pc1.size(); iii++) { 01588 01589 // Check z-coordinate in both clouds to make sure it's > 0 01590 01591 //printf("%s << pc1 = (%f, %f, %f); pc2 = (%f, %f, %f)\n", __FUNCTION__, pc1.at(iii).x, pc1.at(iii).y, pc1.at(iii).z, pc2.at(iii).x, pc2.at(iii).y, pc2.at(iii).z); 01592 01593 if (pc1.at(iii).z > 0) { 01594 inFront1++; 01595 } 01596 01597 if (pc2.at(iii).z > 0) { 01598 inFront2++; 01599 } 01600 01601 if ((pc1.at(iii).z > 0) && (pc2.at(iii).z > 0)) { 01602 retVal++; 01603 } 01604 01605 } 01606 01607 //printf("%s << Pts in front of cams: %d, %d\n", __FUNCTION__, inFront1, inFront2); 01608 01609 return retVal; 01610 01611 } 01612 01613 void convertPoint3dToMat(const Point3d& src, Mat& dst) { 01614 dst = Mat::zeros(4, 1, CV_64FC1); 01615 01616 dst.at<double>(3, 0) = 1.0; 01617 01618 dst.at<double>(0,0) = src.x; 01619 dst.at<double>(1,0) = src.y; 01620 dst.at<double>(2,0) = src.z; 01621 } 01622 01623 void transfer3dPoint(const Point3d& src, Point3d& dst, const Mat& C) { 01624 01625 Mat pt1, pt2; 01626 01627 pt1 = Mat::zeros(4, 1, CV_64FC1); 01628 pt2 = Mat::zeros(4, 1, CV_64FC1); 01629 01630 pt1.at<double>(3, 0) = 1.0; 01631 pt2.at<double>(3, 0) = 1.0; 01632 01633 01634 pt1.at<double>(0,0) = src.x; 01635 pt1.at<double>(1,0) = src.y; 01636 pt1.at<double>(2,0) = src.z; 01637 01638 pt2 = C * pt1; 01639 01640 dst = Point3d(pt2.at<double>(0,0), pt2.at<double>(1,0), pt2.at<double>(2,0)); 01641 01642 } 01643 01644 void transfer3DPoints(const vector<Point3d>& src, vector<Point3d>& dst, const Mat& C) { 01645 01646 Mat pt1, pt2; 01647 01648 pt1 = Mat::zeros(4, 1, CV_64FC1); 01649 pt2 = Mat::zeros(4, 1, CV_64FC1); 01650 01651 pt1.at<double>(3, 0) = 1.0; 01652 pt2.at<double>(3, 0) = 1.0; 01653 01654 Point3d shiftedPoint; 01655 01656 for (unsigned int iii = 0; iii < src.size(); iii++) { 01657 pt1.at<double>(0,0) = src.at(iii).x; 01658 pt1.at<double>(1,0) = src.at(iii).y; 01659 pt1.at<double>(2,0) = src.at(iii).z; 01660 01661 pt2 = C * pt1; // pt2 = C.inv() * pt1; 01662 01663 //printf("%s << pt2.at<double>(3,0) = %f\n", __FUNCTION__, pt2.at<double>(3,0)); 01664 01665 shiftedPoint.x = pt2.at<double>(0,0); 01666 shiftedPoint.y = pt2.at<double>(1,0); 01667 shiftedPoint.z = pt2.at<double>(2,0); 01668 01669 dst.push_back(shiftedPoint); 01670 } 01671 01672 01673 01674 } 01675 01676 void quaternionToMatrix(const Quaterniond& quat, Mat& mat) { 01677 01678 Matrix3d m = quat.toRotationMatrix(); 01679 01680 mat = Mat::zeros(3, 3, CV_64FC1); 01681 01682 mat.at<double>(0,0) = m(0,0); 01683 mat.at<double>(0,1) = m(0,1); 01684 mat.at<double>(0,2) = m(0,2); 01685 01686 mat.at<double>(1,0) = m(1,0); 01687 mat.at<double>(1,1) = m(1,1); 01688 mat.at<double>(1,2) = m(1,2); 01689 01690 mat.at<double>(2,0) = m(2,0); 01691 mat.at<double>(2,1) = m(2,1); 01692 mat.at<double>(2,2) = m(2,2); 01693 01694 return; 01695 01696 Quaterniond quat_N(quat); 01697 01698 quat_N.normalize(); 01699 01700 double x = quat_N.x(); 01701 double y = quat_N.y(); 01702 double z = quat_N.z(); 01703 double w = quat_N.w(); 01704 01705 mat.at<double>(0,0) = 1.0 - 2.0*y*y - 2.0*z*z; 01706 mat.at<double>(0,1) = 2.0*x*y - 2.0*z*w; 01707 mat.at<double>(0,2) = 2.0*x*z + 2.0*y*w; 01708 01709 mat.at<double>(1,0) = 2.0*x*y + 2.0*z*w; 01710 mat.at<double>(1,1) = 1.0 - 2.0*x*x - 2.0*z*z; 01711 mat.at<double>(1,2) = 2.0*y*z - 2.0*x*w; 01712 01713 mat.at<double>(2,0) = 2.0*x*z - 2.0*y*w; 01714 mat.at<double>(2,1) = 2.0*y*z + 2.0*x*w; 01715 mat.at<double>(2,2) = 1.0 - 2.0*x*x - 2.0*y*y; 01716 01717 } 01718 01719 void decomposeTransform(const Mat& c, Mat& R, Mat& t) { 01720 R = Mat::zeros(3, 3, CV_64FC1); 01721 t = Mat::zeros(3, 1, CV_64FC1); 01722 01723 R.at<double>(0,0) = c.at<double>(0,0); 01724 R.at<double>(0,1) = c.at<double>(0,1); 01725 R.at<double>(0,2) = c.at<double>(0,2); 01726 01727 R.at<double>(1,0) = c.at<double>(1,0); 01728 R.at<double>(1,1) = c.at<double>(1,1); 01729 R.at<double>(1,2) = c.at<double>(1,2); 01730 01731 R.at<double>(2,0) = c.at<double>(2,0); 01732 R.at<double>(2,1) = c.at<double>(2,1); 01733 R.at<double>(2,2) = c.at<double>(2,2); 01734 01735 t.at<double>(0,0) = c.at<double>(0,3); 01736 t.at<double>(1,0) = c.at<double>(1,3); 01737 t.at<double>(2,0) = c.at<double>(2,3); 01738 01739 } 01740 void compileTransform(Mat& c, const Mat& R, const Mat& t) { 01741 c = Mat::zeros(4, 4, CV_64FC1); 01742 01743 c.at<double>(0,0) = R.at<double>(0,0); 01744 c.at<double>(0,1) = R.at<double>(0,1); 01745 c.at<double>(0,2) = R.at<double>(0,2); 01746 01747 c.at<double>(1,0) = R.at<double>(1,0); 01748 c.at<double>(1,1) = R.at<double>(1,1); 01749 c.at<double>(1,2) = R.at<double>(1,2); 01750 01751 c.at<double>(2,0) = R.at<double>(2,0); 01752 c.at<double>(2,1) = R.at<double>(2,1); 01753 c.at<double>(2,2) = R.at<double>(2,2); 01754 01755 c.at<double>(0,3) = t.at<double>(0,0); 01756 c.at<double>(1,3) = t.at<double>(1,0); 01757 c.at<double>(2,3) = t.at<double>(2,0); 01758 01759 c.at<double>(3,3) = 1.0; 01760 } 01761 01762 double calcInlierGeometryDistance(vector<Point2f>& points1, vector<Point2f>& points2, Mat& mat, Mat& mask, int distMethod) { 01763 01764 double error = 0.0; 01765 01766 int inlierCounter = 0; 01767 01768 for (unsigned int iii = 0; iii < points1.size(); iii++) { 01769 if (mask.at<char>(iii, 0) > 0) { 01770 01771 error += calcGeometryDistance(points1.at(iii), points2.at(iii), mat, distMethod); 01772 01773 inlierCounter++; 01774 } 01775 } 01776 01777 error /= (double) inlierCounter; 01778 01779 return error; 01780 } 01781 01782 double calcGeometryScore(vector<Point2f>& points1, vector<Point2f>& points2, Mat& F, Mat& Fmask, Mat& H, Mat& Hmask) { 01783 double gScore = 0.0; 01784 01785 int inliers_H = 0, inliers_F = 0; 01786 01787 /* 01788 for (int iii = 0; iii < points1.size(); iii++) { 01789 if (Hmask.at<char>(iii, 0) > 0) { 01790 inliers_H++; 01791 } 01792 01793 if (Fmask.at<char>(iii, 0) > 0) { 01794 inliers_F++; 01795 } 01796 } 01797 * */ 01798 01799 inliers_H = countNonZero(Hmask); 01800 inliers_F = countNonZero(Fmask); 01801 01802 printf("%s << Inliers: %d (H), %d (F)\n", __FUNCTION__, inliers_H, inliers_F); 01803 01804 double sampson_H, sampson_F; 01805 01806 sampson_H = calcSampsonError(points1, points2, H, Hmask); 01807 sampson_F = calcSampsonError(points1, points2, F, Fmask); 01808 01809 double sampson_H2 = 0.0, sampson_F2 = 0.0; 01810 01811 printf("%s << Sampson errors: %f (H), %f (F)\n", __FUNCTION__, sampson_H, sampson_F); 01812 01813 for (unsigned int iii = 0; iii < points1.size(); iii++) { 01814 sampson_H2 += calcSampsonDistance(points1.at(iii), points2.at(iii), H) / (double)points1.size(); 01815 sampson_F2 += calcSampsonDistance(points1.at(iii), points2.at(iii), F) / (double)points1.size(); 01816 } 01817 01818 printf("%s << Sampson errors2: %f (H), %f (F)\n", __FUNCTION__, sampson_H2, sampson_F2); 01819 01820 01821 gScore = (((double) inliers_F) / ((double) inliers_H)) * ( sampson_H / pow(sampson_F, 0.5)); 01822 01823 printf("%s << gScore = %f\n", __FUNCTION__, gScore); 01824 01825 return gScore; 01826 } 01827 01828 double calcFrameScore(double geomScore, int numFeatures, int numTracks) { 01829 01830 double frameScore; 01831 01832 frameScore = geomScore * ((double) numTracks) / ((double) numFeatures); 01833 01834 return frameScore; 01835 } 01836 01837 double calcSampsonError(vector<Point2f>& points1, vector<Point2f>& points2, Mat& H, Mat& Hmask) { 01838 double sampsonError = 0.0; 01839 01840 int inlierCounter = 0; 01841 01842 01843 for (unsigned int iii = 0; iii < points1.size(); iii++) { 01844 if (Hmask.at<char>(iii, 0) > 0) { 01845 01846 sampsonError += lourakisSampsonError(points1.at(iii), points2.at(iii), H); 01847 01848 inlierCounter++; 01849 } 01850 } 01851 01852 sampsonError /= (double) inlierCounter; 01853 01854 return sampsonError; 01855 01856 } 01857 01858 // http://www.mathworks.com.au/help/toolbox/vision/ref/estimatefundamentalmatrix.html 01859 double calcSampsonDistance(Point2f& pt1, Point2f& pt2, Mat& F) { 01860 01861 double dist; 01862 01863 Mat point1(1, 3, CV_64FC1), point2(1, 3, CV_64FC1); 01864 01865 point1.at<double>(0, 0) = (double) pt1.x; 01866 point1.at<double>(0, 1) = (double) pt1.y; 01867 point1.at<double>(0, 2) = 1.0; 01868 01869 Mat t1; 01870 transpose(point1, t1); 01871 01872 point2.at<double>(0, 0) = (double) pt2.x; 01873 point2.at<double>(0, 1) = (double) pt2.y; 01874 point2.at<double>(0, 2) = 1.0; 01875 01876 Mat a, b, c; 01877 01878 a = point2 * F * t1; 01879 b = F * t1; 01880 c = point2 * F; 01881 01882 double val1 = pow(a.at<double>(0, 0), 2.0); 01883 double val2 = 1.0 / ((pow(b.at<double>(0, 0), 2.0)) + (pow(b.at<double>(1, 0), 2.0))); 01884 double val3 = 1.0 / ((pow(c.at<double>(0, 0), 2.0)) + (pow(c.at<double>(1, 0), 2.0))); 01885 01886 dist = val1 * (val2 + val3); 01887 01888 return dist; 01889 01890 } 01891 01892 double calcGeometryScore(int numInliers_H, int numInliers_F, double sampsonError_H, double sampsonError_F) { 01893 double geometryScore = 0.0; 01894 01895 geometryScore = ((double) numInliers_F / (double) numInliers_H) * sampsonError_H / pow(sampsonError_F, 0.5); 01896 01897 return geometryScore; 01898 } 01899 01900 void assignIntrinsicsToP0(Mat& P0, const Mat& K) { 01901 P0 = Mat::zeros(3, 4, CV_64FC1); 01902 01903 for (int iii = 0; iii < 3; iii++) { 01904 for (int jjj = 0; jjj < 3; jjj++) { 01905 P0.at<double>(iii,jjj) = K.at<double>(iii,jjj); 01906 } 01907 } 01908 01909 } 01910 01911 double getQuaternionAngle(const Quaterniond& q1, const Quaterniond& q2) { 01912 double angle, dot_prod; 01913 01914 dot_prod = dotProduct(q1, q2); 01915 01916 angle = 2.0 * acos(abs(dot_prod)); 01917 01918 return angle; 01919 } 01920 01921 double dotProduct(const Quaterniond& q1, const Quaterniond& q2) { 01922 double prod; 01923 01924 prod = q1.x()*q2.x() + q1.y()*q2.y() + q1.z()*q2.z() + q1.w()*q2.w(); 01925 01926 return prod; 01927 } 01928 01929 void combineTransforms(Mat& CN, const Mat& C0, const Mat& C1) { 01930 CN = Mat::eye(4, 4, CV_64FC1); 01931 01932 CN = C0 * C1; 01933 } 01934 01935 double dotProduct(const Mat& vec1, const Mat& vec2) { 01936 double prod; 01937 01938 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); 01939 01940 return prod; 01941 01942 } 01943 01944 double getRotationInDegrees(const Mat& R) { 01945 Quaterniond rotation; 01946 matrixToQuaternion(R, rotation); 01947 Quaterniond dq = defaultQuaternion(); 01948 double qa = getQuaternionAngle(rotation, dq) * 180.0 / M_PI; 01949 01950 return qa; 01951 01952 } 01953 01954 double getDistanceInUnits(const Mat& t) { 01955 double retVal = 0.0; 01956 01957 retVal += pow(t.at<double>(0,0), 2.0); 01958 retVal += pow(t.at<double>(1,0), 2.0); 01959 retVal += pow(t.at<double>(2,0), 2.0); 01960 retVal = pow(retVal, 0.5); 01961 01962 return retVal; 01963 } 01964 01965 01966 void addFixedCamera(SysSBA& sys, cameraParameters& cameraData, const Mat& C) { 01967 addBlankCamera(sys, cameraData, true); 01968 updateCameraNode_2(sys, C, sys.nodes.size()-1); 01969 } 01970 01971 void addNewCamera(SysSBA& sys, cameraParameters& cameraData, const Mat& C) { 01972 addBlankCamera(sys, cameraData, false); 01973 updateCameraNode_2(sys, C, sys.nodes.size()-1); 01974 } 01975 01976 void convertVec4dToMat(const Vector4d& vec4, Mat& mat) { 01977 mat = Mat::zeros(3, 1, CV_64FC1); 01978 01979 mat.at<double>(0,0) = vec4.x(); 01980 mat.at<double>(1,0) = vec4.y(); 01981 mat.at<double>(2,0) = vec4.z(); 01982 01983 } 01984 01985 void updateTracks(vector<featureTrack>& trackVector, const SysSBA& sys) { 01986 Point3d tmpPt; 01987 for (unsigned int iii = 0; iii < sys.tracks.size(); iii++) { 01988 if (iii < trackVector.size()) { 01989 tmpPt.x = sys.tracks[iii].point.x(); 01990 tmpPt.y = sys.tracks[iii].point.y(); 01991 tmpPt.z = sys.tracks[iii].point.z(); 01992 trackVector.at(iii).set3dLoc(tmpPt); 01993 } // otherwise these points mightn't belong in the track vector.. 01994 01995 } 01996 } 01997 01998 void retrieveAllPoints(vector<Point3d>& pts, const SysSBA& sys) { 01999 02000 Point3d point_3; 02001 02002 for (unsigned int iii = 0; iii < sys.tracks.size(); iii++) { 02003 point_3.x = sys.tracks[iii].point.x(); 02004 point_3.y = sys.tracks[iii].point.y(); 02005 point_3.z = sys.tracks[iii].point.z(); 02006 02007 pts.push_back(point_3); 02008 } 02009 } 02010 02011 void retrieveCameraPose(SysSBA& sys, Mat& camPose, int idx) { 02012 02013 Mat R, t, C; 02014 quaternionToMatrix(sys.nodes[idx].qrot, R); 02015 convertVec4dToMat(sys.nodes[idx].trans, t); 02016 02017 compileTransform(C, R, t); 02018 C.copyTo(camPose); 02019 02020 } 02021 02022 void retrieveCamera(Mat& camera, const SysSBA& sys, unsigned int idx) { 02023 02024 Mat R, t, C; 02025 quaternionToMatrix(sys.nodes[idx].qrot, R); 02026 convertVec4dToMat(sys.nodes[idx].trans, t); 02027 compileTransform(C, R, t); 02028 C.copyTo(camera); 02029 02030 } 02031 02032 void retrieveAllCameras(Mat *allCameraPoses, const SysSBA& sys) { 02033 02034 for (unsigned int iii = 0; iii < sys.nodes.size(); iii++) { 02035 //if (allCameraPoses[iii].rows < 4) { 02036 02037 retrieveCamera(allCameraPoses[iii], sys, iii); 02038 02039 /* 02040 Mat R, t, C; 02041 quaternionToMatrix(sys.nodes[iii].qrot, R); 02042 convertVec4dToMat(sys.nodes[iii].trans, t); 02043 02044 compileTransform(C, R, t); 02045 C.copyTo(allCameraPoses[iii]); 02046 */ 02047 //} 02048 } 02049 } 02050 02051 void assignTracksToSBA(SysSBA& sys, vector<featureTrack>& trackVector, int maxIndex) { 02052 02053 sys.tracks.clear(); 02054 02055 // ConnMat ?? 02056 sys.connMat.clear(); 02057 02058 02059 //printf("%s << Assigning (%d) tracks...\n", __FUNCTION__, trackVector.size()); 02060 02061 02062 // For each track 02063 for (unsigned int iii = 0; iii < trackVector.size(); iii++) { 02064 02065 // The first occurence of this feature has to be before the "maxIndex" 02066 if (trackVector.at(iii).locations.at(0).imageIndex < maxIndex) { 02067 Point3d tmp3dPt = trackVector.at(iii).get3dLoc(); 02068 Vector4d temppoint(tmp3dPt.x, tmp3dPt.y, tmp3dPt.z, 1.0); 02069 sys.addPoint(temppoint); 02070 } 02071 02072 } 02073 02074 // For each track 02075 for (unsigned int iii = 0; iii < trackVector.size(); iii++) { 02076 Vector2d proj; 02077 02078 // The first occurence of this feature has to be before the "maxIndex" 02079 if (trackVector.at(iii).locations.at(0).imageIndex < maxIndex) { 02080 02081 // For each projection 02082 for (unsigned int jjj = 0; jjj < trackVector.at(iii).locations.size(); jjj++) { 02083 02084 // Projection cannot be in an image beyond the currently "active" camera 02085 if (trackVector.at(iii).locations.at(jjj).imageIndex < (maxIndex+1)) { 02086 proj.x() = trackVector.at(iii).locations.at(jjj).featureCoord.x; 02087 proj.y() = trackVector.at(iii).locations.at(jjj).featureCoord.y; 02088 02089 sys.addMonoProj(trackVector.at(iii).locations.at(jjj).imageIndex, iii, proj); 02090 } 02091 02092 02093 } 02094 } 02095 02096 02097 } 02098 02099 } 02100 02101 void estimateNewPose(vector<featureTrack>& tracks, Mat& K, int idx, Mat& pose) { 02102 // Find any tracks that have at least 3 "sightings" (so that 3d location is known) 02103 // Use 3D points and 2d locations to estimate R and t and then get pose 02104 02105 vector<Point3d> worldPoints; 02106 vector<Point2f> imagePoints1, imagePoints2; 02107 02108 Mat blankCoeffs = Mat::zeros(1, 8, CV_64FC1); 02109 02110 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 02111 if (tracks.at(iii).locations.size() >= 2) { 02112 02113 int finalIndex = tracks.at(iii).locations.size()-1; 02114 02115 if (tracks.at(iii).locations.at(finalIndex).imageIndex == idx) { 02116 //Point3d tmpPt(tracks.at(iii).xyzEstimate.x, tracks.at(iii).xyzEstimate.y, tracks.at(iii).xyzEstimate.z); 02117 worldPoints.push_back(tracks.at(iii).get3dLoc()); 02118 Point2f tmpPt2(tracks.at(iii).locations.at(finalIndex-1).featureCoord.x, tracks.at(iii).locations.at(finalIndex-1).featureCoord.y); 02119 imagePoints1.push_back(tmpPt2); 02120 tmpPt2 = Point2f(tracks.at(iii).locations.at(finalIndex).featureCoord.x, tracks.at(iii).locations.at(finalIndex).featureCoord.y); 02121 imagePoints2.push_back(tmpPt2); 02122 } 02123 02124 } 02125 } 02126 02127 02128 Mat Rvec, R, t; 02129 02130 vector<Point3f> objectPoints; 02131 Point3f tmpPt; 02132 02133 for (unsigned int jjj = 0; jjj < worldPoints.size(); jjj++) { 02134 tmpPt = Point3f((float) worldPoints.at(jjj).x, (float) worldPoints.at(jjj).y, (float) worldPoints.at(jjj).z); 02135 objectPoints.push_back(tmpPt); 02136 } 02137 02138 //solvePnPRansac(InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess=false, int iterationsCount=100, float reprojectionError=8.0, int minInliersCount=100, OutputArray inliers=noArray() ); 02139 solvePnPRansac(objectPoints, imagePoints2, K, blankCoeffs, Rvec, t); 02140 Rodrigues(Rvec, R); 02141 02142 compileTransform(pose, R, t); 02143 02144 } 02145 02146 void addNewPoints(SysSBA& sys, const vector<Point3d>& pc) { 02147 02148 Vector2d proj; 02149 02150 proj.x() = 0.0; 02151 proj.y() = 0.0; 02152 02153 for (unsigned int iii = 0; iii < pc.size(); iii++) { 02154 Vector4d temppoint(pc.at(iii).x, pc.at(iii).y, pc.at(iii).z, 1.0); 02155 02156 sys.addPoint(temppoint); 02157 02158 sys.addMonoProj(0, iii, proj); 02159 } 02160 } 02161 02162 int addToTracks(SysSBA& sys, int im1, vector<Point2f>& pts1, int im2, vector<Point2f>& pts2) { 02163 02164 //printSystemSummary(sys); 02165 02166 //printf("%s << Entered.\n", __FUNCTION__); 02167 02168 Vector2d proj; 02169 02170 //printf("%s << oldTrackCount = %d\n", __FUNCTION__, oldTrackCount); 02171 //printf("%s << nodes = %d\n", __FUNCTION__, sys.nodes.size()); 02172 02173 for (unsigned int iii = 0; iii < pts1.size(); iii++) { 02174 02175 bool pointInTracks = false; 02176 02177 //printf("%s << [%d][%d][%d] : tracks = %d\n", __FUNCTION__, im1, im2, iii, sys.tracks.size()); 02178 02179 for (unsigned int ttt = 0; ttt < sys.tracks.size(); ttt++) { // NOT oldTrackCount, in case of automatic re-ordering... 02180 02181 //printf("%s << old_track(%d) size = %d\n", __FUNCTION__, ttt, sys.tracks.at(ttt).projections.size()); 02182 02183 int finalIndex = sys.tracks.at(ttt).projections.size() - 1; 02184 02185 //printf("%s << [%d] finalIndex = %d\n", __FUNCTION__, ttt, finalIndex); 02186 02187 if (finalIndex > -1) { 02188 02189 //printf("%s << DEBUG[%d] (%d vs %d)\n", __FUNCTION__, 0, finalIndex, sys.tracks.at(ttt).projections.size()); 02190 02191 printf("%s << Attempting [%d][%d][%d][%d]\n", __FUNCTION__, im1, im2, iii, ttt); 02192 printf("%s << ndi(%d / %d) = \n", __FUNCTION__, finalIndex, sys.tracks.at(ttt).projections.size()); 02193 02194 printf("%s << sizeof() %d\n", __FUNCTION__, sizeof(sys.tracks.at(ttt).projections)); 02195 02196 if (finalIndex > 0) { 02197 printf("%s << (-1) %d\n", __FUNCTION__, sys.tracks.at(ttt).projections.at(finalIndex-1).ndi); 02198 } 02199 02200 printf("%s << %d\n", __FUNCTION__, sys.tracks.at(ttt).projections.at(finalIndex).ndi); 02201 02202 if ((im1 == 2) && (im2 == 3) && (iii == 16) && (ttt == 68)) { 02203 //cin.get(); 02204 } 02205 // 3, 4, 0, #49/50 track 02206 02207 // why would it say that projections is large enough, but then you can't read ndi...? 02208 // or is size returning the wrong info? 02209 02210 if (sys.tracks.at(ttt).projections.at(finalIndex).ndi == im1) { 02211 02212 //printf("%s << DEBUG[%d]\n", __FUNCTION__, 1); 02213 02214 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)) { 02215 02216 //printf("%s << DEBUG[%d]\n", __FUNCTION__, 2); 02217 02218 //printf("%s << Point exists in this track (%d)!\n", __FUNCTION__, ttt); 02219 02220 pointInTracks = true; 02221 02222 proj.x() = pts2.at(iii).x; 02223 proj.y() = pts2.at(iii).y; 02224 02225 if (!sys.addMonoProj(im2, ttt, proj)) { 02226 printf("%s << Adding point failed!\n", __FUNCTION__); 02227 } 02228 02229 //printf("%s << Projection added.\n", __FUNCTION__); 02230 02231 break; 02232 02233 } 02234 02235 //printf("%s << DEBUG[%d]\n", __FUNCTION__, 3); 02236 } 02237 02238 //printf("%s << DEBUG[%d]\n", __FUNCTION__, 4); 02239 } 02240 02241 02242 02243 } 02244 02245 if (!pointInTracks) { 02246 02247 //printf("%s << Point not in any of the tracks...\n", __FUNCTION__); 02248 02249 int newTrackNum = sys.tracks.size(); 02250 02251 Vector4d temppoint(0.0, 0.0, 0.0, 1.0); 02252 02253 //temppoint.x() = 0.0; 02254 //temppoint.y() = 0.0; 02255 //temppoint.z() = 0.0; 02256 sys.addPoint(temppoint); 02257 02258 // Then add a track? 02259 //sys.tracks.push_back(Track(temppoint)); 02260 02261 proj.x() = pts1.at(iii).x; 02262 proj.y() = pts1.at(iii).y; 02263 02264 if (!sys.addMonoProj(im1, newTrackNum, proj)) { 02265 printf("%s << Adding point failed!\n", __FUNCTION__); 02266 } 02267 02268 proj.x() = pts2.at(iii).x; 02269 proj.y() = pts2.at(iii).y; 02270 02271 if (!sys.addMonoProj(im2, newTrackNum, proj)) { 02272 printf("%s << Adding point failed!\n", __FUNCTION__); 02273 } 02274 02275 //printf("%s << Two projections added.\n", __FUNCTION__); 02276 } else { 02277 //printf("%s << Point already in tracks...\n", __FUNCTION__); 02278 } 02279 02280 02281 } 02282 02283 return sys.tracks.size(); 02284 } 02285 02286 void addBlankCamera(SysSBA& sys, cameraParameters& cameraData, bool isFixed) { 02287 02288 frame_common::CamParams cam_params; 02289 02290 cam_params.fx = cameraData.K.at<double>(0, 0); // Focal length in x 02291 cam_params.fy = cameraData.K.at<double>(1, 1); // Focal length in y 02292 cam_params.cx = cameraData.K.at<double>(0, 2); // X position of principal point 02293 cam_params.cy = cameraData.K.at<double>(1, 2); // Y position of principal point 02294 cam_params.tx = 0; // Baseline (no baseline since this is monocular) 02295 02296 Vector4d trans(0, 0, 0, 1); 02297 02298 // Don't rotate. 02299 Quaterniond rot(1, 0, 0, 0); 02300 rot.normalize(); 02301 02302 //printf("%s << rot = (%f, %f, %f, %f)\n", __FUNCTION__, rot.x(), rot.y(), rot.z(), rot.w()); 02303 02304 // Add a new node to the system. 02305 sys.addNode(trans, rot, cam_params, isFixed); // isFixed 02306 02307 if (isFixed) { 02308 // sys.nFixed++; 02309 } 02310 02311 /* 02312 sys.nodes[currIndex].normRot(); 02313 sys.nodes[currIndex].setTransform(); 02314 sys.nodes[currIndex].setProjection(); 02315 sys.nodes[currIndex].setDr(true); 02316 */ 02317 02318 } 02319 02320 void printSystemSummary(SysSBA& sys) { 02321 printf("%s << sys.nodes.size() = %d\n", __FUNCTION__, sys.nodes.size()); 02322 printf("%s << sys.tracks.size() = %d\n", __FUNCTION__, sys.tracks.size()); 02323 } 02324 02325 Quaterniond defaultQuaternion() { 02326 Quaterniond defQuaternion(1, 0, 0, 0); 02327 02328 return defQuaternion; 02329 } 02330 02331 void updateCameraNode_2(SysSBA& sys, const Mat& C, int image_index) { 02332 Mat R, t; 02333 02334 Mat Cnew; 02335 02336 if (C.rows == 4) { 02337 C.copyTo(Cnew); 02338 } else { 02339 Cnew = Mat(4, 4, CV_64FC1); 02340 for (unsigned int iii = 0; iii < 3; iii++) { 02341 for (unsigned int jjj = 0; jjj < 4; jjj++) { 02342 Cnew.at<double>(iii,jjj) = C.at<double>(iii,jjj); 02343 02344 } 02345 } 02346 02347 Cnew.at<double>(3,0) = 0.0; 02348 Cnew.at<double>(3,1) = 0.0; 02349 Cnew.at<double>(3,2) = 0.0; 02350 Cnew.at<double>(3,3) = 1.0; 02351 } 02352 02353 Mat C_inv = Cnew.inv(); 02354 02355 decomposeTransform(C, R, t); 02356 02357 for (unsigned int iii = 0; iii < 3; iii++) { 02358 for (unsigned int jjj = 0; jjj < 4; jjj++) { 02359 sys.nodes.at(image_index).w2n(iii,jjj) = C.at<double>(iii,jjj); 02360 } 02361 } 02362 02363 updateCameraNode_2(sys, R, t, image_index); 02364 } 02365 02366 void updateCameraNode_2(SysSBA& sys, const Mat& R, const Mat& t, int image_index) { 02367 Vector4d translation; 02368 Quaterniond rotation; 02369 02370 // printf("%s << t = (%f, %f, %f, %f)\n", __FUNCTION__, t.at<double>(0,0), t.at<double>(1,0), t.at<double>(2,0), t.at<double>(3,0)); 02371 02372 translation.x() = t.at<double>(0,0); 02373 translation.y() = t.at<double>(1,0); 02374 translation.z() = t.at<double>(2,0); 02375 02376 //printf("%s << Assigning (%d) translation: (%f, %f, %f)\n", __FUNCTION__, image_index, translation.x(), translation.y(), translation.z()); 02377 02378 matrixToQuaternion(R, rotation); 02379 02380 //Quaterniond dq = defaultQuaternion(); 02381 //double qa = getQuaternionAngle(rotation, dq); 02382 02383 //printf("%s << Angle = %f / %f\n", __FUNCTION__, qa, qa * 180.0 / M_PI); 02384 02385 //cout << __FUNCTION__ << " << R = " << R << endl; 02386 02387 //printf("%s << rotation = (%f, %f, %f, %f)\n", __FUNCTION__, rotation.x(), rotation.y(), rotation.z(), rotation.w()); 02388 02389 Mat R2; 02390 quaternionToMatrix(rotation, R2); 02391 02392 //cout << __FUNCTION__ << " << R2 = " << R2 << endl; 02393 02394 sys.nodes[image_index].trans = translation; 02395 sys.nodes[image_index].qrot = rotation; 02396 02397 } 02398 02399 void convertProjectionMatCVToEigen(const Mat& mat, Eigen::Matrix< double, 3, 4 > m) { 02400 02401 m(0,0) = mat.at<double>(0,0); 02402 m(0,1) = mat.at<double>(0,1); 02403 m(0,2) = mat.at<double>(0,2); 02404 m(0,3) = mat.at<double>(0,3); 02405 02406 m(1,0) = mat.at<double>(1,0); 02407 m(1,1) = mat.at<double>(1,1); 02408 m(1,2) = mat.at<double>(1,2); 02409 m(1,3) = mat.at<double>(1,3); 02410 02411 m(2,0) = mat.at<double>(2,0); 02412 m(2,1) = mat.at<double>(2,1); 02413 m(2,2) = mat.at<double>(2,2); 02414 m(2,3) = mat.at<double>(2,3); 02415 02416 } 02417 02418 void convertProjectionMatEigenToCV(const Eigen::Matrix< double, 3, 4 > m, Mat& mat) { 02419 02420 mat = Mat::zeros(3, 4, CV_64FC1); 02421 02422 mat.at<double>(0,0) = m(0,0); 02423 mat.at<double>(0,1) = m(0,1); 02424 mat.at<double>(0,2) = m(0,2); 02425 mat.at<double>(0,3) = m(0,3); 02426 02427 mat.at<double>(1,0) = m(1,0); 02428 mat.at<double>(1,1) = m(1,1); 02429 mat.at<double>(1,2) = m(1,2); 02430 mat.at<double>(1,3) = m(1,3); 02431 02432 mat.at<double>(2,0) = m(2,0); 02433 mat.at<double>(2,1) = m(2,1); 02434 mat.at<double>(2,2) = m(2,2); 02435 mat.at<double>(2,3) = m(2,3); 02436 02437 } 02438 02439 void projectionToRotation(const Mat& src, Mat& dst) { 02440 dst = Mat(3, 3, CV_64FC1); 02441 02442 dst.at<double>(0,0) = src.at<double>(0,0); 02443 dst.at<double>(0,1) = src.at<double>(0,1); 02444 dst.at<double>(0,2) = src.at<double>(0,2); 02445 02446 dst.at<double>(1,0) = src.at<double>(1,0); 02447 dst.at<double>(1,1) = src.at<double>(1,1); 02448 dst.at<double>(1,2) = src.at<double>(1,2); 02449 02450 dst.at<double>(2,0) = src.at<double>(2,0); 02451 dst.at<double>(2,1) = src.at<double>(2,1); 02452 dst.at<double>(2,2) = src.at<double>(2,2); 02453 02454 } 02455 02456 void rotationToProjection(const Mat& src, Mat& dst) { 02457 dst = Mat(3, 4, CV_64FC1); 02458 02459 dst.at<double>(0,0) = src.at<double>(0,0); 02460 dst.at<double>(0,1) = src.at<double>(0,1); 02461 dst.at<double>(0,2) = src.at<double>(0,2); 02462 dst.at<double>(0,3) = 0.0; 02463 02464 dst.at<double>(1,0) = src.at<double>(1,0); 02465 dst.at<double>(1,1) = src.at<double>(1,1); 02466 dst.at<double>(1,2) = src.at<double>(1,2); 02467 dst.at<double>(1,3) = 0.0; 02468 02469 dst.at<double>(2,0) = src.at<double>(2,0); 02470 dst.at<double>(2,1) = src.at<double>(2,1); 02471 dst.at<double>(2,2) = src.at<double>(2,2); 02472 dst.at<double>(2,3) = 0.0; 02473 02474 } 02475 02476 // J.M.P. van Waveren 02477 float ReciprocalSqrt( float x ) { 02478 long i; 02479 float y, r; 02480 02481 y = x * 0.5f; 02482 i = *(long *)( &x ); 02483 i = 0x5f3759df - ( i >> 1 ); 02484 r = *(float *)( &i ); 02485 r = r * ( 1.5f - r * r * y ); 02486 return r; 02487 } 02488 02489 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ethan.htm 02490 void matrixToQuaternion(const Mat& mat, Quaterniond& quat) { 02491 02492 // convert mat to Eigen::Matrix3d m; 02493 /* 02494 Eigen::Matrix3d m; 02495 02496 m(0,0) = mat.at<double>(0,0); 02497 m(0,1) = mat.at<double>(0,1); 02498 m(0,2) = mat.at<double>(0,2); 02499 02500 m(1,0) = mat.at<double>(1,0); 02501 m(1,1) = mat.at<double>(1,1); 02502 m(1,2) = mat.at<double>(1,2); 02503 02504 m(2,0) = mat.at<double>(2,0); 02505 m(2,1) = mat.at<double>(2,1); 02506 m(2,2) = mat.at<double>(2,2); 02507 02508 quat = Quaterniond(m); 02509 02510 quat.normalize(); 02511 02512 return; 02513 */ 02514 // printf("%s << Entered...\n", __FUNCTION__); 02515 02516 double m00 = mat.at<double>(0,0); 02517 double m01 = mat.at<double>(0,1); 02518 double m02 = mat.at<double>(0,2); 02519 02520 double m10 = mat.at<double>(1,0); 02521 double m11 = mat.at<double>(1,1); 02522 double m12 = mat.at<double>(1,2); 02523 02524 double m20 = mat.at<double>(2,0); 02525 double m21 = mat.at<double>(2,1); 02526 double m22 = mat.at<double>(2,2); 02527 02528 double qw, qx, qy, qz; 02529 02530 02531 // ALT 3 02532 // J.M.P. van Waveren 02533 /* 02534 float m[9], q[4]; 02535 m[0] = m00; m[1] = m01; m[2] = m02; 02536 m[3] = m10; m[4] = m11; m[5] = m12; 02537 m[6] = m20; m[7] = m21; m[8] = m22; 02538 02539 //const float *m = jointMats[i].mat; 02540 if ( m[0 * 4 + 0] + m[1 * 4 + 1] + m[2 * 4 + 2] > 0.0f ) { 02541 float t = + m[0 * 4 + 0] + m[1 * 4 + 1] + m[2 * 4 + 2] + 1.0f; 02542 float s = ReciprocalSqrt( t ) * 0.5f; 02543 q[3] = s * t; 02544 q[2] = ( m[0 * 4 + 1] - m[1 * 4 + 0] ) * s; 02545 q[1] = ( m[2 * 4 + 0] - m[0 * 4 + 2] ) * s; 02546 q[0] = ( m[1 * 4 + 2] - m[2 * 4 + 1] ) * s; 02547 } else if ( m[0 * 4 + 0] > m[1 * 4 + 1] && m[0 * 4 + 0] > m[2 * 4 + 2] ) { 02548 float t = + m[0 * 4 + 0] - m[1 * 4 + 1] - m[2 * 4 + 2] + 1.0f; 02549 float s = ReciprocalSqrt( t ) * 0.5f; 02550 q[0] = s * t; 02551 q[1] = ( m[0 * 4 + 1] + m[1 * 4 + 0] ) * s; 02552 q[2] = ( m[2 * 4 + 0] + m[0 * 4 + 2] ) * s; 02553 q[3] = ( m[1 * 4 + 2] - m[2 * 4 + 1] ) * s; 02554 } else if ( m[1 * 4 + 1] > m[2 * 4 + 2] ) { 02555 float t = - m[0 * 4 + 0] + m[1 * 4 + 1] - m[2 * 4 + 2] + 1.0f; 02556 float s = ReciprocalSqrt( t ) * 0.5f; 02557 q[1] = s * t; 02558 q[0] = ( m[0 * 4 + 1] + m[1 * 4 + 0] ) * s; 02559 q[3] = ( m[2 * 4 + 0] - m[0 * 4 + 2] ) * s; 02560 q[2] = ( m[1 * 4 + 2] + m[2 * 4 + 1] ) * s; 02561 } else { 02562 float t = - m[0 * 4 + 0] - m[1 * 4 + 1] + m[2 * 4 + 2] + 1.0f; 02563 float s = ReciprocalSqrt( t ) * 0.5f; 02564 q[2] = s * t; 02565 q[3] = ( m[0 * 4 + 1] - m[1 * 4 + 0] ) * s; 02566 q[0] = ( m[2 * 4 + 0] + m[0 * 4 + 2] ) * s; 02567 q[1] = ( m[1 * 4 + 2] + m[2 * 4 + 1] ) * s; 02568 } 02569 02570 qx = (double) q[0]; 02571 qy = (double) q[1]; 02572 qz = (double) q[2]; 02573 qw = (double) q[3]; 02574 */ 02575 02576 // ALT 2 02577 // http://www.koders.com/cpp/fid38F83F165ABF728D6046FD59CF21ECF65E30E2D4.aspx 02578 /* 02579 double tmp = abs(m00 + m11 + m22 + 1); 02580 double s = sqrt(tmp); 02581 02582 if (s > 0.0001) { 02583 qx = (m21 - m12) / 4*s; 02584 qy = (m02 - m20) / 4*s; 02585 qx = (m10 - m01) / 4*s; 02586 } else { 02587 int s_iNext[3] = { 2, 3, 1 }; 02588 int i = 1; 02589 if ( m11 > m00 ) { 02590 i = 2; 02591 } 02592 02593 if ( m22 > m11 ) { 02594 i = 3; 02595 } 02596 02597 int j = s_iNext[i-1]; 02598 int k = s_iNext[j-1]; 02599 02600 double fRoot = sqrt(mat.at<double>(i-1,i-1) - mat.at<double>(j-1,j-1) - mat.at<double>(k-1,k-1) + 1.0); 02601 02602 double *tmp[3] = { &qx, &qy, &qz }; 02603 *tmp[i-1] = 0.5 * fRoot; 02604 s = (mat.at<double>(k-1,j-1)-mat.at<double>(j-1,k-1))*fRoot; 02605 *tmp[j-1] = (mat.at<double>(j-1,i-1)+mat.at<double>(i-1,j-1))*fRoot; 02606 *tmp[k-1] = (mat.at<double>(k-1,i-1)+mat.at<double>(i-1,k-1))*fRoot; 02607 } 02608 02609 if ((qx*qx + qy*qy + qz*qz) != 1.0) { 02610 qw = sqrt(1 - qx*qx - qy*qy - qz*qz); 02611 } else { 02612 qw = 0.0; 02613 } 02614 */ 02615 02616 // ALT 1 02617 02618 double tr1 = 1.0 + m00 - m11 - m22; 02619 double tr2 = 1.0 - m00 + m11 - m22; 02620 double tr3 = 1.0 - m00 - m11 + m22; 02621 02622 02623 02624 //printf("%s << tr1, tr2, tr3 = (%f, %f, %f)\n", __FUNCTION__, tr1, tr2, tr3); 02625 02626 if ((tr1 > tr2) && (tr1 > tr3)) { 02627 double S = sqrt(tr1) * 2.0; // S=4*qx 02628 //printf("%s << Case 1: %f\n", __FUNCTION__, S); 02629 qw = (m21 - m12) / S; 02630 qx = 0.25 * S; 02631 qy = (m01 + m10) / S; 02632 qz = (m02 + m20) / S; 02633 } else if ((tr2 > tr1) && (tr2 > tr3)) { 02634 double S = sqrt(tr2) * 2.0; // S=4*qy 02635 //printf("%s << Case 2: %f\n", __FUNCTION__, S); 02636 qw = (m02 - m20) / S; 02637 qx = (m01 + m10) / S; 02638 qy = 0.25 * S; 02639 qz = (m12 + m21) / S; 02640 } else if ((tr3 > tr1) && (tr3 > tr2)) { 02641 double S = sqrt(tr3) * 2.0; // S=4*qz 02642 //printf("%s << Case 3: %f\n", __FUNCTION__, S); 02643 qw = (m10 - m01) / S; 02644 qx = (m02 + m20) / S; 02645 qy = (m12 + m21) / S; 02646 qz = 0.25 * S; 02647 } else { 02648 //printf("%s << Case 4\n", __FUNCTION__); 02649 qw = 1.0; 02650 qx = 0.0; 02651 qy = 0.0; 02652 qz = 0.0; 02653 } 02654 02655 02656 02657 02658 02659 quat.x() = qx; 02660 quat.y() = qy; 02661 quat.z() = qz; 02662 quat.w() = qw; 02663 02664 //printf("%s << Quat = (%f, %f, %f, %f)\n", __FUNCTION__, qx, qy, qz, qw); 02665 02666 quat.normalize(); 02667 02668 //printf("%s << Completed.\n", __FUNCTION__); 02669 } 02670 02671 void updateCameraNode(SysSBA& sys, Mat R, Mat t, int img1, int img2) { 02672 02673 Mat full_R; 02674 02675 Rodrigues(R, full_R); 02676 02677 printf("%s << Trying to determine position of camera node (%d, %d)...\n", __FUNCTION__, img1, img2); 02678 02679 cout << "R = " << R << endl; 02680 cout << "t = " << t << endl; 02681 02682 // First camera parameters 02683 Vector4d temptrans = sys.nodes[img1].trans; 02684 Quaterniond tempqrot = sys.nodes[img1].qrot; 02685 02686 //printf("%s << Debug [%d]\n", __FUNCTION__, 0); 02687 02688 // NEED TO COMBINE TRANSLATION AND QUATERNION FOR PREVIOUS CAMERA WITH THE ONE FOR THE PRESENT ONE... 02689 // NEED TO KNOW: CONVERSION FROM R/t to quaternion 02690 // mapping of one co-ordinate system onto another 02691 02692 // Establish ORIGIN relative to NODE A 02693 Vector4d temptrans_N; 02694 Quaterniond tempqrot_N; 02695 temptrans_N.x() = -temptrans.x(); 02696 temptrans_N.y() = -temptrans.y(); 02697 temptrans_N.z() = -temptrans.z(); 02698 tempqrot_N.x() = tempqrot.x(); 02699 tempqrot_N.y() = tempqrot.y(); 02700 tempqrot_N.z() = tempqrot.z(); 02701 tempqrot_N.w() = -tempqrot.w(); 02702 tempqrot_N.normalize(); 02703 02704 sba::Node negativeOrigin; 02705 negativeOrigin.trans = temptrans_N; 02706 negativeOrigin.qrot = tempqrot_N; 02707 02708 //Mat testMat; 02709 //Quaterniond testQuaterniond; 02710 //printf("%s << q(1) = (%f, %f, %f, %f)\n", __FUNCTION__, tempqrot_N.x(), tempqrot_N.y(), tempqrot_N.z(), tempqrot_N.w()); 02711 //convertFromQuaternionToMat(tempqrot_N, testMat); 02712 //cout << "testMat = " << testMat << endl; 02713 //convertFromMatToQuaternion(testMat, testQuaterniond); 02714 //printf("%s << q(2) = (%f, %f, %f, %f)\n", __FUNCTION__, testQuaterniond.x(), testQuaterniond.y(), testQuaterniond.z(), testQuaterniond.w()); 02715 //convertFromQuaternionToMat(testQuaterniond, testMat); 02716 //cout << "testMat2 = " << testMat << endl; 02717 02718 //cout << "temptrans_N = " << temptrans_N << endl; 02719 //cout << "tempqrot_N = " << tempqrot_N << endl; 02720 02721 //printf("%s << Debug [%d]\n", __FUNCTION__, 1); 02722 02723 // Establish NODE B relative to NODE A 02724 02725 Vector4d temptrans_B; 02726 Quaterniond tempqrot_B; 02727 temptrans_B.x() = t.at<double>(0,0); 02728 temptrans_B.y() = t.at<double>(1,0); 02729 temptrans_B.z() = t.at<double>(2,0); 02730 02731 matrixToQuaternion(full_R, tempqrot_B); 02732 02733 //cout << "full_R = " << full_R << endl; 02734 //printf("%s << tempqrot_B = (%f, %f, %f, %f)\n", __FUNCTION__, tempqrot_B.x(), tempqrot_B.y(), tempqrot_B.z(), tempqrot_B.w()); 02735 02736 //tempqrot_B.x() = R.at<double>(0,0); // not correct conversion to quaternion 02737 //tempqrot_B.y() = R.at<double>(1,0); 02738 //tempqrot_B.z() = R.at<double>(2,0); 02739 tempqrot_B.normalize(); 02740 02741 sba::Node secondNode; 02742 secondNode.trans = temptrans_B; 02743 secondNode.qrot = tempqrot_B; 02744 02745 //printf("%s << Debug [%d]\n", __FUNCTION__, 2); 02746 02747 // Find transform from Origin to camera B 02748 02749 Eigen::Matrix< double, 4, 1 > transformationMat; 02750 Eigen::Quaternion< double > quaternionVec; 02751 02752 sba::transformN2N(transformationMat, quaternionVec, negativeOrigin, secondNode); 02753 02754 //printf("%s << Debug [%d]\n", __FUNCTION__, 3); 02755 02756 // Assign this transformation to the new camera mode 02757 02758 temptrans.x() = transformationMat(0,0); 02759 temptrans.y() = transformationMat(1,0); 02760 temptrans.z() = transformationMat(2,0); 02761 02762 tempqrot.x() = quaternionVec.x(); 02763 tempqrot.y() = quaternionVec.y(); 02764 tempqrot.z() = quaternionVec.z(); 02765 tempqrot.normalize(); 02766 02767 sys.nodes[img2].trans = temptrans; 02768 sys.nodes[img2].qrot = tempqrot; 02769 02770 sys.nodes[img2].normRot(); 02771 sys.nodes[img2].setTransform(); 02772 sys.nodes[img2].setProjection(); 02773 sys.nodes[img2].setDr(true); 02774 02775 //printf("%s << Debug [%d]\n", __FUNCTION__, 4); 02776 02777 return; 02778 02779 // OLD 02780 02781 02782 // Add the new translations 02783 temptrans.x() += t.at<double>(0,0); 02784 temptrans.y() += t.at<double>(1,0); 02785 temptrans.z() += t.at<double>(2,0); 02786 02787 // This is probably not a valid conversion 02788 02789 tempqrot.x() += R.at<double>(0,0); 02790 tempqrot.y() += R.at<double>(1,0); 02791 tempqrot.z() += R.at<double>(2,0); 02792 tempqrot.normalize(); 02793 02794 sys.nodes[img2].trans = temptrans; 02795 sys.nodes[img2].qrot = tempqrot; 02796 02797 // These methods should be called to update the node. 02798 02799 sys.nodes[img2].normRot(); 02800 sys.nodes[img2].setTransform(); 02801 sys.nodes[img2].setProjection(); 02802 sys.nodes[img2].setDr(true); 02803 02804 } 02805 02806 void constrainDodgyPoints(SysSBA& sys) { 02807 02808 for (unsigned int iii = 0; iii < sys.nodes.size(); iii++) { 02809 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)) { 02810 sys.nodes[iii].trans.x() = 0.0; 02811 sys.nodes[iii].trans.y() = 0.0; 02812 sys.nodes[iii].trans.z() = 0.0; 02813 } 02814 } 02815 02816 for (unsigned int iii = 0; iii < sys.tracks.size(); iii++) { 02817 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)) { 02818 sys.tracks[iii].point.x() = 0.0; 02819 sys.tracks[iii].point.y() = 0.0; 02820 sys.tracks[iii].point.z() = 0.0; 02821 } 02822 } 02823 } 02824 02825 int TriangulateNewTracks(vector<featureTrack>& trackVector, const int index1, const int index2, const Mat& K, const Mat& K_inv, const Mat& P0, const Mat& P1, bool initializeOnFocalPlane) { 02826 02827 Mat coordinateTransform; 02828 02829 int tracksTriangulated = 0; 02830 02831 02832 for (unsigned int iii = 0; iii < trackVector.size(); iii++) { 02833 02834 for (unsigned int jjj = 0; jjj < trackVector.at(iii).locations.size()-1; jjj++) { 02835 02836 int trInd1 = trackVector.at(iii).locations.at(jjj).imageIndex; 02837 02838 if (trInd1 == index1) { 02839 02840 for (unsigned int kkk = jjj+1; kkk < trackVector.at(iii).locations.size(); kkk++) { 02841 02842 int trInd2 = trackVector.at(iii).locations.at(kkk).imageIndex; 02843 02844 if (trInd2 == index2) { 02845 02846 Point2f loc1 = trackVector.at(iii).locations.at(jjj).featureCoord; 02847 Point2f loc2 = trackVector.at(iii).locations.at(kkk).featureCoord; 02848 02849 Point3d xyzPoint; 02850 02851 // This puts the 3D point out but in camera A's co-ordinates 02852 if (initializeOnFocalPlane) { 02853 xyzPoint.x = loc1.x; 02854 xyzPoint.y = loc1.y; 02855 xyzPoint.z = 1.0; 02856 } else { 02857 Triangulate(loc1, loc2, K, K_inv, P0, P1, xyzPoint); 02858 } 02859 02860 //printf("%s << PT relative to cam A: (%f, %f, %f)\n", __FUNCTION__, xyzPoint.x, xyzPoint.y, xyzPoint.z); 02861 02862 // Convert XYZ co-ordinate to WORLD co-ordinates 02863 02864 trackVector.at(iii).set3dLoc(xyzPoint); 02865 //trackVector.at(iii).xyzEstimate.x = xyzPoint.x; 02866 //trackVector.at(iii).xyzEstimate.y = xyzPoint.y; 02867 //trackVector.at(iii).xyzEstimate.z = xyzPoint.z; 02868 02869 //printf("%s << PT relative to WORLD: (%f, %f, %f)\n", __FUNCTION__, trackVector.at(iii).xyzEstimate.x, trackVector.at(iii).xyzEstimate.y, trackVector.at(iii).xyzEstimate.z); 02870 02871 tracksTriangulated++; 02872 02873 } 02874 02875 } 02876 02877 } 02878 02879 02880 } 02881 02882 02883 02884 02885 } 02886 02887 return tracksTriangulated; 02888 02889 } 02890 02891 void ExtractPointCloud(vector<Point3d>& cloud, vector<featureTrack>& trackVector) { 02892 02893 02894 for (unsigned int iii = 0; iii < trackVector.size(); iii++) { 02895 // Copy the track vector co-ordinate 02896 cloud.push_back(trackVector.at(iii).get3dLoc()); 02897 } 02898 02899 02900 } 02901 02902 02903 02904 void reduceVectorsToTrackedPoints(const vector<Point2f>& points1, vector<Point2f>& trackedPoints1, const vector<Point2f>& points2, vector<Point2f>& trackedPoints2, vector<uchar>& statusVec) { 02905 02906 trackedPoints1.clear(); 02907 trackedPoints2.clear(); 02908 02909 for (unsigned int iii = 0; iii < statusVec.size(); iii++) { 02910 02911 if (statusVec.at(iii) > 0) { 02912 //printf("%s << 1: statusVec.at(%d) = %c\n", __FUNCTION__, iii, statusVec.at(iii)); 02913 trackedPoints1.push_back(points1.at(iii)); 02914 trackedPoints2.push_back(points2.at(iii)); 02915 } else { 02916 //printf("%s << 0: statusVec.at(%d) = %c\n", __FUNCTION__, iii, statusVec.at(iii)); 02917 } 02918 } 02919 02920 } 02921 02922 bool findBestReconstruction(const Mat& P0, Mat& P1, Mat& R, Mat& t, const SVD& svd, const Mat& K, const vector<Point2f>& pts1, const vector<Point2f>& pts2, bool useDefault) { 02923 02924 bool validity = false; 02925 02926 //printf("%s << Entered.\n", __FUNCTION__); 02927 02928 if (pts1.size() != pts2.size()) { 02929 printf("%s << ERROR! Point vector size mismatch.\n", __FUNCTION__); 02930 } 02931 02932 int bestIndex = 0, bestScore = -1; 02933 Mat t33, t_tmp[4], R_tmp[4], W, Z, Winv, I, negI, P1_tmp[4]; 02934 Mat Kinv; 02935 //printf("%s << DEBUG [%d].\n", __FUNCTION__, -2); 02936 //printf("%s << DEBUG [%d].\n", __FUNCTION__, -1); 02937 Kinv = K.inv(); 02938 02939 //printf("%s << DEBUG [%d].\n", __FUNCTION__, 0); 02940 02941 Mat zeroTrans; 02942 zeroTrans = Mat::zeros(3, 1, CV_64F); // correct dimension? 02943 02944 I = Mat::eye(3, 3, CV_64FC1); 02945 negI = -I; 02946 getWandZ(W, Winv, Z); 02947 02948 //printf("%s << DEBUG [%d].\n", __FUNCTION__, 1); 02949 02950 Mat u_transpose; 02951 transpose(svd.u, u_transpose); 02952 02953 Mat rotation1; 02954 Rodrigues(I, rotation1); 02955 02956 //printf("%s << DEBUG [%d].\n", __FUNCTION__, 2); 02957 02958 //cout << "rotation1 = " << rotation1 << endl; 02959 02960 float sig = rotation1.at<double>(0,1); 02961 float phi = rotation1.at<double>(0,2); 02962 02963 //printf("%s << sig = %f; phi = %f\n", __FUNCTION__, sig, phi); 02964 02965 Point3d unitVec1(1.0*sin(sig)*cos(phi), 1.0*sin(sig)*cos(phi), 1.0*cos(sig)); 02966 02967 //printf("%s << DEBUG [%d].\n", __FUNCTION__, 3); 02968 02969 Mat uv1(unitVec1); 02970 02971 //printf("%s << DEBUG [%d].\n", __FUNCTION__, 4); 02972 02973 // Go through all four cases... 02974 for (int zzz = 0; zzz < 4; zzz++) { 02975 02976 //printf("%s << Loop [%d]\n", __FUNCTION__, zzz); 02977 02978 switch (zzz) { 02979 case 0: 02980 //t33 = v * W * SIGMA * vt; 02981 t33 = svd.u * Z * u_transpose; 02982 R_tmp[zzz] = svd.u * Winv * svd.vt; 02983 break; 02984 case 1: 02985 //t33 = v * W_inv * SIGMA * vt; 02986 t33 = negI * svd.u * Z * u_transpose; 02987 R_tmp[zzz] = svd.u * Winv * svd.vt; 02988 break; 02989 case 2: 02990 //t33 = v * W * SIGMA * vt; 02991 t33 = svd.u * Z * u_transpose; 02992 R_tmp[zzz] = svd.u * W * svd.vt; 02993 break; 02994 case 3: 02995 //t33 = v * W_inv * SIGMA * vt; 02996 t33 = negI * svd.u * Z * u_transpose; 02997 R_tmp[zzz] = svd.u * W * svd.vt; 02998 break; 02999 default: 03000 break; 03001 } 03002 03003 // Converting 3x3 t mat to vector 03004 t_tmp[zzz] = Mat::zeros(3, 1, CV_64F); 03005 t_tmp[zzz].at<double>(0,0) = -t33.at<double>(1,2); 03006 t_tmp[zzz].at<double>(1,0) = t33.at<double>(0,2); 03007 t_tmp[zzz].at<double>(2,0) = -t33.at<double>(0,1); 03008 03009 // Get new P1 matrix 03010 findP1Matrix(P1_tmp[zzz], R_tmp[zzz], t_tmp[zzz]); 03011 03012 // Find camera vectors 03013 Mat rotation2; 03014 Rodrigues(R_tmp[zzz], rotation2); 03015 03016 //cout << "rotation2 = " << rotation2 << endl; 03017 03018 sig = rotation2.at<double>(0,1); 03019 phi = rotation2.at<double>(0,2); 03020 03021 //printf("%s << sig = %f; phi = %f\n", __FUNCTION__, sig, phi); 03022 03023 Point3d unitVec2(1.0*sin(sig)*cos(phi), 1.0*sin(sig)*cos(phi), 1.0*cos(sig)); 03024 03025 Mat uv2(unitVec2); 03026 03027 //printf("%s << unitVec2 = (%f, %f, %f)\n", __FUNCTION__, unitVec2.x, unitVec2.y, unitVec2.z); 03028 03029 int badCount = 0; 03030 03031 vector<Point3d> pointcloud; 03032 vector<Point2f> correspImg1Pt; 03033 03034 //printf("%s << DEBUG [%d].\n", __FUNCTION__, 7); 03035 03036 TriangulatePoints(pts1, pts2, K, Kinv, P0, P1_tmp[zzz], pointcloud, correspImg1Pt); 03037 03038 //printf("%s << DEBUG [%d]. (pointcloud.size() = %d)\n", __FUNCTION__, 8, pointcloud.size()); 03039 03040 Mat Rs_k[2], ts_k[2]; 03041 03042 // Then check how many points are NOT in front of BOTH of the cameras 03043 for (unsigned int kkk = 0; kkk < pointcloud.size(); kkk++) { 03044 03045 03046 03047 //printf("%s << DEBUG [%d][%d].\n", __FUNCTION__, kkk, 0); 03048 03049 Point3d rayVec1, rayVec2; 03050 03051 Rs_k[0] = I; 03052 Rs_k[1] = R_tmp[zzz]; 03053 03054 ts_k[0] = zeroTrans; 03055 ts_k[1] = t_tmp[zzz]; 03056 03057 //printf("%s << DEBUG [%d][%d].\n", __FUNCTION__, kkk, 1); 03058 03059 //cout << endl << "t_tmp[zzz] = " << t_tmp[zzz] << endl; 03060 03061 //printf("%s << objpt = (%f, %f, %f)\n", __FUNCTION__, objpt.x, objpt.y, objpt.z); 03062 03063 // so this is getting the displacements between the points and both cameras... 03064 rayVec1.x = pointcloud.at(kkk).x - ts_k[0].at<double>(0,0); 03065 rayVec1.y = pointcloud.at(kkk).y - ts_k[0].at<double>(1,0); 03066 rayVec1.z = pointcloud.at(kkk).z - ts_k[0].at<double>(2,0); 03067 03068 rayVec2.x = pointcloud.at(kkk).x - ts_k[1].at<double>(0,0); 03069 rayVec2.y = pointcloud.at(kkk).y - ts_k[1].at<double>(1,0); 03070 rayVec2.z = pointcloud.at(kkk).z - ts_k[1].at<double>(2,0); 03071 03072 /* 03073 if (kkk < 0) { 03074 printf("%s << pt(%d) = (%f, %f, %f)\n", __FUNCTION__, kkk, pointcloud.at(kkk).x, pointcloud.at(kkk).y, pointcloud.at(kkk).z); 03075 printf("%s << rayVec1(%d) = (%f, %f, %f)\n", __FUNCTION__, kkk, rayVec1.x, rayVec1.y, rayVec1.z); 03076 printf("%s << rayVec2(%d) = (%f, %f, %f)\n", __FUNCTION__, kkk, rayVec2.x, rayVec2.y, rayVec2.z); 03077 } 03078 * */ 03079 03080 //printf("%s << DEBUG [%d][%d].\n", __FUNCTION__, kkk, 2); 03081 03082 //printf("%s << rayVec1 = (%f, %f, %f)\n", __FUNCTION__, rayVec1.x, rayVec1.y, rayVec1.z); 03083 //printf("%s << rayVec2 = (%f, %f, %f)\n", __FUNCTION__, rayVec2.x, rayVec2.y, rayVec2.z); 03084 03085 //cin.get(); 03086 03087 double dot1, dot2; 03088 03089 Mat rv1(rayVec1), rv2(rayVec2); 03090 03091 /* 03092 cout << endl << "uv1 = " << uv1 << endl; 03093 cout << endl << "rv1 = " << rv1 << endl; 03094 03095 cout << endl << "uv2 = " << uv2 << endl; 03096 cout << endl << "rv2 = " << rv2 << endl; 03097 */ 03098 03099 dot1 = uv1.dot(rv1); 03100 dot2 = uv2.dot(rv2); 03101 03102 //printf("%s << DEBUG [%d][%d].\n", __FUNCTION__, kkk, 3); 03103 03104 //printf("%s << dot1 = %f; dot2 = %f\n", __FUNCTION__, dot1, dot2); 03105 03106 double mag1 = pow(pow(rayVec1.x, 2) + pow(rayVec1.y, 2) + pow(rayVec1.z, 2), 0.5); 03107 double mag2 = pow(pow(rayVec2.x, 2) + pow(rayVec2.y, 2) + pow(rayVec2.z, 2), 0.5); 03108 03109 //printf("%s << mag1 = %f; mag2 = %f\n", __FUNCTION__, mag1, mag2); 03110 03111 double ang1 = fmod(acos(dot1 / mag1), 2*M_PI); 03112 double ang2 = fmod(acos(dot2 / mag2), 2*M_PI); 03113 03114 //printf("%s << ang1 = %f; ang2 = %f\n", __FUNCTION__, ang1, ang2); 03115 // just try to check if angle is greater than 90deg from where each camera is facing to the pt 03116 03117 // get vector from each camera to the point 03118 03119 // use dot product to determine angle 03120 if ((abs(ang1) < M_PI/2 ) || (abs(ang2) < M_PI/2)) { 03121 //printf("%s << ang1 = %f; ang2 = %f\n", __FUNCTION__, ang1, ang2); 03122 //if ((dot1 < 0.0) || (dot2 < 0.0)) { 03123 validity = false; 03124 badCount++; 03125 } 03126 03127 if (rayVec1.z < 0) { 03128 //printf("%s << rayVec1.z < 0; abs(ang1) = %f\n", __FUNCTION__, abs(ang1)); 03129 03130 } else { 03131 //printf("%s << rayVec1.z >= 0; abs(ang1) = %f\n", __FUNCTION__, abs(ang1)); 03132 03133 } 03134 03135 //cin.get(); 03136 03137 } 03138 03139 printf("%s << badCount[%d] = %d\n", __FUNCTION__, zzz, badCount); 03140 03141 if (zzz == 0) { 03142 bestScore = badCount; 03143 } else { 03144 if (badCount < bestScore) { 03145 bestScore = badCount; 03146 bestIndex = zzz; 03147 } 03148 } 03149 03150 03151 } 03152 03153 if (bestScore == 0) { 03154 validity = true; 03155 } 03156 03157 // Should be 2 - but try different ones... 03158 if (useDefault) { 03159 bestIndex = 2; 03160 printf("%s << Defaulting to model #%d\n", __FUNCTION__, bestIndex); 03161 } 03162 03163 findP1Matrix(P1, R_tmp[bestIndex], t_tmp[bestIndex]); 03164 03165 R_tmp[bestIndex].copyTo(R); 03166 t_tmp[bestIndex].copyTo(t); 03167 03168 return validity; 03169 } 03170 03171 void initializeP0(Mat& P) { 03172 P = Mat::zeros(3, 4, CV_64FC1); 03173 P.at<double>(0,0) = 1.0; 03174 P.at<double>(0,1) = 0.0; 03175 P.at<double>(0,2) = 0.0; 03176 P.at<double>(0,3) = 0.0; 03177 P.at<double>(1,0) = 0.0; 03178 P.at<double>(1,1) = 1.0; 03179 P.at<double>(1,2) = 0.0; 03180 P.at<double>(1,3) = 0.0; 03181 P.at<double>(2,0) = 0.0; 03182 P.at<double>(2,1) = 0.0; 03183 P.at<double>(2,2) = 1.0; 03184 P.at<double>(2,3) = 0.0; 03185 } 03186 03187 void LinearLSTriangulation(Mat& dst, const Point3d& u, const Mat& P, const Point3d& u1, const Mat& P1) { 03188 //homogenous image point (u,v,1) 03189 //camera 1 matrix 03190 //homogenous image point in 2nd camera 03191 //camera 2 matrix 03192 03193 03194 //build matrix A for homogenous equation system Ax = 0 03195 //assume X = (x,y,z,1), for Linear-LS method 03196 //which turns it into a AX = B system, where A is 4x3, X is 3x1 and B is 4x1 03197 03198 Mat A(4, 3, CV_64FC1); 03199 03200 A.at<double>(0,0) = (double) u.x * P.at<double>(2,0) - P.at<double>(0,0); 03201 A.at<double>(0,1) = (double) u.x * P.at<double>(2,1) - P.at<double>(0,1); 03202 A.at<double>(0,2) = (double) u.x * P.at<double>(2,2) - P.at<double>(0,2); 03203 03204 A.at<double>(1,0) = (double) u.y * P.at<double>(2,0) - P.at<double>(1,0); 03205 A.at<double>(1,1) = (double) u.y * P.at<double>(2,1) - P.at<double>(1,1); 03206 A.at<double>(1,2) = (double) u.y * P.at<double>(2,2) - P.at<double>(1,2); 03207 03208 A.at<double>(2,0) = (double) u1.x * P1.at<double>(2,0) - P1.at<double>(0,0); 03209 A.at<double>(2,1) = (double) u1.x * P1.at<double>(2,1) - P1.at<double>(0,1); 03210 A.at<double>(2,2) = (double) u1.x * P1.at<double>(2,2) - P1.at<double>(0,2); 03211 03212 A.at<double>(3,0) = (double) u1.y * P1.at<double>(2,0) - P1.at<double>(1,0); 03213 A.at<double>(3,1) = (double) u1.y * P1.at<double>(2,1) - P1.at<double>(1,1); 03214 A.at<double>(3,2) = (double) u1.y * P1.at<double>(2,2) - P1.at<double>(1,2); 03215 03216 Mat B(4, 1, CV_64FC1); 03217 03218 B.at<double>(0,0) = -((double) u.x * P.at<double>(2,3) - P.at<double>(0,3)); 03219 B.at<double>(0,1) = -((double) u.y * P.at<double>(2,3) - P.at<double>(1,3)); 03220 B.at<double>(0,2) = -((double) u1.x * P1.at<double>(2,3) - P1.at<double>(0,3)); 03221 B.at<double>(0,3) = -((double) u1.y * P1.at<double>(2,3) - P1.at<double>(1,3)); 03222 03223 solve(A, B, dst, DECOMP_SVD); 03224 03225 } 03226 03227 void IterativeLinearLSTriangulation(Mat& dst, const Point3d& u, const Mat& P, const Point3d& u1, const Mat& P1) { 03228 03229 double wi = 1, wi1 = 1; 03230 int maxIterations = 10; //Hartley suggests 10 iterations at most 03231 03232 Mat X(4, 1, CV_64FC1), X_; 03233 03234 LinearLSTriangulation(X_, u, P, u1, P1); 03235 03236 X.at<double>(0,0) = X_.at<double>(0,0); 03237 X.at<double>(1,0) = X_.at<double>(1,0); 03238 X.at<double>(2,0) = X_.at<double>(2,0); 03239 X.at<double>(3,0) = 1.0; 03240 03241 for (int i=0; i<maxIterations; i++) { 03242 03243 //recalculate weights 03244 Mat p2x_m = P.row(2) * X; 03245 double p2x = p2x_m.at<double>(0, 0); 03246 03247 Mat p2x1_m = P1.row(2) * X; 03248 double p2x1 = p2x1_m.at<double>(0, 0); 03249 03250 //printf("%s << %f, %f, EPSILON = %f\n", __FUNCTION__, fabsf(wi - p2x), fabsf(wi1 - p2x1), EPSILON); 03251 03252 //breaking point 03253 if ((fabsf(wi - p2x) <= EPSILON) && (fabsf(wi1 - p2x1) <= EPSILON)) { 03254 //printf("%s << About to break...\n", __FUNCTION__); 03255 //cin.get(); 03256 break; 03257 } 03258 03259 wi = p2x; 03260 wi1 = p2x1; 03261 03262 //reweight equations and solve 03263 Mat A(4, 3, CV_64FC1); 03264 03265 A.at<double>(0, 0) = (u.x * P.at<double>(2,0) - P.at<double>(0,0))/wi; 03266 A.at<double>(0, 1) = (u.x*P.at<double>(2,1)-P.at<double>(0,1))/wi; 03267 A.at<double>(0, 2) = (u.x*P.at<double>(2,2)-P.at<double>(0,2))/wi; 03268 03269 A.at<double>(1, 0) = (u.y*P.at<double>(2,0)-P.at<double>(1,0))/wi; 03270 A.at<double>(1, 1) = (u.y*P.at<double>(2,1)-P.at<double>(1,1))/wi; 03271 A.at<double>(1, 2) = (u.y*P.at<double>(2,2)-P.at<double>(1,2))/wi; 03272 03273 A.at<double>(2, 0) = (u1.x*P1.at<double>(2,0)-P1.at<double>(0,0))/wi1; 03274 A.at<double>(2, 1) = (u1.x*P1.at<double>(2,1)-P1.at<double>(0,1))/wi1; 03275 A.at<double>(2, 2) = (u1.x*P1.at<double>(2,2)-P1.at<double>(0,2))/wi1; 03276 03277 A.at<double>(3, 0) = (u1.y*P1.at<double>(2,0)-P1.at<double>(1,0))/wi1; 03278 A.at<double>(3, 1) = (u1.y*P1.at<double>(2,1)-P1.at<double>(1,1))/wi1; 03279 A.at<double>(3, 2) = (u1.y*P1.at<double>(2,2)-P1.at<double>(1,2))/wi1; 03280 03281 Mat B(4, 1, CV_64FC1); 03282 03283 B.at<double>(0, 0) = -(u.x*P.at<double>(2,3) -P.at<double>(0,3))/wi; 03284 B.at<double>(1, 0) = -(u.y*P.at<double>(2,3) -P.at<double>(1,3))/wi; 03285 B.at<double>(2, 0) = -(u1.x*P1.at<double>(2,3) -P1.at<double>(0,3))/wi1; 03286 B.at<double>(3, 0) = -(u1.y*P1.at<double>(2,3) -P1.at<double>(1,3))/wi1; 03287 03288 //printf("%s << Solving decomposition...\n", __FUNCTION__); 03289 03290 solve(A, B, X_, DECOMP_SVD); 03291 03292 //printf("%s << Decomposition solved.\n", __FUNCTION__); 03293 03294 X.at<double>(0,0) = X_.at<double>(0,0); 03295 X.at<double>(1,0) = X_.at<double>(1,0); 03296 X.at<double>(2,0) = X_.at<double>(2,0); 03297 X.at<double>(3,0) = 1.0; 03298 03299 } 03300 03301 X.copyTo(dst); 03302 03303 } 03304 03305 void getWandZ(Mat& W, Mat& Winv, Mat& Z) { 03306 W = Mat::zeros(3, 3, CV_64FC1); 03307 03308 W.at<double>(0,0) = 0.0; 03309 W.at<double>(0,1) = -1.0; 03310 W.at<double>(0,2) = 0.0; 03311 03312 W.at<double>(1,0) = 1.0; 03313 W.at<double>(1,1) = 0.0; 03314 W.at<double>(1,2) = 0.0; 03315 03316 W.at<double>(2,0) = 0.0; 03317 W.at<double>(2,1) = 0.0; 03318 W.at<double>(2,2) = 1.0; 03319 03320 Winv = Mat::zeros(3, 3, CV_64FC1); 03321 03322 Winv.at<double>(0,0) = 0.0; 03323 Winv.at<double>(0,1) = 1.0; 03324 Winv.at<double>(0,2) = 0.0; 03325 03326 Winv.at<double>(1,0) = -1.0; 03327 Winv.at<double>(1,1) = 0.0; 03328 Winv.at<double>(1,2) = 0.0; 03329 03330 Winv.at<double>(2,0) = 0.0; 03331 Winv.at<double>(2,1) = 0.0; 03332 Winv.at<double>(2,2) = 1.0; 03333 03334 Z = Mat::zeros(3, 3, CV_64FC1); 03335 03336 Z.at<double>(0,1) = 1.0; 03337 Z.at<double>(1,0) = -1.0; 03338 } 03339 03340 void findP1Matrix(Mat& P1, const Mat& R, const Mat& t) { 03341 //Mat W, Winv, Z; 03342 03343 //getWandZ(W, Z); 03344 //Winv = W.inv(); 03345 03346 //R = svd.u * W * svd.vt; //HZ 9.19 03347 //t = svd.u.col(2); //u3 03348 03349 P1 = Mat(3, 4, CV_64FC1); 03350 03351 P1.at<double>(0,0) = R.at<double>(0,0); 03352 P1.at<double>(0,1) = R.at<double>(0,1); 03353 P1.at<double>(0,2) = R.at<double>(0,2); 03354 P1.at<double>(0,3) = t.at<double>(0,0); 03355 03356 P1.at<double>(1,0) = R.at<double>(1,0); 03357 P1.at<double>(1,1) = R.at<double>(1,1); 03358 P1.at<double>(1,2) = R.at<double>(1,2); 03359 P1.at<double>(1,3) = t.at<double>(1,0); 03360 03361 P1.at<double>(2,0) = R.at<double>(2,0); 03362 P1.at<double>(2,1) = R.at<double>(2,1); 03363 P1.at<double>(2,2) = R.at<double>(2,2); 03364 P1.at<double>(2,3) = t.at<double>(2,0); 03365 } 03366 03367 void Triangulate(const Point2f& pt1, const Point2f& pt2, const Mat& K, const Mat& Kinv, const Mat& P1, const Mat& P2, Point3d& xyzPoint, bool debug) { 03368 03369 Mat C1, C2; 03370 projectionToTransformation(P1, C1); 03371 projectionToTransformation(P2, C2); 03372 03373 // Relative 03374 Mat P0, PR, C0, CR; 03375 initializeP0(P0); 03376 projectionToTransformation(P0, C0); 03377 CR = C2 * C1.inv(); 03378 transformationToProjection(CR, PR); 03379 03380 Point3d xyzPoint_R; 03381 03382 if (debug) { 03383 cout << __FUNCTION__ << " << Provided = " << endl; 03384 cout << "P1 = " << P1 << endl; 03385 cout << "P2 = " << P2 << endl; 03386 } 03387 03388 Point2f kp = pt1; 03389 Point3d u(kp.x, kp.y, 1.0); 03390 03391 Mat um = Kinv * Mat(u); 03392 03393 u.x = um.at<double>(0, 0); 03394 u.y = um.at<double>(1, 0); 03395 u.z = um.at<double>(2, 0); 03396 03397 Point2f kp1 = pt2; 03398 Point3d u1(kp1.x, kp1.y,1.0); 03399 Mat um1 = Kinv * Mat(u1); 03400 03401 u1.x = um1.at<double>(0, 0); 03402 u1.y = um1.at<double>(1, 0); 03403 u1.z = um1.at<double>(2, 0); 03404 03405 if (debug) { 03406 cout << __FUNCTION__ << " << Used = " << endl; 03407 cout << "P0 = " << P0 << endl; 03408 cout << "PR = " << PR << endl; 03409 } 03410 03411 Mat X; 03412 //LinearLSTriangulation(X, u, P0, u1, PR); 03413 IterativeLinearLSTriangulation(X, u, P0, u1, PR); // switched from u then u1 03414 03415 xyzPoint_R = Point3d( X.at<double>(0, 0), X.at<double>(1, 0), X.at<double>(2, 0) ); 03416 03417 Mat A(4, 1, CV_64FC1), B(4, 1, CV_64FC1); 03418 03419 A.at<double>(0,0) = xyzPoint_R.x; 03420 A.at<double>(1,0) = xyzPoint_R.y; 03421 A.at<double>(2,0) = xyzPoint_R.z; 03422 A.at<double>(3,0) = 1.0; 03423 03424 B = C1 * A; 03425 03426 xyzPoint.x = B.at<double>(0,0) / B.at<double>(3,0); 03427 xyzPoint.y = B.at<double>(1,0) / B.at<double>(3,0); 03428 xyzPoint.z = B.at<double>(2,0) / B.at<double>(3,0); 03429 03430 if (debug) { 03431 printf("%s << u = (%f, %f, %f)\n", __FUNCTION__, u.x, u.y, u.z); 03432 printf("%s << u1 = (%f, %f, %f)\n", __FUNCTION__, u1.x, u1.y, u1.z); 03433 printf("%s << xyzPoint_R = (%f, %f, %f)\n", __FUNCTION__, xyzPoint_R.x, xyzPoint_R.y, xyzPoint_R.z); 03434 printf("%s << xyzPoint = (%f, %f, %f)\n", __FUNCTION__, xyzPoint.x, xyzPoint.y, xyzPoint.z); 03435 cin.get(); 03436 } 03437 03438 03439 } 03440 03441 void TriangulatePoints(const vector<Point2f>& pt_set1, 03442 const vector<Point2f>& pt_set2, 03443 const Mat& K, 03444 const Mat& Kinv, 03445 const Mat& P, 03446 const Mat& P1, 03447 vector<Point3d>& pointcloud, 03448 vector<Point2f>& correspImg1Pt) 03449 { 03450 03451 pointcloud.clear(); 03452 correspImg1Pt.clear(); 03453 03454 Point3d point_3; 03455 03456 for (unsigned int iii = 0; iii < pt_set1.size(); iii++) { 03457 03458 Triangulate(pt_set1.at(iii), pt_set2.at(iii), K, Kinv, P, P1, point_3, false); 03459 03460 pointcloud.push_back(point_3); 03461 correspImg1Pt.push_back(pt_set1[iii]); 03462 } 03463 } 03464 03465 void findCentroid(vector<featureTrack>& tracks, Point3d& centroid, Point3d& stdDeviation) { 03466 03467 unsigned int triangulatedPoints = 0; 03468 03469 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 03470 if (tracks.at(iii).isTriangulated) { 03471 triangulatedPoints++; 03472 } 03473 } 03474 03475 printf("%s << triangulatedPoints = %d\n", __FUNCTION__, triangulatedPoints); 03476 03477 centroid = Point3d(0.0, 0.0, 0.0); 03478 stdDeviation = Point3d(0.0, 0.0, 0.0); 03479 03480 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 03481 if (tracks.at(iii).isTriangulated) { 03482 centroid.x += (tracks.at(iii).get3dLoc().x / ((double) triangulatedPoints)); 03483 centroid.y += (tracks.at(iii).get3dLoc().y / ((double) triangulatedPoints)); 03484 centroid.z += (tracks.at(iii).get3dLoc().z / ((double) triangulatedPoints)); 03485 } 03486 } 03487 03488 for (unsigned int iii = 0; iii < tracks.size(); iii++) { 03489 if (tracks.at(iii).isTriangulated) { 03490 stdDeviation.x += (pow((tracks.at(iii).get3dLoc().x - centroid.x), 2.0) / ((double) triangulatedPoints)); 03491 stdDeviation.y += (pow((tracks.at(iii).get3dLoc().y - centroid.y), 2.0) / ((double) triangulatedPoints)); 03492 stdDeviation.z += (pow((tracks.at(iii).get3dLoc().z - centroid.z), 2.0) / ((double) triangulatedPoints)); 03493 } 03494 03495 } 03496 03497 stdDeviation.x = pow(stdDeviation.x, 0.5); 03498 stdDeviation.y = pow(stdDeviation.y, 0.5); 03499 stdDeviation.z = pow(stdDeviation.z, 0.5); 03500 03501 } 03502