Subversion Repositories seema-scanner

Rev

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

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