1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                          License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
16 // Third party copyrights are property of their respective owners.
17 //
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
20 //
21 //   * Redistribution's of source code must retain the above copyright notice,
22 //     this list of conditions and the following disclaimer.
23 //
24 //   * Redistribution's in binary form must reproduce the above copyright notice,
25 //     this list of conditions and the following disclaimer in the documentation
26 //     and/or other materials provided with the distribution.
27 //
28 //   * The name of the copyright holders may not be used to endorse or promote products
29 //     derived from this software without specific prior written permission.
30 //
31 // This software is provided by the copyright holders and contributors "as is" and
32 // any express or implied warranties, including, but not limited to, the implied
33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
34 // In no event shall the Intel Corporation or contributors be liable for any direct,
35 // indirect, incidental, special, exemplary, or consequential damages
36 // (including, but not limited to, procurement of substitute goods or services;
37 // loss of use, data, or profits; or business interruption) however caused
38 // and on any theory of liability, whether in contract, strict liability,
39 // or tort (including negligence or otherwise) arising in any way out of
40 // the use of this software, even if advised of the possibility of such damage.
41 //
42 //M*/
43 
44 #include "precomp.hpp"
45 
46 namespace cv
47 {
48     class FormattedImpl : public Formatted
49     {
50         enum { STATE_PROLOGUE, STATE_EPILOGUE, STATE_INTERLUDE,
51                STATE_ROW_OPEN, STATE_ROW_CLOSE, STATE_CN_OPEN, STATE_CN_CLOSE, STATE_VALUE, STATE_FINISHED,
52                STATE_LINE_SEPARATOR, STATE_CN_SEPARATOR, STATE_VALUE_SEPARATOR };
53         enum {BRACE_ROW_OPEN = 0, BRACE_ROW_CLOSE = 1, BRACE_ROW_SEP=2, BRACE_CN_OPEN=3, BRACE_CN_CLOSE=4 };
54 
55         char floatFormat[8];
56         char buf[32];   // enough for double with precision up to 20
57 
58         Mat mtx;
59         int mcn; // == mtx.channels()
60         bool singleLine;
61         bool alignOrder;    // true when cn first order
62 
63         int state;
64         int row;
65         int col;
66         int cn;
67 
68         String prologue;
69         String epilogue;
70         char braces[5];
71 
72         void (FormattedImpl::*valueToStr)();
valueToStr8u()73         void valueToStr8u()  { sprintf(buf, "%3d", (int)mtx.ptr<uchar>(row, col)[cn]); }
valueToStr8s()74         void valueToStr8s()  { sprintf(buf, "%3d", (int)mtx.ptr<schar>(row, col)[cn]); }
valueToStr16u()75         void valueToStr16u() { sprintf(buf, "%d", (int)mtx.ptr<ushort>(row, col)[cn]); }
valueToStr16s()76         void valueToStr16s() { sprintf(buf, "%d", (int)mtx.ptr<short>(row, col)[cn]); }
valueToStr32s()77         void valueToStr32s() { sprintf(buf, "%d", mtx.ptr<int>(row, col)[cn]); }
valueToStr32f()78         void valueToStr32f() { sprintf(buf, floatFormat, mtx.ptr<float>(row, col)[cn]); }
valueToStr64f()79         void valueToStr64f() { sprintf(buf, floatFormat, mtx.ptr<double>(row, col)[cn]); }
valueToStrOther()80         void valueToStrOther() { buf[0] = 0; }
81 
82     public:
83 
FormattedImpl(String pl,String el,Mat m,char br[5],bool sLine,bool aOrder,int precision)84         FormattedImpl(String pl, String el, Mat m, char br[5], bool sLine, bool aOrder, int precision)
85         {
86             CV_Assert(m.dims <= 2);
87 
88             prologue = pl;
89             epilogue = el;
90             mtx = m;
91             mcn = m.channels();
92             memcpy(braces, br, 5);
93             state = STATE_PROLOGUE;
94             singleLine = sLine;
95             alignOrder = aOrder;
96             row = col = cn =0;
97 
98             if (precision < 0)
99             {
100                 floatFormat[0] = '%';
101                 floatFormat[1] = 'a';
102                 floatFormat[2] = 0;
103             }
104             else
105             {
106                 sprintf(floatFormat, "%%.%dg", std::min(precision, 20));
107             }
108 
109             switch(mtx.depth())
110             {
111                 case CV_8U:  valueToStr = &FormattedImpl::valueToStr8u; break;
112                 case CV_8S:  valueToStr = &FormattedImpl::valueToStr8s; break;
113                 case CV_16U: valueToStr = &FormattedImpl::valueToStr16u; break;
114                 case CV_16S: valueToStr = &FormattedImpl::valueToStr16s; break;
115                 case CV_32S: valueToStr = &FormattedImpl::valueToStr32s; break;
116                 case CV_32F: valueToStr = &FormattedImpl::valueToStr32f; break;
117                 case CV_64F: valueToStr = &FormattedImpl::valueToStr64f; break;
118                 default:     valueToStr = &FormattedImpl::valueToStrOther; break;
119             }
120         }
121 
reset()122         void reset()
123         {
124             state = STATE_PROLOGUE;
125         }
126 
next()127         const char* next()
128         {
129             switch(state)
130             {
131                 case STATE_PROLOGUE:
132                     row = 0;
133                     if (mtx.empty())
134                         state = STATE_EPILOGUE;
135                     else if (alignOrder)
136                         state = STATE_INTERLUDE;
137                     else
138                         state = STATE_ROW_OPEN;
139                     return prologue.c_str();
140                 case STATE_INTERLUDE:
141                     state = STATE_ROW_OPEN;
142                     if (row >= mtx.rows)
143                     {
144                         if (++cn >= mcn)
145                         {
146                             state = STATE_EPILOGUE;
147                             buf[0] = 0;
148                             return buf;
149                         }
150                         else
151                             row = 0;
152                         sprintf(buf, "\n(:, :, %d) = \n", cn+1);
153                         return buf;
154                     }
155                     sprintf(buf, "(:, :, %d) = \n", cn+1);
156                     return buf;
157                 case STATE_EPILOGUE:
158                     state = STATE_FINISHED;
159                     return epilogue.c_str();
160                 case STATE_ROW_OPEN:
161                     col = 0;
162                     state = STATE_CN_OPEN;
163                     {
164                         size_t pos = 0;
165                         if (row > 0)
166                             while(pos < prologue.size() && pos < sizeof(buf) - 2)
167                                 buf[pos++] = ' ';
168                         if (braces[BRACE_ROW_OPEN])
169                             buf[pos++] = braces[BRACE_ROW_OPEN];
170                         if(!pos)
171                             return next();
172                         buf[pos] = 0;
173                     }
174                     return buf;
175                 case STATE_ROW_CLOSE:
176                     state = STATE_LINE_SEPARATOR;
177                     ++row;
178                     if (braces[BRACE_ROW_CLOSE])
179                     {
180                         buf[0] = braces[BRACE_ROW_CLOSE];
181                         buf[1] = row < mtx.rows ? ',' : '\0';
182                         buf[2] = 0;
183                         return buf;
184                     }
185                     else if(braces[BRACE_ROW_SEP] && row < mtx.rows)
186                     {
187                         buf[0] = braces[BRACE_ROW_SEP];
188                         buf[1] = 0;
189                         return buf;
190                     }
191                     return next();
192                 case STATE_CN_OPEN:
193                     state = STATE_VALUE;
194                     if (!alignOrder)
195                         cn = 0;
196                     if (mcn > 1 && braces[BRACE_CN_OPEN])
197                     {
198                         buf[0] = braces[BRACE_CN_OPEN];
199                         buf[1] = 0;
200                         return buf;
201                     }
202                     return next();
203                 case STATE_CN_CLOSE:
204                     ++col;
205                     if (col >= mtx.cols)
206                         state = STATE_ROW_CLOSE;
207                     else
208                         state = STATE_CN_SEPARATOR;
209                     if (mcn > 1 && braces[BRACE_CN_CLOSE])
210                     {
211                         buf[0] = braces[BRACE_CN_CLOSE];
212                         buf[1] = 0;
213                         return buf;
214                     }
215                     return next();
216                 case STATE_VALUE:
217                     (this->*valueToStr)();
218                     state = STATE_CN_CLOSE;
219                     if (alignOrder)
220                         return buf;
221                     if (++cn < mcn)
222                         state = STATE_VALUE_SEPARATOR;
223                     return buf;
224                 case STATE_FINISHED:
225                     return 0;
226                 case STATE_LINE_SEPARATOR:
227                     if (row >= mtx.rows)
228                     {
229                         if (alignOrder)
230                             state = STATE_INTERLUDE;
231                         else
232                             state = STATE_EPILOGUE;
233                         return next();
234                     }
235                     state = STATE_ROW_OPEN;
236                     buf[0] = singleLine ? ' ' : '\n';
237                     buf[1] = 0;
238                     return buf;
239                 case STATE_CN_SEPARATOR:
240                     state = STATE_CN_OPEN;
241                     buf[0] = ',';
242                     buf[1] = ' ';
243                     buf[2] = 0;
244                     return buf;
245                 case STATE_VALUE_SEPARATOR:
246                     state = STATE_VALUE;
247                     buf[0] = ',';
248                     buf[1] = ' ';
249                     buf[2] = 0;
250                     return buf;
251             }
252             return 0;
253         }
254     };
255 
256     class FormatterBase : public Formatter
257     {
258     public:
FormatterBase()259         FormatterBase() : prec32f(8), prec64f(16), multiline(true) {}
260 
set32fPrecision(int p)261         void set32fPrecision(int p)
262         {
263             prec32f = p;
264         }
265 
set64fPrecision(int p)266         void set64fPrecision(int p)
267         {
268             prec64f = p;
269         }
270 
setMultiline(bool ml)271         void setMultiline(bool ml)
272         {
273             multiline = ml;
274         }
275 
276     protected:
277         int prec32f;
278         int prec64f;
279         int multiline;
280     };
281 
282     class DefaultFormatter : public FormatterBase
283     {
284     public:
285 
format(const Mat & mtx) const286         Ptr<Formatted> format(const Mat& mtx) const
287         {
288             char braces[5] = {'\0', '\0', ';', '\0', '\0'};
289             return makePtr<FormattedImpl>("[", "]", mtx, &*braces,
290                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
291         }
292     };
293 
294     class MatlabFormatter : public FormatterBase
295     {
296     public:
297 
format(const Mat & mtx) const298         Ptr<Formatted> format(const Mat& mtx) const
299         {
300             char braces[5] = {'\0', '\0', ';', '\0', '\0'};
301             return makePtr<FormattedImpl>("", "", mtx, &*braces,
302                 mtx.rows == 1 || !multiline, true, mtx.depth() == CV_64F ? prec64f : prec32f );
303         }
304     };
305 
306     class PythonFormatter : public FormatterBase
307     {
308     public:
309 
format(const Mat & mtx) const310         Ptr<Formatted> format(const Mat& mtx) const
311         {
312             char braces[5] = {'[', ']', ',', '[', ']'};
313             if (mtx.cols == 1)
314                 braces[0] = braces[1] = '\0';
315             return makePtr<FormattedImpl>("[", "]", mtx, &*braces,
316                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
317         }
318     };
319 
320     class NumpyFormatter : public FormatterBase
321     {
322     public:
323 
format(const Mat & mtx) const324         Ptr<Formatted> format(const Mat& mtx) const
325         {
326             static const char* numpyTypes[] =
327             {
328                 "uint8", "int8", "uint16", "int16", "int32", "float32", "float64", "uint64"
329             };
330             char braces[5] = {'[', ']', ',', '[', ']'};
331             if (mtx.cols == 1)
332                 braces[0] = braces[1] = '\0';
333             return makePtr<FormattedImpl>("array([",
334                 cv::format("], dtype='%s')", numpyTypes[mtx.depth()]), mtx, &*braces,
335                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
336         }
337     };
338 
339     class CSVFormatter : public FormatterBase
340     {
341     public:
342 
format(const Mat & mtx) const343         Ptr<Formatted> format(const Mat& mtx) const
344         {
345             char braces[5] = {'\0', '\0', '\0', '\0', '\0'};
346             return makePtr<FormattedImpl>(String(),
347                 mtx.rows > 1 ? String("\n") : String(), mtx, &*braces,
348                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
349         }
350     };
351 
352     class CFormatter : public FormatterBase
353     {
354     public:
355 
format(const Mat & mtx) const356         Ptr<Formatted> format(const Mat& mtx) const
357         {
358             char braces[5] = {'\0', '\0', ',', '\0', '\0'};
359             return makePtr<FormattedImpl>("{", "}", mtx, &*braces,
360                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
361         }
362     };
363 
~Formatted()364     Formatted::~Formatted() {}
~Formatter()365     Formatter::~Formatter() {}
366 
get(int fmt)367     Ptr<Formatter> Formatter::get(int fmt)
368     {
369         switch(fmt)
370         {
371             case FMT_DEFAULT:
372                 return makePtr<DefaultFormatter>();
373             case FMT_MATLAB:
374                 return makePtr<MatlabFormatter>();
375             case FMT_CSV:
376                 return makePtr<CSVFormatter>();
377             case FMT_PYTHON:
378                 return makePtr<PythonFormatter>();
379             case FMT_NUMPY:
380                 return makePtr<NumpyFormatter>();
381             case FMT_C:
382                 return makePtr<CFormatter>();
383         }
384         return makePtr<DefaultFormatter>();
385     }
386 } // cv
387