Subversion Repositories seema-scanner

Rev

Rev 163 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 163 Rev 167
1
#include "AlgorithmGrayCodeMax.h"
1
#include "AlgorithmGrayCodeMax.h"
2
#include <cmath>
2
#include <cmath>
3
#include "cvtools.h"
3
#include "cvtools.h"
4
 
4
 
5
#ifndef log2f
5
#ifndef log2f
6
#define log2f(x) (log(x)/log(2.0))
6
#define log2f(x) (log(x)/log(2.0))
7
#endif
7
#endif
8
 
8
 
9
//using namespace std;
9
//using namespace std;
10
 
10
 
11
namespace ggmax {
11
namespace ggmax {
12
 
12
 
13
/*
13
/*
14
 * The purpose of this function is to convert an unsigned
14
 * The purpose of this function is to convert an unsigned
15
 * binary number to reflected binary Gray code.
15
 * binary number to reflected binary Gray code.
16
 *
16
 *
17
 * The operator >> is shift right. The operator ^ is exclusive or.
17
 * The operator >> is shift right. The operator ^ is exclusive or.
18
 * Source: http://en.wikipedia.org/wiki/Gray_code
18
 * Source: http://en.wikipedia.org/wiki/Gray_code
19
 */
19
 */
20
static unsigned int binaryToGray(unsigned int num) {
20
static unsigned int binaryToGray(unsigned int num) {
21
    return (num >> 1) ^ num;
21
    return (num >> 1) ^ num;
22
}
22
}
23
 
23
 
24
/*
24
/*
25
 * From Wikipedia: http://en.wikipedia.org/wiki/Gray_code
25
 * From Wikipedia: http://en.wikipedia.org/wiki/Gray_code
26
 * The purpose of this function is to convert a reflected binary
26
 * The purpose of this function is to convert a reflected binary
27
 * Gray code number to a binary number.
27
 * Gray code number to a binary number.
28
 */
28
 */
29
static unsigned int grayToBinary(unsigned int num){
29
static unsigned int grayToBinary(unsigned int num){
30
    unsigned int mask;
30
    unsigned int mask;
31
    for(mask = num >> 1; mask != 0; mask = mask >> 1)
31
    for(mask = num >> 1; mask != 0; mask = mask >> 1)
32
        num = num ^ mask;
32
        num = num ^ mask;
33
    return num;
33
    return num;
34
}
34
}
35
 
35
 
36
/*
36
/*
37
 * Return the Nth bit of an unsigned integer number
37
 * Return the Nth bit of an unsigned integer number
38
 */
38
 */
39
static bool getBit(int decimal, int N){
39
static bool getBit(int decimal, int N){
40
 
40
 
41
    return decimal & 1 << (N-1);
41
    return decimal & 1 << (N-1);
42
}
42
}
43
 
43
 
44
/*
44
///*
45
 * Return the number of bits set in an integer
45
// * Return the number of bits set in an integer
46
 */
46
// */
47
static int countBits(int n) {
47
//static int countBits(int n) {
48
  unsigned int c; // c accumulates the total bits set in v
48
//  unsigned int c; // c accumulates the total bits set in v
49
  for (c = 0; n>0; c++)
49
//  for (c = 0; n>0; c++)
50
    n &= n - 1; // clear the least significant bit set
50
//    n &= n - 1; // clear the least significant bit set
51
  return c;
51
//  return c;
52
}
52
//}
53
 
53
 
54
/*
54
/*
55
 * Return the position of the least significant bit that is set
55
 * Return the position of the least significant bit that is set
56
 */
56
 */
57
static int leastSignificantBitSet(int x){
57
static int leastSignificantBitSet(int x){
58
  if(x == 0)
58
  if(x == 0)
59
      return 0;
59
      return 0;
60
 
60
 
61
  int val = 1;
61
  int val = 1;
62
  while(x>>=1)
62
  while(x>>=1)
63
      val++;
63
      val++;
64
 
64
 
65
  return val;
65
  return val;
66
}
66
}
67
 
67
 
68
//static int get_bit(int decimal, int N){
68
//static int get_bit(int decimal, int N){
69
 
69
 
70
//    // Shifting the 1 for N-1 bits
70
//    // Shifting the 1 for N-1 bits
71
//    int constant = 1 << (N-1);
71
//    int constant = 1 << (N-1);
72
 
72
 
73
//    // If the bit is set, return 1
73
//    // If the bit is set, return 1
74
//    if( decimal & constant )
74
//    if( decimal & constant )
75
//        return 1;
75
//        return 1;
76
//    else
76
//    else
77
//        return 0;
77
//        return 0;
78
//}
78
//}
79
 
79
 
80
static inline unsigned int powi(int num, unsigned int exponent){
80
static inline unsigned int powi(int num, unsigned int exponent){
81
 
81
 
82
    if(exponent == 0)
82
    if(exponent == 0)
83
        return 1;
83
        return 1;
84
 
84
 
85
    float res = num;
85
    float res = num;
86
    for(unsigned int i=0; i<exponent-1; i++)
86
    for(unsigned int i=0; i<exponent-1; i++)
87
        res *= num;
87
        res *= num;
88
 
88
 
89
    return res;
89
    return res;
90
}
90
}
91
 
91
 
92
static inline unsigned int twopowi(unsigned int exponent){
92
static inline unsigned int twopowi(unsigned int exponent){
93
 
93
 
94
    return 1 << exponent;
94
    return 1 << exponent;
95
}
95
}
96
 
96
 
97
bool sortingLarger(cv::Vec4i i,cv::Vec4i j){ return (i[3]<j[3]);}
97
bool sortingLarger(cv::Vec4i i,cv::Vec4i j){ return (i[3]<j[3]);}
98
bool sortingEqual(cv::Vec4i i,cv::Vec4i j){ return (i[3]==j[3]);}
98
bool sortingEqual(cv::Vec4i i,cv::Vec4i j){ return (i[3]==j[3]);}
99
void getEdgeLabels(const cv::Mat& scanLine, int Nbits, std::vector<cv::Vec4i>& edges){
99
void getEdgeLabels(const cv::Mat& scanLine, int Nbits, std::vector<cv::Vec4i>& edges){
100
 
100
 
101
    int nCols = scanLine.cols;
101
    int nCols = scanLine.cols;
102
    const int *data = scanLine.ptr<const int>(0);
102
    const int *data = scanLine.ptr<const int>(0);
103
 
103
 
104
    int labelLeft;
104
    int labelLeft;
105
    int labelRight = data[0];
105
    int labelRight = data[0];
106
 
106
 
107
    // collect edges
107
    // collect edges
108
    for(int col=1; col<nCols; col++){
108
    for(int col=1; col<nCols; col++){
109
 
109
 
110
        labelLeft = labelRight;
110
        labelLeft = labelRight;
111
        labelRight = data[col];
111
        labelRight = data[col];
112
 
112
 
113
        // labels need to be non-background, and differ in exactly one bit
113
        // labels need to be non-background, and differ in exactly one bit
114
        if(labelLeft != -1 && labelRight != -1 && (ggmax::grayToBinary(labelRight) == ggmax::grayToBinary(labelLeft)+1)){
114
        if(labelLeft != -1 && labelRight != -1 && (ggmax::grayToBinary(labelRight) == ggmax::grayToBinary(labelLeft)+1)){
115
            int orderingRelation = (labelLeft << Nbits) + labelRight;
115
            int orderingRelation = (labelLeft << Nbits) + labelRight;
116
            // store left label column
116
            // store left label column
117
            edges.push_back(cv::Vec4i(col-1, labelLeft, labelRight, orderingRelation));
117
            edges.push_back(cv::Vec4i(col-1, labelLeft, labelRight, orderingRelation));
118
        }
118
        }
119
    }
119
    }
120
 
120
 
121
    // sort
121
    // sort
122
    std::sort(edges.begin(), edges.end(), sortingLarger);
122
    std::sort(edges.begin(), edges.end(), sortingLarger);
123
 
123
 
124
    // remove duplicates
124
    // remove duplicates
125
    std::vector<cv::Vec4i>::iterator it;
125
    std::vector<cv::Vec4i>::iterator it;
126
    it = std::unique(edges.begin(), edges.end(), sortingEqual);
126
    it = std::unique(edges.begin(), edges.end(), sortingEqual);
127
    edges.resize(std::distance(edges.begin(),it));
127
    edges.resize(std::distance(edges.begin(),it));
128
}
128
}
129
} // End ggmax namespace
129
} // End ggmax namespace
130
 
130
 
131
// Algorithm
131
// Algorithm
132
AlgorithmGrayCodeMax::AlgorithmGrayCodeMax(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
132
AlgorithmGrayCodeMax::AlgorithmGrayCodeMax(unsigned int _screenCols, unsigned int _screenRows) : Algorithm(_screenCols, _screenRows){
133
 
133
 
134
    Nbits = ceilf(log2f((float)screenCols)) - 1;
134
    Nbits = ceilf(log2f((float)screenCols)) - 1;
135
    N = 2 + Nbits*2;
135
    N = 2 + Nbits*2;
136
 
136
 
137
    // all on pattern
137
    // all on pattern
138
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
138
    cv::Mat allOn(1, screenCols, CV_8UC3, cv::Scalar::all(255));
139
    patterns.push_back(allOn);
139
    patterns.push_back(allOn);
140
 
140
 
141
    // all off pattern
141
    // all off pattern
142
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
142
    cv::Mat allOff(1, screenCols, CV_8UC3, cv::Scalar::all(0));
143
    patterns.push_back(allOff);
143
    patterns.push_back(allOff);
144
 
144
 
145
 
145
 
146
    // horizontally encoding patterns
146
    // horizontally encoding patterns
147
    for(unsigned int p=0; p<Nbits; p++){
147
    for(unsigned int p=0; p<Nbits; p++){
148
        cv::Mat pattern(1, screenCols, CV_8UC3);
148
        cv::Mat pattern(1, screenCols, CV_8UC3);
149
        cv::Mat patternInv(1, screenCols, CV_8UC3);
149
        cv::Mat patternInv(1, screenCols, CV_8UC3);
150
 
150
 
151
        for(unsigned int j=0; j<screenCols; j++){
151
        for(unsigned int j=0; j<screenCols; j++){
152
 
152
 
153
            unsigned int jGray = ggmax::binaryToGray(j);
153
            unsigned int jGray = ggmax::binaryToGray(j);
154
            // Amplitude of channels
154
            // Amplitude of channels
155
            int bit = (int)ggmax::getBit(jGray, Nbits-p+1);
155
            int bit = (int)ggmax::getBit(jGray, Nbits-p+1);
156
            pattern.at<cv::Vec3b>(0,j) = cv::Vec3b(255.0*bit,255.0*bit,255.0*bit);
156
            pattern.at<cv::Vec3b>(0,j) = cv::Vec3b(255.0*bit,255.0*bit,255.0*bit);
157
            int invBit = bit^1;
157
            int invBit = bit^1;
158
            patternInv.at<cv::Vec3b>(0,j) = cv::Vec3b(255.0*invBit,255.0*invBit,255.0*invBit);
158
            patternInv.at<cv::Vec3b>(0,j) = cv::Vec3b(255.0*invBit,255.0*invBit,255.0*invBit);
159
        }
159
        }
160
        patterns.push_back(pattern);
160
        patterns.push_back(pattern);
161
        patterns.push_back(patternInv);
161
        patterns.push_back(patternInv);
162
    }
162
    }
163
 
163
 
164
 
164
 
165
}
165
}
166
 
166
 
167
cv::Mat AlgorithmGrayCodeMax::getEncodingPattern(unsigned int depth){
167
cv::Mat AlgorithmGrayCodeMax::getEncodingPattern(unsigned int depth){
168
    return patterns[depth];
168
    return patterns[depth];
169
}
169
}
170
 
170
 
171
static cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt){
171
//static cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt){
172
    assert(!img.empty());
172
//    assert(!img.empty());
173
    assert(img.channels() == 3);
173
//    assert(img.channels() == 3);
174
 
174
 
175
    int x = (int)pt.x;
175
//    int x = (int)pt.x;
176
    int y = (int)pt.y;
176
//    int y = (int)pt.y;
177
 
177
 
178
    int x0 = cv::borderInterpolate(x,   img.cols, cv::BORDER_REFLECT_101);
178
//    int x0 = cv::borderInterpolate(x,   img.cols, cv::BORDER_REFLECT_101);
179
    int x1 = cv::borderInterpolate(x+1, img.cols, cv::BORDER_REFLECT_101);
179
//    int x1 = cv::borderInterpolate(x+1, img.cols, cv::BORDER_REFLECT_101);
180
    int y0 = cv::borderInterpolate(y,   img.rows, cv::BORDER_REFLECT_101);
180
//    int y0 = cv::borderInterpolate(y,   img.rows, cv::BORDER_REFLECT_101);
181
    int y1 = cv::borderInterpolate(y+1, img.rows, cv::BORDER_REFLECT_101);
181
//    int y1 = cv::borderInterpolate(y+1, img.rows, cv::BORDER_REFLECT_101);
182
 
182
 
183
    float a = pt.x - (float)x;
183
//    float a = pt.x - (float)x;
184
    float c = pt.y - (float)y;
184
//    float c = pt.y - (float)y;
185
 
185
 
186
    uchar b = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c)
186
//    uchar b = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c)
187
                           + (img.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[0] * a) * c);
187
//                           + (img.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[0] * a) * c);
188
    uchar g = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c)
188
//    uchar g = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c)
189
                           + (img.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[1] * a) * c);
189
//                           + (img.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[1] * a) * c);
190
    uchar r = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c)
190
//    uchar r = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c)
191
                           + (img.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[2] * a) * c);
191
//                           + (img.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[2] * a) * c);
192
 
192
 
193
    return cv::Vec3b(b, g, r);
193
//    return cv::Vec3b(b, g, r);
194
}
194
//}
195
 
195
 
196
void AlgorithmGrayCodeMax::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){
196
void AlgorithmGrayCodeMax::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){
197
 
197
 
198
    assert(frames0.size() == N);
198
    assert(frames0.size() == N);
199
    assert(frames1.size() == N);
199
    assert(frames1.size() == N);
200
 
200
 
201
//    for(int i=0; i<1920; i++){
201
//    for(int i=0; i<1920; i++){
202
//        std::cout << i << " " << binaryToGray(i) << " " << grayToBinary(binaryToGray(i)) << std::endl;
202
//        std::cout << i << " " << binaryToGray(i) << " " << grayToBinary(binaryToGray(i)) << std::endl;
203
//    }
203
//    }
204
 
204
 
205
    int frameRows = frames0[0].rows;
205
    int frameRows = frames0[0].rows;
206
    int frameCols = frames0[0].cols;
206
    int frameCols = frames0[0].cols;
207
 
207
 
208
    // rectifying homographies (rotation+projections)
208
    // rectifying homographies (rotation+projections)
209
    cv::Size frameSize(frameCols, frameRows);
209
    cv::Size frameSize(frameCols, frameRows);
210
    cv::Mat R, T;
210
    cv::Mat R, T;
211
    // stereoRectify segfaults unless R is double precision
211
    // stereoRectify segfaults unless R is double precision
212
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
212
    cv::Mat(calibration.R1).convertTo(R, CV_64F);
213
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
213
    cv::Mat(calibration.T1).convertTo(T, CV_64F);
214
    cv::Mat R0, R1, P0, P1, QRect;
214
    cv::Mat R0, R1, P0, P1, QRect;
215
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
215
    cv::stereoRectify(calibration.K0, calibration.k0, calibration.K1, calibration.k1, frameSize, R, T, R0, R1, P0, P1, QRect, 0);
216
 
216
 
217
//    std::cout << "R0" << std::endl << R0 << std::endl;
217
//    std::cout << "R0" << std::endl << R0 << std::endl;
218
//    std::cout << "P0" << std::endl << P0 << std::endl;
218
//    std::cout << "P0" << std::endl << P0 << std::endl;
219
//    std::cout << "R1" << std::endl << R1 << std::endl;
219
//    std::cout << "R1" << std::endl << R1 << std::endl;
220
//    std::cout << "P1" << std::endl << P1 << std::endl;
220
//    std::cout << "P1" << std::endl << P1 << std::endl;
221
 
221
 
222
    // interpolation maps
222
    // interpolation maps
223
    cv::Mat map0X, map0Y, map1X, map1Y;
223
    cv::Mat map0X, map0Y, map1X, map1Y;
224
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
224
    cv::initUndistortRectifyMap(calibration.K0, calibration.k0, R0, P0, frameSize, CV_32F, map0X, map0Y);
225
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
225
    cv::initUndistortRectifyMap(calibration.K1, calibration.k1, R1, P1, frameSize, CV_32F, map1X, map1Y);
226
 
226
 
227
    // gray-scale and remap (Rasmus has adjusted here)
227
    // gray-scale and remap (Rasmus has adjusted here)
228
    std::vector<cv::Mat> frames0Rect(N);
228
    std::vector<cv::Mat> frames0Rect(N);
229
    std::vector<cv::Mat> frames1Rect(N);
229
    std::vector<cv::Mat> frames1Rect(N);
230
    for(size_t i=0; i<N; i++){
230
    for(size_t i=0; i<N; i++){
231
        cv::Mat temp;
231
        cv::Mat temp;
232
        cv::Mat temp_col;
232
        cv::Mat temp_col;
233
        cv::cvtColor(frames0[i], temp_col, CV_BayerBG2RGB);
233
        cv::cvtColor(frames0[i], temp_col, CV_BayerBG2RGB);
234
		std::vector<cv::Mat> channels(3);
234
		std::vector<cv::Mat> channels(3);
235
        cv::split(temp_col, channels);
235
        cv::split(temp_col, channels);
236
        temp = cv::max(channels[2], cv::max(channels[1], channels[0])); // Calculate max of the three channels
236
        temp = cv::max(channels[2], cv::max(channels[1], channels[0])); // Calculate max of the three channels
237
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
237
        cv::remap(temp, frames0Rect[i], map0X, map0Y, CV_INTER_LINEAR);
238
 
238
 
239
        cv::cvtColor(frames1[i], temp_col, CV_BayerBG2RGB);
239
        cv::cvtColor(frames1[i], temp_col, CV_BayerBG2RGB);
240
        channels.clear();
240
        channels.clear();
241
        cv::split(temp_col, channels);
241
        cv::split(temp_col, channels);
242
        temp = cv::max(channels[2], cv::max(channels[1], channels[0]));
242
        temp = cv::max(channels[2], cv::max(channels[1], channels[0]));
243
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
243
        cv::remap(temp, frames1Rect[i], map1X, map1Y, CV_INTER_LINEAR);
244
    }
244
    }
245
 
245
 
246
 
246
 
247
//    cvtools::writeMat(frames0Rect[0], "frames0Rect_0.mat", "frames0Rect_0");
247
//    cvtools::writeMat(frames0Rect[0], "frames0Rect_0.mat", "frames0Rect_0");
248
//    cvtools::writeMat(frames0[0], "frames0_0.mat", "frames0_0");
248
//    cvtools::writeMat(frames0[0], "frames0_0.mat", "frames0_0");
249
 
249
 
250
//    cvtools::writeMat(frames0Rect[22], "frames0Rect_22.mat", "frames0Rect_22");
250
//    cvtools::writeMat(frames0Rect[22], "frames0Rect_22.mat", "frames0Rect_22");
251
//    cvtools::writeMat(frames0Rect[23], "frames0Rect_23.mat", "frames0Rect_23");
251
//    cvtools::writeMat(frames0Rect[23], "frames0Rect_23.mat", "frames0Rect_23");
252
 
252
 
253
//    cv::imwrite("frames0[0].png", frames0[0]);
253
//    cv::imwrite("frames0[0].png", frames0[0]);
254
//    cv::imwrite("frames0Rect[0].png", frames0Rect[0]);
254
//    cv::imwrite("frames0Rect[0].png", frames0Rect[0]);
255
 
255
 
256
//    cv::imwrite("frames1[0].png", frames1[0]);
256
//    cv::imwrite("frames1[0].png", frames1[0]);
257
//    cv::imwrite("frames1Rect[0].png", frames1Rect[0]);
257
//    cv::imwrite("frames1Rect[0].png", frames1Rect[0]);
258
 
258
 
259
    // color debayer and remap
259
    // color debayer and remap
260
    cv::Mat color0Rect, color1Rect;
260
    cv::Mat color0Rect, color1Rect;
261
//    frames0[0].convertTo(color0Rect, CV_8UC1, 1.0/256.0);
261
//    frames0[0].convertTo(color0Rect, CV_8UC1, 1.0/256.0);
262
    cv::cvtColor(frames0[0], color0Rect, CV_BayerBG2RGB);
262
    cv::cvtColor(frames0[0], color0Rect, CV_BayerBG2RGB);
263
    cv::remap(color0Rect, color0Rect, map0X, map0Y, CV_INTER_LINEAR);
263
    cv::remap(color0Rect, color0Rect, map0X, map0Y, CV_INTER_LINEAR);
264
 
264
 
265
//    frames1[0].convertTo(color1Rect, CV_8UC1, 1.0/256.0);
265
//    frames1[0].convertTo(color1Rect, CV_8UC1, 1.0/256.0);
266
    cv::cvtColor(frames1[0], color1Rect, CV_BayerBG2RGB);
266
    cv::cvtColor(frames1[0], color1Rect, CV_BayerBG2RGB);
267
    cv::remap(color1Rect, color1Rect, map1X, map1Y, CV_INTER_LINEAR);
267
    cv::remap(color1Rect, color1Rect, map1X, map1Y, CV_INTER_LINEAR);
268
 
268
 
269
    int frameRectRows = frames0Rect[0].rows;
269
    int frameRectRows = frames0Rect[0].rows;
270
    int frameRectCols = frames0Rect[0].cols;
270
    int frameRectCols = frames0Rect[0].cols;
271
 
271
 
272
//cvtools::writeMat(frames0Rect[0], "frames0Rect_0.mat", "frames0Rect_0");
272
//cvtools::writeMat(frames0Rect[0], "frames0Rect_0.mat", "frames0Rect_0");
273
//cvtools::writeMat(frames0Rect[1], "frames0Rect_1.mat", "frames0Rect_1");
273
//cvtools::writeMat(frames0Rect[1], "frames0Rect_1.mat", "frames0Rect_1");
274
//cvtools::writeMat(frames0Rect[20], "frames0Rect_20.mat", "frames0Rect_20");
274
//cvtools::writeMat(frames0Rect[20], "frames0Rect_20.mat", "frames0Rect_20");
275
//cvtools::writeMat(frames0Rect[21], "frames0Rect_21.mat", "frames0Rect_21");
275
//cvtools::writeMat(frames0Rect[21], "frames0Rect_21.mat", "frames0Rect_21");
276
 
276
 
277
    // occlusion masks
277
    // occlusion masks
278
    cv::Mat occlusion0Rect, occlusion1Rect;
278
    cv::Mat occlusion0Rect, occlusion1Rect;
279
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0Rect);
279
    cv::subtract(frames0Rect[0], frames0Rect[1], occlusion0Rect);
280
    occlusion0Rect = (occlusion0Rect > 10) & (occlusion0Rect < 250);
280
    occlusion0Rect = (occlusion0Rect > 10) & (occlusion0Rect < 250);
281
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1Rect);
281
    cv::subtract(frames1Rect[0], frames1Rect[1], occlusion1Rect);
282
    occlusion1Rect = (occlusion1Rect > 10) & (occlusion1Rect < 250);
282
    occlusion1Rect = (occlusion1Rect > 10) & (occlusion1Rect < 250);
283
 
283
 
284
    // erode occlusion masks
284
    // erode occlusion masks
285
    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(2,2));
285
    cv::Mat strel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(2,2));
286
    cv::erode(occlusion0Rect, occlusion0Rect, strel);
286
    cv::erode(occlusion0Rect, occlusion0Rect, strel);
287
    cv::erode(occlusion1Rect, occlusion1Rect, strel);
287
    cv::erode(occlusion1Rect, occlusion1Rect, strel);
288
 
288
 
289
//cvtools::writeMat(frames0Rect[0], "frames0Rect_0.mat", "frames0Rect_0");
289
//cvtools::writeMat(frames0Rect[0], "frames0Rect_0.mat", "frames0Rect_0");
290
//cvtools::writeMat(frames0Rect[1], "frames0Rect_1.mat", "frames0Rect_1");
290
//cvtools::writeMat(frames0Rect[1], "frames0Rect_1.mat", "frames0Rect_1");
291
//cvtools::writeMat(frames0Rect[20], "frames0Rect_20.mat", "frames0Rect_20");
291
//cvtools::writeMat(frames0Rect[20], "frames0Rect_20.mat", "frames0Rect_20");
292
//cvtools::writeMat(frames0Rect[21], "frames0Rect_21.mat", "frames0Rect_21");
292
//cvtools::writeMat(frames0Rect[21], "frames0Rect_21.mat", "frames0Rect_21");
293
 
293
 
294
//    // correct for projector inversion error
294
//    // correct for projector inversion error
295
//    cv::Mat W;
295
//    cv::Mat W;
296
//    cv::add(frames0Rect[0], frames0Rect[1], W, cv::noArray(), CV_32F);
296
//    cv::add(frames0Rect[0], frames0Rect[1], W, cv::noArray(), CV_32F);
297
//    for(int i=2; i<N; i+=2){
297
//    for(int i=2; i<N; i+=2){
298
//        cv::Mat S, E;
298
//        cv::Mat S, E;
299
//        cv::add(frames0Rect[i], frames0Rect[i+1], S, cv::noArray(), CV_32F);
299
//        cv::add(frames0Rect[i], frames0Rect[i+1], S, cv::noArray(), CV_32F);
300
//        cv::subtract(W, S, E, cv::noArray(), CV_32F);
300
//        cv::subtract(W, S, E, cv::noArray(), CV_32F);
301
//        E *= 0.5;
301
//        E *= 0.5;
302
//        cv::add(frames0Rect[i], E, frames0Rect[i], cv::noArray(), CV_16UC1);
302
//        cv::add(frames0Rect[i], E, frames0Rect[i], cv::noArray(), CV_16UC1);
303
//        cv::add(frames0Rect[i+1], E, frames0Rect[i+1], cv::noArray(), CV_16UC1);
303
//        cv::add(frames0Rect[i+1], E, frames0Rect[i+1], cv::noArray(), CV_16UC1);
304
//    }
304
//    }
305
 
305
 
306
 
306
 
307
//    // correct for texture modulation and ambient
307
//    // correct for texture modulation and ambient
308
//    cv::Mat A0 = frames0Rect[1];
308
//    cv::Mat A0 = frames0Rect[1];
309
//    cv::Mat M0 = frames0Rect[0]-frames0Rect[1];
309
//    cv::Mat M0 = frames0Rect[0]-frames0Rect[1];
310
////cvtools::writeMat(A0, "A0.mat", "A0");
310
////cvtools::writeMat(A0, "A0.mat", "A0");
311
////cvtools::writeMat(M0, "M0.mat", "M0");
311
////cvtools::writeMat(M0, "M0.mat", "M0");
312
////cvtools::writeMat(frames0Rect[20], "frames0Rect_20.mat", "frames0Rect_20");
312
////cvtools::writeMat(frames0Rect[20], "frames0Rect_20.mat", "frames0Rect_20");
313
////cvtools::writeMat(frames0Rect[21], "frames0Rect_21.mat", "frames0Rect_21");
313
////cvtools::writeMat(frames0Rect[21], "frames0Rect_21.mat", "frames0Rect_21");
314
//    cv::divide(256.0, M0, M0, CV_32F);
314
//    cv::divide(256.0, M0, M0, CV_32F);
315
//    cv::Mat A1 = frames1Rect[1];
315
//    cv::Mat A1 = frames1Rect[1];
316
//    cv::Mat M1 = frames1Rect[0]-frames1Rect[1];
316
//    cv::Mat M1 = frames1Rect[0]-frames1Rect[1];
317
//    cv::divide(256.0, M1, M1, CV_32F);
317
//    cv::divide(256.0, M1, M1, CV_32F);
318
 
318
 
319
//    for(int i=2; i<N; i++){
319
//    for(int i=2; i<N; i++){
320
//        cv::multiply(frames0Rect[i]-A0, M0, frames0Rect[i], 1.0, CV_8UC1);
320
//        cv::multiply(frames0Rect[i]-A0, M0, frames0Rect[i], 1.0, CV_8UC1);
321
//        cv::multiply(frames1Rect[i]-A1, M1, frames1Rect[i], 1.0, CV_8UC1);
321
//        cv::multiply(frames1Rect[i]-A1, M1, frames1Rect[i], 1.0, CV_8UC1);
322
//    }
322
//    }
323
 
323
 
324
//cvtools::writeMat(frames0Rect[22], "frames0Rect_22.mat", "frames0Rect_22");
324
//cvtools::writeMat(frames0Rect[22], "frames0Rect_22.mat", "frames0Rect_22");
325
//cvtools::writeMat(frames0Rect[23], "frames0Rect_23.mat", "frames0Rect_23");
325
//cvtools::writeMat(frames0Rect[23], "frames0Rect_23.mat", "frames0Rect_23");
326
 
326
 
327
//cvtools::writeMat(occlusion0Rect, "occlusion0Rect.mat", "occlusion0Rect");
327
//cvtools::writeMat(occlusion0Rect, "occlusion0Rect.mat", "occlusion0Rect");
328
//cvtools::writeMat(occlusion1Rect, "occlusion1Rect.mat", "occlusion1Rect");
328
//cvtools::writeMat(occlusion1Rect, "occlusion1Rect.mat", "occlusion1Rect");
329
 
329
 
330
    // decode patterns
330
    // decode patterns
331
    cv::Mat code0Rect(frameRectRows, frameRectCols, CV_32S, cv::Scalar(0));
331
    cv::Mat code0Rect(frameRectRows, frameRectCols, CV_32S, cv::Scalar(0));
332
    cv::Mat code1Rect(frameRectRows, frameRectCols, CV_32S, cv::Scalar(0));
332
    cv::Mat code1Rect(frameRectRows, frameRectCols, CV_32S, cv::Scalar(0));
333
 
333
 
334
    // into gray code
334
    // into gray code
335
    for(int i=0; i<Nbits; i++){
335
    for(unsigned int i=0; i<Nbits; i++){
336
        cv::Mat temp, bit0, bit1;
336
        cv::Mat temp, bit0, bit1;
337
 
337
 
338
        cv::compare(frames0Rect[i*2+2], frames0Rect[i*2+3], temp, cv::CMP_GT);
338
        cv::compare(frames0Rect[i*2+2], frames0Rect[i*2+3], temp, cv::CMP_GT);
339
        temp.convertTo(bit0, CV_32S, 1.0/255.0);
339
        temp.convertTo(bit0, CV_32S, 1.0/255.0);
340
        cv::add(code0Rect, bit0*ggmax::twopowi(Nbits-i-1), code0Rect, cv::noArray(), CV_32S);
340
        cv::add(code0Rect, bit0*ggmax::twopowi(Nbits-i-1), code0Rect, cv::noArray(), CV_32S);
341
 
341
 
342
        cv::compare(frames1Rect[i*2+2], frames1Rect[i*2+3], temp, cv::CMP_GT);
342
        cv::compare(frames1Rect[i*2+2], frames1Rect[i*2+3], temp, cv::CMP_GT);
343
        temp.convertTo(bit1, CV_32S, 1.0/255.0);
343
        temp.convertTo(bit1, CV_32S, 1.0/255.0);
344
        cv::add(code1Rect, bit1*ggmax::twopowi(Nbits-i-1), code1Rect, cv::noArray(), CV_32S);
344
        cv::add(code1Rect, bit1*ggmax::twopowi(Nbits-i-1), code1Rect, cv::noArray(), CV_32S);
345
    }
345
    }
346
 
346
 
347
//cvtools::writeMat(code0Rect, "code0Rect.mat", "code0Rect");
347
//cvtools::writeMat(code0Rect, "code0Rect.mat", "code0Rect");
348
//cvtools::writeMat(code1Rect, "code1Rect.mat", "code1Rect");
348
//cvtools::writeMat(code1Rect, "code1Rect.mat", "code1Rect");
349
 
349
 
350
 
350
 
351
//    // convert to standard binary
351
//    // convert to standard binary
352
//    cv::Mat code0Binary(code0Rect.rows, code0Rect.cols, CV_32F);
352
//    cv::Mat code0Binary(code0Rect.rows, code0Rect.cols, CV_32F);
353
//    cv::Mat code1Binary(code1Rect.rows, code1Rect.cols, CV_32F);
353
//    cv::Mat code1Binary(code1Rect.rows, code1Rect.cols, CV_32F);
354
//    for(int r=0; r<frameRectRows; r++){
354
//    for(int r=0; r<frameRectRows; r++){
355
//        for(int c=0; c<frameRectCols; c++){
355
//        for(int c=0; c<frameRectCols; c++){
356
//            if(code0Rect.at<int>(r,c) != -1)
356
//            if(code0Rect.at<int>(r,c) != -1)
357
//                code0Binary.at<float>(r,c) = grayToBinary(code0Rect.at<int>(r,c));
357
//                code0Binary.at<float>(r,c) = grayToBinary(code0Rect.at<int>(r,c));
358
//            if(code1Rect.at<int>(r,c) != -1)
358
//            if(code1Rect.at<int>(r,c) != -1)
359
//                code1Binary.at<float>(r,c) = grayToBinary(code1Rect.at<int>(r,c));
359
//                code1Binary.at<float>(r,c) = grayToBinary(code1Rect.at<int>(r,c));
360
//        }
360
//        }
361
//    }
361
//    }
362
 
362
 
363
//cvtools::writeMat(code0Binary, "code0Binary.mat", "code0Binary");
363
//cvtools::writeMat(code0Binary, "code0Binary.mat", "code0Binary");
364
//cvtools::writeMat(code1Binary, "code1Binary.mat", "code1Binary");
364
//cvtools::writeMat(code1Binary, "code1Binary.mat", "code1Binary");
365
 
365
 
366
//    // threshold on vertical discontinuities (due to imperfect rectification)
366
//    // threshold on vertical discontinuities (due to imperfect rectification)
367
//    cv::Mat edges0;
367
//    cv::Mat edges0;
368
//    cv::Sobel(code0Binary, edges0, -1, 0, 1, 5);
368
//    cv::Sobel(code0Binary, edges0, -1, 0, 1, 5);
369
//    occlusion0Rect = occlusion0Rect & (abs(edges0) < 50);
369
//    occlusion0Rect = occlusion0Rect & (abs(edges0) < 50);
370
 
370
 
371
//    cv::Mat edges1;
371
//    cv::Mat edges1;
372
//    cv::Sobel(code1Binary, edges1, -1, 0, 1, 5);
372
//    cv::Sobel(code1Binary, edges1, -1, 0, 1, 5);
373
//    occlusion1Rect = occlusion1Rect & (abs(edges1) < 50);
373
//    occlusion1Rect = occlusion1Rect & (abs(edges1) < 50);
374
 
374
 
375
//cvtools::writeMat(edges0, "edges0.mat", "edges0");
375
//cvtools::writeMat(edges0, "edges0.mat", "edges0");
376
//cvtools::writeMat(edges1, "edges1.mat", "edges1");
376
//cvtools::writeMat(edges1, "edges1.mat", "edges1");
377
 
377
 
378
    // set occluded pixels to -1
378
    // set occluded pixels to -1
379
    for(int r=0; r<frameRectRows; r++){
379
    for(int r=0; r<frameRectRows; r++){
380
        for(int c=0; c<frameRectCols; c++){
380
        for(int c=0; c<frameRectCols; c++){
381
            if(occlusion0Rect.at<unsigned char>(r,c) == 0)
381
            if(occlusion0Rect.at<unsigned char>(r,c) == 0)
382
                code0Rect.at<int>(r,c) = -1;
382
                code0Rect.at<int>(r,c) = -1;
383
            if(occlusion1Rect.at<unsigned char>(r,c) == 0)
383
            if(occlusion1Rect.at<unsigned char>(r,c) == 0)
384
                code1Rect.at<int>(r,c) = -1;
384
                code1Rect.at<int>(r,c) = -1;
385
        }
385
        }
386
    }
386
    }
387
 
387
 
388
//    cvtools::writeMat(code0Rect, "code0Rect.mat", "code0Rect");
388
//    cvtools::writeMat(code0Rect, "code0Rect.mat", "code0Rect");
389
//    cvtools::writeMat(code1Rect, "code1Rect.mat", "code1Rect");
389
//    cvtools::writeMat(code1Rect, "code1Rect.mat", "code1Rect");
390
 
390
 
391
    // matching
391
    // matching
392
    std::vector<cv::Vec2f> q0Rect, q1Rect;
392
    std::vector<cv::Vec2f> q0Rect, q1Rect;
393
    for(int row=0; row<frameRectRows; row++){
393
    for(int row=0; row<frameRectRows; row++){
394
 
394
 
395
        // edge data structure containing [floor(column), labelLeft, labelRight, orderingRelation]
395
        // edge data structure containing [floor(column), labelLeft, labelRight, orderingRelation]
396
        std::vector<cv::Vec4i> edges0, edges1;
396
        std::vector<cv::Vec4i> edges0, edges1;
397
 
397
 
398
        // sorted, unique edges
398
        // sorted, unique edges
399
        ggmax::getEdgeLabels(code0Rect.row(row), Nbits, edges0);
399
        ggmax::getEdgeLabels(code0Rect.row(row), Nbits, edges0);
400
        ggmax::getEdgeLabels(code1Rect.row(row), Nbits, edges1);
400
        ggmax::getEdgeLabels(code1Rect.row(row), Nbits, edges1);
401
 
401
 
402
        // match edges
402
        // match edges
403
        std::vector<cv::Vec4i> matchedEdges0, matchedEdges1;
403
        std::vector<cv::Vec4i> matchedEdges0, matchedEdges1;
404
        int i=0, j=0;
404
        unsigned int i=0, j=0;
405
        while(i<edges0.size() && j<edges1.size()){
405
        while(i<edges0.size() && j<edges1.size()){
406
 
406
 
407
            if(edges0[i][3] == edges1[j][3]){
407
            if(edges0[i][3] == edges1[j][3]){
408
                matchedEdges0.push_back(edges0[i]);
408
                matchedEdges0.push_back(edges0[i]);
409
                matchedEdges1.push_back(edges1[j]);
409
                matchedEdges1.push_back(edges1[j]);
410
                i += 1;
410
                i += 1;
411
                j += 1;
411
                j += 1;
412
            } else if(edges0[i][3] < edges1[j][3]){
412
            } else if(edges0[i][3] < edges1[j][3]){
413
                i += 1;
413
                i += 1;
414
            } else if(edges0[i][3] > edges1[j][3]){
414
            } else if(edges0[i][3] > edges1[j][3]){
415
                j += 1;
415
                j += 1;
416
            }
416
            }
417
        }
417
        }
418
 
418
 
419
        // crude subpixel refinement
419
        // crude subpixel refinement
420
        // finds the intersection of linear interpolants in the positive/negative pattern
420
        // finds the intersection of linear interpolants in the positive/negative pattern
421
        for(int i=0; i<matchedEdges0.size(); i++){
421
        for(unsigned int i=0; i<matchedEdges0.size(); i++){
422
 
422
 
423
            int level = Nbits - ggmax::leastSignificantBitSet(matchedEdges0[i][1]^matchedEdges0[i][2]);
423
            int level = Nbits - ggmax::leastSignificantBitSet(matchedEdges0[i][1]^matchedEdges0[i][2]);
424
 
424
 
425
            // refine for camera 0
425
            // refine for camera 0
426
            float c0 = matchedEdges0[i][0];
426
            float c0 = matchedEdges0[i][0];
427
            float c1 = c0+1;
427
            float c1 = c0+1;
428
 
428
 
429
            float pos0 = frames0Rect[2*level+2].at<unsigned char>(row, c0);
429
            float pos0 = frames0Rect[2*level+2].at<unsigned char>(row, c0);
430
            float pos1 = frames0Rect[2*level+2].at<unsigned char>(row, c1);
430
            float pos1 = frames0Rect[2*level+2].at<unsigned char>(row, c1);
431
            float neg0 = frames0Rect[2*level+3].at<unsigned char>(row, c0);
431
            float neg0 = frames0Rect[2*level+3].at<unsigned char>(row, c0);
432
            float neg1 = frames0Rect[2*level+3].at<unsigned char>(row, c1);
432
            float neg1 = frames0Rect[2*level+3].at<unsigned char>(row, c1);
433
 
433
 
434
            float col = c0 + (pos0 - neg0)/(neg1 - neg0 - pos1 + pos0);
434
            float col = c0 + (pos0 - neg0)/(neg1 - neg0 - pos1 + pos0);
435
            q0Rect.push_back(cv::Point2f(col, row));
435
            q0Rect.push_back(cv::Point2f(col, row));
436
 
436
 
437
            // refine for camera 1
437
            // refine for camera 1
438
            c0 = matchedEdges1[i][0];
438
            c0 = matchedEdges1[i][0];
439
            c1 = c0+1;
439
            c1 = c0+1;
440
 
440
 
441
            pos0 = frames1Rect[2*level+2].at<unsigned char>(row, c0);
441
            pos0 = frames1Rect[2*level+2].at<unsigned char>(row, c0);
442
            pos1 = frames1Rect[2*level+2].at<unsigned char>(row, c1);
442
            pos1 = frames1Rect[2*level+2].at<unsigned char>(row, c1);
443
            neg0 = frames1Rect[2*level+3].at<unsigned char>(row, c0);
443
            neg0 = frames1Rect[2*level+3].at<unsigned char>(row, c0);
444
            neg1 = frames1Rect[2*level+3].at<unsigned char>(row, c1);
444
            neg1 = frames1Rect[2*level+3].at<unsigned char>(row, c1);
445
 
445
 
446
            col = c0 + (pos0 - neg0)/(neg1 - neg0 - pos1 + pos0);
446
            col = c0 + (pos0 - neg0)/(neg1 - neg0 - pos1 + pos0);
447
            q1Rect.push_back(cv::Point2f(col, row));
447
            q1Rect.push_back(cv::Point2f(col, row));
448
 
448
 
449
        }
449
        }
450
 
450
 
451
    }
451
    }
452
 
452
 
453
    int nMatches = q0Rect.size();
453
    int nMatches = q0Rect.size();
454
 
454
 
455
    if(nMatches < 1){
455
    if(nMatches < 1){
456
        Q.resize(0);
456
        Q.resize(0);
457
        color.resize(0);
457
        color.resize(0);
458
 
458
 
459
        return;
459
        return;
460
    }
460
    }
461
 
461
 
462
    // retrieve color information (at integer coordinates)
462
    // retrieve color information (at integer coordinates)
463
    color.resize(nMatches);
463
    color.resize(nMatches);
464
    for(int i=0; i<nMatches; i++){
464
    for(int i=0; i<nMatches; i++){
465
 
465
 
466
        cv::Vec3b c0 = color0Rect.at<cv::Vec3b>(q0Rect[i][1], q0Rect[i][0]);
466
        cv::Vec3b c0 = color0Rect.at<cv::Vec3b>(q0Rect[i][1], q0Rect[i][0]);
467
        cv::Vec3b c1 = color1Rect.at<cv::Vec3b>(q1Rect[i][1], q1Rect[i][0]);
467
        cv::Vec3b c1 = color1Rect.at<cv::Vec3b>(q1Rect[i][1], q1Rect[i][0]);
468
//        cv::Vec3b c0 = getColorSubpix(color0Rect, q0Rect[i]);
468
//        cv::Vec3b c0 = getColorSubpix(color0Rect, q0Rect[i]);
469
//        cv::Vec3b c1 = getColorSubpix(color1Rect, q0Rect[i]);
469
//        cv::Vec3b c1 = getColorSubpix(color1Rect, q0Rect[i]);
470
 
470
 
471
        color[i] = 0.5*c0 + 0.5*c1;
471
        color[i] = 0.5*c0 + 0.5*c1;
472
    }
472
    }
473
 
473
 
474
    // triangulate points
474
    // triangulate points
475
    cv::Mat QMatHomogenous, QMat;
475
    cv::Mat QMatHomogenous, QMat;
476
//    cv::Mat C0 = P0.clone();
476
//    cv::Mat C0 = P0.clone();
477
//    cv::Mat C1 = P1.clone();
477
//    cv::Mat C1 = P1.clone();
478
//    C0.colRange(0, 3) = C0.colRange(0, 3)*R0;
478
//    C0.colRange(0, 3) = C0.colRange(0, 3)*R0;
479
//    C1.colRange(0, 3) = C1.colRange(0, 3)*R1.t();
479
//    C1.colRange(0, 3) = C1.colRange(0, 3)*R1.t();
480
    cv::triangulatePoints(P0, P1, q0Rect, q1Rect, QMatHomogenous);
480
    cv::triangulatePoints(P0, P1, q0Rect, q1Rect, QMatHomogenous);
481
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
481
    cvtools::convertMatFromHomogeneous(QMatHomogenous, QMat);
482
 
482
 
483
    // undo rectifying rotation
483
    // undo rectifying rotation
484
    cv::Mat R0Inv;
484
    cv::Mat R0Inv;
485
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
485
    cv::Mat(R0.t()).convertTo(R0Inv, CV_32F);
486
    QMat = R0Inv*QMat;
486
    QMat = R0Inv*QMat;
487
 
487
 
488
    cvtools::matToPoints3f(QMat, Q);
488
    cvtools::matToPoints3f(QMat, Q);
489
 
489
 
490
}
490
}
491
 
491