Subversion Repositories seema-scanner

Rev

Rev 233 | Rev 235 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 233 Rev 234
Line 1... Line 1...
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
 
Line 18... Line 23...
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
Line 68... Line 75...
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;
Line 106... Line 123...
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);
Line 147... Line 177...
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
        {
Line 165... Line 200...
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);
Line 207... Line 255...
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
 
Line 233... Line 286...
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]));
Line 260... Line 303...
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);
Line 286... Line 331...
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
 
Line 307... Line 354...
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);