1 |
//
|
1 |
//
|
2 |
// Three Frequency Phase Shifting using the Heterodyne Principle
|
2 |
// Three Frequency Phase Shifting using the Heterodyne Principle
|
3 |
//
|
3 |
//
|
4 |
// This implementation follows "Reich, Ritter, Thesing, White light heterodyne principle for 3D-measurement", SPIE (1997)
|
4 |
// This implementation follows "Reich, Ritter, Thesing, White light heterodyne principle for 3D-measurement", SPIE (1997)
|
5 |
//
|
5 |
//
|
6 |
// The number of periods in the First and Second frequencies can be chosen freely, but small changes can have a considerable impact on quality.
|
6 |
// The number of periods in the First and Second frequencies can be chosen freely, but small changes can have a considerable impact on quality.
|
7 |
// The number of phase shifts can be chosen freely (min. 3), and higher values reduce the effects of image noise. They also allow us to filter bad points based on energy at non-First frequencies.
|
7 |
// The number of phase shifts can be chosen freely (min. 3), and higher values reduce the effects of image noise. They also allow us to filter bad points based on energy at non-First frequencies.
|
8 |
//
|
8 |
//
|
9 |
|
9 |
|
10 |
|
10 |
|
11 |
#include "AlgorithmPhaseShiftThreeFreq.h"
|
11 |
#include "AlgorithmPhaseShiftThreeFreq.h"
|
12 |
#include <math.h>
|
12 |
#include <math.h>
|
13 |
|
13 |
|
14 |
#include "cvtools.h"
|
14 |
#include "cvtools.h"
|
15 |
#include "algorithmtools.h"
|
15 |
#include "algorithmtools.h"
|
16 |
|
16 |
|
17 |
static unsigned int nStepsFirst = 8; // number of shifts/steps in First
|
17 |
static unsigned int nStepsFirst = 8; // number of shifts/steps in First
|
18 |
static unsigned int nStepsSecond = 8; // number of shifts/steps in Second
|
18 |
static unsigned int nStepsSecond = 8; // number of shifts/steps in Second
|
19 |
static unsigned int nStepsThird = 8; // number of shifts/steps in Third
|
19 |
static unsigned int nStepsThird = 8; // number of shifts/steps in Third
|
20 |
static float nPeriodsFirst = 24; // First period
|
20 |
static float nPeriodsFirst = 24; // First period
|
21 |
static float nPeriodsSecond = 30; // First period
|
21 |
static float nPeriodsSecond = 30; // First period
|
22 |
|
22 |
|
23 |
AlgorithmPhaseShiftThreeFreq::AlgorithmPhaseShiftThreeFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
|
23 |
AlgorithmPhaseShiftThreeFreq::AlgorithmPhaseShiftThreeFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
|
24 |
|
24 |
|
25 |
// Set N
|
25 |
// Set N
|
26 |
N = 2+nStepsFirst+nStepsSecond+nStepsThird;
|
26 |
N = 2+nStepsFirst+nStepsSecond+nStepsThird;
|
27 |
|
27 |
|
28 |
// Determine the third number of periods to fulfill the heterodyne condition
|
28 |
// Determine the third number of periods to fulfill the heterodyne condition
|
29 |
float nPeriodsThird = 1 + 2*nPeriodsSecond - nPeriodsFirst;
|
29 |
float nPeriodsThird = 1 + 2*nPeriodsSecond - nPeriodsFirst;
|
30 |
|
30 |
|
31 |
// all on pattern
|
31 |
// all on pattern
|
32 |
cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
|
32 |
cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
|
33 |
patterns.push_back(allOn);
|
33 |
patterns.push_back(allOn);
|
34 |
|
34 |
|
35 |
// all off pattern
|
35 |
// all off pattern
|
36 |
cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
|
36 |
cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
|
37 |
patterns.push_back(allOff);
|
37 |
patterns.push_back(allOff);
|
38 |
|
38 |
|
39 |
// Precompute encoded patterns
|
39 |
// Precompute encoded patterns
|
40 |
|
40 |
|
41 |
// First encoding patterns
|
41 |
// First encoding patterns
|
42 |
for(unsigned int i=0; i<nStepsFirst; i++){
|
42 |
for(unsigned int i=0; i<nStepsFirst; i++){
|
43 |
float phase = 2.0*CV_PI/nStepsFirst * i;
|
43 |
float phase = 2.0*CV_PI/nStepsFirst * i;
|
44 |
float pitch = screenCols/nPeriodsFirst;
|
44 |
float pitch = screenCols/nPeriodsFirst;
|
45 |
cv::Mat patternI(1,1,CV_8U);
|
45 |
cv::Mat patternI(1,1,CV_8U);
|
46 |
patternI = computePhaseVector(screenCols, phase, pitch);
|
46 |
patternI = computePhaseVector(screenCols, phase, pitch);
|
47 |
patterns.push_back(patternI.t());
|
47 |
patterns.push_back(patternI.t());
|
48 |
}
|
48 |
}
|
49 |
|
49 |
|
50 |
// Second encoding patterns
|
50 |
// Second encoding patterns
|
51 |
for(unsigned int i=0; i<nStepsSecond; i++){
|
51 |
for(unsigned int i=0; i<nStepsSecond; i++){
|
52 |
float phase = 2.0*CV_PI/nStepsSecond * i;
|
52 |
float phase = 2.0*CV_PI/nStepsSecond * i;
|
53 |
float pitch = screenCols/nPeriodsSecond;
|
53 |
float pitch = screenCols/nPeriodsSecond;
|
54 |
cv::Mat patternI(1,1,CV_8U);
|
54 |
cv::Mat patternI(1,1,CV_8U);
|
55 |
patternI = computePhaseVector(screenCols, phase, pitch);
|
55 |
patternI = computePhaseVector(screenCols, phase, pitch);
|
56 |
patterns.push_back(patternI.t());
|
56 |
patterns.push_back(patternI.t());
|
57 |
}
|
57 |
}
|
58 |
// Third encoding patterns
|
58 |
// Third encoding patterns
|
59 |
for(unsigned int i=0; i<nStepsThird; i++){
|
59 |
for(unsigned int i=0; i<nStepsThird; i++){
|
60 |
float phase = 2.0*CV_PI/nStepsThird * i;
|
60 |
float phase = 2.0*CV_PI/nStepsThird * i;
|
61 |
float pitch = screenCols/nPeriodsThird;
|
61 |
float pitch = screenCols/nPeriodsThird;
|
62 |
cv::Mat patternI(1,1,CV_8U);
|
62 |
cv::Mat patternI(1,1,CV_8U);
|
63 |
patternI = computePhaseVector(screenCols, phase, pitch);
|
63 |
patternI = computePhaseVector(screenCols, phase, pitch);
|
64 |
patterns.push_back(patternI.t());
|
64 |
patterns.push_back(patternI.t());
|
65 |
}
|
65 |
}
|
66 |
|
66 |
|
67 |
}
|
67 |
}
|
68 |
|
68 |
|
69 |
cv::Mat AlgorithmPhaseShiftThreeFreq::getEncodingPattern(unsigned int depth){
|
69 |
cv::Mat AlgorithmPhaseShiftThreeFreq::getEncodingPattern(unsigned int depth){
|
70 |
return patterns[depth];
|
70 |
return patterns[depth];
|
71 |
}
|
71 |
}
|
72 |
|
72 |
|
73 |
void AlgorithmPhaseShiftThreeFreq::get3DPoints(SMCalibrationParameters calibration, const std::vector<cv::Mat>& frames0, const std::vector<cv::Mat>& frames1, std::vector<cv::Point3f>& Q, std::vector<cv::Vec3b>& color){
|
73 |
void AlgorithmPhaseShiftThreeFreq::get3DPoints(const SMCalibrationParameters & calibration, const std::vector<cv::Mat>& frames0, const std::vector<cv::Mat>& frames1, std::vector<cv::Point3f>& Q, std::vector<cv::Vec3b>& color){
|
74 |
|
74 |
|
75 |
assert(frames0.size() == N);
|
75 |
assert(frames0.size() == N);
|
76 |
assert(frames1.size() == N);
|
76 |
assert(frames1.size() == N);
|
77 |
|
77 |
|
78 |
int frameRows = frames0[0].rows;
|
78 |
int frameRows = frames0[0].rows;
|
79 |
int frameCols = frames0[0].cols;
|
79 |
int frameCols = frames0[0].cols;
|
80 |
|
80 |
|
81 |
float nPeriodsThird = 1 + 2*nPeriodsSecond - nPeriodsFirst;
|
81 |
float nPeriodsThird = 1 + 2*nPeriodsSecond - nPeriodsFirst;
|
82 |
|
82 |
|
83 |
|
83 |
|
84 |
// Rectifying homographies (rotation+projections)
|
84 |
// Rectifying homographies (rotation+projections)
|
85 |
cv::Size frameSize(frameCols, frameRows);
|
85 |
cv::Size frameSize(frameCols, frameRows);
|
86 |
cv::Mat R, T;
|
86 |
cv::Mat R, T;
|
87 |
// stereoRectify segfaults unless R is double precision
|
87 |
// stereoRectify segfaults unless R is double precision
|
88 |
cv::Mat(calibration.R1).convertTo(R, CV_64F);
|
88 |
cv::Mat(calibration.R1).convertTo(R, CV_64F);
|
89 |
cv::Mat(calibration.T1).convertTo(T, CV_64F);
|
89 |
cv::Mat(calibration.T1).convertTo(T, CV_64F);
|
90 |
cv::Mat R0, R1, P0, P1, QRect;
|
90 |
cv::Mat R0, R1, P0, P1, QRect;
|
91 |
cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
|
91 |
cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
|
92 |
|
92 |
|
93 |
// Interpolation maps (lens distortion and rectification)
|
93 |
// Interpolation maps (lens distortion and rectification)
|
94 |
cv::Mat map0X, map0Y, map1X, map1Y;
|
94 |
cv::Mat map0X, map0Y, map1X, map1Y;
|
95 |
cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
|
95 |
cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
|
96 |
cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
|
96 |
cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
|
97 |
|
97 |
|
98 |
|
98 |
|
99 |
// Gray-scale and remap
|
99 |
// Gray-scale and remap
|
100 |
std::vector<cv::Mat> frames0Rect(N);
|
100 |
std::vector<cv::Mat> frames0Rect(N);
|
101 |
std::vector<cv::Mat> frames1Rect(N);
|
101 |
std::vector<cv::Mat> frames1Rect(N);
|
102 |
for(unsigned int i=0; i<N; i++){
|
102 |
for(unsigned int i=0; i<N; i++){
|
103 |
cv::Mat temp;
|
103 |
cv::Mat temp;
|
104 |
cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
|
104 |
cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
|
105 |
cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
|
105 |
cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
|
106 |
cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
|
106 |
cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
|
107 |
cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
|
107 |
cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
|
108 |
}
|
108 |
}
|
109 |
|
109 |
|
110 |
// Decode camera0
|
110 |
// Decode camera0
|
111 |
std::vector<cv::Mat> frames0First(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsFirst);
|
111 |
std::vector<cv::Mat> frames0First(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsFirst);
|
112 |
std::vector<cv::Mat> frames0Second(frames0Rect.begin()+2+nStepsFirst, frames0Rect.end()-nStepsThird);
|
112 |
std::vector<cv::Mat> frames0Second(frames0Rect.begin()+2+nStepsFirst, frames0Rect.end()-nStepsThird);
|
113 |
std::vector<cv::Mat> frames0Third(frames0Rect.end()-nStepsThird, frames0Rect.end());
|
113 |
std::vector<cv::Mat> frames0Third(frames0Rect.end()-nStepsThird, frames0Rect.end());
|
114 |
|
114 |
|
115 |
std::vector<cv::Mat> F0First = getDFTComponents(frames0First);
|
115 |
std::vector<cv::Mat> F0First = getDFTComponents(frames0First);
|
116 |
cv::Mat up0First;
|
116 |
cv::Mat up0First;
|
117 |
cv::phase(F0First[2], -F0First[3], up0First);
|
117 |
cv::phase(F0First[2], -F0First[3], up0First);
|
118 |
std::vector<cv::Mat> F0Second = getDFTComponents(frames0Second);
|
118 |
std::vector<cv::Mat> F0Second = getDFTComponents(frames0Second);
|
119 |
cv::Mat up0Second;
|
119 |
cv::Mat up0Second;
|
120 |
cv::phase(F0Second[2], -F0Second[3], up0Second);
|
120 |
cv::phase(F0Second[2], -F0Second[3], up0Second);
|
121 |
std::vector<cv::Mat> F0Third = getDFTComponents(frames0Third);
|
121 |
std::vector<cv::Mat> F0Third = getDFTComponents(frames0Third);
|
122 |
cv::Mat up0Third;
|
122 |
cv::Mat up0Third;
|
123 |
cv::phase(F0Third[2], -F0Third[3], up0Third);
|
123 |
cv::phase(F0Third[2], -F0Third[3], up0Third);
|
124 |
|
124 |
|
125 |
cv::Mat up0FS = up0Second - up0First;
|
125 |
cv::Mat up0FS = up0Second - up0First;
|
126 |
up0FS = cvtools::modulo(up0FS, 2.0*CV_PI);
|
126 |
up0FS = cvtools::modulo(up0FS, 2.0*CV_PI);
|
127 |
|
127 |
|
128 |
cv::Mat up0ST = up0Third - up0Second;
|
128 |
cv::Mat up0ST = up0Third - up0Second;
|
129 |
up0ST = cvtools::modulo(up0ST, 2.0*CV_PI);
|
129 |
up0ST = cvtools::modulo(up0ST, 2.0*CV_PI);
|
130 |
|
130 |
|
131 |
cv::Mat up0FST = up0ST - up0FS;
|
131 |
cv::Mat up0FST = up0ST - up0FS;
|
132 |
up0FST = cvtools::modulo(up0FST, 2.0*CV_PI);
|
132 |
up0FST = cvtools::modulo(up0FST, 2.0*CV_PI);
|
133 |
|
133 |
|
134 |
cv::Mat up0F = unwrapWithCue(up0First, up0FST, nPeriodsFirst);
|
134 |
cv::Mat up0F = unwrapWithCue(up0First, up0FST, nPeriodsFirst);
|
135 |
cv::Mat up0S = unwrapWithCue(up0Second, up0FST, nPeriodsSecond);
|
135 |
cv::Mat up0S = unwrapWithCue(up0Second, up0FST, nPeriodsSecond);
|
136 |
cv::Mat up0T = unwrapWithCue(up0Third, up0FST, nPeriodsThird);
|
136 |
cv::Mat up0T = unwrapWithCue(up0Third, up0FST, nPeriodsThird);
|
137 |
cv::Mat up0Mean = 1.0/3.0 * (up0F + up0S + up0T);
|
137 |
cv::Mat up0Mean = 1.0/3.0 * (up0F + up0S + up0T);
|
138 |
cv::Mat up0Range = cv::max(up0F, cv::max(up0S, up0T)) - cv::min(up0F, cv::min(up0S, up0T));
|
138 |
cv::Mat up0Range = cv::max(up0F, cv::max(up0S, up0T)) - cv::min(up0F, cv::min(up0S, up0T));
|
139 |
cv::Mat up0 = up0Mean * screenCols/(2.0*CV_PI);
|
139 |
cv::Mat up0 = up0Mean * screenCols/(2.0*CV_PI);
|
140 |
|
140 |
|
141 |
cv::Mat amplitude0;
|
141 |
cv::Mat amplitude0;
|
142 |
cv::magnitude(F0First[2], -F0First[3], amplitude0);
|
142 |
cv::magnitude(F0First[2], -F0First[3], amplitude0);
|
143 |
|
143 |
|
144 |
// Decode camera1
|
144 |
// Decode camera1
|
145 |
std::vector<cv::Mat> frames1First(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsFirst);
|
145 |
std::vector<cv::Mat> frames1First(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsFirst);
|
146 |
std::vector<cv::Mat> frames1Second(frames1Rect.begin()+2+nStepsFirst, frames1Rect.end()-nStepsThird);
|
146 |
std::vector<cv::Mat> frames1Second(frames1Rect.begin()+2+nStepsFirst, frames1Rect.end()-nStepsThird);
|
147 |
std::vector<cv::Mat> frames1Third(frames1Rect.end()-nStepsThird, frames1Rect.end());
|
147 |
std::vector<cv::Mat> frames1Third(frames1Rect.end()-nStepsThird, frames1Rect.end());
|
148 |
|
148 |
|
149 |
std::vector<cv::Mat> F1First = getDFTComponents(frames1First);
|
149 |
std::vector<cv::Mat> F1First = getDFTComponents(frames1First);
|
150 |
cv::Mat up1First;
|
150 |
cv::Mat up1First;
|
151 |
cv::phase(F1First[2], -F1First[3], up1First);
|
151 |
cv::phase(F1First[2], -F1First[3], up1First);
|
152 |
std::vector<cv::Mat> F1Second = getDFTComponents(frames1Second);
|
152 |
std::vector<cv::Mat> F1Second = getDFTComponents(frames1Second);
|
153 |
cv::Mat up1Second;
|
153 |
cv::Mat up1Second;
|
154 |
cv::phase(F1Second[2], -F1Second[3], up1Second);
|
154 |
cv::phase(F1Second[2], -F1Second[3], up1Second);
|
155 |
std::vector<cv::Mat> F1Third = getDFTComponents(frames1Third);
|
155 |
std::vector<cv::Mat> F1Third = getDFTComponents(frames1Third);
|
156 |
cv::Mat up1Third;
|
156 |
cv::Mat up1Third;
|
157 |
cv::phase(F1Third[2], -F1Third[3], up1Third);
|
157 |
cv::phase(F1Third[2], -F1Third[3], up1Third);
|
158 |
|
158 |
|
159 |
cv::Mat up1FS = up1Second - up1First;
|
159 |
cv::Mat up1FS = up1Second - up1First;
|
160 |
up1FS = cvtools::modulo(up1FS, 2.0*CV_PI);
|
160 |
up1FS = cvtools::modulo(up1FS, 2.0*CV_PI);
|
161 |
|
161 |
|
162 |
cv::Mat up1ST = up1Third - up1Second;
|
162 |
cv::Mat up1ST = up1Third - up1Second;
|
163 |
up1ST = cvtools::modulo(up1ST, 2.0*CV_PI);
|
163 |
up1ST = cvtools::modulo(up1ST, 2.0*CV_PI);
|
164 |
|
164 |
|
165 |
cv::Mat up1FST = up1ST - up1FS;
|
165 |
cv::Mat up1FST = up1ST - up1FS;
|
166 |
up1FST = cvtools::modulo(up1FST, 2.0*CV_PI);
|
166 |
up1FST = cvtools::modulo(up1FST, 2.0*CV_PI);
|
167 |
|
167 |
|
168 |
cv::Mat up1F = unwrapWithCue(up1First, up1FST, nPeriodsFirst);
|
168 |
cv::Mat up1F = unwrapWithCue(up1First, up1FST, nPeriodsFirst);
|
169 |
cv::Mat up1S = unwrapWithCue(up1Second, up1FST, nPeriodsSecond);
|
169 |
cv::Mat up1S = unwrapWithCue(up1Second, up1FST, nPeriodsSecond);
|
170 |
cv::Mat up1T = unwrapWithCue(up1Third, up1FST, nPeriodsThird);
|
170 |
cv::Mat up1T = unwrapWithCue(up1Third, up1FST, nPeriodsThird);
|
171 |
cv::Mat up1Mean = 1.0/3.0 * (up1F + up1S + up1T);
|
171 |
cv::Mat up1Mean = 1.0/3.0 * (up1F + up1S + up1T);
|
172 |
cv::Mat up1Range = cv::max(up1F, cv::max(up1S, up1T)) - cv::min(up1F, cv::min(up1S, up1T));
|
172 |
cv::Mat up1Range = cv::max(up1F, cv::max(up1S, up1T)) - cv::min(up1F, cv::min(up1S, up1T));
|
173 |
cv::Mat up1 = up1Mean * screenCols/(2.0*CV_PI);
|
173 |
cv::Mat up1 = up1Mean * screenCols/(2.0*CV_PI);
|
174 |
|
174 |
|
175 |
cv::Mat amplitude1;
|
175 |
cv::Mat amplitude1;
|
176 |
cv::magnitude(F1First[2], -F1First[3], amplitude1);
|
176 |
cv::magnitude(F1First[2], -F1First[3], amplitude1);
|
177 |
|
177 |
|
178 |
#ifdef QT_DEBUG
|
178 |
#ifdef QT_DEBUG
|
179 |
cvtools::writeMat(up0First, "up0First.mat", "up0First");
|
179 |
cvtools::writeMat(up0First, "up0First.mat", "up0First");
|
180 |
cvtools::writeMat(up0Second, "up0Second.mat", "up0Second");
|
180 |
cvtools::writeMat(up0Second, "up0Second.mat", "up0Second");
|
181 |
cvtools::writeMat(up0Third, "up0Third.mat", "up0Third");
|
181 |
cvtools::writeMat(up0Third, "up0Third.mat", "up0Third");
|
182 |
cvtools::writeMat(up0FS, "up0FS.mat", "up0FS");
|
182 |
cvtools::writeMat(up0FS, "up0FS.mat", "up0FS");
|
183 |
cvtools::writeMat(up0ST, "up0ST.mat", "up0ST");
|
183 |
cvtools::writeMat(up0ST, "up0ST.mat", "up0ST");
|
184 |
cvtools::writeMat(up0FST, "up0FST.mat", "up0FST");
|
184 |
cvtools::writeMat(up0FST, "up0FST.mat", "up0FST");
|
185 |
cvtools::writeMat(up0Mean, "up0Mean.mat", "up0Mean");
|
185 |
cvtools::writeMat(up0Mean, "up0Mean.mat", "up0Mean");
|
186 |
cvtools::writeMat(up0Range, "up0Range.mat", "up0Range");
|
186 |
cvtools::writeMat(up0Range, "up0Range.mat", "up0Range");
|
187 |
cvtools::writeMat(up0, "up0.mat", "up0");
|
187 |
cvtools::writeMat(up0, "up0.mat", "up0");
|
188 |
cvtools::writeMat(up1, "up1.mat", "up1");
|
188 |
cvtools::writeMat(up1, "up1.mat", "up1");
|
189 |
cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
|
189 |
cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
|
190 |
|
190 |
|
191 |
cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
|
191 |
cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
|
192 |
cvtools::writeMat(amplitude1, "amplitude1.mat", "amplitude1");
|
192 |
cvtools::writeMat(amplitude1, "amplitude1.mat", "amplitude1");
|
193 |
#endif
|
193 |
#endif
|
194 |
|
194 |
|
195 |
// color debayer and remap
|
195 |
// color debayer and remap
|
196 |
cv::Mat color0, color1;
|
196 |
cv::Mat color0, color1;
|
197 |
cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
|
197 |
cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
|
198 |
cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
|
198 |
cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
|
199 |
|
199 |
|
200 |
cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
|
200 |
cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
|
201 |
cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
|
201 |
cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
|
202 |
|
202 |
|
203 |
#ifdef QT_DEBUG
|
203 |
#ifdef QT_DEBUG
|
204 |
cvtools::writeMat(color0, "color0.mat", "color0");
|
204 |
cvtools::writeMat(color0, "color0.mat", "color0");
|
205 |
cvtools::writeMat(color1, "color1.mat", "color1");
|
205 |
cvtools::writeMat(color1, "color1.mat", "color1");
|
206 |
#endif
|
206 |
#endif
|
207 |
|
207 |
|
208 |
// Occlusion masks
|
208 |
// Occlusion masks
|
209 |
cv::Mat occlusion0, occlusion1;
|
209 |
cv::Mat occlusion0, occlusion1;
|
210 |
cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
|
210 |
cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
|
211 |
occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
|
211 |
occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
|
212 |
cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
|
212 |
cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
|
213 |
occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
|
213 |
occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
|
214 |
|
214 |
|
215 |
// Threshold on range
|
215 |
// Threshold on range
|
216 |
occlusion0 = occlusion0 & (up0Range < 0.05);
|
216 |
occlusion0 = occlusion0 & (up0Range < 0.05);
|
217 |
occlusion1 = occlusion1 & (up1Range < 0.05);
|
217 |
occlusion1 = occlusion1 & (up1Range < 0.05);
|
218 |
|
218 |
|
219 |
// // Erode occlusion masks
|
219 |
// // Erode occlusion masks
|
220 |
// cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
|
220 |
// cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
|
221 |
// cv::erode(occlusion0, occlusion0, strel);
|
221 |
// cv::erode(occlusion0, occlusion0, strel);
|
222 |
// cv::erode(occlusion1, occlusion1, strel);
|
222 |
// cv::erode(occlusion1, occlusion1, strel);
|
223 |
|
223 |
|
224 |
// Threshold on gradient of phase
|
224 |
// Threshold on gradient of phase
|
225 |
cv::Mat edges0;
|
225 |
cv::Mat edges0;
|
226 |
cv::Sobel(up0, edges0, -1, 1, 1, 5);
|
226 |
cv::Sobel(up0, edges0, -1, 1, 1, 5);
|
227 |
occlusion0 = occlusion0 & (abs(edges0) < 150);
|
227 |
occlusion0 = occlusion0 & (abs(edges0) < 150);
|
228 |
cv::Mat edges1;
|
228 |
cv::Mat edges1;
|
229 |
cv::Sobel(up1, edges1, -1, 1, 1, 5);
|
229 |
cv::Sobel(up1, edges1, -1, 1, 1, 5);
|
230 |
occlusion1 = occlusion1 & (abs(edges1) < 150);
|
230 |
occlusion1 = occlusion1 & (abs(edges1) < 150);
|
231 |
|
231 |
|
232 |
#ifdef QT_DEBUG
|
232 |
#ifdef QT_DEBUG
|
233 |
cvtools::writeMat(edges0, "edges0.mat", "edges0");
|
233 |
cvtools::writeMat(edges0, "edges0.mat", "edges0");
|
234 |
cvtools::writeMat(edges1, "edges1.mat", "edges1");
|
234 |
cvtools::writeMat(edges1, "edges1.mat", "edges1");
|
235 |
#endif
|
235 |
#endif
|
236 |
|
236 |
|
237 |
#ifdef QT_DEBUG
|
237 |
#ifdef QT_DEBUG
|
238 |
cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
|
238 |
cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
|
239 |
cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
|
239 |
cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
|
240 |
#endif
|
240 |
#endif
|
241 |
|
241 |
|
242 |
// Match phase maps
|
242 |
// Match phase maps
|
243 |
int frameRectRows = map0X.rows;
|
243 |
int frameRectRows = map0X.rows;
|
244 |
int frameRectCols = map0X.cols;
|
244 |
int frameRectCols = map0X.cols;
|
245 |
|
245 |
|
246 |
// camera0 against camera1
|
246 |
// camera0 against camera1
|
247 |
std::vector<cv::Vec2f> q0, q1;
|
247 |
std::vector<cv::Vec2f> q0, q1;
|
248 |
for(int row=0; row<frameRectRows; row++){
|
248 |
for(int row=0; row<frameRectRows; row++){
|
249 |
for(int col=0; col<frameRectCols; col++){
|
249 |
for(int col=0; col<frameRectCols; col++){
|
250 |
|
250 |
|
251 |
if(!occlusion0.at<char>(row,col))
|
251 |
if(!occlusion0.at<char>(row,col))
|
252 |
continue;
|
252 |
continue;
|
253 |
|
253 |
|
254 |
float up0i = up0.at<float>(row,col);
|
254 |
float up0i = up0.at<float>(row,col);
|
255 |
for(int col1=0; col1<up1.cols-1; col1++){
|
255 |
for(int col1=0; col1<up1.cols-1; col1++){
|
256 |
|
256 |
|
257 |
if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
|
257 |
if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
|
258 |
continue;
|
258 |
continue;
|
259 |
|
259 |
|
260 |
float up1Left = up1.at<float>(row,col1);
|
260 |
float up1Left = up1.at<float>(row,col1);
|
261 |
float up1Right = up1.at<float>(row,col1+1);
|
261 |
float up1Right = up1.at<float>(row,col1+1);
|
262 |
|
262 |
|
263 |
if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0) && (up1Right-up1Left > 0.1)){
|
263 |
if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0) && (up1Right-up1Left > 0.1)){
|
264 |
|
264 |
|
265 |
float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
|
265 |
float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
|
266 |
|
266 |
|
267 |
q0.push_back(cv::Point2f(col, row));
|
267 |
q0.push_back(cv::Point2f(col, row));
|
268 |
q1.push_back(cv::Point2f(col1i, row));
|
268 |
q1.push_back(cv::Point2f(col1i, row));
|
269 |
|
269 |
|
270 |
break;
|
270 |
break;
|
271 |
}
|
271 |
}
|
272 |
}
|
272 |
}
|
273 |
}
|
273 |
}
|
274 |
}
|
274 |
}
|
275 |
|
275 |
|
276 |
int nMatches = q0.size();
|
276 |
int nMatches = q0.size();
|
277 |
|
277 |
|
278 |
if(nMatches < 1){
|
278 |
if(nMatches < 1){
|
279 |
Q.resize(0);
|
279 |
Q.resize(0);
|
280 |
color.resize(0);
|
280 |
color.resize(0);
|
281 |
|
281 |
|
282 |
return;
|
282 |
return;
|
283 |
}
|
283 |
}
|
284 |
|
284 |
|
285 |
// Retrieve color information
|
285 |
// Retrieve color information
|
286 |
color.resize(nMatches);
|
286 |
color.resize(nMatches);
|
287 |
for(int i=0; i<nMatches; i++){
|
287 |
for(int i=0; i<nMatches; i++){
|
288 |
|
288 |
|
289 |
cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
|
289 |
cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
|
290 |
cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
|
290 |
cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
|
291 |
|
291 |
|
292 |
color[i] = 0.5*c0 + 0.5*c1;
|
292 |
color[i] = 0.5*c0 + 0.5*c1;
|
293 |
}
|
293 |
}
|
294 |
|
294 |
|
295 |
// Triangulate points
|
295 |
// Triangulate points
|
296 |
cv::Mat QMatHomogenous, QMat;
|
296 |
cv::Mat QMatHomogenous, QMat;
|
297 |
cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
|
297 |
cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
|
298 |
cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
|
298 |
cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
|
299 |
|
299 |
|
300 |
// Undo rectification
|
300 |
// Undo rectification
|
301 |
cv::Mat R0Inv;
|
301 |
cv::Mat R0Inv;
|
302 |
cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
|
302 |
cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
|
303 |
QMat = R0Inv*QMat;
|
303 |
QMat = R0Inv*QMat;
|
304 |
|
304 |
|
305 |
cvtools::matToPoints3f(QMat, Q);
|
305 |
cvtools::matToPoints3f(QMat, Q);
|
306 |
|
306 |
|
307 |
}
|
307 |
}
|
308 |
|
308 |
|