Subversion Repositories seema-scanner

Rev

Rev 180 | Rev 182 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 180 Rev 181
-
 
1
//
-
 
2
// Two Frequency Phase Shifting using the Heterodyne Principle
-
 
3
//
-
 
4
// This implementation follows "Reich, Ritter, Thesing, White light heterodyne principle for 3D-measurement", SPIE (1997)
-
 
5
// Different from the paper, it uses only two different frequencies.
-
 
6
//
-
 
7
// The number of periods in the primary (higher frequency) can in principle be chosen freely, but small changes can have a considerable impact on quality.
-
 
8
// 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-primary frequencies.
-
 
9
//
-
 
10
 
1
#include "AlgorithmPhaseShiftTwoFreq.h"
11
#include "AlgorithmPhaseShiftTwoFreq.h"
2
#include <math.h>
12
#include <math.h>
3
 
13
 
4
#include "cvtools.h"
14
#include "cvtools.h"
5
 
15
 
6
#ifndef M_PI
16
#ifndef M_PI
7
    #define M_PI 3.14159265358979323846
17
    #define M_PI 3.14159265358979323846
8
#endif
18
#endif
9
 
19
 
10
static unsigned int nStepsPrimary = 16; // number of shifts/steps in primary
20
static unsigned int nStepsPrimary = 16; // number of shifts/steps in primary
11
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
21
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
12
static float periodPrimary = 48; // primary period
22
static float periodPrimary = 48; // primary period
13
 
23
 
14
// Algorithm
24
// Algorithm
15
static cv::Mat computePhaseVector(unsigned int length, float phase, float pitch){
25
static cv::Mat computePhaseVector(unsigned int length, float phase, float pitch){
16
 
26
 
17
    cv::Mat phaseVector(length, 1, CV_8UC3);
27
    cv::Mat phaseVector(length, 1, CV_8UC3);
18
    //phaseVector.setTo(0);
28
    //phaseVector.setTo(0);
19
 
29
 
20
    const float pi = M_PI;
30
    const float pi = M_PI;
21
 
31
 
22
    // Loop through vector
32
    // Loop through vector
23
    for(int i=0; i<phaseVector.rows; i++){
33
    for(int i=0; i<phaseVector.rows; i++){
24
        // Amplitude of channels
34
        // Amplitude of channels
25
        float amp = 0.5*(1+cos(2*pi*i/pitch - phase));
35
        float amp = 0.5*(1+cos(2*pi*i/pitch - phase));
26
        phaseVector.at<cv::Vec3b>(i, 0) = cv::Vec3b(255.0*amp,255.0*amp,255.0*amp);
36
        phaseVector.at<cv::Vec3b>(i, 0) = cv::Vec3b(255.0*amp,255.0*amp,255.0*amp);
27
    }
37
    }
28
 
38
 
29
    return phaseVector;
39
    return phaseVector;
30
}
40
}
31
 
41
 
32
AlgorithmPhaseShiftTwoFreq::AlgorithmPhaseShiftTwoFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
42
AlgorithmPhaseShiftTwoFreq::AlgorithmPhaseShiftTwoFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
33
 
43
 
34
    // Set N
44
    // Set N
35
    N = 2+nStepsPrimary+nStepsSecondary;
45
    N = 2+nStepsPrimary+nStepsSecondary;
36
 
46
 
37
    // Determine the secondary (wider) period
47
    // Determine the secondary (wider) period
38
    float pSecondary = (screenCols*periodPrimary)/(screenCols-periodPrimary);
48
    float pSecondary = (screenCols*periodPrimary)/(screenCols-periodPrimary);
39
 
49
 
40
    // all on pattern
50
    // all on pattern
41
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
51
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
42
    patterns.push_back(allOn);
52
    patterns.push_back(allOn);
43
 
53
 
44
    // all off pattern
54
    // all off pattern
45
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
55
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
46
    patterns.push_back(allOff);
56
    patterns.push_back(allOff);
47
 
57
 
48
    // Precompute encoded patterns
58
    // Precompute encoded patterns
49
    const float pi = M_PI;
59
    const float pi = M_PI;
50
 
60
 
51
    // Primary encoding patterns
61
    // Primary encoding patterns
52
    for(unsigned int i=0; i<nStepsPrimary; i++){
62
    for(unsigned int i=0; i<nStepsPrimary; i++){
53
        float phase = 2.0*pi/nStepsPrimary * i;
63
        float phase = 2.0*pi/nStepsPrimary * i;
54
        float pitch = periodPrimary;
64
        float pitch = periodPrimary;
55
        cv::Mat patternI(1,1,CV_8U);
65
        cv::Mat patternI(1,1,CV_8U);
56
        patternI = computePhaseVector(screenCols, phase, pitch);
66
        patternI = computePhaseVector(screenCols, phase, pitch);
57
        patterns.push_back(patternI.t());
67
        patterns.push_back(patternI.t());
58
    }
68
    }
59
 
69
 
60
    // Secondary encoding patterns
70
    // Secondary encoding patterns
61
    for(unsigned int i=0; i<nStepsSecondary; i++){
71
    for(unsigned int i=0; i<nStepsSecondary; i++){
62
        float phase = 2.0*pi/nStepsSecondary * i;
72
        float phase = 2.0*pi/nStepsSecondary * i;
63
        float pitch = pSecondary;
73
        float pitch = pSecondary;
64
        cv::Mat patternI(1,1,CV_8U);
74
        cv::Mat patternI(1,1,CV_8U);
65
        patternI = computePhaseVector(screenCols, phase, pitch);
75
        patternI = computePhaseVector(screenCols, phase, pitch);
66
        patterns.push_back(patternI.t());
76
        patterns.push_back(patternI.t());
67
    }
77
    }
68
 
78
 
69
 
79
 
70
}
80
}
71
 
81
 
72
cv::Mat AlgorithmPhaseShiftTwoFreq::getEncodingPattern(unsigned int depth){
82
cv::Mat AlgorithmPhaseShiftTwoFreq::getEncodingPattern(unsigned int depth){
73
    return patterns[depth];
83
    return patterns[depth];
74
}
84
}
75
 
85
 
76
 
86
 
77
//// Absolute phase from 3 frames
87
//// Absolute phase from 3 frames
78
//static cv::Mat getPhase(const cv::Mat I1, const cv::Mat I2, const cv::Mat I3){
88
//static cv::Mat getPhase(const cv::Mat I1, const cv::Mat I2, const cv::Mat I3){
79
 
89
 
80
//    cv::Mat_<float> I1_(I1);
90
//    cv::Mat_<float> I1_(I1);
81
//    cv::Mat_<float> I2_(I2);
91
//    cv::Mat_<float> I2_(I2);
82
//    cv::Mat_<float> I3_(I3);
92
//    cv::Mat_<float> I3_(I3);
83
 
93
 
84
//    cv::Mat phase;
94
//    cv::Mat phase;
85
 
95
 
86
//    // One call approach
96
//    // One call approach
87
//    cv::phase(2.0*I1_-I3_-I2_, sqrt(3.0)*(I2_-I3_), phase);
97
//    cv::phase(2.0*I1_-I3_-I2_, sqrt(3.0)*(I2_-I3_), phase);
88
//    return phase;
98
//    return phase;
89
 
99
 
90
//}
100
//}
91
 
101
 
92
// Phase unwrapping by means of a phase cue
102
// Phase unwrapping by means of a phase cue
93
static cv::Mat unwrapWithCue(const cv::Mat up, const cv::Mat upCue, float nPhases){
103
static cv::Mat unwrapWithCue(const cv::Mat up, const cv::Mat upCue, float nPhases){
94
 
104
 
95
    const float pi = M_PI;
105
    const float pi = M_PI;
96
 
106
 
97
    // Determine number of jumps
107
    // Determine number of jumps
98
    cv::Mat P = (upCue*nPhases-up)/(2.0*pi);
108
    cv::Mat P = (upCue*nPhases-up)/(2.0*pi);
99
 
109
 
100
    // Round to integers
110
    // Round to integers
101
    P.convertTo(P, CV_8U);
111
    P.convertTo(P, CV_8U);
102
    P.convertTo(P, CV_32F);
112
    P.convertTo(P, CV_32F);
103
 
113
 
104
    // Add to phase
114
    // Add to phase
105
    cv::Mat upUnwrapped = up + P*2*pi;
115
    cv::Mat upUnwrapped = up + P*2*pi;
106
 
116
 
107
    // Scale to range [0; 2pi]
117
    // Scale to range [0; 2pi]
108
    upUnwrapped *= 1.0/nPhases;
118
    upUnwrapped *= 1.0/nPhases;
109
 
119
 
110
    return upUnwrapped;
120
    return upUnwrapped;
111
}
121
}
112
 
122
 
113
// Absolute phase and magnitude from N frames
123
// Absolute phase and magnitude from N frames
114
static std::vector<cv::Mat> getDFTComponents(const std::vector<cv::Mat> frames){
124
static std::vector<cv::Mat> getDFTComponents(const std::vector<cv::Mat> frames){
115
 
125
 
116
    unsigned int N = frames.size();
126
    unsigned int N = frames.size();
117
 
127
 
118
//    std::vector<cv::Mat> framesReverse = frames;
128
//    std::vector<cv::Mat> framesReverse = frames;
119
//    std::reverse(framesReverse.begin(), framesReverse.end());
129
//    std::reverse(framesReverse.begin(), framesReverse.end());
120
 
130
 
121
    // DFT approach
131
    // DFT approach
122
    cv::Mat I;
132
    cv::Mat I;
123
    cv::merge(frames, I);
133
    cv::merge(frames, I);
124
    unsigned int w = I.cols;
134
    unsigned int w = I.cols;
125
    unsigned int h = I.rows;
135
    unsigned int h = I.rows;
126
    I = I.reshape(1, h*w);
136
    I = I.reshape(1, h*w);
127
    I.convertTo(I, CV_32F);
137
    I.convertTo(I, CV_32F);
128
    cv::Mat fI;
138
    cv::Mat fI;
129
    cv::dft(I, fI, cv::DFT_ROWS + cv::DFT_COMPLEX_OUTPUT);
139
    cv::dft(I, fI, cv::DFT_ROWS + cv::DFT_COMPLEX_OUTPUT);
130
    fI = fI.reshape(N*2, h);
140
    fI = fI.reshape(N*2, h);
131
 
141
 
132
    std::vector<cv::Mat> fIcomp;
142
    std::vector<cv::Mat> fIcomp;
133
    cv::split(fI, fIcomp);
143
    cv::split(fI, fIcomp);
134
 
144
 
135
    return fIcomp;
145
    return fIcomp;
136
 
146
 
137
}
147
}
138
 
148
 
139
void AlgorithmPhaseShiftTwoFreq::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){
149
void AlgorithmPhaseShiftTwoFreq::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){
140
 
150
 
141
    const float pi = M_PI;
151
    const float pi = M_PI;
142
 
152
 
143
    assert(frames0.size() == N);
153
    assert(frames0.size() == N);
144
    assert(frames1.size() == N);
154
    assert(frames1.size() == N);
145
 
155
 
146
    int frameRows = frames0[0].rows;
156
    int frameRows = frames0[0].rows;
147
    int frameCols = frames0[0].cols;
157
    int frameCols = frames0[0].cols;
148
 
158
 
149
    // Rectifying homographies (rotation+projections)
159
    // Rectifying homographies (rotation+projections)
150
    cv::Size frameSize(frameCols, frameRows);
160
    cv::Size frameSize(frameCols, frameRows);
151
    cv::Mat R, T;
161
    cv::Mat R, T;
152
    // stereoRectify segfaults unless R is double precision
162
    // stereoRectify segfaults unless R is double precision
153
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
163
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
154
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
164
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
155
    cv::Mat R0, R1, P0, P1, QRect;
165
    cv::Mat R0, R1, P0, P1, QRect;
156
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
166
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
157
 
167
 
158
    // Interpolation maps (lens distortion and rectification)
168
    // Interpolation maps (lens distortion and rectification)
159
    cv::Mat map0X, map0Y, map1X, map1Y;
169
    cv::Mat map0X, map0Y, map1X, map1Y;
160
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
170
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
161
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
171
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
162
 
172
 
163
    // Gray-scale and remap
173
    // Gray-scale and remap
164
    std::vector<cv::Mat> frames0Rect(N);
174
    std::vector<cv::Mat> frames0Rect(N);
165
    std::vector<cv::Mat> frames1Rect(N);
175
    std::vector<cv::Mat> frames1Rect(N);
166
    for(unsigned int i=0; i<N; i++){
176
    for(unsigned int i=0; i<N; i++){
167
        cv::Mat temp;
177
        cv::Mat temp;
168
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
178
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
169
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
179
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
170
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
180
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
171
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
181
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
172
    }
182
    }
173
 
183
 
174
    // Decode camera0
184
    // Decode camera0
175
    std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
185
    std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
176
    std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end());
186
    std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end());
177
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
187
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
178
    cv::Mat up0Primary;
188
    cv::Mat up0Primary;
179
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
189
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
180
    //cv::Mat up0Secondary = getPhase(frames0Secondary[0], frames0Secondary[1], frames0Secondary[2]);
190
    //cv::Mat up0Secondary = getPhase(frames0Secondary[0], frames0Secondary[1], frames0Secondary[2]);
181
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
191
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
182
    cv::Mat up0Secondary;
192
    cv::Mat up0Secondary;
183
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
193
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
184
    cv::Mat up0Equivalent = up0Primary - up0Secondary;
194
    cv::Mat up0Equivalent = up0Primary - up0Secondary;
185
    up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*pi);
195
    up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*pi);
186
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Equivalent, (float)screenCols/periodPrimary);
196
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Equivalent, (float)screenCols/periodPrimary);
187
    up0 *= screenCols/(2.0*pi);
197
    up0 *= screenCols/(2.0*pi);
188
    cv::Mat amplitude0;
198
    cv::Mat amplitude0;
189
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
199
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
190
 
200
 
191
    // Decode camera1
201
    // Decode camera1
192
    std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
202
    std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
193
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
203
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
194
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
204
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
195
    cv::Mat up1Primary;
205
    cv::Mat up1Primary;
196
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
206
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
197
    //cv::Mat up1Secondary = getPhase(frames1Secondary[0], frames1Secondary[1], frames1Secondary[2]);
207
    //cv::Mat up1Secondary = getPhase(frames1Secondary[0], frames1Secondary[1], frames1Secondary[2]);
198
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
208
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
199
    cv::Mat up1Secondary;
209
    cv::Mat up1Secondary;
200
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
210
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
201
    cv::Mat up1Equivalent = up1Primary - up1Secondary;
211
    cv::Mat up1Equivalent = up1Primary - up1Secondary;
202
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*pi);
212
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*pi);
203
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, (float)screenCols/periodPrimary);
213
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, (float)screenCols/periodPrimary);
204
    up1 *= screenCols/(2.0*pi);
214
    up1 *= screenCols/(2.0*pi);
205
    cv::Mat amplitude1;
215
    cv::Mat amplitude1;
206
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
216
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
207
 
217
 
208
cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
218
cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
209
cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
219
cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
210
cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
220
cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
211
cvtools::writeMat(up0, "up0.mat", "up0");
221
cvtools::writeMat(up0, "up0.mat", "up0");
212
cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
222
cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
213
 
223
 
214
    // color debayer and remap
224
    // color debayer and remap
215
    cv::Mat color0, color1;
225
    cv::Mat color0, color1;
216
//    frames0[0].convertTo(color0Rect, CV_8UC1, 1.0/256.0);
226
//    frames0[0].convertTo(color0Rect, CV_8UC1, 1.0/256.0);
217
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
227
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
218
    cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
228
    cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
219
 
229
 
220
//    frames1[0].convertTo(color1Rect, CV_8UC1, 1.0/256.0);
230
//    frames1[0].convertTo(color1Rect, CV_8UC1, 1.0/256.0);
221
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
231
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
222
    cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
232
    cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
223
 
233
 
224
//cvtools::writeMat(color0, "color0.mat", "color0");
234
//cvtools::writeMat(color0, "color0.mat", "color0");
225
//cvtools::writeMat(color1, "color1.mat", "color1");
235
//cvtools::writeMat(color1, "color1.mat", "color1");
226
 
236
 
227
    // Occlusion masks
237
    // Occlusion masks
228
    cv::Mat occlusion0, occlusion1;
238
    cv::Mat occlusion0, occlusion1;
229
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
239
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
230
    occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
240
    occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
231
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
241
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
232
    occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
242
    occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
233
 
243
 
234
    // Threshold on energy at primary frequency
244
    // Threshold on energy at primary frequency
235
    occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
245
    occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
236
    occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
246
    occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
237
 
247
 
238
//cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
248
//cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
239
//cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
249
//cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
240
 
250
 
241
    // Erode occlusion masks
251
    // Erode occlusion masks
242
    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
252
    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
243
    cv::erode(occlusion0, occlusion0, strel);
253
    cv::erode(occlusion0, occlusion0, strel);
244
    cv::erode(occlusion1, occlusion1, strel);
254
    cv::erode(occlusion1, occlusion1, strel);
245
 
255
 
246
    // Threshold on gradient of phase
256
    // Threshold on gradient of phase
247
    cv::Mat edges0;
257
    cv::Mat edges0;
248
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
258
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
249
    occlusion0 = occlusion0 & (abs(edges0) < 150);
259
    occlusion0 = occlusion0 & (abs(edges0) < 150);
250
 
260
 
251
    cv::Mat edges1;
261
    cv::Mat edges1;
252
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
262
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
253
    occlusion1 = occlusion1 & (abs(edges1) < 150);
263
    occlusion1 = occlusion1 & (abs(edges1) < 150);
254
 
264
 
255
//cvtools::writeMat(edges0, "edges0.mat", "edges0");
265
//cvtools::writeMat(edges0, "edges0.mat", "edges0");
256
//cvtools::writeMat(edges1, "edges1.mat", "edges1");
266
//cvtools::writeMat(edges1, "edges1.mat", "edges1");
257
 
267
 
258
    // Match phase maps
268
    // Match phase maps
259
    int frameRectRows = map0X.rows;
269
    int frameRectRows = map0X.rows;
260
    int frameRectCols = map0X.cols;
270
    int frameRectCols = map0X.cols;
261
 
271
 
262
    // camera0 against camera1
272
    // camera0 against camera1
263
    std::vector<cv::Vec2f> q0, q1;
273
    std::vector<cv::Vec2f> q0, q1;
264
    for(int row=0; row<frameRectRows; row++){
274
    for(int row=0; row<frameRectRows; row++){
265
        for(int col=0; col<frameRectCols; col++){
275
        for(int col=0; col<frameRectCols; col++){
266
 
276
 
267
            if(!occlusion0.at<char>(row,col))
277
            if(!occlusion0.at<char>(row,col))
268
                continue;
278
                continue;
269
 
279
 
270
            float up0i = up0.at<float>(row,col);
280
            float up0i = up0.at<float>(row,col);
271
            for(int col1=0; col1<up1.cols-1; col1++){
281
            for(int col1=0; col1<up1.cols-1; col1++){
272
 
282
 
273
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
283
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
274
                    continue;
284
                    continue;
275
 
285
 
276
                float up1Left = up1.at<float>(row,col1);
286
                float up1Left = up1.at<float>(row,col1);
277
                float up1Right = up1.at<float>(row,col1+1);
287
                float up1Right = up1.at<float>(row,col1+1);
278
 
288
 
279
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1) && (up1Right-up0i < 1)){
289
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1) && (up1Right-up0i < 1)){
280
 
290
 
281
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
291
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
282
 
292
 
283
                    q0.push_back(cv::Point2f(col, row));
293
                    q0.push_back(cv::Point2f(col, row));
284
                    q1.push_back(cv::Point2f(col1i, row));
294
                    q1.push_back(cv::Point2f(col1i, row));
285
 
295
 
286
                    break;
296
                    break;
287
                }
297
                }
288
            }
298
            }
289
        }
299
        }
290
    }
300
    }
291
 
301
 
292
 
302
 
293
    int nMatches = q0.size();
303
    int nMatches = q0.size();
294
 
304
 
295
    if(nMatches < 1){
305
    if(nMatches < 1){
296
        Q.resize(0);
306
        Q.resize(0);
297
        color.resize(0);
307
        color.resize(0);
298
 
308
 
299
        return;
309
        return;
300
    }
310
    }
301
 
311
 
302
    // Retrieve color information
312
    // Retrieve color information
303
    color.resize(nMatches);
313
    color.resize(nMatches);
304
    for(int i=0; i<nMatches; i++){
314
    for(int i=0; i<nMatches; i++){
305
 
315
 
306
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
316
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
307
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
317
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
308
 
318
 
309
        color[i] = 0.5*c0 + 0.5*c1;
319
        color[i] = 0.5*c0 + 0.5*c1;
310
    }
320
    }
311
 
321
 
312
    // Triangulate points
322
    // Triangulate points
313
    cv::Mat QMatHomogenous, QMat;
323
    cv::Mat QMatHomogenous, QMat;
314
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
324
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
315
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
325
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
316
 
326
 
317
    // Undo rectification
327
    // Undo rectification
318
    cv::Mat R0Inv;
328
    cv::Mat R0Inv;
319
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
329
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
320
    QMat = R0Inv*QMat;
330
    QMat = R0Inv*QMat;
321
 
331
 
322
    cvtools::matToPoints3f(QMat, Q);
332
    cvtools::matToPoints3f(QMat, Q);
323
 
333
 
324
}
334
}
325
 
335