Subversion Repositories seema-scanner

Rev

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