Subversion Repositories seema-scanner

Rev

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

Rev 233 Rev 234
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
-
 
5
// principle for 3D-measurement", SPIE (1997).
-
 
6
//
5
// Different from the paper, it uses only two different frequencies.
7
// Different from the paper, it uses only two different frequencies.
6
//
8
//
7
// The number of periods in the primary frequency can be chosen freely, but small changes can have a considerable impact on quality.
9
// The number of periods in the primary frequency can be chosen freely, but
-
 
10
// small changes can have a considerable impact on quality. The number of
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.
11
// phase shifts can be chosen freely (min. 3), and higher values reduce the
-
 
12
// effects of image noise.They also allow us to filter bad points based on
-
 
13
// energy at non-primary frequencies.
9
//
14
//
10
 
15
 
11
#include "AlgorithmPhaseShiftTwoFreq.h"
16
#include "AlgorithmPhaseShiftTwoFreq.h"
12
#include <math.h>
17
#include <math.h>
13
 
18
 
14
#include "cvtools.h"
19
#include "cvtools.h"
15
#include "algorithmtools.h"
20
#include "algorithmtools.h"
16
 
21
 
17
#include <omp.h>
22
#include <omp.h>
18
 
23
 
19
static unsigned int nStepsPrimary = 16; // number of shifts/steps in primary
24
static unsigned int nStepsPrimary = 16; // number of shifts/steps in primary
20
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
25
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
21
static float nPeriodsPrimary = 40; // primary period
26
static float nPeriodsPrimary = 40; // primary period
22
 
27
 
23
AlgorithmPhaseShiftTwoFreq::AlgorithmPhaseShiftTwoFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
28
AlgorithmPhaseShiftTwoFreq::AlgorithmPhaseShiftTwoFreq(unsigned int _screenCols,
-
 
29
                                                       unsigned int _screenRows)
-
 
30
    : Algorithm(_screenCols, _screenRows) {
24
 
31
 
25
    // Set N
32
    // Set N
26
    N = 2+nStepsPrimary+nStepsSecondary;
33
    N = 2+nStepsPrimary+nStepsSecondary;
27
 
34
 
28
    // Determine the secondary (wider) period to fulfill the heterodyne condition
35
    // Determine the secondary (wider) period to fulfill the heterodyne condition
29
    float nPeriodsSecondary = nPeriodsPrimary + 1;
36
    float nPeriodsSecondary = nPeriodsPrimary + 1;
30
 
37
 
31
    // all on pattern
38
    // all on pattern
32
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
39
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
33
    patterns.push_back(allOn);
40
    patterns.push_back(allOn);
34
 
41
 
35
    // all off pattern
42
    // all off pattern
36
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
43
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
37
    patterns.push_back(allOff);
44
    patterns.push_back(allOff);
38
 
45
 
39
    // Primary encoding patterns
46
    // Primary encoding patterns
40
    for(unsigned int i=0; i<nStepsPrimary; i++){
47
    for(unsigned int i=0; i<nStepsPrimary; i++){
41
        float phase = 2.0*CV_PI/nStepsPrimary * i;
48
        float phase = 2.0*CV_PI/nStepsPrimary * i;
42
        float pitch = screenCols/nPeriodsPrimary;
49
        float pitch = screenCols/nPeriodsPrimary;
43
        cv::Mat patternI(1,1,CV_8U);
50
        cv::Mat patternI(1,1,CV_8U);
44
        patternI = computePhaseVector(screenCols, phase, pitch);
51
        patternI = computePhaseVector(screenCols, phase, pitch);
45
        patterns.push_back(patternI.t());
52
        patterns.push_back(patternI.t());
46
    }
53
    }
47
 
54
 
48
    // Secondary encoding patterns
55
    // Secondary encoding patterns
49
    for(unsigned int i=0; i<nStepsSecondary; i++){
56
    for(unsigned int i=0; i<nStepsSecondary; i++){
50
        float phase = 2.0*CV_PI/nStepsSecondary * i;
57
        float phase = 2.0*CV_PI/nStepsSecondary * i;
51
        float pitch = screenCols/nPeriodsSecondary;
58
        float pitch = screenCols/nPeriodsSecondary;
52
        cv::Mat patternI(1,1,CV_8U);
59
        cv::Mat patternI(1,1,CV_8U);
53
        patternI = computePhaseVector(screenCols, phase, pitch);
60
        patternI = computePhaseVector(screenCols, phase, pitch);
54
        patterns.push_back(patternI.t());
61
        patterns.push_back(patternI.t());
55
    }
62
    }
56
 
63
 
57
 
64
 
58
}
65
}
59
 
66
 
60
cv::Mat AlgorithmPhaseShiftTwoFreq::getEncodingPattern(unsigned int depth){
67
cv::Mat AlgorithmPhaseShiftTwoFreq::getEncodingPattern(unsigned int depth){
61
    return patterns[depth];
68
    return patterns[depth];
62
}
69
}
63
 
70
 
64
 
71
 
65
struct StereoRectifyier {
72
struct StereoRectifyier {
66
    cv::Mat map0X, map0Y, map1X, map1Y;
73
    cv::Mat map0X, map0Y, map1X, map1Y;
67
    cv::Mat R0, R1, P0, P1, QRect;
74
    cv::Mat R0, R1, P0, P1, QRect;
68
};
75
};
69
static void getStereoRectifyier(const SMCalibrationParameters &calibration,
76
static void getStereoRectifyier(const SMCalibrationParameters &calibration,
70
                                const cv::Size& frameSize,
77
                                const cv::Size& frameSize,
71
                                StereoRectifyier& stereoRect);
78
                                StereoRectifyier& stereoRect);
72
static void determineAmplitudePhaseEnergy(std::vector<cv::Mat>& frames,
79
static void determineAmplitudePhaseEnergy(std::vector<cv::Mat>& frames,
73
                                    cv::Mat& amplitude, cv::Mat& phase, cv::Mat& energy);
80
                                    cv::Mat& amplitude,
-
 
81
                                    cv::Mat& phase,
-
 
82
                                    cv::Mat& energy);
74
static void collectPhases(const cv::Mat& phasePrimary, const cv::Mat& phaseSecondary,
83
static void collectPhases(const cv::Mat& phasePrimary,
-
 
84
                          const cv::Mat& phaseSecondary,
75
                          cv::Mat& phase);
85
                          cv::Mat& phase);
76
static void matchPhaseMaps(const cv::Mat& occlusion0, const cv::Mat& occlusion1,
86
static void matchPhaseMaps(const cv::Mat& occlusion0, const cv::Mat& occlusion1,
77
                           const cv::Mat& phase0, const cv::Mat& phase1,
87
                           const cv::Mat& phase0, const cv::Mat& phase1,
78
                           std::vector<cv::Vec2f>& q0, std::vector<cv::Vec2f>& q1);
88
                           std::vector<cv::Vec2f>& q0, std::vector<cv::Vec2f>& q1);
79
static void triangulate(const StereoRectifyier& stereoRect,
89
static void triangulate(const StereoRectifyier& stereoRect,
80
                        const std::vector<cv::Vec2f>& q0,
90
                        const std::vector<cv::Vec2f>& q0,
81
                        const std::vector<cv::Vec2f>& q1,
91
                        const std::vector<cv::Vec2f>& q1,
82
                        std::vector<cv::Point3f>& Q);
92
                        std::vector<cv::Point3f>& Q);
83
 
93
 
84
 
94
 
-
 
95
void AlgorithmPhaseShiftTwoFreq::
85
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){
96
    get3DPoints(const SMCalibrationParameters & calibration,
-
 
97
                const std::vector<cv::Mat>& frames0,
-
 
98
                const std::vector<cv::Mat>& frames1,
-
 
99
                std::vector<cv::Point3f>& Q,
-
 
100
                std::vector<cv::Vec3b>& color){
86
 
101
 
87
    assert(frames0.size() == N);
102
    assert(frames0.size() == N);
88
    assert(frames1.size() == N);
103
    assert(frames1.size() == N);
89
 
104
 
90
    StereoRectifyier stereoRect;
105
    StereoRectifyier stereoRect;
-
 
106
    getStereoRectifyier(calibration,
91
    getStereoRectifyier(calibration, cv::Size(frames0[0].cols, frames0[0].rows), stereoRect);
107
                        cv::Size(frames0[0].cols, frames0[0].rows),
-
 
108
                        stereoRect);
92
 
109
 
93
    // // Erode occlusion masks
110
    // // Erode occlusion masks
94
    // cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
111
    // cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
95
 
112
 
96
    cv::Mat up0, up1;
113
    cv::Mat up0, up1;
97
    cv::Mat occlusion0, occlusion1;
114
    cv::Mat occlusion0, occlusion1;
98
    cv::Mat color0, color1;
115
    cv::Mat color0, color1;
99
 
116
 
100
    #pragma omp parallel sections
117
    #pragma omp parallel sections
101
    {
118
    {
102
        #pragma omp section
119
        #pragma omp section
103
        {
120
        {
104
 
121
 
105
            // Gray-scale and remap/rectify
122
            // Gray-scale and remap/rectify
106
            std::vector<cv::Mat> frames0Rect(N);
123
            std::vector<cv::Mat> frames0Rect(N);
107
 
124
 
108
            for(unsigned int i=0; i<N; i++){
125
            for(unsigned int i=0; i<N; i++){
109
                cv::Mat temp;
126
                cv::Mat temp;
110
                cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
127
                cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
-
 
128
                cv::remap(temp, frames0Rect[i],
111
                cv::remap(temp, frames0Rect[i], stereoRect.map0X, stereoRect.map0Y, CV_INTER_LINEAR);
129
                          stereoRect.map0X, stereoRect.map0Y,
-
 
130
                          CV_INTER_LINEAR);
112
            }
131
            }
113
 
132
 
-
 
133
            cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
-
 
134
            cv::remap(color0, color0,
-
 
135
                      stereoRect.map1X, stereoRect.map1Y,
-
 
136
                      CV_INTER_LINEAR);
-
 
137
 
114
            // Occlusion masks
138
            // Occlusion masks
115
            cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
139
            cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
116
            occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
140
            occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
117
 
141
 
118
            // Decode camera0
142
            // Decode camera0
119
            std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
143
            std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2,
-
 
144
                                                frames0Rect.begin()+2+nStepsPrimary);
120
            std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end());
145
            std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary,
-
 
146
                                                  frames0Rect.end());
121
 
147
 
122
            frames0Rect.clear();
148
            frames0Rect.clear();
123
 
149
 
124
            cv::Mat amplitude0Primary, amplitude0Secondary;
150
            cv::Mat amplitude0Primary, amplitude0Secondary;
125
            cv::Mat up0Primary, up0Secondary;
151
            cv::Mat up0Primary, up0Secondary;
126
            cv::Mat energy0Primary, energy0Secondary;
152
            cv::Mat energy0Primary, energy0Secondary;
127
            determineAmplitudePhaseEnergy(frames0Primary,
153
            determineAmplitudePhaseEnergy(frames0Primary,
128
                                          amplitude0Primary, up0Primary, energy0Primary);
154
                                          amplitude0Primary,
-
 
155
                                          up0Primary,
-
 
156
                                          energy0Primary);
129
            determineAmplitudePhaseEnergy(frames0Secondary,
157
            determineAmplitudePhaseEnergy(frames0Secondary,
130
                                          amplitude0Secondary, up0Secondary, energy0Secondary);
158
                                          amplitude0Secondary,
-
 
159
                                          up0Secondary,
-
 
160
                                          energy0Secondary);
131
 
161
 
132
            collectPhases(up0Primary, up0Secondary, up0);
162
            collectPhases(up0Primary, up0Secondary, up0);
133
 
163
 
134
            // Threshold on energy at primary frequency
164
            // Threshold on energy at primary frequency
135
            occlusion0 = occlusion0 & (amplitude0Primary > 5.0*nStepsPrimary);
165
            occlusion0 = occlusion0 & (amplitude0Primary > 5.0*nStepsPrimary);
136
            // Threshold on energy ratios
166
            // Threshold on energy ratios
137
            occlusion0 = occlusion0 & (amplitude0Primary > 0.25*energy0Primary);
167
            occlusion0 = occlusion0 & (amplitude0Primary > 0.25*energy0Primary);
138
            occlusion0 = occlusion0 & (amplitude0Secondary > 0.25*energy0Secondary);
168
            occlusion0 = occlusion0 & (amplitude0Secondary > 0.25*energy0Secondary);
139
 
169
 
140
            // // Erode occlusion masks
170
            // // Erode occlusion masks
141
            // cv::erode(occlusion0, occlusion0, strel);
171
            // cv::erode(occlusion0, occlusion0, strel);
142
 
172
 
143
            // Threshold on gradient of phase
173
            // Threshold on gradient of phase
144
            cv::Mat edges0;
174
            cv::Mat edges0;
145
            cv::Sobel(up0, edges0, -1, 1, 1, 5);
175
            cv::Sobel(up0, edges0, -1, 1, 1, 5);
146
            occlusion0 = occlusion0 & (abs(edges0) < 10);
176
            occlusion0 = occlusion0 & (abs(edges0) < 10);
147
 
177
 
148
            #ifdef SM_DEBUG
178
            #ifdef SM_DEBUG
149
                cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
179
                cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
150
                cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
180
                cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
151
                cvtools::writeMat(up0, "up0.mat", "up0");
181
                cvtools::writeMat(up0, "up0.mat", "up0");
-
 
182
                cvtools::writeMat(amplitude0Primary,
152
                cvtools::writeMat(amplitude0Primary, "amplitude0Primary.mat", "amplitude0Primary");
183
                                  "amplitude0Primary.mat", "amplitude0Primary");
-
 
184
                cvtools::writeMat(amplitude0Secondary,
153
                cvtools::writeMat(amplitude0Secondary, "amplitude0Secondary.mat", "amplitude0Secondary");
185
                                  "amplitude0Secondary.mat", "amplitude0Secondary");
-
 
186
                cvtools::writeMat(energy0Primary,
154
                cvtools::writeMat(energy0Primary, "energy0Primary.mat", "energy0Primary");
187
                                  "energy0Primary.mat", "energy0Primary");
-
 
188
                cvtools::writeMat(energy0Secondary,
155
                cvtools::writeMat(energy0Secondary, "energy0Secondary.mat", "energy0Secondary");
189
                                  "energy0Secondary.mat", "energy0Secondary");
156
                cvtools::writeMat(edges0, "edges0.mat", "edges0");
190
                cvtools::writeMat(edges0, "edges0.mat", "edges0");
157
                cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
191
                cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
-
 
192
                cvtools::writeMat(color0, "color0.mat", "color0");
158
            #endif
193
            #endif
159
 
194
 
160
        }
195
        }
161
        #pragma omp section
196
        #pragma omp section
162
        {
197
        {
163
 
198
 
164
            // Gray-scale and remap
199
            // Gray-scale and remap
165
            std::vector<cv::Mat> frames1Rect(N);
200
            std::vector<cv::Mat> frames1Rect(N);
166
 
201
 
167
            for(unsigned int i=0; i<N; i++){
202
            for(unsigned int i=0; i<N; i++){
168
                cv::Mat temp;
203
                cv::Mat temp;
169
                cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
204
                cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
-
 
205
                cv::remap(temp, frames1Rect[i],
170
                cv::remap(temp, frames1Rect[i], stereoRect.map1X, stereoRect.map1Y, CV_INTER_LINEAR);
206
                          stereoRect.map1X, stereoRect.map1Y,
-
 
207
                          CV_INTER_LINEAR);
171
            }
208
            }
172
 
209
 
-
 
210
            cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
-
 
211
            cv::remap(color1, color1,
-
 
212
                      stereoRect.map1X, stereoRect.map1Y,
-
 
213
                      CV_INTER_LINEAR);
-
 
214
 
173
            // Occlusion masks
215
            // Occlusion masks
174
            cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
216
            cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
175
            occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
217
            occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
176
 
218
 
177
            // Decode camera1
219
            // Decode camera1
178
            std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
220
            std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2,
-
 
221
                                                frames1Rect.begin()+2+nStepsPrimary);
179
            std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
222
            std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary,
-
 
223
                                                  frames1Rect.end());
180
 
224
 
181
            frames1Rect.clear();
225
            frames1Rect.clear();
182
 
226
 
183
            cv::Mat amplitude1Primary, amplitude1Secondary;
227
            cv::Mat amplitude1Primary, amplitude1Secondary;
184
            cv::Mat up1Primary, up1Secondary;
228
            cv::Mat up1Primary, up1Secondary;
185
            cv::Mat energy1Primary, energy1Secondary;
229
            cv::Mat energy1Primary, energy1Secondary;
186
            determineAmplitudePhaseEnergy(frames1Primary,
230
            determineAmplitudePhaseEnergy(frames1Primary,
187
                                          amplitude1Primary, up1Primary, energy1Primary);
231
                                          amplitude1Primary,
-
 
232
                                          up1Primary,
-
 
233
                                          energy1Primary);
188
            determineAmplitudePhaseEnergy(frames1Secondary,
234
            determineAmplitudePhaseEnergy(frames1Secondary,
189
                                          amplitude1Secondary, up1Secondary, energy1Secondary);
235
                                          amplitude1Secondary,
-
 
236
                                          up1Secondary,
-
 
237
                                          energy1Secondary);
190
 
238
 
191
            collectPhases(up1Primary, up1Secondary, up1);
239
            collectPhases(up1Primary, up1Secondary, up1);
192
 
240
 
193
            // Threshold on energy at primary frequency
241
            // Threshold on energy at primary frequency
194
            occlusion1 = occlusion1 & (amplitude1Primary > 5.0*nStepsPrimary);
242
            occlusion1 = occlusion1 & (amplitude1Primary > 5.0*nStepsPrimary);
195
            // Threshold on energy ratios
243
            // Threshold on energy ratios
196
            occlusion1 = occlusion1 & (amplitude1Primary > 0.25*energy1Primary);
244
            occlusion1 = occlusion1 & (amplitude1Primary > 0.25*energy1Primary);
197
            occlusion1 = occlusion1 & (amplitude1Secondary > 0.25*energy1Secondary);
245
            occlusion1 = occlusion1 & (amplitude1Secondary > 0.25*energy1Secondary);
198
 
246
 
199
            // // Erode occlusion masks
247
            // // Erode occlusion masks
200
            // cv::erode(occlusion1, occlusion1, strel);
248
            // cv::erode(occlusion1, occlusion1, strel);
201
 
249
 
202
 
250
 
203
            // Threshold on gradient of phase
251
            // Threshold on gradient of phase
204
            cv::Mat edges1;
252
            cv::Mat edges1;
205
            cv::Sobel(up1, edges1, -1, 1, 1, 5);
253
            cv::Sobel(up1, edges1, -1, 1, 1, 5);
206
            occlusion1 = occlusion1 & (abs(edges1) < 10);
254
            occlusion1 = occlusion1 & (abs(edges1) < 10);
207
 
255
 
208
            #ifdef SM_DEBUG
256
            #ifdef SM_DEBUG
209
                cvtools::writeMat(up1Primary, "up1Primary.mat", "up1Primary");
257
                cvtools::writeMat(up1Primary, "up1Primary.mat", "up1Primary");
210
                cvtools::writeMat(up1Secondary, "up1Secondary.mat", "up1Secondary");
258
                cvtools::writeMat(up1Secondary, "up1Secondary.mat", "up1Secondary");
211
                cvtools::writeMat(up1, "up1.mat", "up1");
259
                cvtools::writeMat(up1, "up1.mat", "up1");
-
 
260
                cvtools::writeMat(amplitude1Primary,
212
                cvtools::writeMat(amplitude1Primary, "amplitude1Primary.mat", "amplitude1Primary");
261
                                  "amplitude1Primary.mat", "amplitude1Primary");
-
 
262
                cvtools::writeMat(amplitude1Secondary,
213
                cvtools::writeMat(amplitude1Secondary, "amplitude1Secondary.mat", "amplitude1Secondary");
263
                                  "amplitude1Secondary.mat", "amplitude1Secondary");
-
 
264
                cvtools::writeMat(energy1Primary,
214
                cvtools::writeMat(energy1Primary, "energy1Primary.mat", "energy1Primary");
265
                                  "energy1Primary.mat", "energy1Primary");
-
 
266
                cvtools::writeMat(energy1Secondary,
215
                cvtools::writeMat(energy1Secondary, "energy1Secondary.mat", "energy1Secondary");
267
                                  "energy1Secondary.mat", "energy1Secondary");
216
                cvtools::writeMat(edges1, "edges1.mat", "edges1");
268
                cvtools::writeMat(edges1, "edges1.mat", "edges1");
217
                cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
269
                cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
-
 
270
                cvtools::writeMat(color1, "color1.mat", "color1");
218
            #endif
271
            #endif
219
 
272
 
220
        }
273
        }
221
    }
274
    }
222
 
275
 
223
 
276
 
224
    // Match phase maps
277
    // Match phase maps
225
 
278
 
226
    // camera0 against camera1
279
    // camera0 against camera1
227
    std::vector<cv::Vec2f> q0, q1;
280
    std::vector<cv::Vec2f> q0, q1;
228
    matchPhaseMaps(occlusion0, occlusion1, up0, up1, q0, q1);
281
    matchPhaseMaps(occlusion0, occlusion1, up0, up1, q0, q1);
229
 
282
 
230
    size_t nMatches = q0.size();
283
    size_t nMatches = q0.size();
231
 
284
 
232
    if(nMatches < 1){
285
    if(nMatches < 1){
233
        Q.resize(0);
286
        Q.resize(0);
234
        color.resize(0);
287
        color.resize(0);
235
 
288
 
236
        return;
289
        return;
237
    }
290
    }
238
    {
291
    else {
239
        // color debayer and remap/rectify
-
 
240
 
-
 
241
        cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
-
 
242
        cv::remap(color1, color1, stereoRect.map1X, stereoRect.map1Y, CV_INTER_LINEAR);
-
 
243
 
-
 
244
        #ifdef SM_DEBUG
-
 
245
            cvtools::writeMat(color0, "color0.mat", "color0");
-
 
246
            cvtools::writeMat(color1, "color1.mat", "color1");
-
 
247
        #endif
-
 
248
 
-
 
249
        // Retrieve color information
292
        // Retrieve color information
250
        color.resize(nMatches);
293
        color.resize(nMatches);
251
        for(unsigned int i=0; i<nMatches; i++){
294
        for(unsigned int i=0; i<nMatches; i++){
252
 
295
 
253
            cv::Vec3b c0 = color0.at<cv::Vec3b>(int(q0[i][1]), int(q0[i][0]));
296
            cv::Vec3b c0 = color0.at<cv::Vec3b>(int(q0[i][1]), int(q0[i][0]));
254
            cv::Vec3b c1 = color1.at<cv::Vec3b>(int(q1[i][1]), int(q1[i][0]));
297
            cv::Vec3b c1 = color1.at<cv::Vec3b>(int(q1[i][1]), int(q1[i][0]));
255
 
298
 
256
            color[i] = 0.5*c0 + 0.5*c1;
299
            color[i] = 0.5*c0 + 0.5*c1;
257
        }
300
        }
258
    }
301
    }
259
 
302
 
260
    // Triangulate points
303
    // Triangulate points
261
    triangulate(stereoRect, q0, q1, Q);
304
    triangulate(stereoRect, q0, q1, Q);
262
 
305
 
263
}
306
}
264
 
307
 
265
void getStereoRectifyier(const SMCalibrationParameters &calibration, const cv::Size& frameSize, StereoRectifyier& stereoRect){
308
void getStereoRectifyier(const SMCalibrationParameters &calibration,
-
 
309
                         const cv::Size& frameSize,
-
 
310
                         StereoRectifyier& stereoRect){
266
 
311
 
267
    // cv::stereoRectify segfaults unless R is double precision
312
    // cv::stereoRectify segfaults unless R is double precision
268
    cv::Mat R, T;
313
    cv::Mat R, T;
269
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
314
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
270
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
315
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
271
 
316
 
272
    cv::stereoRectify(calibration.K0, calibration.k0,
317
    cv::stereoRectify(calibration.K0, calibration.k0,
273
                      calibration.K1, calibration.k1,
318
                      calibration.K1, calibration.k1,
274
                      frameSize, R, T,
319
                      frameSize, R, T,
275
                      stereoRect.R0, stereoRect.R1,
320
                      stereoRect.R0, stereoRect.R1,
276
                      stereoRect.P0, stereoRect.P1,
321
                      stereoRect.P0, stereoRect.P1,
277
                      stereoRect.QRect, 0);
322
                      stereoRect.QRect, 0);
278
 
323
 
279
    // Interpolation maps (lens distortion and rectification)
324
    // Interpolation maps (lens distortion and rectification)
280
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0,
325
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0,
281
                                stereoRect.R0, stereoRect.P0,
326
                                stereoRect.R0, stereoRect.P0,
282
                                frameSize, CV_32F,
327
                                frameSize, CV_32F,
283
                                stereoRect.map0X, stereoRect.map0Y);
328
                                stereoRect.map0X, stereoRect.map0Y);
284
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1,
329
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1,
285
                                stereoRect.R1, stereoRect.P1,
330
                                stereoRect.R1, stereoRect.P1,
286
                                frameSize, CV_32F,
331
                                frameSize, CV_32F,
287
                                stereoRect.map1X, stereoRect.map1Y);
332
                                stereoRect.map1X, stereoRect.map1Y);
288
}
333
}
289
 
334
 
290
void determineAmplitudePhaseEnergy(std::vector<cv::Mat>& frames,
335
void determineAmplitudePhaseEnergy(std::vector<cv::Mat>& frames,
291
                                   cv::Mat& amplitude, cv::Mat& phase, cv::Mat& energy) {
336
                                   cv::Mat& amplitude,
-
 
337
                                   cv::Mat& phase,
-
 
338
                                   cv::Mat& energy) {
292
 
339
 
293
    std::vector<cv::Mat> fourier = getDFTComponents(frames);
340
    std::vector<cv::Mat> fourier = getDFTComponents(frames);
294
 
341
 
295
    cv::phase(fourier[2], -fourier[3], phase);
342
    cv::phase(fourier[2], -fourier[3], phase);
296
 
343
 
297
    // Signal energy at unit frequency
344
    // Signal energy at unit frequency
298
    cv::magnitude(fourier[2], -fourier[3], amplitude);
345
    cv::magnitude(fourier[2], -fourier[3], amplitude);
299
 
346
 
300
    // Collected signal energy at higher frequencies
347
    // Collected signal energy at higher frequencies
301
    energy = cv::Mat(phase.rows, phase.cols, CV_32F, cv::Scalar(0.0));
348
    energy = cv::Mat(phase.rows, phase.cols, CV_32F, cv::Scalar(0.0));
302
 
349
 
303
    for(unsigned int i=0; i<frames.size()-1; i++){
350
    for(unsigned int i=0; i<frames.size()-1; i++){
304
        cv::Mat magnitude;
351
        cv::Mat magnitude;
305
        cv::magnitude(fourier[i*2 + 2], fourier[i*2 + 3], magnitude);
352
        cv::magnitude(fourier[i*2 + 2], fourier[i*2 + 3], magnitude);
306
        cv::add(energy, magnitude, energy, cv::noArray(), CV_32F);
353
        cv::add(energy, magnitude, energy, cv::noArray(), CV_32F);
307
    }
354
    }
308
 
355
 
309
    frames.clear();
356
    frames.clear();
310
}
357
}
311
 
358
 
312
void collectPhases(const cv::Mat& phasePrimary, const cv::Mat& phaseSecondary,
359
void collectPhases(const cv::Mat& phasePrimary,
-
 
360
                   const cv::Mat& phaseSecondary,
313
                   cv::Mat& phase) {
361
                   cv::Mat& phase) {
314
    cv::Mat phaseEquivalent = phaseSecondary - phasePrimary;
362
    cv::Mat phaseEquivalent = phaseSecondary - phasePrimary;
315
    phaseEquivalent = cvtools::modulo(phaseEquivalent, 2.0*CV_PI);
363
    phaseEquivalent = cvtools::modulo(phaseEquivalent, 2.0*CV_PI);
316
    phase = unwrapWithCue(phasePrimary, phaseEquivalent, nPeriodsPrimary);
364
    phase = unwrapWithCue(phasePrimary, phaseEquivalent, nPeriodsPrimary);
317
    phase *= phasePrimary.cols/(2.0*CV_PI);
365
    phase *= phasePrimary.cols/(2.0*CV_PI);
318
}
366
}
319
 
367
 
320
 
368
 
321
void matchPhaseMaps(const cv::Mat& occlusion0, const cv::Mat& occlusion1,
369
void matchPhaseMaps(const cv::Mat& occlusion0, const cv::Mat& occlusion1,
322
                    const cv::Mat& phase0, const cv::Mat& phase1,
370
                    const cv::Mat& phase0, const cv::Mat& phase1,
323
                    std::vector<cv::Vec2f>& q0, std::vector<cv::Vec2f>& q1) {
371
                    std::vector<cv::Vec2f>& q0, std::vector<cv::Vec2f>& q1) {
324
 
372
 
325
    #pragma omp parallel for
373
    #pragma omp parallel for
326
    for(int row=0; row<occlusion0.rows; row++){
374
    for(int row=0; row<occlusion0.rows; row++){
327
        for(int col=0; col<occlusion0.cols; col++){
375
        for(int col=0; col<occlusion0.cols; col++){
328
 
376
 
329
            if(!occlusion0.at<char>(row,col))
377
            if(!occlusion0.at<char>(row,col))
330
                continue;
378
                continue;
331
 
379
 
332
            float phase0i = phase0.at<float>(row,col);
380
            float phase0i = phase0.at<float>(row,col);
333
            for(int col1=0; col1<phase1.cols-1; col1++){
381
            for(int col1=0; col1<phase1.cols-1; col1++){
334
 
382
 
335
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
383
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
336
                    continue;
384
                    continue;
337
 
385
 
338
                float phase1Left = phase1.at<float>(row,col1);
386
                float phase1Left = phase1.at<float>(row,col1);
339
                float phase1Right = phase1.at<float>(row,col1+1);
387
                float phase1Right = phase1.at<float>(row,col1+1);
340
 
388
 
341
                bool match = (phase1Left <= phase0i)
389
                bool match = (phase1Left <= phase0i)
342
                              && (phase0i <= phase1Right)
390
                              && (phase0i <= phase1Right)
343
                              && (phase0i-phase1Left < 1.0)
391
                              && (phase0i-phase1Left < 1.0)
344
                              && (phase1Right-phase0i < 1.0)
392
                              && (phase1Right-phase0i < 1.0)
345
                              && (phase1Right-phase1Left > 0.1);
393
                              && (phase1Right-phase1Left > 0.1);
346
 
394
 
347
                if(match){
395
                if(match){
348
 
396
 
349
                    float col1i = col1 + (phase0i-phase1Left)/(phase1Right-phase1Left);
397
                    float col1i = col1 + (phase0i-phase1Left)/(phase1Right-phase1Left);
350
 
398
 
351
                    #pragma omp critical
399
                    #pragma omp critical
352
                    {
400
                    {
353
                    q0.push_back(cv::Point2f(col, row));
401
                    q0.push_back(cv::Point2f(col, row));
354
                    q1.push_back(cv::Point2f(col1i, row));
402
                    q1.push_back(cv::Point2f(col1i, row));
355
                    }
403
                    }
356
                    break;
404
                    break;
357
                }
405
                }
358
            }
406
            }
359
        }
407
        }
360
    }
408
    }
361
 
409
 
362
}
410
}
363
 
411
 
364
void triangulate(const StereoRectifyier& stereoRect,
412
void triangulate(const StereoRectifyier& stereoRect,
365
                 const std::vector<cv::Vec2f>& q0,
413
                 const std::vector<cv::Vec2f>& q0,
366
                 const std::vector<cv::Vec2f>& q1,
414
                 const std::vector<cv::Vec2f>& q1,
367
                 std::vector<cv::Point3f>& Q) {
415
                 std::vector<cv::Point3f>& Q) {
368
 
416
 
369
    // cv::Mat QMatHomogenous, QMat;
417
    // cv::Mat QMatHomogenous, QMat;
370
    // cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
418
    // cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
371
    // cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
419
    // cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
372
 
420
 
373
    // // Undo rectification
421
    // // Undo rectification
374
    // cv::Mat R0Inv;
422
    // cv::Mat R0Inv;
375
    // cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
423
    // cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
376
    // QMat = R0Inv*QMat;
424
    // QMat = R0Inv*QMat;
377
 
425
 
378
    // cvtools::matToPoints3f(QMat, Q);
426
    // cvtools::matToPoints3f(QMat, Q);
379
 
427
 
380
 
428
 
381
    // Triangulate by means of disparity projection
429
    // Triangulate by means of disparity projection
382
    Q.resize(q0.size());
430
    Q.resize(q0.size());
383
    cv::Matx44f QRectx = cv::Matx44f(stereoRect.QRect);
431
    cv::Matx44f QRectx = cv::Matx44f(stereoRect.QRect);
384
    cv::Matx33f R0invx = cv::Matx33f(cv::Mat(stereoRect.R0.t()));
432
    cv::Matx33f R0invx = cv::Matx33f(cv::Mat(stereoRect.R0.t()));
385
 
433
 
386
    #pragma omp parallel for
434
    #pragma omp parallel for
387
    for(unsigned int i=0; i < q0.size(); i++){
435
    for(unsigned int i=0; i < q0.size(); i++){
388
        float disparity = q0[i][0] - q1[i][0];
436
        float disparity = q0[i][0] - q1[i][0];
389
        cv::Vec4f Qih = QRectx*cv::Vec4f(q0[i][0], q0[i][1], disparity, 1.0);
437
        cv::Vec4f Qih = QRectx*cv::Vec4f(q0[i][0], q0[i][1], disparity, 1.0);
390
        float winv = float(1.0) / Qih[3];
438
        float winv = float(1.0) / Qih[3];
391
        Q[i] = R0invx * cv::Point3f(Qih[0]*winv, Qih[1]*winv, Qih[2]*winv);
439
        Q[i] = R0invx * cv::Point3f(Qih[0]*winv, Qih[1]*winv, Qih[2]*winv);
392
    }
440
    }
393
}
441
}
394
 
442