Subversion Repositories seema-scanner

Rev

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

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