Skip to content

Commit c3fce19

Browse files
committed
Final touches
1 parent 314b466 commit c3fce19

File tree

2 files changed

+59
-78
lines changed

2 files changed

+59
-78
lines changed

stereo/Stereography.cpp

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ bool FindFundamentalMatrixWithRANSAC(const vector<pair<Feature, Feature>>& match
238238
}
239239
if (localInliers > 0)
240240
avgError /= localInliers;
241-
//cout << avgError << endl;
241+
242242
if (localInliers > MIN_NUM_INLIERS && avgError < minError)
243243
{
244244
minError = avgError;
@@ -346,7 +346,6 @@ bool DecomposeEssentialMatrix(
346346
t(2) = U(2, 2);
347347

348348
// we either need t or -t
349-
350349
// t can also be t = UWDU.transpose()
351350
// or t = UZU.transpose, z = -W without the 1 in the borrom right
352351

@@ -417,15 +416,10 @@ bool Triangulate(float& depth0, float& depth1, Vector3f& x, Vector3f& xprime, Ma
417416

418417
float g = c * c - b * e;
419418
if (fabs(g) < 1e-9) return false;
420-
//{
421-
// do this the other way
422-
// turns out this doesn't work.
423-
// This gets degenerate solutions when the epipolar lines are parallel
424-
// Need to compute an example with some rotation
425-
//}
419+
426420
float d0 = 0;
427421
float d1 = 0;
428-
if (fabs(c) < 1e-9)// return false;
422+
if (fabs(c) < 1e-9)
429423
{
430424
d1 = (a * c - b * d) / (c * c - b * e);
431425
d0 = (c * d1 - a) / b;
@@ -461,10 +455,6 @@ bool Triangulate(float& depth0, float& depth1, Vector3f& x, Vector3f& xprime, Ma
461455
by virtue of being a rotation matrix. Conveniently, RQ decomposition decomposes a matrix A into
462456
two components, one being upper-triangular - R - and the other being orthogonal. While every rotation
463457
is orthogonal, it's also true that every orthogonal matrix is a rotation.
464-
465-
Questions:
466-
- is this how the translation is computed? What if it is just the final column?
467-
- Do we need to scale K? Divide by final element?
468458
*/
469459
void DecomposeProjectiveMatrixIntoKAndE(const MatrixXf& P, Matrix3f& K, Matrix3f& E)
470460
{
@@ -517,7 +507,6 @@ void DecomposeProjectiveMatrixIntoKAndE(const MatrixXf& P, Matrix3f& K, Matrix3f
517507
compute the necessary rotations that transform the images
518508
into the rectified versions
519509
520-
521510
Output: both homographies
522511
*/
523512
void ComputeRectificationRotations(
@@ -553,34 +542,25 @@ void ComputeRectificationRotations(
553542
// We get the logarithm of the rotation to put this in the
554543
// Lie algebra space, halve this vector, and then take the exponential
555544
// to convert back to the group space
556-
cout << "R total:" << endl << R1 << endl;
557545
Vector3f rotation = SO3_log(R1);
558-
cout << "log:" << endl << rotation << endl;
559546
rotation /= 2;
560547
Matrix3f R_half = SO3_exp(rotation);
561548

562-
cout << "R_half: " << endl << R_half << endl;
563-
564-
// TODO: This might need to be reversed
565-
R_0 = R_half;// .transpose();
566-
R_1 = R_half.transpose();
567-
568-
// Z axis and Y axis are flipped???
549+
R_0 = R_half.transpose();
550+
R_1 = R_half;// .transpose();
569551

570552
// Now build the rotation that makes the baseline the x-axis
571553
Vector3f rx = t / t.norm();
572-
cout << "rx " << endl << rx << endl;
573554
Vector3f ry = Vector3f(0, 0, 1).cross(rx);
574555
ry /= ry.norm();
575-
cout << "ry " << endl << ry << endl;
576556
Vector3f rz = rx.cross(ry);
577557
// make sure everything is normalised
578558
rz /= rz.norm();
579-
cout << "rz " << endl << rz << endl;
559+
580560
Matrix3f R_baseline;
581561
R_baseline.row(0) = rx;
582-
R_baseline.row(1) = -rz;// ry;
583-
R_baseline.row(2) = ry;// rz;
562+
R_baseline.row(1) = ry;
563+
R_baseline.row(2) = rz;
584564
R_baseline << rx(0), rx(1), rx(2),
585565
ry(0), ry(1), ry(2),
586566
rz(0), rz(1), rz(2);
@@ -592,7 +572,6 @@ void ComputeRectificationRotations(
592572
/*
593573
Given a homography from the original to the rectified image,
594574
and an image, compute the rectified image using projection.
595-
596575
*/
597576
// Helper
598577
uchar BilinearInterpolatePixel(const Mat& img, const float& x, const float& y)
@@ -624,9 +603,12 @@ void RectifyImage(
624603
// If it is there, bilinearly interpolate the value of that sub-pixel location
625604
// In the original Mat, if this clashes with a point in the original image,
626605
// take the average and place that there
606+
627607
// TODO: multithread
628608
// To multithread, just use openmp on the outer for loop or something
629609
// and cap threads at a reasonable number
610+
611+
// Iterate over the size of the original image
630612
for (unsigned int y = 0; y < rectified.rows; ++y)
631613
{
632614
for (unsigned int x = 0; x < rectified.cols; ++x)
@@ -668,7 +650,44 @@ Mat ComputeDepthImage(
668650
_In_ const Mat& img0,
669651
_In_ const Mat& img1)
670652
{
671-
return img0;
653+
// This assumes vertical alignment
654+
// and the same image size
655+
if (img0.cols != img1.cols || img0.rows != img1.rows)
656+
{
657+
cout << "Cannot compute depth!" << endl;
658+
return Mat(Size(0,0), CV_8U);
659+
}
660+
661+
// Depth Image
662+
Mat depth = Mat::zeros(Size(img0.cols, img0.rows), CV_8U);
663+
664+
for (int y = 0; y < img0.rows; ++y)
665+
{
666+
for (int x = 0; x < img0.cols; ++x)
667+
{
668+
// For each pixel, find the best-matching pixel in the same row in the other image
669+
uchar pixel0 = img0.at<uchar>(y,x);
670+
if (pixel0 == 0) continue;
671+
int xBestMatch = 0;
672+
int distance = 255; // biggest distance any two pixel values can be
673+
for (int x1 = 0; x1 < img1.cols; ++x1)
674+
{
675+
uchar pixel1 = img1.at<uchar>(y,x1);
676+
if (pixel1 == 0) continue;
677+
if (abs(pixel1 - pixel0) < distance)
678+
{
679+
distance = abs(pixel1 - pixel0);
680+
xBestMatch = x1;
681+
}
682+
}
683+
684+
// Now that we have the best match
685+
// For now, directly set depth to x distance
686+
depth.at<uchar>(y,x) = abs(xBestMatch -x);
687+
}
688+
}
689+
690+
return depth;
672691
}
673692

674693
/*

stereo/main.cpp

Lines changed: 10 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
#include "Stereography.h"
2020
#include "Estimation.h"
2121
#include <stdlib.h>
22-
//#include <GL/glew.h> // This must appear before freeglut.h
23-
//#include <GL/freeglut.h>
2422
#include <omp.h>
2523

2624
using namespace std;
@@ -34,6 +32,7 @@ using namespace Eigen;
3432
//#define DEBUG_MATCHES
3533
//#define DEBUG_FUNDAMENTAL
3634
//#define DEBUG_ESSENTIAL_MATRIX
35+
#define DEBUG_RECTIFICATION
3736

3837
#define ROTATION_STEP 0.2f
3938
#define TRANSLATION_STEP 0.1f
@@ -75,12 +74,7 @@ using namespace Eigen;
7574
This will be computed using Peter Lindstrom's algorithm
7675
7776
Rectification
78-
79-
80-
TODO:
81-
- rectification
82-
- write up Lindstrom
83-
- lovely comments
77+
This is computed using the extrinsics of the cameras
8478
8579
*/
8680

@@ -121,26 +115,6 @@ void DebugEpipolarLines(
121115
// Main
122116
int main(int argc, char** argv)
123117
{
124-
/*
125-
// unit testing SO3
126-
Matrix3f R;
127-
R << 1, 0, 0,
128-
0, 0, -1,
129-
0, 1, 0;
130-
cout << "R total:" << endl << R << endl;
131-
Vector3f rotation = SO3_log(R);
132-
133-
cout << "log: " << endl << rotation << endl;
134-
rotation /= 2;
135-
Matrix3f R_half = SO3_exp(rotation);
136-
137-
cout << "R_half: " << endl << R_half << endl;
138-
// This should return exactly the same thign
139-
140-
return 0;*/
141-
142-
143-
144118
// first arg is the folder containing all the images
145119
if (argc < 2 || strcmp(argv[1], "-h") == 0)
146120
{
@@ -320,8 +294,6 @@ int main(int argc, char** argv)
320294
Vector3f pointXPrime = stereo.img1.K.inverse() * Vector3f(xprime.x, xprime.y, 1);
321295
float d0 = 0;
322296
float d1 = 0;
323-
// TODO - do I need to do this the other way?
324-
// TODO - normalise or no? No?
325297
Matrix3f Einverse = stereo.E.inverse();
326298
if (!Triangulate(d0, d1, pointX, pointXPrime, stereo.E))
327299
{
@@ -330,9 +302,6 @@ int main(int argc, char** argv)
330302
continue;
331303
}
332304

333-
// Is this depth in first frame or second frame?
334-
// There is also a bug where depth is negative sometimes.
335-
// This can happen from triangulation
336305
d0 = abs(d0);
337306
d1 = abs(d1);
338307
match.first.depth = abs(d0);
@@ -387,15 +356,9 @@ int main(int argc, char** argv)
387356
imread(stereo.img2.filename, 0),
388357
R0, R1);
389358

390-
cout << "Rotation for image 0: " << endl << R0 << endl;
391-
cout << "Rotation for image 1: " << endl << R1 << endl;
392-
// the rotations have y and z flipped
393-
// Also z is negative
394-
// why is this giving a weird rotation? Like it's correct but it also isn't?
395-
// R_half is flipping the axes and I'm not sure why cos the inter-camera rotation
396-
// should be tiny
397-
398-
// Apply to images
359+
// Apply rotation to images
360+
// Sometimes the rectified images don't fit nicely within the original image
361+
// frames given. Here I don't tackle that, but it can be necessary
399362
Mat rectified_img1 = Mat::zeros(Size(stereo.img1.width, stereo.img1.height), CV_8U);
400363
RectifyImage(imread(stereo.img1.filename, 0),
401364
rectified_img1,
@@ -405,21 +368,20 @@ int main(int argc, char** argv)
405368
rectified_img2,
406369
stereo.img2.K* R1 * stereo.img2.K.inverse());
407370

408-
// Need to give images that accomodate the homography
409-
// and then also need to vertically align the images
410-
411-
// DEBUG
371+
#ifdef DEBUG_RECTIFICATION
412372
// Show rectified images
413373
imshow("rectified 0", rectified_img1);
414374
imshow("rectified 1", rectified_img2);
415375
waitKey(0);
376+
#endif
416377

417378
// Compute depth map
379+
// This doesn't work
418380
Mat depth = ComputeDepthImage(rectified_img1, rectified_img2);
419381

420382
// Show depth map
421-
422-
// save depth map?
383+
imshow("depth", depth);
384+
waitKey(0);
423385
#endif
424386

425387
return 0;

0 commit comments

Comments
 (0)