Subversion Repositories seema-scanner

Rev

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

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