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