Subversion Repositories seema-scanner

Rev

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

Rev 179 Rev 182
-
 
1
//
-
 
2
// Three Frequency Phase Shifting using the Heterodyne Principle
-
 
3
//
-
 
4
// This implementation follows "Reich, Ritter, Thesing, White light heterodyne principle for 3D-measurement", SPIE (1997)
-
 
5
//
-
 
6
// The number of periods in the primary and secondary frequencies can be chosen freely, but small changes can have a considerable impact on quality.
-
 
7
// 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
//
-
 
9
 
-
 
10
 
1
#include "AlgorithmPhaseShiftThreeFreq.h"
11
#include "AlgorithmPhaseShiftThreeFreq.h"
2
#include <math.h>
12
#include <math.h>
3
 
13
 
4
#include "cvtools.h"
14
#include "cvtools.h"
-
 
15
#include "algorithmtools.h"
5
 
16
 
6
#ifndef M_PI
17
#ifndef M_PI
7
    #define M_PI 3.14159265358979323846
18
    #define M_PI 3.14159265358979323846
8
#endif
19
#endif
9
 
20
 
10
static unsigned int nStepsPrimary = 32; // number of shifts/steps in primary
21
static unsigned int nStepsPrimary = 8; // number of shifts/steps in primary
11
static unsigned int nStepsSecondary = 16; // number of shifts/steps in secondary
22
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
12
static unsigned int nStepsTertiary = 16; // number of shifts/steps in tertiary
23
static unsigned int nStepsTertiary = 8; // number of shifts/steps in tertiary
13
static float nPeriodPrimary = 256; // number of primary periods
24
static float nPeriodsPrimary = 24; // primary period
14
static float nPeriodSecondary = 16; // number of secondary periods
25
static float nPeriodsSecondary = 30; // primary period
15
 
-
 
16
// Algorithm
-
 
17
static cv::Mat computePhaseVector(unsigned int length, float phase, float pitch){
-
 
18
 
-
 
19
    cv::Mat phaseVector(length, 1, CV_8UC3);
-
 
20
    //phaseVector.setTo(0);
-
 
21
 
-
 
22
    const float pi = M_PI;
-
 
23
 
-
 
24
    // Loop through vector
-
 
25
    for(int i=0; i<phaseVector.rows; i++){
-
 
26
        // Amplitude of channels
-
 
27
        float amp = 0.5*(1+cos(2*pi*i/pitch - phase));
-
 
28
        phaseVector.at<cv::Vec3b>(i, 0) = cv::Vec3b(255.0*amp, 255.0*amp, 255.0*amp);
-
 
29
    }
-
 
30
 
-
 
31
    return phaseVector;
-
 
32
}
-
 
33
 
26
 
34
AlgorithmPhaseShiftThreeFreq::AlgorithmPhaseShiftThreeFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
27
AlgorithmPhaseShiftThreeFreq::AlgorithmPhaseShiftThreeFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
35
 
28
 
36
    // Set N
29
    // Set N
37
    N = 2+nStepsPrimary+nStepsSecondary+nStepsTertiary;
30
    N = 2+nStepsPrimary+nStepsSecondary+nStepsTertiary;
38
 
31
 
-
 
32
    // Determine the tertiary period to fulfill the heterodyne condition
-
 
33
    float nPeriodsTertiary = (screenCols*nPeriodsPrimary*nPeriodsSecondary)/(nPeriodsPrimary*nPeriodsSecondary+2*screenCols*nPeriodsPrimary-screenCols*nPeriodsSecondary);
-
 
34
 
39
    // all on pattern
35
    // all on pattern
40
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
36
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
41
    patterns.push_back(allOn);
37
    patterns.push_back(allOn);
42
 
38
 
43
    // all off pattern
39
    // all off pattern
44
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
40
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
45
    patterns.push_back(allOff);
41
    patterns.push_back(allOff);
46
 
42
 
47
    // Precompute encoded patterns
43
    // Precompute encoded patterns
48
    const float pi = M_PI;
44
    const float pi = M_PI;
49
 
45
 
50
    // Primary encoding patterns
46
    // Primary encoding patterns
51
    for(unsigned int i=0; i<nStepsPrimary; i++){
47
    for(unsigned int i=0; i<nStepsPrimary; i++){
52
        float phase = 2.0*pi/nStepsPrimary * i;
48
        float phase = 2.0*pi/nStepsPrimary * i;
53
        float pitch = screenCols/nPeriodPrimary;
49
        float pitch = screenCols/nPeriodsPrimary;
54
        cv::Mat patternI(1,1,CV_8U);
50
        cv::Mat patternI(1,1,CV_8U);
55
        patternI = computePhaseVector(screenCols, phase, pitch);
51
        patternI = computePhaseVector(screenCols, phase, pitch);
56
        patterns.push_back(patternI.t());
52
        patterns.push_back(patternI.t());
57
    }
53
    }
58
 
54
 
59
    // Secondary encoding patterns
55
    // Secondary encoding patterns
60
    for(unsigned int i=0; i<nStepsSecondary; i++){
56
    for(unsigned int i=0; i<nStepsSecondary; i++){
61
        float phase = 2.0*pi/nStepsSecondary * i;
57
        float phase = 2.0*pi/nStepsSecondary * i;
62
        float pitch = screenCols/nPeriodSecondary;
58
        float pitch = screenCols/nPeriodsSecondary;
63
        cv::Mat patternI(1,1,CV_8U);
59
        cv::Mat patternI(1,1,CV_8U);
64
        patternI = computePhaseVector(screenCols, phase, pitch);
60
        patternI = computePhaseVector(screenCols, phase, pitch);
65
        patterns.push_back(patternI.t());
61
        patterns.push_back(patternI.t());
66
    }
62
    }
67
    // Tertiary encoding patterns
63
    // Tertiary encoding patterns
68
    for(unsigned int i=0; i<nStepsTertiary; i++){
64
    for(unsigned int i=0; i<nStepsTertiary; i++){
69
        float phase = 2.0*pi/nStepsTertiary * i;
65
        float phase = 2.0*pi/nStepsTertiary * i;
70
        float pitch = screenCols;
66
        float pitch = screenCols/nPeriodsTertiary;
71
        cv::Mat patternI(1,1,CV_8U);
67
        cv::Mat patternI(1,1,CV_8U);
72
        patternI = computePhaseVector(screenCols, phase, pitch);
68
        patternI = computePhaseVector(screenCols, phase, pitch);
73
        patterns.push_back(patternI.t());
69
        patterns.push_back(patternI.t());
74
    }
70
    }
75
 
71
 
76
}
72
}
77
 
73
 
78
cv::Mat AlgorithmPhaseShiftThreeFreq::getEncodingPattern(unsigned int depth){
74
cv::Mat AlgorithmPhaseShiftThreeFreq::getEncodingPattern(unsigned int depth){
79
    return patterns[depth];
75
    return patterns[depth];
80
}
76
}
81
 
77
 
82
 
-
 
83
//// Absolute phase from 3 frames
-
 
84
//static cv::Mat getPhase(const cv::Mat I1, const cv::Mat I2, const cv::Mat I3){
-
 
85
 
-
 
86
//    cv::Mat_<float> I1_(I1);
-
 
87
//    cv::Mat_<float> I2_(I2);
-
 
88
//    cv::Mat_<float> I3_(I3);
-
 
89
 
-
 
90
//    cv::Mat phase;
-
 
91
 
-
 
92
//    // One call approach
-
 
93
//    cv::phase(2.0*I1_-I3_-I2_, sqrt(3.0)*(I2_-I3_), phase);
-
 
94
//    return phase;
-
 
95
 
-
 
96
//}
-
 
97
 
-
 
98
// Phase unwrapping by means of a phase cue
-
 
99
static cv::Mat unwrapWithCue(const cv::Mat up, const cv::Mat upCue, float nPhases){
-
 
100
 
-
 
101
    const float pi = M_PI;
-
 
102
 
-
 
103
    // Determine number of jumps
-
 
104
    cv::Mat P = (upCue*nPhases-up)/(2.0*pi);
-
 
105
 
-
 
106
    // Round to integers
-
 
107
    P.convertTo(P, CV_8U);
-
 
108
    P.convertTo(P, CV_32F);
-
 
109
 
-
 
110
    // Add to phase
-
 
111
    cv::Mat upUnwrapped = up + P*2*pi;
-
 
112
 
-
 
113
    // Scale to range [0; 2pi]
-
 
114
    upUnwrapped *= 1.0/nPhases;
-
 
115
 
-
 
116
    return upUnwrapped;
-
 
117
}
-
 
118
 
-
 
119
// Absolute phase and magnitude from N frames
-
 
120
static std::vector<cv::Mat> getDFTComponents(const std::vector<cv::Mat> frames){
-
 
121
 
-
 
122
    unsigned int N = frames.size();
-
 
123
 
-
 
124
//    std::vector<cv::Mat> framesReverse = frames;
-
 
125
//    std::reverse(framesReverse.begin(), framesReverse.end());
-
 
126
 
-
 
127
    // DFT approach
-
 
128
    cv::Mat I;
-
 
129
    cv::merge(frames, I);
-
 
130
    unsigned int w = I.cols;
-
 
131
    unsigned int h = I.rows;
-
 
132
    I = I.reshape(1, h*w);
-
 
133
    I.convertTo(I, CV_32F);
-
 
134
    cv::Mat fI;
-
 
135
    cv::dft(I, fI, cv::DFT_ROWS + cv::DFT_COMPLEX_OUTPUT);
-
 
136
    fI = fI.reshape(N*2, h);
-
 
137
 
-
 
138
    std::vector<cv::Mat> fIcomp;
-
 
139
    cv::split(fI, fIcomp);
-
 
140
 
-
 
141
    return fIcomp;
-
 
142
 
-
 
143
}
-
 
144
 
-
 
145
void AlgorithmPhaseShiftThreeFreq::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){
78
void AlgorithmPhaseShiftThreeFreq::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){
146
 
79
 
147
    const float pi = M_PI;
80
    const float pi = M_PI;
148
 
81
 
149
    assert(frames0.size() == N);
82
    assert(frames0.size() == N);
150
    assert(frames1.size() == N);
83
    assert(frames1.size() == N);
151
 
84
 
152
    int frameRows = frames0[0].rows;
85
    int frameRows = frames0[0].rows;
153
    int frameCols = frames0[0].cols;
86
    int frameCols = frames0[0].cols;
154
 
87
 
155
    // Rectifying homographies (rotation+projections)
88
    // Rectifying homographies (rotation+projections)
156
    cv::Size frameSize(frameCols, frameRows);
89
    cv::Size frameSize(frameCols, frameRows);
157
    cv::Mat R, T;
90
    cv::Mat R, T;
158
    // stereoRectify segfaults unless R is double precision
91
    // stereoRectify segfaults unless R is double precision
159
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
92
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
160
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
93
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
161
    cv::Mat R0, R1, P0, P1, QRect;
94
    cv::Mat R0, R1, P0, P1, QRect;
162
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
95
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
163
 
96
 
164
    // Interpolation maps (lens distortion and rectification)
97
    // Interpolation maps (lens distortion and rectification)
165
    cv::Mat map0X, map0Y, map1X, map1Y;
98
    cv::Mat map0X, map0Y, map1X, map1Y;
166
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
99
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
167
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
100
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
168
 
101
 
169
 
102
 
170
    // Gray-scale and remap
103
    // Gray-scale and remap
171
    std::vector<cv::Mat> frames0Rect(N);
104
    std::vector<cv::Mat> frames0Rect(N);
172
    std::vector<cv::Mat> frames1Rect(N);
105
    std::vector<cv::Mat> frames1Rect(N);
173
    for(unsigned int i=0; i<N; i++){
106
    for(unsigned int i=0; i<N; i++){
174
        cv::Mat temp;
107
        cv::Mat temp;
175
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
108
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
176
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
109
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
177
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
110
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
178
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
111
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
179
    }
112
    }
180
 
113
 
181
    // Decode camera0
114
    // Decode camera0
182
    std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
115
    std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
183
    std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end()-nStepsTertiary);
116
    std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end()-nStepsTertiary);
184
    std::vector<cv::Mat> frames0Tertiary(frames0Rect.end()-nStepsTertiary, frames0Rect.end());
117
    std::vector<cv::Mat> frames0Tertiary(frames0Rect.end()-nStepsTertiary, frames0Rect.end());
185
 
118
 
186
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
119
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
187
    cv::Mat up0Primary;
120
    cv::Mat up0Primary;
188
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
121
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
189
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
122
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
190
    cv::Mat up0Secondary;
123
    cv::Mat up0Secondary;
191
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
124
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
192
    std::vector<cv::Mat> F0Tertiary = getDFTComponents(frames0Tertiary);
125
    std::vector<cv::Mat> F0Tertiary = getDFTComponents(frames0Tertiary);
193
    cv::Mat up0Tertiary;
126
    cv::Mat up0Tertiary;
194
    cv::phase(F0Tertiary[2], -F0Tertiary[3], up0Tertiary);
127
    cv::phase(F0Tertiary[2], -F0Tertiary[3], up0Tertiary);
195
 
128
 
-
 
129
    cv::Mat up0EquivalentPS = up0Primary - up0Secondary;
-
 
130
    up0EquivalentPS = cvtools::modulo(up0EquivalentPS, 2.0*pi);
-
 
131
 
196
    cv::Mat up0Unwrap = unwrapWithCue(up0Secondary, up0Tertiary, nPeriodSecondary);
132
    cv::Mat up0EquivalentST = up0Secondary - up0Tertiary;
-
 
133
    up0EquivalentST = cvtools::modulo(up0EquivalentST, 2.0*pi);
-
 
134
 
-
 
135
    cv::Mat up0Equivalent = up0EquivalentPS - up0EquivalentST;
-
 
136
    up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*pi);
-
 
137
 
197
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Unwrap, nPeriodPrimary);
138
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Equivalent, (float)screenCols/nPeriodsPrimary);
198
    up0 *= screenCols/(2.0*pi);
139
    up0 *= screenCols/(2.0*pi);
199
    cv::Mat amplitude0;
140
    cv::Mat amplitude0;
200
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
141
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
201
 
142
 
202
    // Decode camera1
143
    // Decode camera1
203
    std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
144
    std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
204
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end()-nStepsTertiary);
145
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end()-nStepsTertiary);
205
    std::vector<cv::Mat> frames1Tertiary(frames1Rect.end()-nStepsTertiary, frames1Rect.end());
146
    std::vector<cv::Mat> frames1Tertiary(frames1Rect.end()-nStepsTertiary, frames1Rect.end());
206
 
147
 
207
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
148
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
208
    cv::Mat up1Primary;
149
    cv::Mat up1Primary;
209
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
150
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
210
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
151
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
211
    cv::Mat up1Secondary;
152
    cv::Mat up1Secondary;
212
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
153
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
213
    std::vector<cv::Mat> F1Tertiary = getDFTComponents(frames1Tertiary);
154
    std::vector<cv::Mat> F1Tertiary = getDFTComponents(frames1Tertiary);
214
    cv::Mat up1Tertiary;
155
    cv::Mat up1Tertiary;
215
    cv::phase(F1Tertiary[2], -F1Tertiary[3], up1Tertiary);
156
    cv::phase(F1Tertiary[2], -F1Tertiary[3], up1Tertiary);
216
 
157
 
-
 
158
    cv::Mat up1EquivalentPS = up1Primary - up1Secondary;
-
 
159
    up1EquivalentPS = cvtools::modulo(up1EquivalentPS, 2.0*pi);
-
 
160
 
217
    cv::Mat up1Unwrap = unwrapWithCue(up1Secondary, up1Tertiary, nPeriodSecondary);
161
    cv::Mat up1EquivalentST = up1Secondary - up1Tertiary;
-
 
162
    up1EquivalentST = cvtools::modulo(up1EquivalentST, 2.0*pi);
-
 
163
 
-
 
164
    cv::Mat up1Equivalent = up1EquivalentPS - up1EquivalentST;
-
 
165
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*pi);
-
 
166
 
218
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Unwrap, nPeriodPrimary);
167
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, (float)screenCols/nPeriodsPrimary);
219
    up1 *= screenCols/(2.0*pi);
168
    up1 *= screenCols/(2.0*pi);
220
    cv::Mat amplitude1;
169
    cv::Mat amplitude1;
221
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
170
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
222
 
171
 
-
 
172
    #ifdef Q_DEBUG
223
//cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
173
        cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
224
//cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
174
        cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
225
//cvtools::writeMat(up0Tertiary, "up0Tertiary.mat", "up0Tertiary");
175
        cvtools::writeMat(up0Tertiary, "up0Tertiary.mat", "up0Tertiary");
-
 
176
        cvtools::writeMat(up0EquivalentPS, "up0EquivalentPS.mat", "up0EquivalentPS");
226
//cvtools::writeMat(up0Unwrap, "up0Unwrap.mat", "up0Unwrap");
177
        cvtools::writeMat(up0EquivalentST, "up0EquivalentST.mat", "up0EquivalentST");
227
//cvtools::writeMat(up0, "up0.mat", "up0");
178
        cvtools::writeMat(up0, "up0.mat", "up0");
228
//cvtools::writeMat(up1, "up1.mat", "up1");
179
        cvtools::writeMat(up1, "up1.mat", "up1");
229
//cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
180
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
230
 
181
 
231
//cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
182
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
232
//cvtools::writeMat(amplitude1, "amplitude1.mat", "amplitude1");
183
        cvtools::writeMat(amplitude1, "amplitude1.mat", "amplitude1");
-
 
184
    #endif
233
 
185
 
234
    // Color debayer and remap
186
    // Color debayer and remap
235
    cv::Mat color0, color1;
187
    cv::Mat color0, color1;
236
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
188
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
237
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
189
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
238
 
190
 
-
 
191
    #ifdef Q_DEBUG
239
//cvtools::writeMat(color0, "color0.mat", "color0");
192
        cvtools::writeMat(color0, "color0.mat", "color0");
240
//cvtools::writeMat(color1, "color1.mat", "color1");
193
        cvtools::writeMat(color1, "color1.mat", "color1");
-
 
194
    #endif
241
 
195
 
242
    // Occlusion masks
196
    // Occlusion masks
243
    cv::Mat occlusion0, occlusion1;
197
    cv::Mat occlusion0, occlusion1;
244
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
198
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
245
    occlusion0 = (occlusion0 > 5) & (occlusion0 < 250);
199
    occlusion0 = (occlusion0 > 5) & (occlusion0 < 250);
246
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
200
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
247
    occlusion1 = (occlusion1 > 5) & (occlusion1 < 250);
201
    occlusion1 = (occlusion1 > 5) & (occlusion1 < 250);
248
 
202
 
249
//    // Threshold on energy at primary frequency
203
    #ifdef Q_DEBUG
250
//    occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
-
 
251
//    occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
-
 
252
 
-
 
253
//cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
-
 
254
//cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
-
 
255
 
-
 
256
//    // Erode occlusion masks
204
        // Erode occlusion masks
257
//    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
205
        cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
258
//    cv::erode(occlusion0, occlusion0, strel);
206
        cv::erode(occlusion0, occlusion0, strel);
259
//    cv::erode(occlusion1, occlusion1, strel);
207
        cv::erode(occlusion1, occlusion1, strel);
-
 
208
    #endif
260
 
209
 
261
    // Threshold on gradient of phase
210
    // Threshold on gradient of phase
262
    cv::Mat edges0;
211
    cv::Mat edges0;
263
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
212
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
264
    occlusion0 = occlusion0 & (abs(edges0) < 150);
213
    occlusion0 = occlusion0 & (abs(edges0) < 150);
265
    cv::Mat edges1;
214
    cv::Mat edges1;
266
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
215
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
267
    occlusion1 = occlusion1 & (abs(edges1) < 150);
216
    occlusion1 = occlusion1 & (abs(edges1) < 150);
268
 
217
 
-
 
218
    #ifdef Q_DEBUG
269
//cvtools::writeMat(edges0, "edges0.mat", "edges0");
219
        cvtools::writeMat(edges0, "edges0.mat", "edges0");
270
//cvtools::writeMat(edges1, "edges1.mat", "edges1");
220
        cvtools::writeMat(edges1, "edges1.mat", "edges1");
-
 
221
    #endif
271
 
222
 
272
    // Match phase maps
223
    // Match phase maps
273
    int frameRectRows = map0X.rows;
224
    int frameRectRows = map0X.rows;
274
    int frameRectCols = map0X.cols;
225
    int frameRectCols = map0X.cols;
275
 
226
 
276
    // camera0 against camera1
227
    // camera0 against camera1
277
    std::vector<cv::Vec2f> q0, q1;
228
    std::vector<cv::Vec2f> q0, q1;
278
    for(int row=0; row<frameRectRows; row++){
229
    for(int row=0; row<frameRectRows; row++){
279
        for(int col=0; col<frameRectCols; col++){
230
        for(int col=0; col<frameRectCols; col++){
280
 
231
 
281
            if(!occlusion0.at<char>(row,col))
232
            if(!occlusion0.at<char>(row,col))
282
                continue;
233
                continue;
283
 
234
 
284
            float up0i = up0.at<float>(row,col);
235
            float up0i = up0.at<float>(row,col);
285
            for(int col1=0; col1<up1.cols-1; col1++){
236
            for(int col1=0; col1<up1.cols-1; col1++){
286
 
237
 
287
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
238
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
288
                    continue;
239
                    continue;
289
 
240
 
290
                float up1Left = up1.at<float>(row,col1);
241
                float up1Left = up1.at<float>(row,col1);
291
                float up1Right = up1.at<float>(row,col1+1);
242
                float up1Right = up1.at<float>(row,col1+1);
292
 
243
 
293
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0)){
244
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0)){
294
 
245
 
295
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
246
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
296
 
247
 
297
                    q0.push_back(cv::Point2f(col, row));
248
                    q0.push_back(cv::Point2f(col, row));
298
                    q1.push_back(cv::Point2f(col1i, row));
249
                    q1.push_back(cv::Point2f(col1i, row));
299
 
250
 
300
                    break;
251
                    break;
301
                }
252
                }
302
            }
253
            }
303
        }
254
        }
304
    }
255
    }
305
 
256
 
306
    int nMatches = q0.size();
257
    int nMatches = q0.size();
307
 
258
 
308
    if(nMatches < 1){
259
    if(nMatches < 1){
309
        Q.resize(0);
260
        Q.resize(0);
310
        color.resize(0);
261
        color.resize(0);
311
 
262
 
312
        return;
263
        return;
313
    }
264
    }
314
 
265
 
315
    // Retrieve color information
266
    // Retrieve color information
316
    color.resize(nMatches);
267
    color.resize(nMatches);
317
    for(int i=0; i<nMatches; i++){
268
    for(int i=0; i<nMatches; i++){
318
 
269
 
319
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
270
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
320
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
271
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
321
 
272
 
322
        color[i] = 0.5*c0 + 0.5*c1;
273
        color[i] = 0.5*c0 + 0.5*c1;
323
    }
274
    }
324
 
275
 
325
    // Triangulate points
276
    // Triangulate points
326
    cv::Mat QMatHomogenous, QMat;
277
    cv::Mat QMatHomogenous, QMat;
327
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
278
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
328
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
279
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
329
 
280
 
330
    // Undo rectification
281
    // Undo rectification
331
    cv::Mat R0Inv;
282
    cv::Mat R0Inv;
332
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
283
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
333
    QMat = R0Inv*QMat;
284
    QMat = R0Inv*QMat;
334
 
285
 
335
    cvtools::matToPoints3f(QMat, Q);
286
    cvtools::matToPoints3f(QMat, Q);
336
 
287
 
337
}
288
}
338
 
289