Subversion Repositories seema-scanner

Rev

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

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