Subversion Repositories seema-scanner

Rev

Rev 31 | Rev 34 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 jakw 1
#include "cvtools.h"
2
 
3
#ifdef _WIN32
4
#include <cstdint>
5
#endif
6
 
7
#include <stdio.h>
8
 
9
namespace cvtools{
10
 
31 jakw 11
// Function to fit two sets of corresponding transformation data.
12
// Algorithm and notation according to Mili Shah, Comparing two sets of corresponding six degree of freedom data, CVIU 2011.
13
// DTU, 2013, Oline V. Olesen, Jakob Wilm
14
void fitSixDofData(const std::vector<cv::Matx33f> R, const std::vector<cv::Vec3f> t, const std::vector<cv::Matx33f> R_mark, const std::vector<cv::Vec3f> t_mark, cv::Matx33f &Omega, cv::Vec3f &tau){
15
// NOT DEBUGGED!
16
    int N = R.size();
17
    assert(N == R_mark.size());
18
    assert(N == t.size());
19
    assert(N == t_mark.size());
20
 
21
    // Mean translations
22
    cv::Vec3f t_mean;
23
    cv::Vec3f t_mark_mean;
24
    for(int i=0; i<N; i++){
25
        t_mean += 1.0/N * t[i];
26
        t_mark_mean += 1.0/N * t_mark[i];
27
    }
28
 
29
    // Data with mean adjusted translations
30
    cv::Mat X_bar(3, 4*N, CV_32F);
31
    cv::Mat X_mark_bar(3, 4*N, CV_32F);
32
    for(int i=0; i<N; i++){
33 jakw 33
        cv::Mat(R[i]).copyTo(X_bar.colRange(i*4,i*4+3));
34
        cv::Mat(t[i] - t_mean).copyTo(X_bar.col(i*4+3));
35
        cv::Mat(R_mark[i]).copyTo(X_mark_bar.colRange(i*4,i*4+3));
36
        cv::Mat(t_mark[i] - t_mark_mean).copyTo(X_mark_bar.col(i*4+3));
31 jakw 37
    }
33 jakw 38
    //std::cout << X_bar << std::endl;
31 jakw 39
    // SVD
33 jakw 40
    cv::Mat W, U, VT;
31 jakw 41
    cv::SVDecomp(X_bar*X_mark_bar.t(), W, U, VT);
42
 
43
    cv::Matx33f D = cv::Matx33f::eye();
44
    if(cv::determinant(VT*U) < 0)
45
        D(3,3) = -1;
46
 
47
    // Best rotation
33 jakw 48
    Omega = cv::Matx33f(cv::Mat(VT.t()))*D*cv::Matx33f(cv::Mat(U.t()));
31 jakw 49
 
50
    // Best translation
51
    tau = t_mark_mean - Omega*t_mean;
52
 
53
}
54
 
1 jakw 55
// Forward distortion of points. The inverse of the undistortion in cv::initUndistortRectifyMap().
56
// Inspired by Pascal Thomet, http://code.opencv.org/issues/1387#note-11
57
// Convention for distortion parameters: http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/parameters.html
58
void initDistortMap(const cv::Matx33f cameraMatrix, const cv::Vec<float, 5> distCoeffs, const cv::Size size, cv::Mat &map1, cv::Mat &map2){
59
 
60
    float fx = cameraMatrix(0,0);
61
    float fy = cameraMatrix(1,1);
62
    float ux = cameraMatrix(0,2);
63
    float uy = cameraMatrix(1,2);
64
 
65
    float k1 = distCoeffs[0];
66
    float k2 = distCoeffs[1];
67
    float p1 = distCoeffs[2];
68
    float p2 = distCoeffs[3];
69
    float k3 = distCoeffs[4];
70
 
71
    map1.create(size, CV_32F);
72
    map2.create(size, CV_32F);
73
 
74
    for(int col = 0; col < size.width; col++){
75
        for(int row = 0; row < size.height; row++){
76
 
77
            // move origo to principal point and convert using focal length
78
            float x = (col-ux)/fx;
79
            float y = (row-uy)/fy;
80
 
81
            float xCorrected, yCorrected;
82
 
83
            //Step 1 : correct distortion
84
            float r2 = x*x + y*y;
85
            //radial
86
            xCorrected = x * (1. + k1*r2 + k2*r2*r2 + k3*r2*r2*r2);
87
            yCorrected = y * (1. + k1*r2 + k2*r2*r2 + k3*r2*r2*r2);
88
            //tangential
89
            xCorrected = xCorrected + (2.*p1*x*y + p2*(r2+2.*x*x));
90
            yCorrected = yCorrected + (p1*(r2+2.*y*y) + 2.*p2*x*y);
91
 
92
            //convert back to pixel coordinates
93
            float col_displaced = xCorrected * fx + ux;
94
            float row_displaced = yCorrected * fy + uy;
95
 
96
            // correct the vector in the opposite direction
97
            map1.at<float>(row,col) = col+(col-col_displaced);
98
            map2.at<float>(row,col) = row +(row-row_displaced);
99
        }
100
    }
101
}
102
 
103
// Downsample a texture which was created in virtual column/row space for a diamond pixel array projector
104
cv::Mat diamondDownsample(cv::Mat &pattern){
105
 
106
    cv::Mat pattern_diamond(pattern.rows,pattern.cols/2,CV_8UC3);
107
 
108
    for(unsigned int col = 0; col < pattern_diamond.cols; col++){
109
        for(unsigned int row = 0; row < pattern_diamond.rows; row++){
110
 
111
            pattern_diamond.at<cv::Vec3b>(row,col)=pattern.at<cv::Vec3b>(row,col*2+row%2);
112
        }
113
    }
114
 
115
    return pattern_diamond;
116
 
117
}
118
 
119
 
120
void mouseCallback(int evt, int x, int y, int flags, void* param){
121
    cv::Mat *im = (cv::Mat*) param;
122
    if (evt == CV_EVENT_LBUTTONDOWN) {
123
        if(im->type() == CV_8UC3){
124
            printf("%d %d: %d, %d, %d\n",
125
                   x, y,
126
                   (int)(*im).at<cv::Vec3b>(y, x)[0],
127
                    (int)(*im).at<cv::Vec3b>(y, x)[1],
128
                    (int)(*im).at<cv::Vec3b>(y, x)[2]);
129
        } else if (im->type() == CV_32F) {
130
            printf("%d %d: %f\n",
131
                   x, y,
132
                   im->at<float>(y, x));
133
        }
134
    }
135
}
136
 
137
void imshow(const char *windowName, cv::Mat im, unsigned int x, unsigned int y){
138
 
139
    // Imshow
140
    if(!cvGetWindowHandle(windowName)){
141
        int windowFlags = CV_GUI_EXPANDED | CV_WINDOW_KEEPRATIO;
142
        cv::namedWindow(windowName, windowFlags);
143
        cv::moveWindow(windowName, x, y);
144
    }
145
    cv::imshow(windowName, im);
146
}
147
 
148
void imagesc(const char *windowName, cv::Mat im){
149
 
150
    // Imshow with scaled image
151
 
152
 
153
}
154
 
155
cv::Mat histimage(cv::Mat histogram){
156
 
157
    cv::Mat histImage(512, 640, CV_8UC3, cv::Scalar(0));
158
 
159
    // Normalize the result to [ 2, histImage.rows-2 ]
160
    cv::normalize(histogram, histogram, 2, histImage.rows-2, cv::NORM_MINMAX, -1, cv::Mat());
161
 
162
    float bin_w = (float)histImage.cols/(float)histogram.rows;
163
 
164
    // Draw main histogram
165
    for(int i = 1; i < histogram.rows-10; i++){
166
        cv::line(histImage, cv::Point( bin_w*(i-1), histImage.rows - cvRound(histogram.at<float>(i-1)) ),
167
                 cv::Point( bin_w*(i), histImage.rows - cvRound(histogram.at<float>(i)) ),
168
                 cv::Scalar(255, 255, 255), 2, 4);
169
    }
170
 
171
    // Draw red max
172
    for(int i = histogram.rows-10; i < histogram.rows; i++){
173
        cv::line(histImage, cv::Point( bin_w*(i-1), histImage.rows - cvRound(histogram.at<float>(i-1)) ),
174
                 cv::Point( bin_w*(i), histImage.rows - cvRound(histogram.at<float>(i)) ),
175
                 cv::Scalar(0, 0, 255), 2, 4);
176
    }
177
 
178
    return histImage;
179
}
180
 
181
void hist(const char *windowName, cv::Mat histogram, unsigned int x, unsigned int y){
182
 
183
    // Display
184
    imshow(windowName, histimage(histogram), x, y);
185
    cv::Point(1,2);
186
}
187
 
188
 
189
void writeMat(cv::Mat const& mat, const char* filename, const char* varName, bool bgr2rgb){
190
    /*!
191
         *  \author Philip G. Lee <rocketman768@gmail.com>
192
         *  Write \b mat into \b filename
193
         *  in uncompressed .mat format (Level 5 MATLAB) for Matlab.
194
         *  The variable name in matlab will be \b varName. If
195
         *  \b bgr2rgb is true and there are 3 channels, swaps 1st and 3rd
196
         *  channels in the output. This is needed because OpenCV matrices
197
         *  are bgr, while Matlab is rgb. This has been tested to work with
198
         *  3-channel single-precision floating point matrices, and I hope
199
         *  it works on other types/channels, but not exactly sure.
200
         *  Documentation at <http://www.mathworks.com/help/pdf_doc/matlab/matfile_format.pdf>
201
         */
202
    int textLen = 116;
203
    char* text;
204
    int subsysOffsetLen = 8;
205
    char* subsysOffset;
206
    int verLen = 2;
207
    char* ver;
208
    char flags;
209
    int bytes;
210
    int padBytes;
211
    int bytesPerElement;
212
    int i,j,k,k2;
213
    bool doBgrSwap;
214
    char mxClass;
215
    int32_t miClass;
216
    uchar const* rowPtr;
217
    uint32_t tmp32;
218
    float tmp;
219
    FILE* fp;
220
 
221
    // Matlab constants.
222
    const uint16_t MI = 0x4d49; // Contains "MI" in ascii.
223
    const int32_t miINT8 = 1;
224
    const int32_t miUINT8 = 2;
225
    const int32_t miINT16 = 3;
226
    const int32_t miUINT16 = 4;
227
    const int32_t miINT32 = 5;
228
    const int32_t miUINT32 = 6;
229
    const int32_t miSINGLE = 7;
230
    const int32_t miDOUBLE = 9;
231
    const int32_t miMATRIX = 14;
232
    const char mxDOUBLE_CLASS = 6;
233
    const char mxSINGLE_CLASS = 7;
234
    const char mxINT8_CLASS = 8;
235
    const char mxUINT8_CLASS = 9;
236
    const char mxINT16_CLASS = 10;
237
    const char mxUINT16_CLASS = 11;
238
    const char mxINT32_CLASS = 12;
239
    const char mxUINT32_CLASS = 13;
240
    const uint64_t zero = 0; // Used for padding.
241
 
242
    fp = fopen( filename, "wb" );
243
 
244
    if( fp == 0 )
245
        return;
246
 
247
    const int rows = mat.rows;
248
    const int cols = mat.cols;
249
    const int chans = mat.channels();
250
 
251
    doBgrSwap = (chans==3) && bgr2rgb;
252
 
253
    // I hope this mapping is right :-/
254
    switch( mat.depth() ){
255
    case CV_8U:
256
        mxClass = mxUINT8_CLASS;
257
        miClass = miUINT8;
258
        bytesPerElement = 1;
259
        break;
260
    case CV_8S:
261
        mxClass = mxINT8_CLASS;
262
        miClass = miINT8;
263
        bytesPerElement = 1;
264
        break;
265
    case CV_16U:
266
        mxClass = mxUINT16_CLASS;
267
        miClass = miUINT16;
268
        bytesPerElement = 2;
269
        break;
270
    case CV_16S:
271
        mxClass = mxINT16_CLASS;
272
        miClass = miINT16;
273
        bytesPerElement = 2;
274
        break;
275
    case CV_32S:
276
        mxClass = mxINT32_CLASS;
277
        miClass = miINT32;
278
        bytesPerElement = 4;
279
        break;
280
    case CV_32F:
281
        mxClass = mxSINGLE_CLASS;
282
        miClass = miSINGLE;
283
        bytesPerElement = 4;
284
        break;
285
    case CV_64F:
286
        mxClass = mxDOUBLE_CLASS;
287
        miClass = miDOUBLE;
288
        bytesPerElement = 8;
289
        break;
290
    default:
291
        return;
292
    }
293
 
294
    //==================Mat-file header (128 bytes, page 1-5)==================
295
    text = new char[textLen]; // Human-readable text.
296
    memset( text, ' ', textLen );
297
    text[textLen-1] = '\0';
298
    const char* t = "MATLAB 5.0 MAT-file, Platform: PCWIN";
299
    memcpy( text, t, strlen(t) );
300
 
301
    subsysOffset = new char[subsysOffsetLen]; // Zeros for us.
302
    memset( subsysOffset, 0x00, subsysOffsetLen );
303
    ver = new char[verLen];
304
    ver[0] = 0x00;
305
    ver[1] = 0x01;
306
 
307
    fwrite( text, 1, textLen, fp );
308
    fwrite( subsysOffset, 1, subsysOffsetLen, fp );
309
    fwrite( ver, 1, verLen, fp );
310
    // Endian indicator. MI will show up as "MI" on big-endian
311
    // systems and "IM" on little-endian systems.
312
    fwrite( &MI, 2, 1, fp );
313
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
314
 
315
    //===================Data element tag (8 bytes, page 1-8)==================
316
    bytes = 16 + 24 + (8 + strlen(varName) + (8-(strlen(varName)%8))%8)
317
            + (8 + rows*cols*chans*bytesPerElement);
318
    fwrite( &miMATRIX, 4, 1, fp ); // Data type.
319
    fwrite( &bytes, 4, 1, fp); // Data size in bytes.
320
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
321
 
322
    //====================Array flags (16 bytes, page 1-15)====================
323
    bytes = 8;
324
    fwrite( &miUINT32, 4, 1, fp );
325
    fwrite( &bytes, 4, 1, fp );
326
    flags = 0x00; // Complex, logical, and global flags all off.
327
 
328
    tmp32 = 0;
329
    tmp32 = (flags << 8 ) | (mxClass);
330
    fwrite( &tmp32, 4, 1, fp );
331
 
332
    fwrite( &zero, 4, 1, fp ); // Padding to 64-bit boundary.
333
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
334
 
335
    //===============Dimensions subelement (24 bytes, page 1-17)===============
336
    bytes = 12;
337
    fwrite( &miINT32, 4, 1, fp );
338
    fwrite( &bytes, 4, 1, fp );
339
 
340
    fwrite( &rows, 4, 1, fp );
341
    fwrite( &cols, 4, 1, fp );
342
    fwrite( &chans, 4, 1, fp );
343
    fwrite( &zero, 4, 1, fp ); // Padding to 64-bit boundary.
344
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
345
 
346
    //==Array name (8 + strlen(varName) + (8-(strlen(varName)%8))%8 bytes, page 1-17)==
347
    bytes = strlen(varName);
348
 
349
    fwrite( &miINT8, 4, 1, fp );
350
    fwrite( &bytes, 4, 1, fp );
351
    fwrite( varName, 1, bytes, fp );
352
 
353
    // Pad to nearest 64-bit boundary.
354
    padBytes = (8-(bytes%8))%8;
355
    fwrite( &zero, 1, padBytes, fp );
356
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
357
 
358
    //====Matrix data (rows*cols*chans*bytesPerElement+8 bytes, page 1-20)=====
359
    bytes = rows*cols*chans*bytesPerElement;
360
    fwrite( &miClass, 4, 1, fp );
361
    fwrite( &bytes, 4, 1, fp );
362
 
363
    for( k = 0; k < chans; ++k )
364
    {
365
        if( doBgrSwap )
366
        {
367
            k2 = (k==0)? 2 : ((k==2)? 0 : 1);
368
        }
369
        else
370
            k2 = k;
371
 
372
        for( j = 0; j < cols; ++j )
373
        {
374
            for( i = 0; i < rows; ++i )
375
            {
376
                rowPtr = mat.data + mat.step*i;
377
                fwrite( rowPtr + (chans*j + k2)*bytesPerElement, bytesPerElement, 1, fp );
378
            }
379
        }
380
    }
381
 
382
    // Pad to 64-bit boundary.
383
    padBytes = (8-(bytes%8))%8;
384
    fwrite( &zero, 1, padBytes, fp );
385
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
386
 
387
    fclose(fp);
388
    delete[] text;
389
    delete[] subsysOffset;
390
    delete[] ver;
391
}
392
 
393
 
394
 
395
 
396
 
397
}