Subversion Repositories seema-scanner

Rev

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

Rev 192 Rev 195
1
//
1
//
2
// Two Frequency Phase Shifting using the Heterodyne Principle
2
// Two Frequency Phase Shifting using the Heterodyne Principle
3
//
3
//
4
// This implementation follows "Reich, Ritter, Thesing, White light heterodyne principle for 3D-measurement", SPIE (1997)
4
// This implementation follows "Reich, Ritter, Thesing, White light heterodyne principle for 3D-measurement", SPIE (1997)
5
// Different from the paper, it uses only two different frequencies.
5
// Different from the paper, it uses only two different frequencies.
6
//
6
//
7
// The number of periods in the primary frequency can be chosen freely, but small changes can have a considerable impact on quality.
7
// The number of periods in the primary frequency can be chosen freely, but small changes can have a considerable impact on quality.
8
// The number of phase shifts can be chosen freely (min. 3), and higher values reduce the effects of image noise. They also allow us to filter bad points based on energy at non-primary frequencies.
8
// The number of phase shifts can be chosen freely (min. 3), and higher values reduce the effects of image noise. They also allow us to filter bad points based on energy at non-primary frequencies.
9
//
9
//
10
 
10
 
11
#include "AlgorithmPhaseShiftTwoFreq.h"
11
#include "AlgorithmPhaseShiftTwoFreq.h"
12
#include <math.h>
12
#include <math.h>
13
 
13
 
14
#include "cvtools.h"
14
#include "cvtools.h"
15
#include "algorithmtools.h"
15
#include "algorithmtools.h"
16
 
16
 
17
static unsigned int nStepsPrimary = 16; // number of shifts/steps in primary
17
static unsigned int nStepsPrimary = 16; // number of shifts/steps in primary
18
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
18
static unsigned int nStepsSecondary = 8; // number of shifts/steps in secondary
19
static float nPeriodsPrimary = 40; // primary period
19
static float nPeriodsPrimary = 40; // primary period
20
 
20
 
21
AlgorithmPhaseShiftTwoFreq::AlgorithmPhaseShiftTwoFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
21
AlgorithmPhaseShiftTwoFreq::AlgorithmPhaseShiftTwoFreq(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
22
 
22
 
23
    // Set N
23
    // Set N
24
    N = 2+nStepsPrimary+nStepsSecondary;
24
    N = 2+nStepsPrimary+nStepsSecondary;
25
 
25
 
26
    // Determine the secondary (wider) period to fulfill the heterodyne condition
26
    // Determine the secondary (wider) period to fulfill the heterodyne condition
27
    float nPeriodsSecondary = nPeriodsPrimary + 1;
27
    float nPeriodsSecondary = nPeriodsPrimary + 1;
28
 
28
 
29
    // all on pattern
29
    // all on pattern
30
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
30
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
31
    patterns.push_back(allOn);
31
    patterns.push_back(allOn);
32
 
32
 
33
    // all off pattern
33
    // all off pattern
34
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
34
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
35
    patterns.push_back(allOff);
35
    patterns.push_back(allOff);
36
 
36
 
37
    // Primary encoding patterns
37
    // Primary encoding patterns
38
    for(unsigned int i=0; i<nStepsPrimary; i++){
38
    for(unsigned int i=0; i<nStepsPrimary; i++){
39
        float phase = 2.0*CV_PI/nStepsPrimary * i;
39
        float phase = 2.0*CV_PI/nStepsPrimary * i;
40
        float pitch = screenCols/nPeriodsPrimary;
40
        float pitch = screenCols/nPeriodsPrimary;
41
        cv::Mat patternI(1,1,CV_8U);
41
        cv::Mat patternI(1,1,CV_8U);
42
        patternI = computePhaseVector(screenCols, phase, pitch);
42
        patternI = computePhaseVector(screenCols, phase, pitch);
43
        patterns.push_back(patternI.t());
43
        patterns.push_back(patternI.t());
44
    }
44
    }
45
 
45
 
46
    // Secondary encoding patterns
46
    // Secondary encoding patterns
47
    for(unsigned int i=0; i<nStepsSecondary; i++){
47
    for(unsigned int i=0; i<nStepsSecondary; i++){
48
        float phase = 2.0*CV_PI/nStepsSecondary * i;
48
        float phase = 2.0*CV_PI/nStepsSecondary * i;
49
        float pitch = screenCols/nPeriodsSecondary;
49
        float pitch = screenCols/nPeriodsSecondary;
50
        cv::Mat patternI(1,1,CV_8U);
50
        cv::Mat patternI(1,1,CV_8U);
51
        patternI = computePhaseVector(screenCols, phase, pitch);
51
        patternI = computePhaseVector(screenCols, phase, pitch);
52
        patterns.push_back(patternI.t());
52
        patterns.push_back(patternI.t());
53
    }
53
    }
54
 
54
 
55
 
55
 
56
}
56
}
57
 
57
 
58
cv::Mat AlgorithmPhaseShiftTwoFreq::getEncodingPattern(unsigned int depth){
58
cv::Mat AlgorithmPhaseShiftTwoFreq::getEncodingPattern(unsigned int depth){
59
    return patterns[depth];
59
    return patterns[depth];
60
}
60
}
61
 
61
 
62
void AlgorithmPhaseShiftTwoFreq::get3DPoints(SMCalibrationParameters calibration, const std::vector<cv::Mat>& frames0, const std::vector<cv::Mat>& frames1, std::vector<cv::Point3f>& Q, std::vector<cv::Vec3b>& color){
62
void AlgorithmPhaseShiftTwoFreq::get3DPoints(SMCalibrationParameters calibration, const std::vector<cv::Mat>& frames0, const std::vector<cv::Mat>& frames1, std::vector<cv::Point3f>& Q, std::vector<cv::Vec3b>& color){
63
 
63
 
64
    assert(frames0.size() == N);
64
    assert(frames0.size() == N);
65
    assert(frames1.size() == N);
65
    assert(frames1.size() == N);
66
 
66
 
67
    int frameRows = frames0[0].rows;
67
    int frameRows = frames0[0].rows;
68
    int frameCols = frames0[0].cols;
68
    int frameCols = frames0[0].cols;
69
 
69
 
70
    // Rectifying homographies (rotation+projections)
70
    // Rectifying homographies (rotation+projections)
71
    cv::Size frameSize(frameCols, frameRows);
71
    cv::Size frameSize(frameCols, frameRows);
72
    cv::Mat R, T;
72
    cv::Mat R, T;
73
    // stereoRectify segfaults unless R is double precision
73
    // stereoRectify segfaults unless R is double precision
74
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
74
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
75
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
75
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
76
    cv::Mat R0, R1, P0, P1, QRect;
76
    cv::Mat R0, R1, P0, P1, QRect;
77
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
77
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
78
 
78
 
79
    // Interpolation maps (lens distortion and rectification)
79
    // Interpolation maps (lens distortion and rectification)
80
    cv::Mat map0X, map0Y, map1X, map1Y;
80
    cv::Mat map0X, map0Y, map1X, map1Y;
81
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
81
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
82
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
82
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
83
 
83
 
84
    int frameRectRows = map0X.rows;
84
    int frameRectRows = map0X.rows;
85
    int frameRectCols = map0X.cols;
85
    int frameRectCols = map0X.cols;
86
 
86
 
87
    // Gray-scale and remap
87
    // Gray-scale and remap
88
    std::vector<cv::Mat> frames0Rect(N);
88
    std::vector<cv::Mat> frames0Rect(N);
89
    std::vector<cv::Mat> frames1Rect(N);
89
    std::vector<cv::Mat> frames1Rect(N);
90
    for(unsigned int i=0; i<N; i++){
90
    for(unsigned int i=0; i<N; i++){
91
        cv::Mat temp;
91
        cv::Mat temp;
92
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
92
        cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
93
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
93
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
94
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
94
        cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
95
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
95
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
96
    }
96
    }
97
 
97
 
98
    // Decode camera0
98
    // Decode camera0
99
    std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
99
    std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
100
    std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end());
100
    std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end());
101
 
101
 
102
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
102
    std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
103
    cv::Mat up0Primary;
103
    cv::Mat up0Primary;
104
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
104
    cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
105
 
105
 
106
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
106
    std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
107
    cv::Mat up0Secondary;
107
    cv::Mat up0Secondary;
108
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
108
    cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
109
 
109
 
110
    cv::Mat up0Equivalent = up0Secondary - up0Primary;
110
    cv::Mat up0Equivalent = up0Secondary - up0Primary;
111
    up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*CV_PI);
111
    up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*CV_PI);
112
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Equivalent, nPeriodsPrimary);
112
    cv::Mat up0 = unwrapWithCue(up0Primary, up0Equivalent, nPeriodsPrimary);
113
    up0 *= screenCols/(2.0*CV_PI);
113
    up0 *= screenCols/(2.0*CV_PI);
114
    cv::Mat amplitude0;
114
    cv::Mat amplitude0;
115
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
115
    cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0);
116
 
116
 
117
    // Collected signal energy at higher frequencies
117
    // Collected signal energy at higher frequencies
118
    cv::Mat energy0Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
118
    cv::Mat energy0Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
119
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
119
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
120
        cv::Mat magnitude;
120
        cv::Mat magnitude;
121
        cv::magnitude(F0Primary[i*2 + 2], F0Primary[i*2 + 3], magnitude);
121
        cv::magnitude(F0Primary[i*2 + 2], F0Primary[i*2 + 3], magnitude);
122
        cv::add(energy0Primary, magnitude, energy0Primary, cv::noArray(), CV_32F);
122
        cv::add(energy0Primary, magnitude, energy0Primary, cv::noArray(), CV_32F);
123
    }
123
    }
124
 
124
 
125
    cv::Mat energy0Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
125
    cv::Mat energy0Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
126
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
126
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
127
        cv::Mat magnitude;
127
        cv::Mat magnitude;
128
        cv::magnitude(F0Secondary[i*2 + 2], F0Secondary[i*2 + 3], magnitude);
128
        cv::magnitude(F0Secondary[i*2 + 2], F0Secondary[i*2 + 3], magnitude);
129
        cv::add(energy0Secondary, magnitude, energy0Secondary, cv::noArray(), CV_32F);
129
        cv::add(energy0Secondary, magnitude, energy0Secondary, cv::noArray(), CV_32F);
130
    }
130
    }
131
 
131
 
132
    #ifdef QT_DEBUG
132
    #ifdef QT_DEBUG
133
        cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
133
        cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
134
        cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
134
        cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
135
        cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
135
        cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
136
        cvtools::writeMat(up0, "up0.mat", "up0");
136
        cvtools::writeMat(up0, "up0.mat", "up0");
137
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
137
        cvtools::writeMat(amplitude0, "amplitude0.mat", "amplitude0");
138
        cvtools::writeMat(energy0Primary, "energy0Primary.mat", "energy0Primary");
138
        cvtools::writeMat(energy0Primary, "energy0Primary.mat", "energy0Primary");
139
        cvtools::writeMat(energy0Secondary, "energy0Secondary.mat", "energy0Secondary");
139
        cvtools::writeMat(energy0Secondary, "energy0Secondary.mat", "energy0Secondary");
140
    #endif
140
    #endif
141
 
141
 
142
    // Decode camera1
142
    // Decode camera1
143
    std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
143
    std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
144
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
144
    std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
145
 
145
 
146
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
146
    std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
147
    cv::Mat up1Primary;
147
    cv::Mat up1Primary;
148
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
148
    cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
149
 
149
 
150
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
150
    std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
151
    cv::Mat up1Secondary;
151
    cv::Mat up1Secondary;
152
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
152
    cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
153
 
153
 
154
    cv::Mat up1Equivalent = up1Secondary - up1Primary;
154
    cv::Mat up1Equivalent = up1Secondary - up1Primary;
155
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*CV_PI);
155
    up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*CV_PI);
156
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, nPeriodsPrimary);
156
    cv::Mat up1 = unwrapWithCue(up1Primary, up1Equivalent, nPeriodsPrimary);
157
    up1 *= screenCols/(2.0*CV_PI);
157
    up1 *= screenCols/(2.0*CV_PI);
158
    cv::Mat amplitude1;
158
    cv::Mat amplitude1;
159
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
159
    cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1);
160
 
160
 
161
    // Collected signal energy at higher frequencies
161
    // Collected signal energy at higher frequencies
162
    cv::Mat energy1Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
162
    cv::Mat energy1Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
163
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
163
    for(unsigned int i=0; i<nStepsPrimary-1; i++){
164
        cv::Mat magnitude;
164
        cv::Mat magnitude;
165
        cv::magnitude(F1Primary[i*2 + 2], F1Primary[i*2 + 3], magnitude);
165
        cv::magnitude(F1Primary[i*2 + 2], F1Primary[i*2 + 3], magnitude);
166
        cv::add(energy1Primary, magnitude, energy1Primary, cv::noArray(), CV_32F);
166
        cv::add(energy1Primary, magnitude, energy1Primary, cv::noArray(), CV_32F);
167
    }
167
    }
168
 
168
 
169
    cv::Mat energy1Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
169
    cv::Mat energy1Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
170
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
170
    for(unsigned int i=0; i<nStepsSecondary-1; i++){
171
        cv::Mat magnitude;
171
        cv::Mat magnitude;
172
        cv::magnitude(F1Secondary[i*2 + 2], F1Secondary[i*2 + 3], magnitude);
172
        cv::magnitude(F1Secondary[i*2 + 2], F1Secondary[i*2 + 3], magnitude);
173
        cv::add(energy1Secondary, magnitude, energy1Secondary, cv::noArray(), CV_32F);
173
        cv::add(energy1Secondary, magnitude, energy1Secondary, cv::noArray(), CV_32F);
174
    }
174
    }
175
 
175
 
176
    #ifdef QT_DEBUG
176
    #ifdef QT_DEBUG
177
        cvtools::writeMat(up1, "up1.mat", "up1");
177
        cvtools::writeMat(up1, "up1.mat", "up1");
178
    #endif
178
    #endif
179
 
179
 
180
    // color debayer and remap
180
    // color debayer and remap
181
    cv::Mat color0, color1;
181
    cv::Mat color0, color1;
182
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
182
    cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
183
    cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
183
    cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
184
 
184
 
185
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
185
    cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
186
    cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
186
    cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
187
 
187
 
188
    #ifdef QT_DEBUG
188
    #ifdef QT_DEBUG
189
        cvtools::writeMat(color0, "color0.mat", "color0");
189
        cvtools::writeMat(color0, "color0.mat", "color0");
190
        cvtools::writeMat(color1, "color1.mat", "color1");
190
        cvtools::writeMat(color1, "color1.mat", "color1");
191
    #endif
191
    #endif
192
 
192
 
193
    // Occlusion masks
193
    // Occlusion masks
194
    cv::Mat occlusion0, occlusion1;
194
    cv::Mat occlusion0, occlusion1;
195
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
195
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
196
    occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
196
    occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
197
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
197
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
198
    occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
198
    occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
199
 
199
 
200
    // Threshold on energy at primary frequency
200
    // Threshold on energy at primary frequency
201
    occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
201
    occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
202
    occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
202
    occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
203
 
203
 
204
    // Threshold on energy ratios
204
    // Threshold on energy ratios
205
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Primary);
205
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Primary);
206
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Secondary);
206
    occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Secondary);
207
 
207
 
208
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Primary);
208
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Primary);
209
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Secondary);
209
    occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Secondary);
210
 
210
 
211
//    // Erode occlusion masks
211
//    // Erode occlusion masks
212
//    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
212
//    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
213
//    cv::erode(occlusion0, occlusion0, strel);
213
//    cv::erode(occlusion0, occlusion0, strel);
214
//    cv::erode(occlusion1, occlusion1, strel);
214
//    cv::erode(occlusion1, occlusion1, strel);
215
 
215
 
216
    // Threshold on gradient of phase
216
    // Threshold on gradient of phase
217
    cv::Mat edges0;
217
    cv::Mat edges0;
218
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
218
    cv::Sobel(up0, edges0, -1, 1, 1, 5);
219
    occlusion0 = occlusion0 & (abs(edges0) < 150);
219
    occlusion0 = occlusion0 & (abs(edges0) < 10);
220
 
220
 
221
    cv::Mat edges1;
221
    cv::Mat edges1;
222
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
222
    cv::Sobel(up1, edges1, -1, 1, 1, 5);
223
    occlusion1 = occlusion1 & (abs(edges1) < 150);
223
    occlusion1 = occlusion1 & (abs(edges1) < 10);
224
 
224
 
225
    #ifdef QT_DEBUG
225
    #ifdef QT_DEBUG
-
 
226
        cvtools::writeMat(edges0, "edges0.mat", "edges0");
-
 
227
        cvtools::writeMat(edges1, "edges1.mat", "edges1");
226
        cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
228
        cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
227
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
229
        cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
228
    #endif
230
    #endif
229
 
231
 
230
    // Match phase maps
232
    // Match phase maps
231
 
233
 
232
    // camera0 against camera1
234
    // camera0 against camera1
233
    std::vector<cv::Vec2f> q0, q1;
235
    std::vector<cv::Vec2f> q0, q1;
234
    for(int row=0; row<frameRectRows; row++){
236
    for(int row=0; row<frameRectRows; row++){
235
        for(int col=0; col<frameRectCols; col++){
237
        for(int col=0; col<frameRectCols; col++){
236
 
238
 
237
            if(!occlusion0.at<char>(row,col))
239
            if(!occlusion0.at<char>(row,col))
238
                continue;
240
                continue;
239
 
241
 
240
            float up0i = up0.at<float>(row,col);
242
            float up0i = up0.at<float>(row,col);
241
            for(int col1=0; col1<up1.cols-1; col1++){
243
            for(int col1=0; col1<up1.cols-1; col1++){
242
 
244
 
243
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
245
                if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
244
                    continue;
246
                    continue;
245
 
247
 
246
                float up1Left = up1.at<float>(row,col1);
248
                float up1Left = up1.at<float>(row,col1);
247
                float up1Right = up1.at<float>(row,col1+1);
249
                float up1Right = up1.at<float>(row,col1+1);
248
 
250
 
249
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0) && (up1Right-up1Left > 0.1)){
251
                if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0) && (up1Right-up1Left > 0.1)){
250
 
252
 
251
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
253
                    float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
252
 
254
 
253
                    q0.push_back(cv::Point2f(col, row));
255
                    q0.push_back(cv::Point2f(col, row));
254
                    q1.push_back(cv::Point2f(col1i, row));
256
                    q1.push_back(cv::Point2f(col1i, row));
255
 
257
 
256
                    break;
258
                    break;
257
                }
259
                }
258
            }
260
            }
259
        }
261
        }
260
    }
262
    }
261
 
263
 
262
 
264
 
263
    int nMatches = q0.size();
265
    int nMatches = q0.size();
264
 
266
 
265
    if(nMatches < 1){
267
    if(nMatches < 1){
266
        Q.resize(0);
268
        Q.resize(0);
267
        color.resize(0);
269
        color.resize(0);
268
 
270
 
269
        return;
271
        return;
270
    }
272
    }
271
 
273
 
272
    // Retrieve color information
274
    // Retrieve color information
273
    color.resize(nMatches);
275
    color.resize(nMatches);
274
    for(int i=0; i<nMatches; i++){
276
    for(int i=0; i<nMatches; i++){
275
 
277
 
276
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
278
        cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
277
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
279
        cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
278
 
280
 
279
        color[i] = 0.5*c0 + 0.5*c1;
281
        color[i] = 0.5*c0 + 0.5*c1;
280
    }
282
    }
281
 
283
 
282
    // Triangulate points
284
    // Triangulate points
283
    cv::Mat QMatHomogenous, QMat;
285
    cv::Mat QMatHomogenous, QMat;
284
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
286
    cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
285
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
287
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
286
 
288
 
287
    // Undo rectification
289
    // Undo rectification
288
    cv::Mat R0Inv;
290
    cv::Mat R0Inv;
289
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
291
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
290
    QMat = R0Inv*QMat;
292
    QMat = R0Inv*QMat;
291
 
293
 
292
    cvtools::matToPoints3f(QMat, Q);
294
    cvtools::matToPoints3f(QMat, Q);
293
 
295
 
294
}
296
}
295
 
297