From 84257b57d0e1e3806a7d420467c783bcf8e6c80b Mon Sep 17 00:00:00 2001 From: KayKwon Date: Wed, 16 Apr 2014 10:56:27 +0900 Subject: [PATCH] Fix for (Bug #2789) Add MatlabFormatter for matlab style output. See http://code.opencv.org/issues/2789 --- modules/core/include/opencv2/core.hpp | 12 ++--- modules/core/src/out.cpp | 71 +++++++++++++++++++++------ samples/cpp/cout_mat.cpp | 5 +- 3 files changed, 66 insertions(+), 22 deletions(-) diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index 12d11b006d..97070b63e8 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -953,12 +953,12 @@ public: class CV_EXPORTS Formatter { public: - enum { FMT_MATLAB = 0, - FMT_CSV = 1, - FMT_PYTHON = 2, - FMT_NUMPY = 3, - FMT_C = 4, - FMT_DEFAULT = FMT_MATLAB + enum { FMT_DEFAULT = 0, + FMT_MATLAB = 1, + FMT_CSV = 2, + FMT_PYTHON = 3, + FMT_NUMPY = 4, + FMT_C = 5 }; virtual ~Formatter(); diff --git a/modules/core/src/out.cpp b/modules/core/src/out.cpp index d639ac2126..89919715ec 100644 --- a/modules/core/src/out.cpp +++ b/modules/core/src/out.cpp @@ -47,7 +47,8 @@ namespace { class FormattedImpl : public cv::Formatted { - enum { STATE_PROLOGUE, STATE_EPILOGUE, STATE_ROW_OPEN, STATE_ROW_CLOSE, STATE_CN_OPEN, STATE_CN_CLOSE, STATE_VALUE, STATE_FINISHED, + enum { STATE_PROLOGUE, STATE_EPILOGUE, STATE_INTERLUDE, + STATE_ROW_OPEN, STATE_ROW_CLOSE, STATE_CN_OPEN, STATE_CN_CLOSE, STATE_VALUE, STATE_FINISHED, STATE_LINE_SEPARATOR, STATE_CN_SEPARATOR, STATE_VALUE_SEPARATOR }; enum {BRACE_ROW_OPEN = 0, BRACE_ROW_CLOSE = 1, BRACE_ROW_SEP=2, BRACE_CN_OPEN=3, BRACE_CN_CLOSE=4 }; @@ -57,6 +58,7 @@ namespace cv::Mat mtx; int mcn; // == mtx.channels() bool singleLine; + bool alignOrder; // true when cn first order int state; int row; @@ -79,8 +81,10 @@ namespace public: - FormattedImpl(cv::String pl, cv::String el, cv::Mat m, char br[5], bool sLine, int precision) + FormattedImpl(cv::String pl, cv::String el, cv::Mat m, char br[5], bool sLine, bool aOrder, int precision) { + CV_Assert(m.dims <= 2); + prologue = pl; epilogue = el; mtx = m; @@ -88,6 +92,8 @@ namespace memcpy(braces, br, 5); state = STATE_PROLOGUE; singleLine = sLine; + alignOrder = aOrder; + row = col = cn =0; if (precision < 0) { @@ -126,9 +132,28 @@ namespace row = 0; if (mtx.empty()) state = STATE_EPILOGUE; + else if (alignOrder) + state = STATE_INTERLUDE; else state = STATE_ROW_OPEN; return prologue.c_str(); + case STATE_INTERLUDE: + state = STATE_ROW_OPEN; + if (row >= mtx.rows) + { + if (++cn >= mcn) + { + state = STATE_EPILOGUE; + buf[0] = 0; + return buf; + } + else + row = 0; + sprintf(buf, "\n(:, :, %d) = \n", cn+1); + return buf; + } + sprintf(buf, "(:, :, %d) = \n", cn+1); + return buf; case STATE_EPILOGUE: state = STATE_FINISHED; return epilogue.c_str(); @@ -165,8 +190,9 @@ namespace } return next(); case STATE_CN_OPEN: - cn = 0; state = STATE_VALUE; + if (!alignOrder) + cn = 0; if (mcn > 1 && braces[BRACE_CN_OPEN]) { buf[0] = braces[BRACE_CN_OPEN]; @@ -189,9 +215,10 @@ namespace return next(); case STATE_VALUE: (this->*valueToStr)(); - if (++cn >= mcn) - state = STATE_CN_CLOSE; - else + state = STATE_CN_CLOSE; + if (alignOrder) + return buf; + if (++cn < mcn) state = STATE_VALUE_SEPARATOR; return buf; case STATE_FINISHED: @@ -199,7 +226,10 @@ namespace case STATE_LINE_SEPARATOR: if (row >= mtx.rows) { - state = STATE_EPILOGUE; + if (alignOrder) + state = STATE_INTERLUDE; + else + state = STATE_EPILOGUE; return next(); } state = STATE_ROW_OPEN; @@ -248,6 +278,17 @@ namespace int prec64f; int multiline; }; + class DefaultFormatter : public FormatterBase + { + public: + + cv::Ptr format(const cv::Mat& mtx) const + { + char braces[5] = {'\0', '\0', ';', '\0', '\0'}; + return cv::makePtr("[", "]", mtx, &*braces, + mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f ); + } + }; class MatlabFormatter : public FormatterBase { @@ -256,8 +297,8 @@ namespace cv::Ptr format(const cv::Mat& mtx) const { char braces[5] = {'\0', '\0', ';', '\0', '\0'}; - return cv::makePtr("[", "]", mtx, &*braces, - mtx.rows == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + return cv::makePtr("", "", mtx, &*braces, + mtx.rows == 1 || !multiline, true, mtx.depth() == CV_64F ? prec64f : prec32f ); } }; @@ -271,7 +312,7 @@ namespace if (mtx.cols == 1) braces[0] = braces[1] = '\0'; return cv::makePtr("[", "]", mtx, &*braces, - mtx.rows*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f ); } }; @@ -290,7 +331,7 @@ namespace braces[0] = braces[1] = '\0'; return cv::makePtr("array([", cv::format("], type='%s')", numpyTypes[mtx.depth()]), mtx, &*braces, - mtx.rows*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f ); } }; @@ -303,7 +344,7 @@ namespace char braces[5] = {'\0', '\0', '\0', '\0', '\0'}; return cv::makePtr(cv::String(), mtx.rows > 1 ? cv::String("\n") : cv::String(), mtx, &*braces, - mtx.rows*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f ); } }; @@ -315,7 +356,7 @@ namespace { char braces[5] = {'\0', '\0', ',', '\0', '\0'}; return cv::makePtr("{", "}", mtx, &*braces, - mtx.rows == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); + mtx.rows == 1 || !multiline, false, mtx.depth() == CV_64F ? prec64f : prec32f ); } }; @@ -331,6 +372,8 @@ namespace cv { switch(fmt) { + case FMT_DEFAULT: + return makePtr(); case FMT_MATLAB: return makePtr(); case FMT_CSV: @@ -342,6 +385,6 @@ namespace cv case FMT_C: return makePtr(); } - return makePtr(); + return makePtr(); } } // cv diff --git a/samples/cpp/cout_mat.cpp b/samples/cpp/cout_mat.cpp index 0ef94db125..2261d837c9 100644 --- a/samples/cpp/cout_mat.cpp +++ b/samples/cpp/cout_mat.cpp @@ -17,8 +17,8 @@ static void help() << "\n------------------------------------------------------------------\n" << " This program shows the serial out capabilities of cv::Mat\n" << "That is, cv::Mat M(...); cout << M; Now works.\n" - << "Output can be formated to OpenCV, python, numpy, csv and C styles" - << "Usage:\n" + << "Output can be formated to OpenCV, matlab, python, numpy, csv and \n" + << "C styles Usage:\n" << "./cvout_sample\n" << "------------------------------------------------------------------\n\n" << endl; @@ -36,6 +36,7 @@ int main(int,char**) randu(r, Scalar::all(0), Scalar::all(255)); cout << "r (default) = \n" << r << ";" << endl << endl; + cout << "r (matlab) = \n" << format(r, Formatter::FMT_MATLAB) << ";" << endl << endl; cout << "r (python) = \n" << format(r, Formatter::FMT_PYTHON) << ";" << endl << endl; cout << "r (numpy) = \n" << format(r, Formatter::FMT_NUMPY) << ";" << endl << endl; cout << "r (csv) = \n" << format(r, Formatter::FMT_CSV) << ";" << endl << endl;