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 CV_FINAL : 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]); }
valueToStr16f()80         void valueToStr16f() { sprintf(buf, floatFormat, (float)mtx.ptr<float16_t>(row, col)[cn]); }
valueToStrOther()81         void valueToStrOther() { buf[0] = 0; }
82 
83     public:
84 
FormattedImpl(String pl,String el,Mat m,char br[5],bool sLine,bool aOrder,int precision)85         FormattedImpl(String pl, String el, Mat m, char br[5], bool sLine, bool aOrder, int precision)
86         {
87             CV_Assert(m.dims <= 2);
88 
89             prologue = pl;
90             epilogue = el;
91             mtx = m;
92             mcn = m.channels();
93             memcpy(braces, br, 5);
94             state = STATE_PROLOGUE;
95             singleLine = sLine;
96             alignOrder = aOrder;
97             row = col = cn =0;
98 
99             if (precision < 0)
100             {
101                 floatFormat[0] = '%';
102                 floatFormat[1] = 'a';
103                 floatFormat[2] = 0;
104             }
105             else
106             {
107                 cv_snprintf(floatFormat, sizeof(floatFormat), "%%.%dg", std::min(precision, 20));
108             }
109 
110             switch(mtx.depth())
111             {
112                 case CV_8U:  valueToStr = &FormattedImpl::valueToStr8u; break;
113                 case CV_8S:  valueToStr = &FormattedImpl::valueToStr8s; break;
114                 case CV_16U: valueToStr = &FormattedImpl::valueToStr16u; break;
115                 case CV_16S: valueToStr = &FormattedImpl::valueToStr16s; break;
116                 case CV_32S: valueToStr = &FormattedImpl::valueToStr32s; break;
117                 case CV_32F: valueToStr = &FormattedImpl::valueToStr32f; break;
118                 case CV_64F: valueToStr = &FormattedImpl::valueToStr64f; break;
119                 default:     CV_Assert(mtx.depth() == CV_16F);
120                              valueToStr = &FormattedImpl::valueToStr16f;
121             }
122         }
123 
reset()124         void reset() CV_OVERRIDE
125         {
126             state = STATE_PROLOGUE;
127         }
128 
next()129         const char* next() CV_OVERRIDE
130         {
131             switch(state)
132             {
133                 case STATE_PROLOGUE:
134                     row = 0;
135                     if (mtx.empty())
136                         state = STATE_EPILOGUE;
137                     else if (alignOrder)
138                         state = STATE_INTERLUDE;
139                     else
140                         state = STATE_ROW_OPEN;
141                     return prologue.c_str();
142                 case STATE_INTERLUDE:
143                     state = STATE_ROW_OPEN;
144                     if (row >= mtx.rows)
145                     {
146                         if (++cn >= mcn)
147                         {
148                             state = STATE_EPILOGUE;
149                             buf[0] = 0;
150                             return buf;
151                         }
152                         else
153                             row = 0;
154                         sprintf(buf, "\n(:, :, %d) = \n", cn+1);
155                         return buf;
156                     }
157                     sprintf(buf, "(:, :, %d) = \n", cn+1);
158                     return buf;
159                 case STATE_EPILOGUE:
160                     state = STATE_FINISHED;
161                     return epilogue.c_str();
162                 case STATE_ROW_OPEN:
163                     col = 0;
164                     state = STATE_CN_OPEN;
165                     {
166                         size_t pos = 0;
167                         if (row > 0)
168                             while(pos < prologue.size() && pos < sizeof(buf) - 2)
169                                 buf[pos++] = ' ';
170                         if (braces[BRACE_ROW_OPEN])
171                             buf[pos++] = braces[BRACE_ROW_OPEN];
172                         if(!pos)
173                             return next();
174                         buf[pos] = 0;
175                     }
176                     return buf;
177                 case STATE_ROW_CLOSE:
178                     state = STATE_LINE_SEPARATOR;
179                     ++row;
180                     if (braces[BRACE_ROW_CLOSE])
181                     {
182                         buf[0] = braces[BRACE_ROW_CLOSE];
183                         buf[1] = row < mtx.rows ? ',' : '\0';
184                         buf[2] = 0;
185                         return buf;
186                     }
187                     else if(braces[BRACE_ROW_SEP] && row < mtx.rows)
188                     {
189                         buf[0] = braces[BRACE_ROW_SEP];
190                         buf[1] = 0;
191                         return buf;
192                     }
193                     return next();
194                 case STATE_CN_OPEN:
195                     state = STATE_VALUE;
196                     if (!alignOrder)
197                         cn = 0;
198                     if (mcn > 1 && braces[BRACE_CN_OPEN])
199                     {
200                         buf[0] = braces[BRACE_CN_OPEN];
201                         buf[1] = 0;
202                         return buf;
203                     }
204                     return next();
205                 case STATE_CN_CLOSE:
206                     ++col;
207                     if (col >= mtx.cols)
208                         state = STATE_ROW_CLOSE;
209                     else
210                         state = STATE_CN_SEPARATOR;
211                     if (mcn > 1 && braces[BRACE_CN_CLOSE])
212                     {
213                         buf[0] = braces[BRACE_CN_CLOSE];
214                         buf[1] = 0;
215                         return buf;
216                     }
217                     return next();
218                 case STATE_VALUE:
219                     (this->*valueToStr)();
220                     state = STATE_CN_CLOSE;
221                     if (alignOrder)
222                         return buf;
223                     if (++cn < mcn)
224                         state = STATE_VALUE_SEPARATOR;
225                     return buf;
226                 case STATE_FINISHED:
227                     return 0;
228                 case STATE_LINE_SEPARATOR:
229                     if (row >= mtx.rows)
230                     {
231                         if (alignOrder)
232                             state = STATE_INTERLUDE;
233                         else
234                             state = STATE_EPILOGUE;
235                         return next();
236                     }
237                     state = STATE_ROW_OPEN;
238                     buf[0] = singleLine ? ' ' : '\n';
239                     buf[1] = 0;
240                     return buf;
241                 case STATE_CN_SEPARATOR:
242                     state = STATE_CN_OPEN;
243                     buf[0] = ',';
244                     buf[1] = ' ';
245                     buf[2] = 0;
246                     return buf;
247                 case STATE_VALUE_SEPARATOR:
248                     state = STATE_VALUE;
249                     buf[0] = ',';
250                     buf[1] = ' ';
251                     buf[2] = 0;
252                     return buf;
253             }
254             return 0;
255         }
256     };
257 
258     class FormatterBase : public Formatter
259     {
260     public:
FormatterBase()261         FormatterBase() : prec16f(4), prec32f(8), prec64f(16), multiline(true) {}
262 
set16fPrecision(int p)263         void set16fPrecision(int p) CV_OVERRIDE
264         {
265             prec16f = p;
266         }
267 
set32fPrecision(int p)268         void set32fPrecision(int p) CV_OVERRIDE
269         {
270             prec32f = p;
271         }
272 
set64fPrecision(int p)273         void set64fPrecision(int p) CV_OVERRIDE
274         {
275             prec64f = p;
276         }
277 
setMultiline(bool ml)278         void setMultiline(bool ml) CV_OVERRIDE
279         {
280             multiline = ml;
281         }
282 
283     protected:
284         int prec16f;
285         int prec32f;
286         int prec64f;
287         int multiline;
288     };
289 
290     class DefaultFormatter CV_FINAL : public FormatterBase
291     {
292     public:
293 
format(const Mat & mtx) const294         Ptr<Formatted> format(const Mat& mtx) const CV_OVERRIDE
295         {
296             char braces[5] = {'\0', '\0', ';', '\0', '\0'};
297             return makePtr<FormattedImpl>("[", "]", mtx, &*braces,
298                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
299         }
300     };
301 
302     class MatlabFormatter CV_FINAL : public FormatterBase
303     {
304     public:
305 
format(const Mat & mtx) const306         Ptr<Formatted> format(const Mat& mtx) const CV_OVERRIDE
307         {
308             char braces[5] = {'\0', '\0', ';', '\0', '\0'};
309             return makePtr<FormattedImpl>("", "", mtx, &*braces,
310                 mtx.rows == 1 || !multiline, true, mtx.depth() == CV_64F ? prec64f : prec32f );
311         }
312     };
313 
314     class PythonFormatter CV_FINAL : public FormatterBase
315     {
316     public:
317 
format(const Mat & mtx) const318         Ptr<Formatted> format(const Mat& mtx) const CV_OVERRIDE
319         {
320             char braces[5] = {'[', ']', ',', '[', ']'};
321             if (mtx.cols == 1)
322                 braces[0] = braces[1] = '\0';
323             return makePtr<FormattedImpl>("[", "]", mtx, &*braces,
324                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
325         }
326     };
327 
328     class NumpyFormatter CV_FINAL : public FormatterBase
329     {
330     public:
331 
format(const Mat & mtx) const332         Ptr<Formatted> format(const Mat& mtx) const CV_OVERRIDE
333         {
334             static const char* numpyTypes[] =
335             {
336                 "uint8", "int8", "uint16", "int16", "int32", "float32", "float64", "float16"
337             };
338             char braces[5] = {'[', ']', ',', '[', ']'};
339             if (mtx.cols == 1)
340                 braces[0] = braces[1] = '\0';
341             return makePtr<FormattedImpl>("array([",
342                 cv::format("], dtype='%s')", numpyTypes[mtx.depth()]), mtx, &*braces,
343                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
344         }
345     };
346 
347     class CSVFormatter CV_FINAL : public FormatterBase
348     {
349     public:
350 
format(const Mat & mtx) const351         Ptr<Formatted> format(const Mat& mtx) const CV_OVERRIDE
352         {
353             char braces[5] = {'\0', '\0', '\0', '\0', '\0'};
354             return makePtr<FormattedImpl>(String(),
355                 mtx.rows > 1 ? String("\n") : String(), mtx, &*braces,
356                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
357         }
358     };
359 
360     class CFormatter CV_FINAL : public FormatterBase
361     {
362     public:
363 
format(const Mat & mtx) const364         Ptr<Formatted> format(const Mat& mtx) const CV_OVERRIDE
365         {
366             char braces[5] = {'\0', '\0', ',', '\0', '\0'};
367             return makePtr<FormattedImpl>("{", "}", mtx, &*braces,
368                 mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f );
369         }
370     };
371 
~Formatted()372     Formatted::~Formatted() {}
~Formatter()373     Formatter::~Formatter() {}
374 
get(Formatter::FormatType fmt)375     Ptr<Formatter> Formatter::get(Formatter::FormatType fmt)
376     {
377         switch(fmt)
378         {
379             case FMT_DEFAULT:
380                 return makePtr<DefaultFormatter>();
381             case FMT_MATLAB:
382                 return makePtr<MatlabFormatter>();
383             case FMT_CSV:
384                 return makePtr<CSVFormatter>();
385             case FMT_PYTHON:
386                 return makePtr<PythonFormatter>();
387             case FMT_NUMPY:
388                 return makePtr<NumpyFormatter>();
389             case FMT_C:
390                 return makePtr<CFormatter>();
391         }
392         return makePtr<DefaultFormatter>();
393     }
394 } // cv
395