Subversion Repositories seema-scanner

Rev

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

Rev 185 Rev 190
1
//
1
//
2
// Two Frequency Phase Shifting using the Heterodyne Principle
2
// Two 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
// Different from the paper, it uses only two different frequencies.
5
// Different from the paper, it uses only two different frequencies.
6
//
6
//
7
// The number of periods in the primary frequency can be chosen freely, but small changes can have a considerable impact on quality.
7
// The number of periods in the primary frequency can be chosen freely, but small changes can have a considerable impact on quality.
8
// The number of phase shifts can be chosen freely (min. 3), and higher values reduce the effects of image noise. They also allow us to filter bad points based on energy at non-primary frequencies.
8
// The number of phase shifts can be chosen freely (min. 3), and higher values reduce the effects of image noise. They also allow us to filter bad points based on energy at non-primary frequencies.
9
//
9
//
10
 
10
 
11
#include "AlgorithmPhaseShiftTwoFreq.h"
11
#include "AlgorithmPhaseShiftTwoFreq.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 nStepsPrimary = 16; // number of shifts/steps in primary
21
static unsigned int nStepsPrimary = 16; // number of shifts/steps in primary
22
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
22
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
23
static float nPeriodsPrimary = 48; // primary period
23
static float nPeriodsPrimary = 40; // primary period
24
 
24
 
25
AlgorithmPhaseShiftTwoFreq::AlgorithmPhaseShiftTwoFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
25
AlgorithmPhaseShiftTwoFreq::AlgorithmPhaseShiftTwoFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
26
 
26
 
27
    // Set N
27
    // Set N
28
    N = 2+nStepsPrimary+nStepsSecondary;
28
    N = 2+nStepsPrimary+nStepsSecondary;
29
 
29
 
30
    // Determine the secondary (wider) period
30
    // Determine the secondary (wider) period to fulfill the heterodyne condition
31
    float nPeriodsSecondary = (screenCols*nPeriodsPrimary)/(screenCols-nPeriodsPrimary);
31
    float nPeriodsSecondary = nPeriodsPrimary + 1;
32
 
32
 
33
    // all on pattern
33
    // all on pattern
34
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
34
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
35
    patterns.push_back(allOn);
35
    patterns.push_back(allOn);
36
 
36
 
37
    // all off pattern
37
    // all off pattern
38
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
38
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
39
    patterns.push_back(allOff);
39
    patterns.push_back(allOff);
40
 
40
 
41
    // Precompute encoded patterns
41
    // Precompute encoded patterns
42
    const float pi = M_PI;
42
    const float pi = M_PI;
43
 
43
 
44
    // Primary encoding patterns
44
    // Primary encoding patterns
45
    for(unsigned int i=0; i<nStepsPrimary; i++){
45
    for(unsigned int i=0; i<nStepsPrimary; i++){
46
        float phase = 2.0*pi/nStepsPrimary * i;
46
        float phase = 2.0*pi/nStepsPrimary * i;
47
        float pitch = nPeriodsPrimary;
47
        float pitch = screenCols/nPeriodsPrimary;
48
        cv::Mat patternI(1,1,CV_8U);
48
        cv::Mat patternI(1,1,CV_8U);
49
        patternI = computePhaseVector(screenCols, phase, pitch);
49
        patternI = computePhaseVector(screenCols, phase, pitch);
50
        patterns.push_back(patternI.t());
50
        patterns.push_back(patternI.t());
51
    }
51
    }
52
 
52
 
53
    // Secondary encoding patterns
53
    // Secondary encoding patterns
54
    for(unsigned int i=0; i<nStepsSecondary; i++){
54
    for(unsigned int i=0; i<nStepsSecondary; i++){
55
        float phase = 2.0*pi/nStepsSecondary * i;
55
        float phase = 2.0*pi/nStepsSecondary * i;
56
        float pitch = nPeriodsSecondary;
56
        float pitch = screenCols/nPeriodsSecondary;
57
        cv::Mat patternI(1,1,CV_8U);
57
        cv::Mat patternI(1,1,CV_8U);
58
        patternI = computePhaseVector(screenCols, phase, pitch);
58
        patternI = computePhaseVector(screenCols, phase, pitch);
59
        patterns.push_back(patternI.t());
59
        patterns.push_back(patternI.t());
60
    }
60
    }
61
 
61
 
62
 
62
 
63
}
63
}
64
 
64
 
65
cv::Mat AlgorithmPhaseShiftTwoFreq::getEncodingPattern(unsigned int depth){
65
cv::Mat AlgorithmPhaseShiftTwoFreq::getEncodingPattern(unsigned int depth){
66
    return patterns[depth];
66
    return patterns[depth];
67
}
67
}
68
 
68
 
69
void AlgorithmPhaseShiftTwoFreq::get3DPoints(SMCalibrationParameters calibration, const std::vector<cv::Mat>& frames0, const std::vector<cv::Mat>& frames1, std::vector<cv::Point3f>& Q, std::vector<cv::Vec3b>& color){
69
void AlgorithmPhaseShiftTwoFreq::get3DPoints(SMCalibrationParameters calibration, const std::vector<cv::Mat>& frames0, const std::vector<cv::Mat>& frames1, std::vector<cv::Point3f>& Q, std::vector<cv::Vec3b>& color){
70
 
70
 
71
    const float pi = M_PI;
71
    const float pi = M_PI;
72
 
72
 
73
    assert(frames0.size() == N);
73
    assert(frames0.size() == N);
74
    assert(frames1.size() == N);
74
    assert(frames1.size() == N);
75
 
75
 
76
    int frameRows = frames0[0].rows;
76
    int frameRows = frames0[0].rows;
77
    int frameCols = frames0[0].cols;
77
    int frameCols = frames0[0].cols;
78
 
78
 
79
    // Rectifying homographies (rotation+projections)
79
    // Rectifying homographies (rotation+projections)
80
    cv::Size frameSize(frameCols, frameRows);
80
    cv::Size frameSize(frameCols, frameRows);
81
    cv::Mat R, T;
81
    cv::Mat R, T;
82
    // stereoRectify segfaults unless R is double precision
82
    // stereoRectify segfaults unless R is double precision
83
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
83
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
84
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
84
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
85
    cv::Mat R0, R1, P0, P1, QRect;
85
    cv::Mat R0, R1, P0, P1, QRect;
86
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
86
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
87
 
87
 
88
    // Interpolation maps (lens distortion and rectification)
88
    // Interpolation maps (lens distortion and rectification)
89
    cv::Mat map0X, map0Y, map1X, map1Y;
89
    cv::Mat map0X, map0Y, map1X, map1Y;
90
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
90
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
91
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
91
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
92
 
92
 
93
    int frameRectRows = map0X.rows;
93
    int frameRectRows = map0X.rows;
94
    int frameRectCols = map0X.cols;
94
    int frameRectCols = map0X.cols;
95
 
95
 
96
    // Gray-scale and remap
96
    // Gray-scale and remap
97
    std::vector<cv::Mat> frames0Rect(N);
97
    std::vector<cv::Mat> frames0Rect(N);
98
    std::vector<cv::Mat> frames1Rect(N);
98
    std::vector<cv::Mat> frames1Rect(N);
99
    for(unsigned int i=0; i<N; i++){
99
    for(unsigned int i=0; i<N; i++){
100
        cv::Mat temp;
100
        cv::Mat temp;
101
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
101
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
102
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
102
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
103
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
103
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
104
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
104
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
105
    }
105
    }
106
 
106
 
107
    // Decode camera0
107
    // Decode camera0
108
    std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
108
    std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
109
    std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end());
109
    std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end());
110
 
110
 
111
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
111
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
112
    cv::Mat up0Primary;
112
    cv::Mat up0Primary;
113
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
113
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
114
 
114
 
115
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
115
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
116
    cv::Mat up0Secondary;
116
    cv::Mat up0Secondary;
117
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
117
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
118
 
118
 
119
    cv::Mat up0Equivalent = up0Primary - up0Secondary;
119
    cv::Mat up0Equivalent = up0Secondary - up0Primary;
120
    up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*pi);
120
    up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*pi);
121
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Equivalent, (float)screenCols/nPeriodsPrimary);
121
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Equivalent, nPeriodsPrimary);
122
    up0 *= screenCols/(2.0*pi);
122
    up0 *= screenCols/(2.0*pi);
123
    cv::Mat amplitude0;
123
    cv::Mat amplitude0;
124
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
124
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
125
 
125
 
126
    // Collected signal energy at higher frequencies
126
    // Collected signal energy at higher frequencies
127
    cv::Mat energy0Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
127
    cv::Mat energy0Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
128
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
128
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
129
        cv::Mat magnitude;
129
        cv::Mat magnitude;
130
        cv::magnitude(F0Primary[i*2 + 2], F0Primary[i*2 + 3], magnitude);
130
        cv::magnitude(F0Primary[i*2 + 2], F0Primary[i*2 + 3], magnitude);
131
        cv::add(energy0Primary, magnitude, energy0Primary, cv::noArray(), CV_32F);
131
        cv::add(energy0Primary, magnitude, energy0Primary, cv::noArray(), CV_32F);
132
    }
132
    }
133
 
133
 
134
    cv::Mat energy0Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
134
    cv::Mat energy0Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
135
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
135
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
136
        cv::Mat magnitude;
136
        cv::Mat magnitude;
137
        cv::magnitude(F0Secondary[i*2 + 2], F0Secondary[i*2 + 3], magnitude);
137
        cv::magnitude(F0Secondary[i*2 + 2], F0Secondary[i*2 + 3], magnitude);
138
        cv::add(energy0Secondary, magnitude, energy0Secondary, cv::noArray(), CV_32F);
138
        cv::add(energy0Secondary, magnitude, energy0Secondary, cv::noArray(), CV_32F);
139
    }
139
    }
140
 
140
 
141
    #ifdef QT_DEBUG
141
    #ifdef QT_DEBUG
142
        cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
142
        cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
143
        cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
143
        cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
144
        cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
144
        cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
145
        cvtools::writeMat(up0, "up0.mat", "up0");
145
        cvtools::writeMat(up0, "up0.mat", "up0");
146
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
146
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
147
        cvtools::writeMat(energy0Primary, "energy0Primary.mat", "energy0Primary");
147
        cvtools::writeMat(energy0Primary, "energy0Primary.mat", "energy0Primary");
148
        cvtools::writeMat(energy0Secondary, "energy0Secondary.mat", "energy0Secondary");
148
        cvtools::writeMat(energy0Secondary, "energy0Secondary.mat", "energy0Secondary");
149
    #endif
149
    #endif
150
 
150
 
151
    // Decode camera1
151
    // Decode camera1
152
    std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
152
    std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
153
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
153
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
154
 
154
 
155
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
155
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
156
    cv::Mat up1Primary;
156
    cv::Mat up1Primary;
157
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
157
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
158
 
158
 
159
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
159
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
160
    cv::Mat up1Secondary;
160
    cv::Mat up1Secondary;
161
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
161
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
162
 
162
 
163
    cv::Mat up1Equivalent = up1Primary - up1Secondary;
163
    cv::Mat up1Equivalent = up1Secondary - up1Primary;
164
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*pi);
164
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*pi);
165
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, (float)screenCols/nPeriodsPrimary);
165
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, nPeriodsPrimary);
166
    up1 *= screenCols/(2.0*pi);
166
    up1 *= screenCols/(2.0*pi);
167
    cv::Mat amplitude1;
167
    cv::Mat amplitude1;
168
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
168
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
169
 
169
 
170
    // Collected signal energy at higher frequencies
170
    // Collected signal energy at higher frequencies
171
    cv::Mat energy1Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
171
    cv::Mat energy1Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
172
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
172
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
173
        cv::Mat magnitude;
173
        cv::Mat magnitude;
174
        cv::magnitude(F1Primary[i*2 + 2], F1Primary[i*2 + 3], magnitude);
174
        cv::magnitude(F1Primary[i*2 + 2], F1Primary[i*2 + 3], magnitude);
175
        cv::add(energy1Primary, magnitude, energy1Primary, cv::noArray(), CV_32F);
175
        cv::add(energy1Primary, magnitude, energy1Primary, cv::noArray(), CV_32F);
176
    }
176
    }
177
 
177
 
178
    cv::Mat energy1Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
178
    cv::Mat energy1Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
179
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
179
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
180
        cv::Mat magnitude;
180
        cv::Mat magnitude;
181
        cv::magnitude(F1Secondary[i*2 + 2], F1Secondary[i*2 + 3], magnitude);
181
        cv::magnitude(F1Secondary[i*2 + 2], F1Secondary[i*2 + 3], magnitude);
182
        cv::add(energy1Secondary, magnitude, energy1Secondary, cv::noArray(), CV_32F);
182
        cv::add(energy1Secondary, magnitude, energy1Secondary, cv::noArray(), CV_32F);
183
    }
183
    }
184
 
184
 
185
    #ifdef QT_DEBUG
185
    #ifdef QT_DEBUG
186
        cvtools::writeMat(up1, "up1.mat", "up1");
186
        cvtools::writeMat(up1, "up1.mat", "up1");
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 > 25) & (occlusion0 < 250);
205
    occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
206
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
206
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
207
    occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
207
    occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
208
 
208
 
209
    // Threshold on energy at primary frequency
209
    // Threshold on energy at primary frequency
210
    occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
210
    occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
211
    occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
211
    occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
212
 
212
 
213
    // Threshold on energy ratios
213
    // Threshold on energy ratios
214
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Primary);
214
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Primary);
215
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Secondary);
215
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Secondary);
216
 
216
 
217
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Primary);
217
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Primary);
218
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Secondary);
218
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Secondary);
219
 
219
 
220
//    // Erode occlusion masks
220
//    // Erode occlusion masks
221
//    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
221
//    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
222
//    cv::erode(occlusion0, occlusion0, strel);
222
//    cv::erode(occlusion0, occlusion0, strel);
223
//    cv::erode(occlusion1, occlusion1, strel);
223
//    cv::erode(occlusion1, occlusion1, strel);
224
 
224
 
225
//    // Threshold on gradient of phase
225
    // Threshold on gradient of phase
226
//    cv::Mat edges0;
226
    cv::Mat edges0;
227
//    cv::Sobel(up0, edges0, -1, 1, 1, 5);
227
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
228
//    occlusion0 = occlusion0 & (abs(edges0) < 150);
228
    occlusion0 = occlusion0 & (abs(edges0) < 150);
229
 
229
 
230
//    cv::Mat edges1;
230
    cv::Mat edges1;
231
//    cv::Sobel(up1, edges1, -1, 1, 1, 5);
231
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
232
//    occlusion1 = occlusion1 & (abs(edges1) < 150);
232
    occlusion1 = occlusion1 & (abs(edges1) < 150);
233
 
233
 
234
    #ifdef QT_DEBUG
234
    #ifdef QT_DEBUG
235
        cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
235
        cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
236
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
236
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
237
    #endif
237
    #endif
238
 
238
 
239
    // Match phase maps
239
    // Match phase maps
240
 
240
 
241
    // camera0 against camera1
241
    // camera0 against camera1
242
    std::vector<cv::Vec2f> q0, q1;
242
    std::vector<cv::Vec2f> q0, q1;
243
    for(int row=0; row<frameRectRows; row++){
243
    for(int row=0; row<frameRectRows; row++){
244
        for(int col=0; col<frameRectCols; col++){
244
        for(int col=0; col<frameRectCols; col++){
245
 
245
 
246
            if(!occlusion0.at<char>(row,col))
246
            if(!occlusion0.at<char>(row,col))
247
                continue;
247
                continue;
248
 
248
 
249
            float up0i = up0.at<float>(row,col);
249
            float up0i = up0.at<float>(row,col);
250
            for(int col1=0; col1<up1.cols-1; col1++){
250
            for(int col1=0; col1<up1.cols-1; col1++){
251
 
251
 
252
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
252
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
253
                    continue;
253
                    continue;
254
 
254
 
255
                float up1Left = up1.at<float>(row,col1);
255
                float up1Left = up1.at<float>(row,col1);
256
                float up1Right = up1.at<float>(row,col1+1);
256
                float up1Right = up1.at<float>(row,col1+1);
257
 
257
 
258
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1) && (up1Right-up0i < 1)){
258
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0) && (up1Right-up1Left > 0.1)){
259
 
259
 
260
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
260
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
261
 
261
 
262
                    q0.push_back(cv::Point2f(col, row));
262
                    q0.push_back(cv::Point2f(col, row));
263
                    q1.push_back(cv::Point2f(col1i, row));
263
                    q1.push_back(cv::Point2f(col1i, row));
264
 
264
 
265
                    break;
265
                    break;
266
                }
266
                }
267
            }
267
            }
268
        }
268
        }
269
    }
269
    }
270
 
270
 
271
 
271
 
272
    int nMatches = q0.size();
272
    int nMatches = q0.size();
273
 
273
 
274
    if(nMatches < 1){
274
    if(nMatches < 1){
275
        Q.resize(0);
275
        Q.resize(0);
276
        color.resize(0);
276
        color.resize(0);
277
 
277
 
278
        return;
278
        return;
279
    }
279
    }
280
 
280
 
281
    // Retrieve color information
281
    // Retrieve color information
282
    color.resize(nMatches);
282
    color.resize(nMatches);
283
    for(int i=0; i<nMatches; i++){
283
    for(int i=0; i<nMatches; i++){
284
 
284
 
285
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
285
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
286
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
286
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
287
 
287
 
288
        color[i] = 0.5*c0 + 0.5*c1;
288
        color[i] = 0.5*c0 + 0.5*c1;
289
    }
289
    }
290
 
290
 
291
    // Triangulate points
291
    // Triangulate points
292
    cv::Mat QMatHomogenous, QMat;
292
    cv::Mat QMatHomogenous, QMat;
293
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
293
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
294
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
294
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
295
 
295
 
296
    // Undo rectification
296
    // Undo rectification
297
    cv::Mat R0Inv;
297
    cv::Mat R0Inv;
298
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
298
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
299
    QMat = R0Inv*QMat;
299
    QMat = R0Inv*QMat;
300
 
300
 
301
    cvtools::matToPoints3f(QMat, Q);
301
    cvtools::matToPoints3f(QMat, Q);
302
 
302
 
303
}
303
}
304
 
304