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