Subversion Repositories seema-scanner

Rev

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

Rev 185 Rev 187
1
//
1
//
2
// Three Frequency Phase Shifting using the Heterodyne Principle
2
// Three 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
//
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.
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.
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
//
8
//
9
 
9
 
10
 
10
 
11
#include "AlgorithmPhaseShiftThreeFreq.h"
11
#include "AlgorithmPhaseShiftThreeFreq.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
#ifndef M_PI
17
#ifndef M_PI
18
    #define M_PI 3.14159265358979323846
18
    #define M_PI 3.14159265358979323846
19
#endif
19
#endif
20
 
20
 
21
static unsigned int nStepsPrimary = 8; // number of shifts/steps in primary
21
static unsigned int nStepsPrimary = 8; // number of shifts/steps in primary
22
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
22
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
23
static unsigned int nStepsTertiary = 8; // number of shifts/steps in tertiary
23
static unsigned int nStepsTertiary = 8; // number of shifts/steps in tertiary
24
static float nPeriodsPrimary = 24; // primary period
24
static float nPeriodsPrimary = 24; // primary period
25
static float nPeriodsSecondary = 30; // primary period
25
static float nPeriodsSecondary = 30; // primary period
26
 
26
 
27
AlgorithmPhaseShiftThreeFreq::AlgorithmPhaseShiftThreeFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
27
AlgorithmPhaseShiftThreeFreq::AlgorithmPhaseShiftThreeFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
28
 
28
 
29
    // Set N
29
    // Set N
30
    N = 2+nStepsPrimary+nStepsSecondary+nStepsTertiary;
30
    N = 2+nStepsPrimary+nStepsSecondary+nStepsTertiary;
31
 
31
 
32
    // Determine the tertiary period to fulfill the heterodyne condition
32
    // Determine the tertiary period to fulfill the heterodyne condition
33
    float nPeriodsTertiary = (screenCols*nPeriodsPrimary*nPeriodsSecondary)/(nPeriodsPrimary*nPeriodsSecondary+2*screenCols*nPeriodsPrimary-screenCols*nPeriodsSecondary);
33
    float nPeriodsTertiary = (screenCols*nPeriodsPrimary*nPeriodsSecondary)/(nPeriodsPrimary*nPeriodsSecondary+2*screenCols*nPeriodsPrimary-screenCols*nPeriodsSecondary);
34
 
34
 
35
    // all on pattern
35
    // all on pattern
36
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
36
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
37
    patterns.push_back(allOn);
37
    patterns.push_back(allOn);
38
 
38
 
39
    // all off pattern
39
    // all off pattern
40
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
40
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
41
    patterns.push_back(allOff);
41
    patterns.push_back(allOff);
42
 
42
 
43
    // Precompute encoded patterns
43
    // Precompute encoded patterns
44
    const float pi = M_PI;
44
    const float pi = M_PI;
45
 
45
 
46
    // Primary encoding patterns
46
    // Primary encoding patterns
47
    for(unsigned int i=0; i<nStepsPrimary; i++){
47
    for(unsigned int i=0; i<nStepsPrimary; i++){
48
        float phase = 2.0*pi/nStepsPrimary * i;
48
        float phase = 2.0*pi/nStepsPrimary * i;
49
        float pitch = screenCols/nPeriodsPrimary;
49
        float pitch = screenCols/nPeriodsPrimary;
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
    // Secondary encoding patterns
55
    // Secondary encoding patterns
56
    for(unsigned int i=0; i<nStepsSecondary; i++){
56
    for(unsigned int i=0; i<nStepsSecondary; i++){
57
        float phase = 2.0*pi/nStepsSecondary * i;
57
        float phase = 2.0*pi/nStepsSecondary * i;
58
        float pitch = screenCols/nPeriodsSecondary;
58
        float pitch = screenCols/nPeriodsSecondary;
59
        cv::Mat patternI(1,1,CV_8U);
59
        cv::Mat patternI(1,1,CV_8U);
60
        patternI = computePhaseVector(screenCols, phase, pitch);
60
        patternI = computePhaseVector(screenCols, phase, pitch);
61
        patterns.push_back(patternI.t());
61
        patterns.push_back(patternI.t());
62
    }
62
    }
63
    // Tertiary encoding patterns
63
    // Tertiary encoding patterns
64
    for(unsigned int i=0; i<nStepsTertiary; i++){
64
    for(unsigned int i=0; i<nStepsTertiary; i++){
65
        float phase = 2.0*pi/nStepsTertiary * i;
65
        float phase = 2.0*pi/nStepsTertiary * i;
66
        float pitch = screenCols/nPeriodsTertiary;
66
        float pitch = screenCols/nPeriodsTertiary;
67
        cv::Mat patternI(1,1,CV_8U);
67
        cv::Mat patternI(1,1,CV_8U);
68
        patternI = computePhaseVector(screenCols, phase, pitch);
68
        patternI = computePhaseVector(screenCols, phase, pitch);
69
        patterns.push_back(patternI.t());
69
        patterns.push_back(patternI.t());
70
    }
70
    }
71
 
71
 
72
}
72
}
73
 
73
 
74
cv::Mat AlgorithmPhaseShiftThreeFreq::getEncodingPattern(unsigned int depth){
74
cv::Mat AlgorithmPhaseShiftThreeFreq::getEncodingPattern(unsigned int depth){
75
    return patterns[depth];
75
    return patterns[depth];
76
}
76
}
77
 
77
 
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){
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){
79
 
79
 
80
    const float pi = M_PI;
80
    const float pi = M_PI;
81
 
81
 
82
    assert(frames0.size() == N);
82
    assert(frames0.size() == N);
83
    assert(frames1.size() == N);
83
    assert(frames1.size() == N);
84
 
84
 
85
    int frameRows = frames0[0].rows;
85
    int frameRows = frames0[0].rows;
86
    int frameCols = frames0[0].cols;
86
    int frameCols = frames0[0].cols;
87
 
87
 
88
    // Rectifying homographies (rotation+projections)
88
    // Rectifying homographies (rotation+projections)
89
    cv::Size frameSize(frameCols, frameRows);
89
    cv::Size frameSize(frameCols, frameRows);
90
    cv::Mat R, T;
90
    cv::Mat R, T;
91
    // stereoRectify segfaults unless R is double precision
91
    // stereoRectify segfaults unless R is double precision
92
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
92
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
93
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
93
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
94
    cv::Mat R0, R1, P0, P1, QRect;
94
    cv::Mat R0, R1, P0, P1, QRect;
95
    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);
96
 
96
 
97
    // Interpolation maps (lens distortion and rectification)
97
    // Interpolation maps (lens distortion and rectification)
98
    cv::Mat map0X, map0Y, map1X, map1Y;
98
    cv::Mat map0X, map0Y, map1X, map1Y;
99
    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);
100
    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);
101
 
101
 
102
 
102
 
103
    // Gray-scale and remap
103
    // Gray-scale and remap
104
    std::vector<cv::Mat> frames0Rect(N);
104
    std::vector<cv::Mat> frames0Rect(N);
105
    std::vector<cv::Mat> frames1Rect(N);
105
    std::vector<cv::Mat> frames1Rect(N);
106
    for(unsigned int i=0; i<N; i++){
106
    for(unsigned int i=0; i<N; i++){
107
        cv::Mat temp;
107
        cv::Mat temp;
108
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
108
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
109
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
109
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
110
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
110
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
111
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
111
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
112
    }
112
    }
113
 
113
 
114
    // Decode camera0
114
    // Decode camera0
115
    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);
116
    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);
117
    std::vector<cv::Mat> frames0Tertiary(frames0Rect.end()-nStepsTertiary, frames0Rect.end());
117
    std::vector<cv::Mat> frames0Tertiary(frames0Rect.end()-nStepsTertiary, frames0Rect.end());
118
 
118
 
119
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
119
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
120
    cv::Mat up0Primary;
120
    cv::Mat up0Primary;
121
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
121
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
122
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
122
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
123
    cv::Mat up0Secondary;
123
    cv::Mat up0Secondary;
124
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
124
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
125
    std::vector<cv::Mat> F0Tertiary = getDFTComponents(frames0Tertiary);
125
    std::vector<cv::Mat> F0Tertiary = getDFTComponents(frames0Tertiary);
126
    cv::Mat up0Tertiary;
126
    cv::Mat up0Tertiary;
127
    cv::phase(F0Tertiary[2], -F0Tertiary[3], up0Tertiary);
127
    cv::phase(F0Tertiary[2], -F0Tertiary[3], up0Tertiary);
128
 
128
 
129
    cv::Mat up0EquivalentPS = up0Primary - up0Secondary;
129
    cv::Mat up0EquivalentPS = up0Primary - up0Secondary;
130
    up0EquivalentPS = cvtools::modulo(up0EquivalentPS, 2.0*pi);
130
    up0EquivalentPS = cvtools::modulo(up0EquivalentPS, 2.0*pi);
131
 
131
 
132
    cv::Mat up0EquivalentST = up0Secondary - up0Tertiary;
132
    cv::Mat up0EquivalentPT = up0Primary - up0Tertiary;
133
    up0EquivalentST = cvtools::modulo(up0EquivalentST, 2.0*pi);
133
    up0EquivalentPT = cvtools::modulo(up0EquivalentPT, 2.0*pi);
134
 
134
 
135
    cv::Mat up0Equivalent = up0EquivalentPS - up0EquivalentST;
135
    cv::Mat up0Equivalent = up0EquivalentPS - up0EquivalentPT;
136
    up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*pi);
136
    up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*pi);
137
 
137
 
138
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Equivalent, (float)screenCols/nPeriodsPrimary);
138
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Equivalent, (float)screenCols/nPeriodsPrimary);
139
    up0 *= screenCols/(2.0*pi);
139
    up0 *= screenCols/(2.0*pi);
140
    cv::Mat amplitude0;
140
    cv::Mat amplitude0;
141
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
141
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
142
 
142
 
143
    // Decode camera1
143
    // Decode camera1
144
    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);
145
    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);
146
    std::vector<cv::Mat> frames1Tertiary(frames1Rect.end()-nStepsTertiary, frames1Rect.end());
146
    std::vector<cv::Mat> frames1Tertiary(frames1Rect.end()-nStepsTertiary, frames1Rect.end());
147
 
147
 
148
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
148
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
149
    cv::Mat up1Primary;
149
    cv::Mat up1Primary;
150
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
150
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
151
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
151
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
152
    cv::Mat up1Secondary;
152
    cv::Mat up1Secondary;
153
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
153
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
154
    std::vector<cv::Mat> F1Tertiary = getDFTComponents(frames1Tertiary);
154
    std::vector<cv::Mat> F1Tertiary = getDFTComponents(frames1Tertiary);
155
    cv::Mat up1Tertiary;
155
    cv::Mat up1Tertiary;
156
    cv::phase(F1Tertiary[2], -F1Tertiary[3], up1Tertiary);
156
    cv::phase(F1Tertiary[2], -F1Tertiary[3], up1Tertiary);
157
 
157
 
158
    cv::Mat up1EquivalentPS = up1Primary - up1Secondary;
158
    cv::Mat up1EquivalentPS = up1Primary - up1Secondary;
159
    up1EquivalentPS = cvtools::modulo(up1EquivalentPS, 2.0*pi);
159
    up1EquivalentPS = cvtools::modulo(up1EquivalentPS, 2.0*pi);
160
 
160
 
161
    cv::Mat up1EquivalentST = up1Secondary - up1Tertiary;
161
    cv::Mat up1EquivalentST = up1Secondary - up1Tertiary;
162
    up1EquivalentST = cvtools::modulo(up1EquivalentST, 2.0*pi);
162
    up1EquivalentST = cvtools::modulo(up1EquivalentST, 2.0*pi);
163
 
163
 
164
    cv::Mat up1Equivalent = up1EquivalentPS - up1EquivalentST;
164
    cv::Mat up1Equivalent = up1EquivalentPS - up1EquivalentST;
165
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*pi);
165
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*pi);
166
 
166
 
-
 
167
    // TODO: we should use backward phase unwrapping (Song Zhang term)...
-
 
168
 
167
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, (float)screenCols/nPeriodsPrimary);
169
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, (float)screenCols/nPeriodsPrimary);
168
    up1 *= screenCols/(2.0*pi);
170
    up1 *= screenCols/(2.0*pi);
169
    cv::Mat amplitude1;
171
    cv::Mat amplitude1;
170
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
172
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
171
 
173
 
172
    #ifdef QT_DEBUG
174
    #ifdef QT_DEBUG
173
        cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
175
        cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
174
        cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
176
        cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
175
        cvtools::writeMat(up0Tertiary, "up0Tertiary.mat", "up0Tertiary");
177
        cvtools::writeMat(up0Tertiary, "up0Tertiary.mat", "up0Tertiary");
176
        cvtools::writeMat(up0EquivalentPS, "up0EquivalentPS.mat", "up0EquivalentPS");
178
        cvtools::writeMat(up0EquivalentPS, "up0EquivalentPS.mat", "up0EquivalentPS");
177
        cvtools::writeMat(up0EquivalentST, "up0EquivalentST.mat", "up0EquivalentST");
179
        cvtools::writeMat(up0EquivalentPT, "up0EquivalentPT.mat", "up0EquivalentPT");
-
 
180
        cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
178
        cvtools::writeMat(up0, "up0.mat", "up0");
181
        cvtools::writeMat(up0, "up0.mat", "up0");
179
        cvtools::writeMat(up1, "up1.mat", "up1");
182
        cvtools::writeMat(up1, "up1.mat", "up1");
180
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
183
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
181
 
184
 
182
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
185
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
183
        cvtools::writeMat(amplitude1, "amplitude1.mat", "amplitude1");
186
        cvtools::writeMat(amplitude1, "amplitude1.mat", "amplitude1");
184
    #endif
187
    #endif
185
 
188
 
186
    // Color debayer and remap
189
    // color debayer and remap
187
    cv::Mat color0, color1;
190
    cv::Mat color0, color1;
188
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
191
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
-
 
192
    cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
-
 
193
 
189
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
194
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
-
 
195
    cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
190
 
196
 
191
    #ifdef QT_DEBUG
197
    #ifdef QT_DEBUG
192
        cvtools::writeMat(color0, "color0.mat", "color0");
198
        cvtools::writeMat(color0, "color0.mat", "color0");
193
        cvtools::writeMat(color1, "color1.mat", "color1");
199
        cvtools::writeMat(color1, "color1.mat", "color1");
194
    #endif
200
    #endif
195
 
201
 
196
    // Occlusion masks
202
    // Occlusion masks
197
    cv::Mat occlusion0, occlusion1;
203
    cv::Mat occlusion0, occlusion1;
198
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
204
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
199
    occlusion0 = (occlusion0 > 5) & (occlusion0 < 250);
205
    occlusion0 = (occlusion0 > 5) & (occlusion0 < 250);
200
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
206
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
201
    occlusion1 = (occlusion1 > 5) & (occlusion1 < 250);
207
    occlusion1 = (occlusion1 > 5) & (occlusion1 < 250);
202
 
208
 
203
    #ifdef QT_DEBUG
-
 
204
        // Erode occlusion masks
-
 
205
        cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
-
 
206
        cv::erode(occlusion0, occlusion0, strel);
-
 
207
        cv::erode(occlusion1, occlusion1, strel);
-
 
208
    #endif
-
 
209
 
-
 
210
    // Threshold on gradient of phase
209
    // Threshold on gradient of phase
211
    cv::Mat edges0;
210
    cv::Mat edges0;
212
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
211
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
213
    occlusion0 = occlusion0 & (abs(edges0) < 150);
212
    occlusion0 = occlusion0 & (abs(edges0) < 150);
214
    cv::Mat edges1;
213
    cv::Mat edges1;
215
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
214
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
216
    occlusion1 = occlusion1 & (abs(edges1) < 150);
215
    occlusion1 = occlusion1 & (abs(edges1) < 150);
217
 
216
 
218
    #ifdef QT_DEBUG
217
    #ifdef QT_DEBUG
219
        cvtools::writeMat(edges0, "edges0.mat", "edges0");
218
        cvtools::writeMat(edges0, "edges0.mat", "edges0");
220
        cvtools::writeMat(edges1, "edges1.mat", "edges1");
219
        cvtools::writeMat(edges1, "edges1.mat", "edges1");
221
    #endif
220
    #endif
-
 
221
 
-
 
222
    #ifdef QT_DEBUG
-
 
223
        cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
-
 
224
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
-
 
225
    #endif
222
 
226
 
223
    // Match phase maps
227
    // Match phase maps
224
    int frameRectRows = map0X.rows;
228
    int frameRectRows = map0X.rows;
225
    int frameRectCols = map0X.cols;
229
    int frameRectCols = map0X.cols;
226
 
230
 
227
    // camera0 against camera1
231
    // camera0 against camera1
228
    std::vector<cv::Vec2f> q0, q1;
232
    std::vector<cv::Vec2f> q0, q1;
229
    for(int row=0; row<frameRectRows; row++){
233
    for(int row=0; row<frameRectRows; row++){
230
        for(int col=0; col<frameRectCols; col++){
234
        for(int col=0; col<frameRectCols; col++){
231
 
235
 
232
            if(!occlusion0.at<char>(row,col))
236
            if(!occlusion0.at<char>(row,col))
233
                continue;
237
                continue;
234
 
238
 
235
            float up0i = up0.at<float>(row,col);
239
            float up0i = up0.at<float>(row,col);
236
            for(int col1=0; col1<up1.cols-1; col1++){
240
            for(int col1=0; col1<up1.cols-1; col1++){
237
 
241
 
238
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
242
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
239
                    continue;
243
                    continue;
240
 
244
 
241
                float up1Left = up1.at<float>(row,col1);
245
                float up1Left = up1.at<float>(row,col1);
242
                float up1Right = up1.at<float>(row,col1+1);
246
                float up1Right = up1.at<float>(row,col1+1);
243
 
247
 
244
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0)){
248
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0)){
245
 
249
 
246
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
250
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
247
 
251
 
248
                    q0.push_back(cv::Point2f(col, row));
252
                    q0.push_back(cv::Point2f(col, row));
249
                    q1.push_back(cv::Point2f(col1i, row));
253
                    q1.push_back(cv::Point2f(col1i, row));
250
 
254
 
251
                    break;
255
                    break;
252
                }
256
                }
253
            }
257
            }
254
        }
258
        }
255
    }
259
    }
256
 
260
 
257
    int nMatches = q0.size();
261
    int nMatches = q0.size();
258
 
262
 
259
    if(nMatches < 1){
263
    if(nMatches < 1){
260
        Q.resize(0);
264
        Q.resize(0);
261
        color.resize(0);
265
        color.resize(0);
262
 
266
 
263
        return;
267
        return;
264
    }
268
    }
265
 
269
 
266
    // Retrieve color information
270
    // Retrieve color information
267
    color.resize(nMatches);
271
    color.resize(nMatches);
268
    for(int i=0; i<nMatches; i++){
272
    for(int i=0; i<nMatches; i++){
269
 
273
 
270
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
274
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
271
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
275
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
272
 
276
 
273
        color[i] = 0.5*c0 + 0.5*c1;
277
        color[i] = 0.5*c0 + 0.5*c1;
274
    }
278
    }
275
 
279
 
276
    // Triangulate points
280
    // Triangulate points
277
    cv::Mat QMatHomogenous, QMat;
281
    cv::Mat QMatHomogenous, QMat;
278
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
282
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
279
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
283
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
280
 
284
 
281
    // Undo rectification
285
    // Undo rectification
282
    cv::Mat R0Inv;
286
    cv::Mat R0Inv;
283
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
287
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
284
    QMat = R0Inv*QMat;
288
    QMat = R0Inv*QMat;
285
 
289
 
286
    cvtools::matToPoints3f(QMat, Q);
290
    cvtools::matToPoints3f(QMat, Q);
287
 
291
 
288
}
292
}
289
 
293