Subversion Repositories seema-scanner

Rev

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

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