Subversion Repositories seema-scanner

Rev

Rev 236 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 236 Rev 245
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(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){
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::Vec3f>& 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_RGB2GRAY);
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_RGB2GRAY);
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 remap
196
    cv::Mat color0, color1;
196
    cv::Mat color0, color1;
197
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
-
 
198
    cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
197
    cv::remap(frames0[0], color0, map0X, map0Y, CV_INTER_LINEAR);
199
 
-
 
200
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
-
 
201
    cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
198
    cv::remap(frames1[0], color1, map1X, map1Y, CV_INTER_LINEAR);
202
 
199
 
203
    #ifdef QT_DEBUG
200
    #ifdef QT_DEBUG
204
        cvtools::writeMat(color0, "color0.mat", "color0");
201
        cvtools::writeMat(color0, "color0.mat", "color0");
205
        cvtools::writeMat(color1, "color1.mat", "color1");
202
        cvtools::writeMat(color1, "color1.mat", "color1");
206
    #endif
203
    #endif
207
 
204
 
208
    // Occlusion masks
205
    // Occlusion masks
209
    cv::Mat occlusion0, occlusion1;
206
    cv::Mat occlusion0, occlusion1;
210
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
207
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
211
    occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
208
    occlusion0 = (occlusion0 > 0.1) & (occlusion0 < 0.98);
212
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
209
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
213
    occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
210
    occlusion1 = (occlusion1 > 0.1) & (occlusion1 < 0.98);
214
 
211
 
215
    // Threshold on range
212
    // Threshold on range
216
    occlusion0 = occlusion0 & (up0Range < 0.05);
213
    occlusion0 = occlusion0 & (up0Range < 0.05);
217
    occlusion1 = occlusion1 & (up1Range < 0.05);
214
    occlusion1 = occlusion1 & (up1Range < 0.05);
218
 
215
 
219
//    // Erode occlusion masks
216
//    // Erode occlusion masks
220
//    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
217
//    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
221
//    cv::erode(occlusion0, occlusion0, strel);
218
//    cv::erode(occlusion0, occlusion0, strel);
222
//    cv::erode(occlusion1, occlusion1, strel);
219
//    cv::erode(occlusion1, occlusion1, strel);
223
 
220
 
224
    // Threshold on gradient of phase
221
    // Threshold on vertical gradient of phase
225
    cv::Mat edges0;
222
    cv::Mat edges0;
226
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
223
    cv::Sobel(up0, edges0, -1, 0, 1, 5);
227
    occlusion0 = occlusion0 & (abs(edges0) < 150);
224
    occlusion0 = occlusion0 & (abs(edges0) < 100);
228
    cv::Mat edges1;
225
    cv::Mat edges1;
229
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
226
    cv::Sobel(up1, edges1, -1, 0, 1, 5);
230
    occlusion1 = occlusion1 & (abs(edges1) < 150);
227
    occlusion1 = occlusion1 & (abs(edges1) < 100);
231
 
228
 
232
    #ifdef QT_DEBUG
229
    #ifdef QT_DEBUG
233
        cvtools::writeMat(edges0, "edges0.mat", "edges0");
230
        cvtools::writeMat(edges0, "edges0.mat", "edges0");
234
        cvtools::writeMat(edges1, "edges1.mat", "edges1");
231
        cvtools::writeMat(edges1, "edges1.mat", "edges1");
235
    #endif
232
    #endif
236
 
233
 
237
    #ifdef QT_DEBUG
234
    #ifdef QT_DEBUG
238
        cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
235
        cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
239
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
236
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
240
    #endif
237
    #endif
241
 
238
 
242
    // Match phase maps
239
    // Match phase maps
243
    int frameRectRows = map0X.rows;
240
    int frameRectRows = map0X.rows;
244
    int frameRectCols = map0X.cols;
241
    int frameRectCols = map0X.cols;
245
 
242
 
246
    // camera0 against camera1
243
    // camera0 against camera1
247
    std::vector<cv::Vec2f> q0, q1;
244
    std::vector<cv::Vec2f> q0, q1;
248
    for(int row=0; row<frameRectRows; row++){
245
    for(int row=0; row<frameRectRows; row++){
249
        for(int col=0; col<frameRectCols; col++){
246
        for(int col=0; col<frameRectCols; col++){
250
 
247
 
251
            if(!occlusion0.at<char>(row,col))
248
            if(!occlusion0.at<char>(row,col))
252
                continue;
249
                continue;
253
 
250
 
254
            float up0i = up0.at<float>(row,col);
251
            float up0i = up0.at<float>(row,col);
255
            for(int col1=0; col1<up1.cols-1; col1++){
252
            for(int col1=0; col1<up1.cols-1; col1++){
256
 
253
 
257
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
254
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
258
                    continue;
255
                    continue;
259
 
256
 
260
                float up1Left = up1.at<float>(row,col1);
257
                float up1Left = up1.at<float>(row,col1);
261
                float up1Right = up1.at<float>(row,col1+1);
258
                float up1Right = up1.at<float>(row,col1+1);
262
 
259
 
263
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0) && (up1Right-up1Left > 0.1)){
260
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0) && (up1Right-up1Left > 0.1)){
264
 
261
 
265
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
262
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
266
 
263
 
267
                    q0.push_back(cv::Point2f(col, row));
264
                    q0.push_back(cv::Point2f(col, row));
268
                    q1.push_back(cv::Point2f(col1i, row));
265
                    q1.push_back(cv::Point2f(col1i, row));
269
 
266
 
270
                    break;
267
                    break;
271
                }
268
                }
272
            }
269
            }
273
        }
270
        }
274
    }
271
    }
275
 
272
 
276
    int nMatches = q0.size();
273
    int nMatches = q0.size();
277
 
274
 
278
    if(nMatches < 1){
275
    if(nMatches < 1){
279
        Q.resize(0);
276
        Q.resize(0);
280
        color.resize(0);
277
        color.resize(0);
281
 
278
 
282
        return;
279
        return;
283
    }
280
    }
284
 
281
 
285
    // Retrieve color information
282
    // Retrieve color information
286
    color.resize(nMatches);
283
    color.resize(nMatches);
287
    for(int i=0; i<nMatches; i++){
284
    for(int i=0; i<nMatches; i++){
288
 
285
 
289
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
286
        cv::Vec3f c0 = color0.at<cv::Vec3f>(q0[i][1], q0[i][0]);
290
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
287
        cv::Vec3f c1 = color1.at<cv::Vec3f>(q1[i][1], q1[i][0]);
291
 
288
 
292
        color[i] = 0.5*c0 + 0.5*c1;
289
        color[i] = 0.5*c0 + 0.5*c1;
293
    }
290
    }
294
 
291
 
295
    // Triangulate by means of disparity projection
292
    // Triangulate by means of disparity projection
296
    Q.resize(q0.size());
293
    Q.resize(q0.size());
297
    cv::Matx44f QRectx = cv::Matx44f(QRect);
294
    cv::Matx44f QRectx = cv::Matx44f(QRect);
298
    cv::Matx33f R0invx = cv::Matx33f(cv::Mat(R0.t()));
295
    cv::Matx33f R0invx = cv::Matx33f(cv::Mat(R0.t()));
299
 
296
 
300
    #pragma omp parallel for
297
    #pragma omp parallel for
301
    for(unsigned int i=0; i<q0.size(); i++){
298
    for(unsigned int i=0; i<q0.size(); i++){
302
        float disparity = q0[i][0]-q1[i][0];
299
        float disparity = q0[i][0]-q1[i][0];
303
        cv::Vec4f Qih = QRectx*cv::Vec4f(q0[i][0], q0[i][1], disparity, 1.0);
300
        cv::Vec4f Qih = QRectx*cv::Vec4f(q0[i][0], q0[i][1], disparity, 1.0);
304
        float winv = float(1.0)/Qih[3];
301
        float winv = float(1.0)/Qih[3];
305
        Q[i] = R0invx * cv::Point3f(Qih[0]*winv, Qih[1]*winv, Qih[2]*winv);
302
        Q[i] = R0invx * cv::Point3f(Qih[0]*winv, Qih[1]*winv, Qih[2]*winv);
306
    }
303
    }
307
 
304
 
308
}
305
}
309
 
306