Subversion Repositories seema-scanner

Rev

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

Rev 182 Rev 185
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 = 48; // 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
31
    float nPeriodsSecondary = (screenCols*nPeriodsPrimary)/(screenCols-nPeriodsPrimary);
31
    float nPeriodsSecondary = (screenCols*nPeriodsPrimary)/(screenCols-nPeriodsPrimary);
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 = 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 = 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 = up0Primary - up0Secondary;
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, (float)screenCols/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
-
 
142
        cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
-
 
143
        cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
-
 
144
        cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
-
 
145
        cvtools::writeMat(up0, "up0.mat", "up0");
-
 
146
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
-
 
147
        cvtools::writeMat(energy0Primary, "energy0Primary.mat", "energy0Primary");
-
 
148
        cvtools::writeMat(energy0Secondary, "energy0Secondary.mat", "energy0Secondary");
-
 
149
    #endif
-
 
150
 
141
    // Decode camera1
151
    // Decode camera1
142
    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);
143
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
153
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
144
 
154
 
145
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
155
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
146
    cv::Mat up1Primary;
156
    cv::Mat up1Primary;
147
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
157
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
148
 
158
 
149
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
159
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
150
    cv::Mat up1Secondary;
160
    cv::Mat up1Secondary;
151
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
161
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
152
 
162
 
153
    cv::Mat up1Equivalent = up1Primary - up1Secondary;
163
    cv::Mat up1Equivalent = up1Primary - up1Secondary;
154
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*pi);
164
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*pi);
155
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, (float)screenCols/nPeriodsPrimary);
165
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, (float)screenCols/nPeriodsPrimary);
156
    up1 *= screenCols/(2.0*pi);
166
    up1 *= screenCols/(2.0*pi);
157
    cv::Mat amplitude1;
167
    cv::Mat amplitude1;
158
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
168
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
159
 
169
 
160
    #ifdef Q_DEBUG
-
 
161
        cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
-
 
162
        cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
-
 
163
        cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
-
 
164
        cvtools::writeMat(up0, "up0.mat", "up0");
-
 
165
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
-
 
166
    #endif
-
 
167
 
-
 
168
    // Collected signal energy at higher frequencies
170
    // Collected signal energy at higher frequencies
169
    cv::Mat energy1Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
171
    cv::Mat energy1Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
170
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
172
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
171
        cv::Mat magnitude;
173
        cv::Mat magnitude;
172
        cv::magnitude(F1Primary[i*2 + 2], F1Primary[i*2 + 3], magnitude);
174
        cv::magnitude(F1Primary[i*2 + 2], F1Primary[i*2 + 3], magnitude);
173
        cv::add(energy1Primary, magnitude, energy1Primary, cv::noArray(), CV_32F);
175
        cv::add(energy1Primary, magnitude, energy1Primary, cv::noArray(), CV_32F);
174
    }
176
    }
175
 
177
 
176
    cv::Mat energy1Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
178
    cv::Mat energy1Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
177
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
179
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
178
        cv::Mat magnitude;
180
        cv::Mat magnitude;
179
        cv::magnitude(F1Secondary[i*2 + 2], F1Secondary[i*2 + 3], magnitude);
181
        cv::magnitude(F1Secondary[i*2 + 2], F1Secondary[i*2 + 3], magnitude);
180
        cv::add(energy1Secondary, magnitude, energy1Secondary, cv::noArray(), CV_32F);
182
        cv::add(energy1Secondary, magnitude, energy1Secondary, cv::noArray(), CV_32F);
181
    }
183
    }
182
 
184
 
-
 
185
    #ifdef QT_DEBUG
-
 
186
        cvtools::writeMat(up1, "up1.mat", "up1");
-
 
187
    #endif
-
 
188
 
183
    // color debayer and remap
189
    // color debayer and remap
184
    cv::Mat color0, color1;
190
    cv::Mat color0, color1;
185
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
191
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
186
    cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
192
    cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
187
 
193
 
188
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
194
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
189
    cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
195
    cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
190
 
196
 
191
    #ifdef Q_DEBUG
197
    #ifdef QT_DEBUG
192
        cvtools::writeMat(color0, "color0.mat", "color0");
198
        cvtools::writeMat(color0, "color0.mat", "color0");
193
        cvtools::writeMat(color1, "color1.mat", "color1");
199
        cvtools::writeMat(color1, "color1.mat", "color1");
194
    #endif
200
    #endif
195
 
201
 
196
    // Occlusion masks
202
    // Occlusion masks
197
    cv::Mat occlusion0, occlusion1;
203
    cv::Mat occlusion0, occlusion1;
198
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
204
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
199
    occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
205
    occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
200
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
206
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
201
    occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
207
    occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
202
 
208
 
203
    // Threshold on energy at primary frequency
209
    // Threshold on energy at primary frequency
204
    occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
210
    occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
205
    occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
211
    occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
206
 
212
 
207
    // Threshold on energy ratios
213
    // Threshold on energy ratios
208
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Primary);
214
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Primary);
209
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Secondary);
215
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Secondary);
210
 
216
 
211
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Primary);
217
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Primary);
212
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Secondary);
218
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Secondary);
213
 
219
 
214
//    // Erode occlusion masks
220
//    // Erode occlusion masks
215
//    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));
216
//    cv::erode(occlusion0, occlusion0, strel);
222
//    cv::erode(occlusion0, occlusion0, strel);
217
//    cv::erode(occlusion1, occlusion1, strel);
223
//    cv::erode(occlusion1, occlusion1, strel);
218
 
224
 
219
//    // Threshold on gradient of phase
225
//    // Threshold on gradient of phase
220
//    cv::Mat edges0;
226
//    cv::Mat edges0;
221
//    cv::Sobel(up0, edges0, -1, 1, 1, 5);
227
//    cv::Sobel(up0, edges0, -1, 1, 1, 5);
222
//    occlusion0 = occlusion0 & (abs(edges0) < 150);
228
//    occlusion0 = occlusion0 & (abs(edges0) < 150);
223
 
229
 
224
//    cv::Mat edges1;
230
//    cv::Mat edges1;
225
//    cv::Sobel(up1, edges1, -1, 1, 1, 5);
231
//    cv::Sobel(up1, edges1, -1, 1, 1, 5);
226
//    occlusion1 = occlusion1 & (abs(edges1) < 150);
232
//    occlusion1 = occlusion1 & (abs(edges1) < 150);
227
 
233
 
228
    #ifdef Q_DEBUG
234
    #ifdef QT_DEBUG
229
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
235
        cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
230
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
236
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
231
    #endif
237
    #endif
232
 
238
 
233
    // Match phase maps
239
    // Match phase maps
234
 
240
 
235
    // camera0 against camera1
241
    // camera0 against camera1
236
    std::vector<cv::Vec2f> q0, q1;
242
    std::vector<cv::Vec2f> q0, q1;
237
    for(int row=0; row<frameRectRows; row++){
243
    for(int row=0; row<frameRectRows; row++){
238
        for(int col=0; col<frameRectCols; col++){
244
        for(int col=0; col<frameRectCols; col++){
239
 
245
 
240
            if(!occlusion0.at<char>(row,col))
246
            if(!occlusion0.at<char>(row,col))
241
                continue;
247
                continue;
242
 
248
 
243
            float up0i = up0.at<float>(row,col);
249
            float up0i = up0.at<float>(row,col);
244
            for(int col1=0; col1<up1.cols-1; col1++){
250
            for(int col1=0; col1<up1.cols-1; col1++){
245
 
251
 
246
                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))
247
                    continue;
253
                    continue;
248
 
254
 
249
                float up1Left = up1.at<float>(row,col1);
255
                float up1Left = up1.at<float>(row,col1);
250
                float up1Right = up1.at<float>(row,col1+1);
256
                float up1Right = up1.at<float>(row,col1+1);
251
 
257
 
252
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1) && (up1Right-up0i < 1)){
258
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1) && (up1Right-up0i < 1)){
253
 
259
 
254
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
260
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
255
 
261
 
256
                    q0.push_back(cv::Point2f(col, row));
262
                    q0.push_back(cv::Point2f(col, row));
257
                    q1.push_back(cv::Point2f(col1i, row));
263
                    q1.push_back(cv::Point2f(col1i, row));
258
 
264
 
259
                    break;
265
                    break;
260
                }
266
                }
261
            }
267
            }
262
        }
268
        }
263
    }
269
    }
264
 
270
 
265
 
271
 
266
    int nMatches = q0.size();
272
    int nMatches = q0.size();
267
 
273
 
268
    if(nMatches < 1){
274
    if(nMatches < 1){
269
        Q.resize(0);
275
        Q.resize(0);
270
        color.resize(0);
276
        color.resize(0);
271
 
277
 
272
        return;
278
        return;
273
    }
279
    }
274
 
280
 
275
    // Retrieve color information
281
    // Retrieve color information
276
    color.resize(nMatches);
282
    color.resize(nMatches);
277
    for(int i=0; i<nMatches; i++){
283
    for(int i=0; i<nMatches; i++){
278
 
284
 
279
        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]);
280
        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]);
281
 
287
 
282
        color[i] = 0.5*c0 + 0.5*c1;
288
        color[i] = 0.5*c0 + 0.5*c1;
283
    }
289
    }
284
 
290
 
285
    // Triangulate points
291
    // Triangulate points
286
    cv::Mat QMatHomogenous, QMat;
292
    cv::Mat QMatHomogenous, QMat;
287
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
293
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
288
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
294
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
289
 
295
 
290
    // Undo rectification
296
    // Undo rectification
291
    cv::Mat R0Inv;
297
    cv::Mat R0Inv;
292
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
298
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
293
    QMat = R0Inv*QMat;
299
    QMat = R0Inv*QMat;
294
 
300
 
295
    cvtools::matToPoints3f(QMat, Q);
301
    cvtools::matToPoints3f(QMat, Q);
296
 
302
 
297
}
303
}
298
 
304