Subversion Repositories seema-scanner

Rev

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