Subversion Repositories seema-scanner

Rev

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

Rev 192 Rev 207
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