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(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){
|
62 |
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){
|
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 |
cv::Mat map0X, map0Y, map1X, map1Y;
|
67 |
cv::Mat map0X, map0Y, map1X, map1Y;
|
68 |
cv::Mat R0, P0, P1;
|
68 |
cv::Mat R0, P0, P1;
|
69 |
{
|
69 |
{
|
70 |
int frameRows = frames0[0].rows;
|
70 |
int frameRows = frames0[0].rows;
|
71 |
int frameCols = frames0[0].cols;
|
71 |
int frameCols = frames0[0].cols;
|
72 |
|
72 |
|
73 |
// Rectifying homographies (rotation+projections)
|
73 |
// Rectifying homographies (rotation+projections)
|
74 |
cv::Size frameSize(frameCols, frameRows);
|
74 |
cv::Size frameSize(frameCols, frameRows);
|
75 |
cv::Mat R, T;
|
75 |
cv::Mat R, T;
|
76 |
// stereoRectify segfaults unless R is double precision
|
76 |
// stereoRectify segfaults unless R is double precision
|
77 |
cv::Mat(calibration.R1).convertTo(R, CV_64F);
|
77 |
cv::Mat(calibration.R1).convertTo(R, CV_64F);
|
78 |
cv::Mat(calibration.T1).convertTo(T, CV_64F);
|
78 |
cv::Mat(calibration.T1).convertTo(T, CV_64F);
|
79 |
cv::Mat R1, QRect;
|
79 |
cv::Mat R1, QRect;
|
80 |
cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
|
80 |
cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
|
81 |
|
81 |
|
82 |
// Interpolation maps (lens distortion and rectification)
|
82 |
// Interpolation maps (lens distortion and rectification)
|
83 |
cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
|
83 |
cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
|
84 |
cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
|
84 |
cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
|
85 |
|
85 |
|
86 |
}
|
86 |
}
|
87 |
|
87 |
|
88 |
int frameRectRows = map0X.rows;
|
88 |
int frameRectRows = map0X.rows;
|
89 |
int frameRectCols = map0X.cols;
|
89 |
int frameRectCols = map0X.cols;
|
90 |
|
90 |
|
91 |
cv::Mat up0;
|
91 |
cv::Mat up0;
|
92 |
cv::Mat occlusion0;
|
92 |
cv::Mat occlusion0;
|
93 |
{
|
93 |
{
|
94 |
// Gray-scale and remap
|
94 |
// Gray-scale and remap
|
95 |
std::vector<cv::Mat> frames0Rect(N);
|
95 |
std::vector<cv::Mat> frames0Rect(N);
|
96 |
for(unsigned int i=0; i<N; i++){
|
96 |
for(unsigned int i=0; i<N; i++){
|
97 |
cv::Mat temp;
|
97 |
cv::Mat temp;
|
98 |
cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
|
98 |
cv::cvtColor(frames0[i], temp, CV_BayerBG2GRAY);
|
99 |
cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
|
99 |
cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
|
100 |
}
|
100 |
}
|
101 |
// Occlusion masks
|
101 |
// Occlusion masks
|
102 |
cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
|
102 |
cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0);
|
103 |
occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
|
103 |
occlusion0 = (occlusion0 > 25) & (occlusion0 < 250);
|
104 |
|
104 |
|
105 |
// Decode camera0
|
105 |
// Decode camera0
|
106 |
std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
|
106 |
std::vector<cv::Mat> frames0Primary(frames0Rect.begin()+2, frames0Rect.begin()+2+nStepsPrimary);
|
107 |
std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end());
|
107 |
std::vector<cv::Mat> frames0Secondary(frames0Rect.begin()+2+nStepsPrimary, frames0Rect.end());
|
108 |
|
108 |
|
109 |
frames0Rect.clear();
|
109 |
frames0Rect.clear();
|
110 |
|
110 |
|
111 |
std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
|
111 |
std::vector<cv::Mat> F0Primary = getDFTComponents(frames0Primary);
|
112 |
frames0Primary.clear();
|
112 |
frames0Primary.clear();
|
113 |
cv::Mat up0Primary;
|
113 |
cv::Mat up0Primary;
|
114 |
cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
|
114 |
cv::phase(F0Primary[2], -F0Primary[3], up0Primary);
|
115 |
|
115 |
|
116 |
std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
|
116 |
std::vector<cv::Mat> F0Secondary = getDFTComponents(frames0Secondary);
|
117 |
frames0Secondary.clear();
|
117 |
frames0Secondary.clear();
|
118 |
cv::Mat up0Secondary;
|
118 |
cv::Mat up0Secondary;
|
119 |
cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
|
119 |
cv::phase(F0Secondary[2], -F0Secondary[3], up0Secondary);
|
120 |
|
120 |
|
121 |
cv::Mat up0Equivalent = up0Secondary - up0Primary;
|
121 |
cv::Mat up0Equivalent = up0Secondary - up0Primary;
|
122 |
up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*CV_PI);
|
122 |
up0Equivalent = cvtools::modulo(up0Equivalent, 2.0*CV_PI);
|
123 |
up0 = unwrapWithCue(up0Primary, up0Equivalent, nPeriodsPrimary);
|
123 |
up0 = unwrapWithCue(up0Primary, up0Equivalent, nPeriodsPrimary);
|
124 |
up0 *= screenCols/(2.0*CV_PI);
|
124 |
up0 *= screenCols/(2.0*CV_PI);
|
125 |
|
125 |
|
126 |
// Signal energy at unit frequency
|
126 |
// Signal energy at unit frequency
|
127 |
cv::Mat amplitude0Primary, amplitude0Secondary;
|
127 |
cv::Mat amplitude0Primary, amplitude0Secondary;
|
128 |
cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0Primary);
|
128 |
cv::magnitude(F0Primary[2], -F0Primary[3], amplitude0Primary);
|
129 |
cv::magnitude(F0Secondary[2], -F0Secondary[3], amplitude0Secondary);
|
129 |
cv::magnitude(F0Secondary[2], -F0Secondary[3], amplitude0Secondary);
|
130 |
|
130 |
|
131 |
// Collected signal energy at higher frequencies
|
131 |
// Collected signal energy at higher frequencies
|
132 |
cv::Mat energy0Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
|
132 |
cv::Mat energy0Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
|
133 |
for(unsigned int i=0; i<nStepsPrimary-1; i++){
|
133 |
for(unsigned int i=0; i<nStepsPrimary-1; i++){
|
134 |
cv::Mat magnitude;
|
134 |
cv::Mat magnitude;
|
135 |
cv::magnitude(F0Primary[i*2 + 2], F0Primary[i*2 + 3], magnitude);
|
135 |
cv::magnitude(F0Primary[i*2 + 2], F0Primary[i*2 + 3], magnitude);
|
136 |
cv::add(energy0Primary, magnitude, energy0Primary, cv::noArray(), CV_32F);
|
136 |
cv::add(energy0Primary, magnitude, energy0Primary, cv::noArray(), CV_32F);
|
137 |
}
|
137 |
}
|
138 |
|
138 |
|
139 |
cv::Mat energy0Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
|
139 |
cv::Mat energy0Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
|
140 |
for(unsigned int i=0; i<nStepsSecondary-1; i++){
|
140 |
for(unsigned int i=0; i<nStepsSecondary-1; i++){
|
141 |
cv::Mat magnitude;
|
141 |
cv::Mat magnitude;
|
142 |
cv::magnitude(F0Secondary[i*2 + 2], F0Secondary[i*2 + 3], magnitude);
|
142 |
cv::magnitude(F0Secondary[i*2 + 2], F0Secondary[i*2 + 3], magnitude);
|
143 |
cv::add(energy0Secondary, magnitude, energy0Secondary, cv::noArray(), CV_32F);
|
143 |
cv::add(energy0Secondary, magnitude, energy0Secondary, cv::noArray(), CV_32F);
|
144 |
}
|
144 |
}
|
145 |
|
145 |
|
146 |
// Threshold on energy at primary frequency
|
146 |
// Threshold on energy at primary frequency
|
147 |
occlusion0 = occlusion0 & (amplitude0 > 5.0*nStepsPrimary);
|
147 |
occlusion0 = occlusion0 & (amplitude0Primary > 5.0*nStepsPrimary);
|
148 |
// Threshold on energy ratios
|
148 |
// Threshold on energy ratios
|
149 |
occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Primary);
|
149 |
occlusion0 = occlusion0 & (amplitude0Primary > 0.85*energy0Primary);
|
150 |
occlusion0 = occlusion0 & (amplitude0 > 0.85*energy0Secondary);
|
150 |
occlusion0 = occlusion0 & (amplitude0Secondary > 0.85*energy0Secondary);
|
151 |
|
151 |
|
152 |
#ifdef QT_DEBUG
|
152 |
#ifdef SM_DEBUG
|
153 |
cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
|
153 |
cvtools::writeMat(up0Primary, "up0Primary.mat", "up0Primary");
|
154 |
cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
|
154 |
cvtools::writeMat(up0Secondary, "up0Secondary.mat", "up0Secondary");
|
155 |
cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
|
155 |
cvtools::writeMat(up0Equivalent, "up0Equivalent.mat", "up0Equivalent");
|
156 |
cvtools::writeMat(up0, "up0.mat", "up0");
|
156 |
cvtools::writeMat(up0, "up0.mat", "up0");
|
157 |
cvtools::writeMat(amplitude0Primary, "amplitude0Primary.mat", "amplitude0Primary");
|
157 |
cvtools::writeMat(amplitude0Primary, "amplitude0Primary.mat", "amplitude0Primary");
|
158 |
cvtools::writeMat(energy0Primary, "energy0Primary.mat", "energy0Primary");
|
158 |
cvtools::writeMat(energy0Primary, "energy0Primary.mat", "energy0Primary");
|
159 |
cvtools::writeMat(energy0Secondary, "energy0Secondary.mat", "energy0Secondary");
|
159 |
cvtools::writeMat(energy0Secondary, "energy0Secondary.mat", "energy0Secondary");
|
160 |
#endif
|
160 |
#endif
|
161 |
}
|
161 |
}
|
162 |
|
162 |
|
163 |
cv::Mat up1;
|
163 |
cv::Mat up1;
|
164 |
cv::Mat occlusion1;
|
164 |
cv::Mat occlusion1;
|
165 |
{
|
165 |
{
|
166 |
|
166 |
|
167 |
// Gray-scale and remap
|
167 |
// Gray-scale and remap
|
168 |
std::vector<cv::Mat> frames1Rect(N);
|
168 |
std::vector<cv::Mat> frames1Rect(N);
|
169 |
for(unsigned int i=0; i<N; i++){
|
169 |
for(unsigned int i=0; i<N; i++){
|
170 |
cv::Mat temp;
|
170 |
cv::Mat temp;
|
171 |
cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
|
171 |
cv::cvtColor(frames1[i], temp, CV_BayerBG2GRAY);
|
172 |
cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
|
172 |
cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
|
173 |
}
|
173 |
}
|
174 |
|
174 |
|
175 |
// Occlusion masks
|
175 |
// Occlusion masks
|
176 |
cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
|
176 |
cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1);
|
177 |
occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
|
177 |
occlusion1 = (occlusion1 > 25) & (occlusion1 < 250);
|
178 |
|
178 |
|
179 |
// Decode camera1
|
179 |
// Decode camera1
|
180 |
std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
|
180 |
std::vector<cv::Mat> frames1Primary(frames1Rect.begin()+2, frames1Rect.begin()+2+nStepsPrimary);
|
181 |
std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
|
181 |
std::vector<cv::Mat> frames1Secondary(frames1Rect.begin()+2+nStepsPrimary, frames1Rect.end());
|
182 |
|
182 |
|
183 |
frames1Rect.clear();
|
183 |
frames1Rect.clear();
|
184 |
|
184 |
|
185 |
std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
|
185 |
std::vector<cv::Mat> F1Primary = getDFTComponents(frames1Primary);
|
186 |
frames1Primary.clear();
|
186 |
frames1Primary.clear();
|
187 |
cv::Mat up1Primary;
|
187 |
cv::Mat up1Primary;
|
188 |
cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
|
188 |
cv::phase(F1Primary[2], -F1Primary[3], up1Primary);
|
189 |
|
189 |
|
190 |
std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
|
190 |
std::vector<cv::Mat> F1Secondary = getDFTComponents(frames1Secondary);
|
191 |
frames1Secondary.clear();
|
191 |
frames1Secondary.clear();
|
192 |
cv::Mat up1Secondary;
|
192 |
cv::Mat up1Secondary;
|
193 |
cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
|
193 |
cv::phase(F1Secondary[2], -F1Secondary[3], up1Secondary);
|
194 |
|
194 |
|
195 |
cv::Mat up1Equivalent = up1Secondary - up1Primary;
|
195 |
cv::Mat up1Equivalent = up1Secondary - up1Primary;
|
196 |
up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*CV_PI);
|
196 |
up1Equivalent = cvtools::modulo(up1Equivalent, 2.0*CV_PI);
|
197 |
up1 = unwrapWithCue(up1Primary, up1Equivalent, nPeriodsPrimary);
|
197 |
up1 = unwrapWithCue(up1Primary, up1Equivalent, nPeriodsPrimary);
|
198 |
up1 *= screenCols/(2.0*CV_PI);
|
198 |
up1 *= screenCols/(2.0*CV_PI);
|
199 |
|
199 |
|
200 |
// Signal energy at unit frequency
|
200 |
// Signal energy at unit frequency
|
201 |
cv::Mat amplitude1Primary, amplitude1Secondary;
|
201 |
cv::Mat amplitude1Primary, amplitude1Secondary;
|
202 |
cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1Primary);
|
202 |
cv::magnitude(F1Primary[2], -F1Primary[3], amplitude1Primary);
|
203 |
cv::magnitude(F1Secondary[2], -F1Secondary[3], amplitude1Secondary);
|
203 |
cv::magnitude(F1Secondary[2], -F1Secondary[3], amplitude1Secondary);
|
204 |
|
204 |
|
205 |
// Collected signal energy at higher frequencies
|
205 |
// Collected signal energy at higher frequencies
|
206 |
cv::Mat energy1Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
|
206 |
cv::Mat energy1Primary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
|
207 |
for(unsigned int i=0; i<nStepsPrimary-1; i++){
|
207 |
for(unsigned int i=0; i<nStepsPrimary-1; i++){
|
208 |
cv::Mat magnitude;
|
208 |
cv::Mat magnitude;
|
209 |
cv::magnitude(F1Primary[i*2 + 2], F1Primary[i*2 + 3], magnitude);
|
209 |
cv::magnitude(F1Primary[i*2 + 2], F1Primary[i*2 + 3], magnitude);
|
210 |
cv::add(energy1Primary, magnitude, energy1Primary, cv::noArray(), CV_32F);
|
210 |
cv::add(energy1Primary, magnitude, energy1Primary, cv::noArray(), CV_32F);
|
211 |
}
|
211 |
}
|
212 |
|
212 |
|
213 |
cv::Mat energy1Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
|
213 |
cv::Mat energy1Secondary(frameRectRows, frameRectCols, CV_32F, cv::Scalar(0.0));
|
214 |
for(unsigned int i=0; i<nStepsSecondary-1; i++){
|
214 |
for(unsigned int i=0; i<nStepsSecondary-1; i++){
|
215 |
cv::Mat magnitude;
|
215 |
cv::Mat magnitude;
|
216 |
cv::magnitude(F1Secondary[i*2 + 2], F1Secondary[i*2 + 3], magnitude);
|
216 |
cv::magnitude(F1Secondary[i*2 + 2], F1Secondary[i*2 + 3], magnitude);
|
217 |
cv::add(energy1Secondary, magnitude, energy1Secondary, cv::noArray(), CV_32F);
|
217 |
cv::add(energy1Secondary, magnitude, energy1Secondary, cv::noArray(), CV_32F);
|
218 |
}
|
218 |
}
|
219 |
|
219 |
|
220 |
// Threshold on energy at primary frequency
|
220 |
// Threshold on energy at primary frequency
|
221 |
occlusion1 = occlusion1 & (amplitude1 > 5.0*nStepsPrimary);
|
221 |
occlusion1 = occlusion1 & (amplitude1Primary > 5.0*nStepsPrimary);
|
222 |
// Threshold on energy ratios
|
222 |
// Threshold on energy ratios
|
223 |
occlusion1 = occlusion1 & (amplitude1 > 0.85*energy1Primary);
|
- |
|
224 |
occlusion1 = occlusion1 & (amplitude1Primary > 0.85*energy1Primary);
|
223 |
occlusion1 = occlusion1 & (amplitude1Primary > 0.85*energy1Primary);
|
225 |
occlusion1 = occlusion1 & (amplitude1Secondary > 0.85*energy1Secondary);
|
224 |
occlusion1 = occlusion1 & (amplitude1Secondary > 0.85*energy1Secondary);
|
226 |
|
225 |
|
227 |
#ifdef QT_DEBUG
|
226 |
#ifdef SM_DEBUG
|
228 |
cvtools::writeMat(up1, "up1.mat", "up1");
|
227 |
cvtools::writeMat(up1, "up1.mat", "up1");
|
229 |
#endif
|
228 |
#endif
|
230 |
}
|
229 |
}
|
231 |
|
230 |
|
232 |
// // Erode occlusion masks
|
231 |
// // Erode occlusion masks
|
233 |
// cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
|
232 |
// cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5,5));
|
234 |
// cv::erode(occlusion0, occlusion0, strel);
|
233 |
// cv::erode(occlusion0, occlusion0, strel);
|
235 |
// cv::erode(occlusion1, occlusion1, strel);
|
234 |
// cv::erode(occlusion1, occlusion1, strel);
|
236 |
{
|
235 |
{
|
237 |
// Threshold on gradient of phase
|
236 |
// Threshold on gradient of phase
|
238 |
cv::Mat edges0;
|
237 |
cv::Mat edges0;
|
239 |
cv::Sobel(up0, edges0, -1, 1, 1, 5);
|
238 |
cv::Sobel(up0, edges0, -1, 1, 1, 5);
|
240 |
occlusion0 = occlusion0 & (abs(edges0) < 10);
|
239 |
occlusion0 = occlusion0 & (abs(edges0) < 10);
|
241 |
|
240 |
|
242 |
cv::Mat edges1;
|
241 |
cv::Mat edges1;
|
243 |
cv::Sobel(up1, edges1, -1, 1, 1, 5);
|
242 |
cv::Sobel(up1, edges1, -1, 1, 1, 5);
|
244 |
occlusion1 = occlusion1 & (abs(edges1) < 10);
|
243 |
occlusion1 = occlusion1 & (abs(edges1) < 10);
|
245 |
|
244 |
|
246 |
#ifdef QT_DEBUG
|
245 |
#ifdef SM_DEBUG
|
247 |
cvtools::writeMat(edges0, "edges0.mat", "edges0");
|
246 |
cvtools::writeMat(edges0, "edges0.mat", "edges0");
|
248 |
cvtools::writeMat(edges1, "edges1.mat", "edges1");
|
247 |
cvtools::writeMat(edges1, "edges1.mat", "edges1");
|
249 |
cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
|
248 |
cvtools::writeMat(occlusion0, "occlusion0.mat", "occlusion0");
|
250 |
cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
|
249 |
cvtools::writeMat(occlusion1, "occlusion1.mat", "occlusion1");
|
251 |
#endif
|
250 |
#endif
|
252 |
}
|
251 |
}
|
253 |
// Match phase maps
|
252 |
// Match phase maps
|
254 |
|
253 |
|
255 |
// camera0 against camera1
|
254 |
// camera0 against camera1
|
256 |
std::vector<cv::Vec2f> q0, q1;
|
255 |
std::vector<cv::Vec2f> q0, q1;
|
257 |
for(int row=0; row<frameRectRows; row++){
|
256 |
for(int row=0; row<frameRectRows; row++){
|
258 |
for(int col=0; col<frameRectCols; col++){
|
257 |
for(int col=0; col<frameRectCols; col++){
|
259 |
|
258 |
|
260 |
if(!occlusion0.at<char>(row,col))
|
259 |
if(!occlusion0.at<char>(row,col))
|
261 |
continue;
|
260 |
continue;
|
262 |
|
261 |
|
263 |
float up0i = up0.at<float>(row,col);
|
262 |
float up0i = up0.at<float>(row,col);
|
264 |
for(int col1=0; col1<up1.cols-1; col1++){
|
263 |
for(int col1=0; col1<up1.cols-1; col1++){
|
265 |
|
264 |
|
266 |
if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
|
265 |
if(!occlusion1.at<char>(row,col1) || !occlusion1.at<char>(row,col1+1))
|
267 |
continue;
|
266 |
continue;
|
268 |
|
267 |
|
269 |
float up1Left = up1.at<float>(row,col1);
|
268 |
float up1Left = up1.at<float>(row,col1);
|
270 |
float up1Right = up1.at<float>(row,col1+1);
|
269 |
float up1Right = up1.at<float>(row,col1+1);
|
271 |
|
270 |
|
272 |
if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0) && (up1Right-up1Left > 0.1)){
|
271 |
if((up1Left <= up0i) && (up0i <= up1Right) && (up0i-up1Left < 1.0) && (up1Right-up0i < 1.0) && (up1Right-up1Left > 0.1)){
|
273 |
|
272 |
|
274 |
float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
|
273 |
float col1i = col1 + (up0i-up1Left)/(up1Right-up1Left);
|
275 |
|
274 |
|
276 |
q0.push_back(cv::Point2f(col, row));
|
275 |
q0.push_back(cv::Point2f(col, row));
|
277 |
q1.push_back(cv::Point2f(col1i, row));
|
276 |
q1.push_back(cv::Point2f(col1i, row));
|
278 |
|
277 |
|
279 |
break;
|
278 |
break;
|
280 |
}
|
279 |
}
|
281 |
}
|
280 |
}
|
282 |
}
|
281 |
}
|
283 |
}
|
282 |
}
|
284 |
|
283 |
|
285 |
|
284 |
|
286 |
int nMatches = q0.size();
|
285 |
int nMatches = q0.size();
|
287 |
|
286 |
|
288 |
if(nMatches < 1){
|
287 |
if(nMatches < 1){
|
289 |
Q.resize(0);
|
288 |
Q.resize(0);
|
290 |
color.resize(0);
|
289 |
color.resize(0);
|
291 |
|
290 |
|
292 |
return;
|
291 |
return;
|
293 |
}
|
292 |
}
|
294 |
{
|
293 |
{
|
295 |
// color debayer and remap
|
294 |
// color debayer and remap
|
296 |
cv::Mat color0, color1;
|
295 |
cv::Mat color0, color1;
|
297 |
cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
|
296 |
cv::cvtColor(frames0[0], color0, CV_BayerBG2RGB);
|
298 |
cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
|
297 |
cv::remap(color0, color0, map0X, map0Y, CV_INTER_LINEAR);
|
299 |
|
298 |
|
300 |
cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
|
299 |
cv::cvtColor(frames1[0], color1, CV_BayerBG2RGB);
|
301 |
cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
|
300 |
cv::remap(color1, color1, map1X, map1Y, CV_INTER_LINEAR);
|
302 |
|
301 |
|
303 |
#ifdef QT_DEBUG
|
302 |
#ifdef SM_DEBUG
|
304 |
cvtools::writeMat(color0, "color0.mat", "color0");
|
303 |
cvtools::writeMat(color0, "color0.mat", "color0");
|
305 |
cvtools::writeMat(color1, "color1.mat", "color1");
|
304 |
cvtools::writeMat(color1, "color1.mat", "color1");
|
306 |
#endif
|
305 |
#endif
|
307 |
|
306 |
|
308 |
// Retrieve color information
|
307 |
// Retrieve color information
|
309 |
color.resize(nMatches);
|
308 |
color.resize(nMatches);
|
310 |
for(int i=0; i<nMatches; i++){
|
309 |
for(int i=0; i<nMatches; i++){
|
311 |
|
310 |
|
312 |
cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
|
311 |
cv::Vec3b c0 = color0.at<cv::Vec3b>(q0[i][1], q0[i][0]);
|
313 |
cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
|
312 |
cv::Vec3b c1 = color1.at<cv::Vec3b>(q1[i][1], q1[i][0]);
|
314 |
|
313 |
|
315 |
color[i] = 0.5*c0 + 0.5*c1;
|
314 |
color[i] = 0.5*c0 + 0.5*c1;
|
316 |
}
|
315 |
}
|
317 |
}
|
316 |
}
|
318 |
// Triangulate points
|
317 |
// Triangulate points
|
319 |
cv::Mat QMatHomogenous, QMat;
|
318 |
cv::Mat QMatHomogenous, QMat;
|
320 |
cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
|
319 |
cv::triangulatePoints(P0, P1, q0, q1, QMatHomogenous);
|
321 |
cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
|
320 |
cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
|
322 |
|
321 |
|
323 |
// Undo rectification
|
322 |
// Undo rectification
|
324 |
cv::Mat R0Inv;
|
323 |
cv::Mat R0Inv;
|
325 |
cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
|
324 |
cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
|
326 |
QMat = R0Inv*QMat;
|
325 |
QMat = R0Inv*QMat;
|
327 |
|
326 |
|
328 |
cvtools::matToPoints3f(QMat, Q);
|
327 |
cvtools::matToPoints3f(QMat, Q);
|
329 |
|
328 |
|
330 |
}
|
329 |
}
|
331 |
|
330 |
|