From e37b9469dac0cad460d8e6731f210f26a56d835d Mon Sep 17 00:00:00 2001
From: Daniil Osokin <daniil.osokin@itseez.com>
Date: Fri, 10 Aug 2012 17:17:09 +0400
Subject: [PATCH] Added perf tests

---
 modules/imgproc/perf/perf_cvt_color.cpp |  538 +++---
 modules/imgproc/perf/perf_warp.cpp      |  336 ++--
 modules/stitching/perf/perf_stich.cpp   |  268 +--
 modules/ts/src/ts_perf.cpp              | 2310 +++++++++++------------
 4 files changed, 1726 insertions(+), 1726 deletions(-)

diff --git a/modules/imgproc/perf/perf_cvt_color.cpp b/modules/imgproc/perf/perf_cvt_color.cpp
index 123904e99..95c3f59d0 100644
--- a/modules/imgproc/perf/perf_cvt_color.cpp
+++ b/modules/imgproc/perf/perf_cvt_color.cpp
@@ -1,269 +1,269 @@
-#include "perf_precomp.hpp"
-
-using namespace std;
-using namespace cv;
-using namespace perf;
-using std::tr1::make_tuple;
-using std::tr1::get;
-
-//extra color conversions supported implicitly
-enum
-{
-    CX_BGRA2HLS      = CV_COLORCVT_MAX + CV_BGR2HLS,
-    CX_BGRA2HLS_FULL = CV_COLORCVT_MAX + CV_BGR2HLS_FULL,
-    CX_BGRA2HSV      = CV_COLORCVT_MAX + CV_BGR2HSV,
-    CX_BGRA2HSV_FULL = CV_COLORCVT_MAX + CV_BGR2HSV_FULL,
-    CX_BGRA2Lab      = CV_COLORCVT_MAX + CV_BGR2Lab,
-    CX_BGRA2Luv      = CV_COLORCVT_MAX + CV_BGR2Luv,
-    CX_BGRA2XYZ      = CV_COLORCVT_MAX + CV_BGR2XYZ,
-    CX_BGRA2YCrCb    = CV_COLORCVT_MAX + CV_BGR2YCrCb,
-    CX_BGRA2YUV      = CV_COLORCVT_MAX + CV_BGR2YUV,
-    CX_HLS2BGRA      = CV_COLORCVT_MAX + CV_HLS2BGR,
-    CX_HLS2BGRA_FULL = CV_COLORCVT_MAX + CV_HLS2BGR_FULL,
-    CX_HLS2RGBA      = CV_COLORCVT_MAX + CV_HLS2RGB,
-    CX_HLS2RGBA_FULL = CV_COLORCVT_MAX + CV_HLS2RGB_FULL,
-    CX_HSV2BGRA      = CV_COLORCVT_MAX + CV_HSV2BGR,
-    CX_HSV2BGRA_FULL = CV_COLORCVT_MAX + CV_HSV2BGR_FULL,
-    CX_HSV2RGBA      = CV_COLORCVT_MAX + CV_HSV2RGB,
-    CX_HSV2RGBA_FULL = CV_COLORCVT_MAX + CV_HSV2RGB_FULL,
-    CX_Lab2BGRA      = CV_COLORCVT_MAX + CV_Lab2BGR,
-    CX_Lab2LBGRA     = CV_COLORCVT_MAX + CV_Lab2LBGR,
-    CX_Lab2LRGBA     = CV_COLORCVT_MAX + CV_Lab2LRGB,
-    CX_Lab2RGBA      = CV_COLORCVT_MAX + CV_Lab2RGB,
-    CX_LBGRA2Lab     = CV_COLORCVT_MAX + CV_LBGR2Lab,
-    CX_LBGRA2Luv     = CV_COLORCVT_MAX + CV_LBGR2Luv,
-    CX_LRGBA2Lab     = CV_COLORCVT_MAX + CV_LRGB2Lab,
-    CX_LRGBA2Luv     = CV_COLORCVT_MAX + CV_LRGB2Luv,
-    CX_Luv2BGRA      = CV_COLORCVT_MAX + CV_Luv2BGR,
-    CX_Luv2LBGRA     = CV_COLORCVT_MAX + CV_Luv2LBGR,
-    CX_Luv2LRGBA     = CV_COLORCVT_MAX + CV_Luv2LRGB,
-    CX_Luv2RGBA      = CV_COLORCVT_MAX + CV_Luv2RGB,
-    CX_RGBA2HLS      = CV_COLORCVT_MAX + CV_RGB2HLS,
-    CX_RGBA2HLS_FULL = CV_COLORCVT_MAX + CV_RGB2HLS_FULL,
-    CX_RGBA2HSV      = CV_COLORCVT_MAX + CV_RGB2HSV,
-    CX_RGBA2HSV_FULL = CV_COLORCVT_MAX + CV_RGB2HSV_FULL,
-    CX_RGBA2Lab      = CV_COLORCVT_MAX + CV_RGB2Lab,
-    CX_RGBA2Luv      = CV_COLORCVT_MAX + CV_RGB2Luv,
-    CX_RGBA2XYZ      = CV_COLORCVT_MAX + CV_RGB2XYZ,
-    CX_RGBA2YCrCb    = CV_COLORCVT_MAX + CV_RGB2YCrCb,
-    CX_RGBA2YUV      = CV_COLORCVT_MAX + CV_RGB2YUV,
-    CX_XYZ2BGRA      = CV_COLORCVT_MAX + CV_XYZ2BGR,
-    CX_XYZ2RGBA      = CV_COLORCVT_MAX + CV_XYZ2RGB,
-    CX_YCrCb2BGRA    = CV_COLORCVT_MAX + CV_YCrCb2BGR,
-    CX_YCrCb2RGBA    = CV_COLORCVT_MAX + CV_YCrCb2RGB,
-    CX_YUV2BGRA      = CV_COLORCVT_MAX + CV_YUV2BGR,
-    CX_YUV2RGBA      = CV_COLORCVT_MAX + CV_YUV2RGB
-};
-
-CV_ENUM(CvtMode,
-    CV_BayerBG2BGR, CV_BayerBG2BGR_VNG, CV_BayerBG2GRAY,
-    CV_BayerGB2BGR, CV_BayerGB2BGR_VNG, CV_BayerGB2GRAY,
-    CV_BayerGR2BGR, CV_BayerGR2BGR_VNG, CV_BayerGR2GRAY,
-    CV_BayerRG2BGR, CV_BayerRG2BGR_VNG, CV_BayerRG2GRAY,
-
-    CV_BGR2BGR555, CV_BGR2BGR565, CV_BGR2BGRA, CV_BGR2GRAY,
-    CV_BGR2HLS, CV_BGR2HLS_FULL, CV_BGR2HSV, CV_BGR2HSV_FULL,
-    CV_BGR2Lab, CV_BGR2Luv, CV_BGR2RGB, CV_BGR2RGBA, CV_BGR2XYZ,
-    CV_BGR2YCrCb, CV_BGR2YUV, CV_BGR5552BGR, CV_BGR5552BGRA,
-
-    CV_BGR5552GRAY, CV_BGR5552RGB, CV_BGR5552RGBA, CV_BGR5652BGR,
-    CV_BGR5652BGRA, CV_BGR5652GRAY, CV_BGR5652RGB, CV_BGR5652RGBA,
-
-    CV_BGRA2BGR, CV_BGRA2BGR555, CV_BGRA2BGR565, CV_BGRA2GRAY, CV_BGRA2RGBA,
-    CX_BGRA2HLS, CX_BGRA2HLS_FULL, CX_BGRA2HSV, CX_BGRA2HSV_FULL,
-    CX_BGRA2Lab, CX_BGRA2Luv, CX_BGRA2XYZ,
-    CX_BGRA2YCrCb, CX_BGRA2YUV,
-
-    CV_GRAY2BGR, CV_GRAY2BGR555, CV_GRAY2BGR565, CV_GRAY2BGRA,
-
-    CV_HLS2BGR, CV_HLS2BGR_FULL, CV_HLS2RGB, CV_HLS2RGB_FULL,
-    CX_HLS2BGRA, CX_HLS2BGRA_FULL, CX_HLS2RGBA, CX_HLS2RGBA_FULL,
-
-    CV_HSV2BGR, CV_HSV2BGR_FULL, CV_HSV2RGB, CV_HSV2RGB_FULL,
-    CX_HSV2BGRA, CX_HSV2BGRA_FULL, CX_HSV2RGBA,    CX_HSV2RGBA_FULL,
-
-    CV_Lab2BGR, CV_Lab2LBGR, CV_Lab2LRGB, CV_Lab2RGB,
-    CX_Lab2BGRA, CX_Lab2LBGRA, CX_Lab2LRGBA, CX_Lab2RGBA,
-
-    CV_LBGR2Lab, CV_LBGR2Luv, CV_LRGB2Lab, CV_LRGB2Luv,
-    CX_LBGRA2Lab, CX_LBGRA2Luv, CX_LRGBA2Lab, CX_LRGBA2Luv,
-
-    CV_Luv2BGR, CV_Luv2LBGR, CV_Luv2LRGB, CV_Luv2RGB,
-    CX_Luv2BGRA, CX_Luv2LBGRA, CX_Luv2LRGBA, CX_Luv2RGBA,
-
-    CV_RGB2BGR555, CV_RGB2BGR565, CV_RGB2GRAY,
-    CV_RGB2HLS, CV_RGB2HLS_FULL, CV_RGB2HSV, CV_RGB2HSV_FULL,
-    CV_RGB2Lab, CV_RGB2Luv, CV_RGB2XYZ, CV_RGB2YCrCb, CV_RGB2YUV,
-
-    CV_RGBA2BGR, CV_RGBA2BGR555, CV_RGBA2BGR565, CV_RGBA2GRAY,
-    CX_RGBA2HLS, CX_RGBA2HLS_FULL, CX_RGBA2HSV, CX_RGBA2HSV_FULL,
-    CX_RGBA2Lab, CX_RGBA2Luv, CX_RGBA2XYZ,
-    CX_RGBA2YCrCb, CX_RGBA2YUV,
-
-    CV_XYZ2BGR, CV_XYZ2RGB, CX_XYZ2BGRA, CX_XYZ2RGBA,
-
-    CV_YCrCb2BGR, CV_YCrCb2RGB, CX_YCrCb2BGRA, CX_YCrCb2RGBA,
-    CV_YUV2BGR, CV_YUV2RGB, CX_YUV2BGRA, CX_YUV2RGBA
-    )
-
-CV_ENUM(CvtMode2, CV_YUV2BGR_NV12, CV_YUV2BGRA_NV12, CV_YUV2RGB_NV12, CV_YUV2RGBA_NV12, CV_YUV2BGR_NV21, CV_YUV2BGRA_NV21, CV_YUV2RGB_NV21, CV_YUV2RGBA_NV21,
-                  CV_YUV2BGR_YV12, CV_YUV2BGRA_YV12, CV_YUV2RGB_YV12, CV_YUV2RGBA_YV12, CV_YUV2BGR_IYUV, CV_YUV2BGRA_IYUV, CV_YUV2RGB_IYUV, CV_YUV2RGBA_IYUV,
-                  COLOR_YUV2GRAY_420)
-
-struct ChPair
-{
-    ChPair(int _scn, int _dcn): scn(_scn), dcn(_dcn) {}
-    int scn, dcn;
-};
-
-ChPair getConversionInfo(int cvtMode)
-{
-    switch(cvtMode)
-    {
-    case CV_BayerBG2GRAY: case CV_BayerGB2GRAY:
-    case CV_BayerGR2GRAY: case CV_BayerRG2GRAY:
-    case CV_YUV2GRAY_420:
-        return ChPair(1,1);
-    case CV_GRAY2BGR555: case CV_GRAY2BGR565:
-        return ChPair(1,2);
-    case CV_BayerBG2BGR: case CV_BayerBG2BGR_VNG:
-    case CV_BayerGB2BGR: case CV_BayerGB2BGR_VNG:
-    case CV_BayerGR2BGR: case CV_BayerGR2BGR_VNG:
-    case CV_BayerRG2BGR: case CV_BayerRG2BGR_VNG:
-    case CV_GRAY2BGR:
-    case CV_YUV2BGR_NV12: case CV_YUV2RGB_NV12:
-    case CV_YUV2BGR_NV21: case CV_YUV2RGB_NV21:
-    case CV_YUV2BGR_YV12: case CV_YUV2RGB_YV12:
-    case CV_YUV2BGR_IYUV: case CV_YUV2RGB_IYUV:
-        return ChPair(1,3);
-    case CV_GRAY2BGRA:
-    case CV_YUV2BGRA_NV12: case CV_YUV2RGBA_NV12:
-    case CV_YUV2BGRA_NV21: case CV_YUV2RGBA_NV21:
-    case CV_YUV2BGRA_YV12: case CV_YUV2RGBA_YV12:
-    case CV_YUV2BGRA_IYUV: case CV_YUV2RGBA_IYUV:
-        return ChPair(1,4);
-    case CV_BGR5552GRAY: case CV_BGR5652GRAY:
-        return ChPair(2,1);
-    case CV_BGR5552BGR: case CV_BGR5552RGB:
-    case CV_BGR5652BGR: case CV_BGR5652RGB:
-        return ChPair(2,3);
-    case CV_BGR5552BGRA: case CV_BGR5552RGBA:
-    case CV_BGR5652BGRA: case CV_BGR5652RGBA:
-        return ChPair(2,4);
-    case CV_BGR2GRAY: case CV_RGB2GRAY:
-        return ChPair(3,1);
-    case CV_BGR2BGR555: case CV_BGR2BGR565:
-    case CV_RGB2BGR555: case CV_RGB2BGR565:
-        return ChPair(3,2);
-    case CV_BGR2HLS: case CV_BGR2HLS_FULL:
-    case CV_BGR2HSV: case CV_BGR2HSV_FULL:
-    case CV_BGR2Lab: case CV_BGR2Luv:
-    case CV_BGR2RGB: case CV_BGR2XYZ:
-    case CV_BGR2YCrCb: case CV_BGR2YUV:
-    case CV_HLS2BGR: case CV_HLS2BGR_FULL:
-    case CV_HLS2RGB: case CV_HLS2RGB_FULL:
-    case CV_HSV2BGR: case CV_HSV2BGR_FULL:
-    case CV_HSV2RGB: case CV_HSV2RGB_FULL:
-    case CV_Lab2BGR: case CV_Lab2LBGR:
-    case CV_Lab2LRGB: case CV_Lab2RGB:
-    case CV_LBGR2Lab: case CV_LBGR2Luv:
-    case CV_LRGB2Lab: case CV_LRGB2Luv:
-    case CV_Luv2BGR: case CV_Luv2LBGR:
-    case CV_Luv2LRGB: case CV_Luv2RGB:
-    case CV_RGB2HLS: case CV_RGB2HLS_FULL:
-    case CV_RGB2HSV: case CV_RGB2HSV_FULL:
-    case CV_RGB2Lab: case CV_RGB2Luv:
-    case CV_RGB2XYZ: case CV_RGB2YCrCb:
-    case CV_RGB2YUV: case CV_XYZ2BGR:
-    case CV_XYZ2RGB: case CV_YCrCb2BGR:
-    case CV_YCrCb2RGB: case CV_YUV2BGR:
-    case CV_YUV2RGB:
-        return ChPair(3,3);
-    case CV_BGR2BGRA: case CV_BGR2RGBA:
-    case CX_HLS2BGRA: case CX_HLS2BGRA_FULL:
-    case CX_HLS2RGBA: case CX_HLS2RGBA_FULL:
-    case CX_HSV2BGRA: case CX_HSV2BGRA_FULL:
-    case CX_HSV2RGBA: case CX_HSV2RGBA_FULL:
-    case CX_Lab2BGRA: case CX_Lab2LBGRA:
-    case CX_Lab2LRGBA: case CX_Lab2RGBA:
-    case CX_Luv2BGRA: case CX_Luv2LBGRA:
-    case CX_Luv2LRGBA: case CX_Luv2RGBA:
-    case CX_XYZ2BGRA: case CX_XYZ2RGBA:
-    case CX_YCrCb2BGRA: case CX_YCrCb2RGBA:
-    case CX_YUV2BGRA: case CX_YUV2RGBA:
-        return ChPair(3,4);
-    case CV_BGRA2GRAY: case CV_RGBA2GRAY:
-        return ChPair(4,1);
-    case CV_BGRA2BGR555: case CV_BGRA2BGR565:
-    case CV_RGBA2BGR555: case CV_RGBA2BGR565:
-        return ChPair(4,2);
-    case CV_BGRA2BGR: case CX_BGRA2HLS:
-    case CX_BGRA2HLS_FULL: case CX_BGRA2HSV:
-    case CX_BGRA2HSV_FULL: case CX_BGRA2Lab:
-    case CX_BGRA2Luv: case CX_BGRA2XYZ:
-    case CX_BGRA2YCrCb: case CX_BGRA2YUV:
-    case CX_LBGRA2Lab: case CX_LBGRA2Luv:
-    case CX_LRGBA2Lab: case CX_LRGBA2Luv:
-    case CV_RGBA2BGR: case CX_RGBA2HLS:
-    case CX_RGBA2HLS_FULL: case CX_RGBA2HSV:
-    case CX_RGBA2HSV_FULL: case CX_RGBA2Lab:
-    case CX_RGBA2Luv: case CX_RGBA2XYZ:
-    case CX_RGBA2YCrCb: case CX_RGBA2YUV:
-        return ChPair(4,3);
-    case CV_BGRA2RGBA:
-        return ChPair(4,4);
-    default:
-        ADD_FAILURE() << "Unknown conversion type";
-        break;
-    };
-    return ChPair(0,0);
-}
-
-typedef std::tr1::tuple<Size, CvtMode> Size_CvtMode_t;
-typedef perf::TestBaseWithParam<Size_CvtMode_t> Size_CvtMode;
-
-PERF_TEST_P(Size_CvtMode, cvtColor8u,
-            testing::Combine(
-                testing::Values(TYPICAL_MAT_SIZES),
-                testing::ValuesIn(CvtMode::all())
-                )
-            )
-{
-    Size sz = get<0>(GetParam());
-    int mode = get<1>(GetParam());
-    ChPair ch = getConversionInfo(mode);
-    mode %= CV_COLORCVT_MAX;
-
-    Mat src(sz, CV_8UC(ch.scn));
-    Mat dst(sz, CV_8UC(ch.dcn));
-
-    declare.in(src, WARMUP_RNG).out(dst);
-
-    TEST_CYCLE() cvtColor(src, dst, mode, ch.dcn);
-
-    SANITY_CHECK(dst, 1);
-}
-
-typedef std::tr1::tuple<Size, CvtMode2> Size_CvtMode2_t;
-typedef perf::TestBaseWithParam<Size_CvtMode2_t> Size_CvtMode2;
-
-PERF_TEST_P(Size_CvtMode2, cvtColorYUV420,
-            testing::Combine(
-                testing::Values(szVGA, sz720p, sz1080p, Size(130, 60)),
-                testing::ValuesIn(CvtMode2::all())
-                )
-            )
-{
-    Size sz = get<0>(GetParam());
-    int mode = get<1>(GetParam());
-    ChPair ch = getConversionInfo(mode);
-
-    Mat src(sz.height + sz.height / 2, sz.width, CV_8UC(ch.scn));
-    Mat dst(sz, CV_8UC(ch.dcn));
-
-    declare.in(src, WARMUP_RNG).out(dst);
-
-    TEST_CYCLE() cvtColor(src, dst, mode, ch.dcn);
-
-    SANITY_CHECK(dst, 1);
-}
+#include "perf_precomp.hpp"
+
+using namespace std;
+using namespace cv;
+using namespace perf;
+using std::tr1::make_tuple;
+using std::tr1::get;
+
+//extra color conversions supported implicitly
+enum
+{
+    CX_BGRA2HLS      = CV_COLORCVT_MAX + CV_BGR2HLS,
+    CX_BGRA2HLS_FULL = CV_COLORCVT_MAX + CV_BGR2HLS_FULL,
+    CX_BGRA2HSV      = CV_COLORCVT_MAX + CV_BGR2HSV,
+    CX_BGRA2HSV_FULL = CV_COLORCVT_MAX + CV_BGR2HSV_FULL,
+    CX_BGRA2Lab      = CV_COLORCVT_MAX + CV_BGR2Lab,
+    CX_BGRA2Luv      = CV_COLORCVT_MAX + CV_BGR2Luv,
+    CX_BGRA2XYZ      = CV_COLORCVT_MAX + CV_BGR2XYZ,
+    CX_BGRA2YCrCb    = CV_COLORCVT_MAX + CV_BGR2YCrCb,
+    CX_BGRA2YUV      = CV_COLORCVT_MAX + CV_BGR2YUV,
+    CX_HLS2BGRA      = CV_COLORCVT_MAX + CV_HLS2BGR,
+    CX_HLS2BGRA_FULL = CV_COLORCVT_MAX + CV_HLS2BGR_FULL,
+    CX_HLS2RGBA      = CV_COLORCVT_MAX + CV_HLS2RGB,
+    CX_HLS2RGBA_FULL = CV_COLORCVT_MAX + CV_HLS2RGB_FULL,
+    CX_HSV2BGRA      = CV_COLORCVT_MAX + CV_HSV2BGR,
+    CX_HSV2BGRA_FULL = CV_COLORCVT_MAX + CV_HSV2BGR_FULL,
+    CX_HSV2RGBA      = CV_COLORCVT_MAX + CV_HSV2RGB,
+    CX_HSV2RGBA_FULL = CV_COLORCVT_MAX + CV_HSV2RGB_FULL,
+    CX_Lab2BGRA      = CV_COLORCVT_MAX + CV_Lab2BGR,
+    CX_Lab2LBGRA     = CV_COLORCVT_MAX + CV_Lab2LBGR,
+    CX_Lab2LRGBA     = CV_COLORCVT_MAX + CV_Lab2LRGB,
+    CX_Lab2RGBA      = CV_COLORCVT_MAX + CV_Lab2RGB,
+    CX_LBGRA2Lab     = CV_COLORCVT_MAX + CV_LBGR2Lab,
+    CX_LBGRA2Luv     = CV_COLORCVT_MAX + CV_LBGR2Luv,
+    CX_LRGBA2Lab     = CV_COLORCVT_MAX + CV_LRGB2Lab,
+    CX_LRGBA2Luv     = CV_COLORCVT_MAX + CV_LRGB2Luv,
+    CX_Luv2BGRA      = CV_COLORCVT_MAX + CV_Luv2BGR,
+    CX_Luv2LBGRA     = CV_COLORCVT_MAX + CV_Luv2LBGR,
+    CX_Luv2LRGBA     = CV_COLORCVT_MAX + CV_Luv2LRGB,
+    CX_Luv2RGBA      = CV_COLORCVT_MAX + CV_Luv2RGB,
+    CX_RGBA2HLS      = CV_COLORCVT_MAX + CV_RGB2HLS,
+    CX_RGBA2HLS_FULL = CV_COLORCVT_MAX + CV_RGB2HLS_FULL,
+    CX_RGBA2HSV      = CV_COLORCVT_MAX + CV_RGB2HSV,
+    CX_RGBA2HSV_FULL = CV_COLORCVT_MAX + CV_RGB2HSV_FULL,
+    CX_RGBA2Lab      = CV_COLORCVT_MAX + CV_RGB2Lab,
+    CX_RGBA2Luv      = CV_COLORCVT_MAX + CV_RGB2Luv,
+    CX_RGBA2XYZ      = CV_COLORCVT_MAX + CV_RGB2XYZ,
+    CX_RGBA2YCrCb    = CV_COLORCVT_MAX + CV_RGB2YCrCb,
+    CX_RGBA2YUV      = CV_COLORCVT_MAX + CV_RGB2YUV,
+    CX_XYZ2BGRA      = CV_COLORCVT_MAX + CV_XYZ2BGR,
+    CX_XYZ2RGBA      = CV_COLORCVT_MAX + CV_XYZ2RGB,
+    CX_YCrCb2BGRA    = CV_COLORCVT_MAX + CV_YCrCb2BGR,
+    CX_YCrCb2RGBA    = CV_COLORCVT_MAX + CV_YCrCb2RGB,
+    CX_YUV2BGRA      = CV_COLORCVT_MAX + CV_YUV2BGR,
+    CX_YUV2RGBA      = CV_COLORCVT_MAX + CV_YUV2RGB
+};
+
+CV_ENUM(CvtMode,
+    CV_BayerBG2BGR, CV_BayerBG2BGR_VNG, CV_BayerBG2GRAY,
+    CV_BayerGB2BGR, CV_BayerGB2BGR_VNG, CV_BayerGB2GRAY,
+    CV_BayerGR2BGR, CV_BayerGR2BGR_VNG, CV_BayerGR2GRAY,
+    CV_BayerRG2BGR, CV_BayerRG2BGR_VNG, CV_BayerRG2GRAY,
+
+    CV_BGR2BGR555, CV_BGR2BGR565, CV_BGR2BGRA, CV_BGR2GRAY,
+    CV_BGR2HLS, CV_BGR2HLS_FULL, CV_BGR2HSV, CV_BGR2HSV_FULL,
+    CV_BGR2Lab, CV_BGR2Luv, CV_BGR2RGB, CV_BGR2RGBA, CV_BGR2XYZ,
+    CV_BGR2YCrCb, CV_BGR2YUV, CV_BGR5552BGR, CV_BGR5552BGRA,
+
+    CV_BGR5552GRAY, CV_BGR5552RGB, CV_BGR5552RGBA, CV_BGR5652BGR,
+    CV_BGR5652BGRA, CV_BGR5652GRAY, CV_BGR5652RGB, CV_BGR5652RGBA,
+
+    CV_BGRA2BGR, CV_BGRA2BGR555, CV_BGRA2BGR565, CV_BGRA2GRAY, CV_BGRA2RGBA,
+    CX_BGRA2HLS, CX_BGRA2HLS_FULL, CX_BGRA2HSV, CX_BGRA2HSV_FULL,
+    CX_BGRA2Lab, CX_BGRA2Luv, CX_BGRA2XYZ,
+    CX_BGRA2YCrCb, CX_BGRA2YUV,
+
+    CV_GRAY2BGR, CV_GRAY2BGR555, CV_GRAY2BGR565, CV_GRAY2BGRA,
+
+    CV_HLS2BGR, CV_HLS2BGR_FULL, CV_HLS2RGB, CV_HLS2RGB_FULL,
+    CX_HLS2BGRA, CX_HLS2BGRA_FULL, CX_HLS2RGBA, CX_HLS2RGBA_FULL,
+
+    CV_HSV2BGR, CV_HSV2BGR_FULL, CV_HSV2RGB, CV_HSV2RGB_FULL,
+    CX_HSV2BGRA, CX_HSV2BGRA_FULL, CX_HSV2RGBA,    CX_HSV2RGBA_FULL,
+
+    CV_Lab2BGR, CV_Lab2LBGR, CV_Lab2LRGB, CV_Lab2RGB,
+    CX_Lab2BGRA, CX_Lab2LBGRA, CX_Lab2LRGBA, CX_Lab2RGBA,
+
+    CV_LBGR2Lab, CV_LBGR2Luv, CV_LRGB2Lab, CV_LRGB2Luv,
+    CX_LBGRA2Lab, CX_LBGRA2Luv, CX_LRGBA2Lab, CX_LRGBA2Luv,
+
+    CV_Luv2BGR, CV_Luv2LBGR, CV_Luv2LRGB, CV_Luv2RGB,
+    CX_Luv2BGRA, CX_Luv2LBGRA, CX_Luv2LRGBA, CX_Luv2RGBA,
+
+    CV_RGB2BGR555, CV_RGB2BGR565, CV_RGB2GRAY,
+    CV_RGB2HLS, CV_RGB2HLS_FULL, CV_RGB2HSV, CV_RGB2HSV_FULL,
+    CV_RGB2Lab, CV_RGB2Luv, CV_RGB2XYZ, CV_RGB2YCrCb, CV_RGB2YUV,
+
+    CV_RGBA2BGR, CV_RGBA2BGR555, CV_RGBA2BGR565, CV_RGBA2GRAY,
+    CX_RGBA2HLS, CX_RGBA2HLS_FULL, CX_RGBA2HSV, CX_RGBA2HSV_FULL,
+    CX_RGBA2Lab, CX_RGBA2Luv, CX_RGBA2XYZ,
+    CX_RGBA2YCrCb, CX_RGBA2YUV,
+
+    CV_XYZ2BGR, CV_XYZ2RGB, CX_XYZ2BGRA, CX_XYZ2RGBA,
+
+    CV_YCrCb2BGR, CV_YCrCb2RGB, CX_YCrCb2BGRA, CX_YCrCb2RGBA,
+    CV_YUV2BGR, CV_YUV2RGB, CX_YUV2BGRA, CX_YUV2RGBA
+    )
+
+CV_ENUM(CvtMode2, CV_YUV2BGR_NV12, CV_YUV2BGRA_NV12, CV_YUV2RGB_NV12, CV_YUV2RGBA_NV12, CV_YUV2BGR_NV21, CV_YUV2BGRA_NV21, CV_YUV2RGB_NV21, CV_YUV2RGBA_NV21,
+                  CV_YUV2BGR_YV12, CV_YUV2BGRA_YV12, CV_YUV2RGB_YV12, CV_YUV2RGBA_YV12, CV_YUV2BGR_IYUV, CV_YUV2BGRA_IYUV, CV_YUV2RGB_IYUV, CV_YUV2RGBA_IYUV,
+                  COLOR_YUV2GRAY_420)
+
+struct ChPair
+{
+    ChPair(int _scn, int _dcn): scn(_scn), dcn(_dcn) {}
+    int scn, dcn;
+};
+
+ChPair getConversionInfo(int cvtMode)
+{
+    switch(cvtMode)
+    {
+    case CV_BayerBG2GRAY: case CV_BayerGB2GRAY:
+    case CV_BayerGR2GRAY: case CV_BayerRG2GRAY:
+    case CV_YUV2GRAY_420:
+        return ChPair(1,1);
+    case CV_GRAY2BGR555: case CV_GRAY2BGR565:
+        return ChPair(1,2);
+    case CV_BayerBG2BGR: case CV_BayerBG2BGR_VNG:
+    case CV_BayerGB2BGR: case CV_BayerGB2BGR_VNG:
+    case CV_BayerGR2BGR: case CV_BayerGR2BGR_VNG:
+    case CV_BayerRG2BGR: case CV_BayerRG2BGR_VNG:
+    case CV_GRAY2BGR:
+    case CV_YUV2BGR_NV12: case CV_YUV2RGB_NV12:
+    case CV_YUV2BGR_NV21: case CV_YUV2RGB_NV21:
+    case CV_YUV2BGR_YV12: case CV_YUV2RGB_YV12:
+    case CV_YUV2BGR_IYUV: case CV_YUV2RGB_IYUV:
+        return ChPair(1,3);
+    case CV_GRAY2BGRA:
+    case CV_YUV2BGRA_NV12: case CV_YUV2RGBA_NV12:
+    case CV_YUV2BGRA_NV21: case CV_YUV2RGBA_NV21:
+    case CV_YUV2BGRA_YV12: case CV_YUV2RGBA_YV12:
+    case CV_YUV2BGRA_IYUV: case CV_YUV2RGBA_IYUV:
+        return ChPair(1,4);
+    case CV_BGR5552GRAY: case CV_BGR5652GRAY:
+        return ChPair(2,1);
+    case CV_BGR5552BGR: case CV_BGR5552RGB:
+    case CV_BGR5652BGR: case CV_BGR5652RGB:
+        return ChPair(2,3);
+    case CV_BGR5552BGRA: case CV_BGR5552RGBA:
+    case CV_BGR5652BGRA: case CV_BGR5652RGBA:
+        return ChPair(2,4);
+    case CV_BGR2GRAY: case CV_RGB2GRAY:
+        return ChPair(3,1);
+    case CV_BGR2BGR555: case CV_BGR2BGR565:
+    case CV_RGB2BGR555: case CV_RGB2BGR565:
+        return ChPair(3,2);
+    case CV_BGR2HLS: case CV_BGR2HLS_FULL:
+    case CV_BGR2HSV: case CV_BGR2HSV_FULL:
+    case CV_BGR2Lab: case CV_BGR2Luv:
+    case CV_BGR2RGB: case CV_BGR2XYZ:
+    case CV_BGR2YCrCb: case CV_BGR2YUV:
+    case CV_HLS2BGR: case CV_HLS2BGR_FULL:
+    case CV_HLS2RGB: case CV_HLS2RGB_FULL:
+    case CV_HSV2BGR: case CV_HSV2BGR_FULL:
+    case CV_HSV2RGB: case CV_HSV2RGB_FULL:
+    case CV_Lab2BGR: case CV_Lab2LBGR:
+    case CV_Lab2LRGB: case CV_Lab2RGB:
+    case CV_LBGR2Lab: case CV_LBGR2Luv:
+    case CV_LRGB2Lab: case CV_LRGB2Luv:
+    case CV_Luv2BGR: case CV_Luv2LBGR:
+    case CV_Luv2LRGB: case CV_Luv2RGB:
+    case CV_RGB2HLS: case CV_RGB2HLS_FULL:
+    case CV_RGB2HSV: case CV_RGB2HSV_FULL:
+    case CV_RGB2Lab: case CV_RGB2Luv:
+    case CV_RGB2XYZ: case CV_RGB2YCrCb:
+    case CV_RGB2YUV: case CV_XYZ2BGR:
+    case CV_XYZ2RGB: case CV_YCrCb2BGR:
+    case CV_YCrCb2RGB: case CV_YUV2BGR:
+    case CV_YUV2RGB:
+        return ChPair(3,3);
+    case CV_BGR2BGRA: case CV_BGR2RGBA:
+    case CX_HLS2BGRA: case CX_HLS2BGRA_FULL:
+    case CX_HLS2RGBA: case CX_HLS2RGBA_FULL:
+    case CX_HSV2BGRA: case CX_HSV2BGRA_FULL:
+    case CX_HSV2RGBA: case CX_HSV2RGBA_FULL:
+    case CX_Lab2BGRA: case CX_Lab2LBGRA:
+    case CX_Lab2LRGBA: case CX_Lab2RGBA:
+    case CX_Luv2BGRA: case CX_Luv2LBGRA:
+    case CX_Luv2LRGBA: case CX_Luv2RGBA:
+    case CX_XYZ2BGRA: case CX_XYZ2RGBA:
+    case CX_YCrCb2BGRA: case CX_YCrCb2RGBA:
+    case CX_YUV2BGRA: case CX_YUV2RGBA:
+        return ChPair(3,4);
+    case CV_BGRA2GRAY: case CV_RGBA2GRAY:
+        return ChPair(4,1);
+    case CV_BGRA2BGR555: case CV_BGRA2BGR565:
+    case CV_RGBA2BGR555: case CV_RGBA2BGR565:
+        return ChPair(4,2);
+    case CV_BGRA2BGR: case CX_BGRA2HLS:
+    case CX_BGRA2HLS_FULL: case CX_BGRA2HSV:
+    case CX_BGRA2HSV_FULL: case CX_BGRA2Lab:
+    case CX_BGRA2Luv: case CX_BGRA2XYZ:
+    case CX_BGRA2YCrCb: case CX_BGRA2YUV:
+    case CX_LBGRA2Lab: case CX_LBGRA2Luv:
+    case CX_LRGBA2Lab: case CX_LRGBA2Luv:
+    case CV_RGBA2BGR: case CX_RGBA2HLS:
+    case CX_RGBA2HLS_FULL: case CX_RGBA2HSV:
+    case CX_RGBA2HSV_FULL: case CX_RGBA2Lab:
+    case CX_RGBA2Luv: case CX_RGBA2XYZ:
+    case CX_RGBA2YCrCb: case CX_RGBA2YUV:
+        return ChPair(4,3);
+    case CV_BGRA2RGBA:
+        return ChPair(4,4);
+    default:
+        ADD_FAILURE() << "Unknown conversion type";
+        break;
+    };
+    return ChPair(0,0);
+}
+
+typedef std::tr1::tuple<Size, CvtMode> Size_CvtMode_t;
+typedef perf::TestBaseWithParam<Size_CvtMode_t> Size_CvtMode;
+
+PERF_TEST_P(Size_CvtMode, cvtColor8u,
+            testing::Combine(
+                testing::Values(TYPICAL_MAT_SIZES),
+                testing::ValuesIn(CvtMode::all())
+                )
+            )
+{
+    Size sz = get<0>(GetParam());
+    int mode = get<1>(GetParam());
+    ChPair ch = getConversionInfo(mode);
+    mode %= CV_COLORCVT_MAX;
+
+    Mat src(sz, CV_8UC(ch.scn));
+    Mat dst(sz, CV_8UC(ch.dcn));
+
+    declare.in(src, WARMUP_RNG).out(dst);
+
+    TEST_CYCLE() cvtColor(src, dst, mode, ch.dcn);
+
+    SANITY_CHECK(dst, 1);
+}
+
+typedef std::tr1::tuple<Size, CvtMode2> Size_CvtMode2_t;
+typedef perf::TestBaseWithParam<Size_CvtMode2_t> Size_CvtMode2;
+
+PERF_TEST_P(Size_CvtMode2, cvtColorYUV420,
+            testing::Combine(
+                testing::Values(szVGA, sz720p, sz1080p, Size(130, 60)),
+                testing::ValuesIn(CvtMode2::all())
+                )
+            )
+{
+    Size sz = get<0>(GetParam());
+    int mode = get<1>(GetParam());
+    ChPair ch = getConversionInfo(mode);
+
+    Mat src(sz.height + sz.height / 2, sz.width, CV_8UC(ch.scn));
+    Mat dst(sz, CV_8UC(ch.dcn));
+
+    declare.in(src, WARMUP_RNG).out(dst);
+
+    TEST_CYCLE() cvtColor(src, dst, mode, ch.dcn);
+
+    SANITY_CHECK(dst, 1);
+}
diff --git a/modules/imgproc/perf/perf_warp.cpp b/modules/imgproc/perf/perf_warp.cpp
index 215580e92..823ff53f1 100644
--- a/modules/imgproc/perf/perf_warp.cpp
+++ b/modules/imgproc/perf/perf_warp.cpp
@@ -1,168 +1,168 @@
-#include "perf_precomp.hpp"
-
-using namespace std;
-using namespace cv;
-using namespace perf;
-using namespace testing;
-using std::tr1::make_tuple;
-using std::tr1::get;
-
-enum{HALF_SIZE=0, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH};
-
-CV_ENUM(BorderMode, BORDER_CONSTANT, BORDER_REPLICATE);
-CV_ENUM(InterType, INTER_NEAREST, INTER_LINEAR);
-CV_ENUM(RemapMode, HALF_SIZE, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH);
-
-typedef TestBaseWithParam< tr1::tuple<Size, InterType, BorderMode> > TestWarpAffine;
-typedef TestBaseWithParam< tr1::tuple<Size, InterType, BorderMode> > TestWarpPerspective;
-typedef TestBaseWithParam< tr1::tuple<MatType, Size, InterType, BorderMode, RemapMode> > TestRemap;
-
-void update_map(const Mat& src, Mat& map_x, Mat& map_y, const int remapMode );
-
-PERF_TEST_P( TestWarpAffine, WarpAffine,
-             Combine(
-                Values( szVGA, sz720p, sz1080p ),
-                ValuesIn( InterType::all() ),
-                ValuesIn( BorderMode::all() )
-             )
-)
-{
-    Size sz;
-    int borderMode, interType;
-    sz         = get<0>(GetParam());
-    borderMode = get<1>(GetParam());
-    interType  = get<2>(GetParam());
-
-    Mat src, img = imread(getDataPath("cv/shared/fruits.jpg"));
-    cvtColor(img, src, COLOR_BGR2RGBA, 4);
-    Mat warpMat = getRotationMatrix2D(Point2f(src.cols/2.f, src.rows/2.f), 30., 2.2);
-    Mat dst(sz, CV_8UC4);
-
-    declare.in(src).out(dst);
-
-    TEST_CYCLE() warpAffine( src, dst, warpMat, sz, interType, borderMode, Scalar::all(150) );
-
-    SANITY_CHECK(dst);
-
-}
-
-PERF_TEST_P( TestWarpPerspective, WarpPerspective,
-             Combine(
-                Values( szVGA, sz720p, sz1080p ),
-                ValuesIn( InterType::all() ),
-                ValuesIn( BorderMode::all() )
-             )
-)
-{
-    Size sz;
-    int borderMode, interType;
-    sz         = get<0>(GetParam());
-    borderMode = get<1>(GetParam());
-    interType  = get<2>(GetParam());
-
-
-    Mat src, img = imread(getDataPath("cv/shared/fruits.jpg"));
-    cvtColor(img, src, COLOR_BGR2RGBA, 4);
-    Mat rotMat = getRotationMatrix2D(Point2f(src.cols/2.f, src.rows/2.f), 30., 2.2);
-    Mat warpMat(3, 3, CV_64FC1);
-    for(int r=0; r<2; r++)
-        for(int c=0; c<3; c++)
-            warpMat.at<double>(r, c) = rotMat.at<double>(r, c);
-    warpMat.at<double>(2, 0) = .3/sz.width;
-    warpMat.at<double>(2, 1) = .3/sz.height;
-    warpMat.at<double>(2, 2) = 1;
-    Mat dst(sz, CV_8UC4);
-
-    declare.in(src).out(dst);
-
-    TEST_CYCLE() warpPerspective( src, dst, warpMat, sz, interType, borderMode, Scalar::all(150) );
-
-    SANITY_CHECK(dst);
-}
-
-PERF_TEST_P( TestRemap, remap,
-             Combine(
-                 Values( TYPICAL_MAT_TYPES ),
-                 Values( szVGA, sz720p, sz1080p ),
-                 ValuesIn( InterType::all() ),
-                 ValuesIn( BorderMode::all() ),
-                 ValuesIn( RemapMode::all() )
-                 )
-             )
-{
-    int type = get<0>(GetParam());
-    Size size = get<1>(GetParam());
-    int interpolationType = get<2>(GetParam());
-    int borderMode = get<3>(GetParam());
-    int remapMode = get<4>(GetParam());
-    unsigned int height = size.height;
-    unsigned int width = size.width;
-    Mat source(height, width, type);
-    Mat destination;
-    Mat map_x(height, width, CV_32F);
-    Mat map_y(height, width, CV_32F);
-
-    declare.in(source, WARMUP_RNG);
-
-    update_map(source, map_x, map_y, remapMode);
-
-    TEST_CYCLE()
-    {
-        remap(source, destination, map_x, map_y, interpolationType, borderMode);
-    }
-
-    SANITY_CHECK(destination, 1);
-}
-
-void update_map(const Mat& src, Mat& map_x, Mat& map_y, const int remapMode )
-{
-    for( int j = 0; j < src.rows; j++ )
-    {
-        for( int i = 0; i < src.cols; i++ )
-        {
-            switch( remapMode )
-            {
-            case HALF_SIZE:
-                if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
-                {
-                    map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;
-                    map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;
-                }
-                else
-                {
-                    map_x.at<float>(j,i) = 0 ;
-                    map_y.at<float>(j,i) = 0 ;
-                }
-                break;
-            case UPSIDE_DOWN:
-                map_x.at<float>(j,i) = i ;
-                map_y.at<float>(j,i) = src.rows - j ;
-                break;
-            case REFLECTION_X:
-                map_x.at<float>(j,i) = src.cols - i ;
-                map_y.at<float>(j,i) = j ;
-                break;
-            case REFLECTION_BOTH:
-                map_x.at<float>(j,i) = src.cols - i ;
-                map_y.at<float>(j,i) = src.rows - j ;
-                break;
-            } // end of switch
-        }
-    }
-}
-
-PERF_TEST(Transform, getPerspectiveTransform)
-{
-    unsigned int size = 8;
-    Mat source(1, size/2, CV_32FC2);
-    Mat destination(1, size/2, CV_32FC2);
-    Mat transformCoefficient;
-
-    declare.in(source, destination, WARMUP_RNG);
-
-    TEST_CYCLE()
-    {
-        transformCoefficient = getPerspectiveTransform(source, destination);
-    }
-}
-
+#include "perf_precomp.hpp"
+
+using namespace std;
+using namespace cv;
+using namespace perf;
+using namespace testing;
+using std::tr1::make_tuple;
+using std::tr1::get;
+
+enum{HALF_SIZE=0, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH};
+
+CV_ENUM(BorderMode, BORDER_CONSTANT, BORDER_REPLICATE);
+CV_ENUM(InterType, INTER_NEAREST, INTER_LINEAR);
+CV_ENUM(RemapMode, HALF_SIZE, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH);
+
+typedef TestBaseWithParam< tr1::tuple<Size, InterType, BorderMode> > TestWarpAffine;
+typedef TestBaseWithParam< tr1::tuple<Size, InterType, BorderMode> > TestWarpPerspective;
+typedef TestBaseWithParam< tr1::tuple<MatType, Size, InterType, BorderMode, RemapMode> > TestRemap;
+
+void update_map(const Mat& src, Mat& map_x, Mat& map_y, const int remapMode );
+
+PERF_TEST_P( TestWarpAffine, WarpAffine,
+             Combine(
+                Values( szVGA, sz720p, sz1080p ),
+                ValuesIn( InterType::all() ),
+                ValuesIn( BorderMode::all() )
+             )
+)
+{
+    Size sz;
+    int borderMode, interType;
+    sz         = get<0>(GetParam());
+    borderMode = get<1>(GetParam());
+    interType  = get<2>(GetParam());
+
+    Mat src, img = imread(getDataPath("cv/shared/fruits.jpg"));
+    cvtColor(img, src, COLOR_BGR2RGBA, 4);
+    Mat warpMat = getRotationMatrix2D(Point2f(src.cols/2.f, src.rows/2.f), 30., 2.2);
+    Mat dst(sz, CV_8UC4);
+
+    declare.in(src).out(dst);
+
+    TEST_CYCLE() warpAffine( src, dst, warpMat, sz, interType, borderMode, Scalar::all(150) );
+
+    SANITY_CHECK(dst);
+
+}
+
+PERF_TEST_P( TestWarpPerspective, WarpPerspective,
+             Combine(
+                Values( szVGA, sz720p, sz1080p ),
+                ValuesIn( InterType::all() ),
+                ValuesIn( BorderMode::all() )
+             )
+)
+{
+    Size sz;
+    int borderMode, interType;
+    sz         = get<0>(GetParam());
+    borderMode = get<1>(GetParam());
+    interType  = get<2>(GetParam());
+
+
+    Mat src, img = imread(getDataPath("cv/shared/fruits.jpg"));
+    cvtColor(img, src, COLOR_BGR2RGBA, 4);
+    Mat rotMat = getRotationMatrix2D(Point2f(src.cols/2.f, src.rows/2.f), 30., 2.2);
+    Mat warpMat(3, 3, CV_64FC1);
+    for(int r=0; r<2; r++)
+        for(int c=0; c<3; c++)
+            warpMat.at<double>(r, c) = rotMat.at<double>(r, c);
+    warpMat.at<double>(2, 0) = .3/sz.width;
+    warpMat.at<double>(2, 1) = .3/sz.height;
+    warpMat.at<double>(2, 2) = 1;
+    Mat dst(sz, CV_8UC4);
+
+    declare.in(src).out(dst);
+
+    TEST_CYCLE() warpPerspective( src, dst, warpMat, sz, interType, borderMode, Scalar::all(150) );
+
+    SANITY_CHECK(dst);
+}
+
+PERF_TEST_P( TestRemap, remap,
+             Combine(
+                 Values( TYPICAL_MAT_TYPES ),
+                 Values( szVGA, sz720p, sz1080p ),
+                 ValuesIn( InterType::all() ),
+                 ValuesIn( BorderMode::all() ),
+                 ValuesIn( RemapMode::all() )
+                 )
+             )
+{
+    int type = get<0>(GetParam());
+    Size size = get<1>(GetParam());
+    int interpolationType = get<2>(GetParam());
+    int borderMode = get<3>(GetParam());
+    int remapMode = get<4>(GetParam());
+    unsigned int height = size.height;
+    unsigned int width = size.width;
+    Mat source(height, width, type);
+    Mat destination;
+    Mat map_x(height, width, CV_32F);
+    Mat map_y(height, width, CV_32F);
+
+    declare.in(source, WARMUP_RNG);
+
+    update_map(source, map_x, map_y, remapMode);
+
+    TEST_CYCLE()
+    {
+        remap(source, destination, map_x, map_y, interpolationType, borderMode);
+    }
+
+    SANITY_CHECK(destination, 1);
+}
+
+void update_map(const Mat& src, Mat& map_x, Mat& map_y, const int remapMode )
+{
+    for( int j = 0; j < src.rows; j++ )
+    {
+        for( int i = 0; i < src.cols; i++ )
+        {
+            switch( remapMode )
+            {
+            case HALF_SIZE:
+                if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
+                {
+                    map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;
+                    map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;
+                }
+                else
+                {
+                    map_x.at<float>(j,i) = 0 ;
+                    map_y.at<float>(j,i) = 0 ;
+                }
+                break;
+            case UPSIDE_DOWN:
+                map_x.at<float>(j,i) = i ;
+                map_y.at<float>(j,i) = src.rows - j ;
+                break;
+            case REFLECTION_X:
+                map_x.at<float>(j,i) = src.cols - i ;
+                map_y.at<float>(j,i) = j ;
+                break;
+            case REFLECTION_BOTH:
+                map_x.at<float>(j,i) = src.cols - i ;
+                map_y.at<float>(j,i) = src.rows - j ;
+                break;
+            } // end of switch
+        }
+    }
+}
+
+PERF_TEST(Transform, getPerspectiveTransform)
+{
+    unsigned int size = 8;
+    Mat source(1, size/2, CV_32FC2);
+    Mat destination(1, size/2, CV_32FC2);
+    Mat transformCoefficient;
+
+    declare.in(source, destination, WARMUP_RNG);
+
+    TEST_CYCLE()
+    {
+        transformCoefficient = getPerspectiveTransform(source, destination);
+    }
+}
+
diff --git a/modules/stitching/perf/perf_stich.cpp b/modules/stitching/perf/perf_stich.cpp
index bf62f8680..dd97bb278 100644
--- a/modules/stitching/perf/perf_stich.cpp
+++ b/modules/stitching/perf/perf_stich.cpp
@@ -1,134 +1,134 @@
-#include "perf_precomp.hpp"
-#include "opencv2/highgui/highgui.hpp"
-#include "opencv2/core/internal.hpp"
-#include "opencv2/flann/flann.hpp"
-#include "opencv2/opencv_modules.hpp"
-
-using namespace std;
-using namespace cv;
-using namespace perf;
-using std::tr1::make_tuple;
-using std::tr1::get;
-
-#define SURF_MATCH_CONFIDENCE 0.65f
-#define ORB_MATCH_CONFIDENCE  0.3f
-#define WORK_MEGAPIX 0.6
-
-typedef TestBaseWithParam<String> stitch;
-typedef TestBaseWithParam<String> match;
-
-#ifdef HAVE_OPENCV_NONFREE
-#define TEST_DETECTORS testing::Values("surf", "orb")
-#else
-#define TEST_DETECTORS testing::Values<String>("orb")
-#endif
-
-PERF_TEST_P(stitch, a123, TEST_DETECTORS)
-{
-    Mat pano;
-
-    vector<Mat> imgs;
-    imgs.push_back( imread( getDataPath("stitching/a1.jpg") ) );
-    imgs.push_back( imread( getDataPath("stitching/a2.jpg") ) );
-    imgs.push_back( imread( getDataPath("stitching/a3.jpg") ) );
-
-    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
-            ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder()
-            : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder();
-
-    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
-            ? new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE)
-            : new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
-
-    declare.time(30 * 20).iterations(20);
-
-    while(next())
-    {
-        Stitcher stitcher = Stitcher::createDefault();
-        stitcher.setFeaturesFinder(featuresFinder);
-        stitcher.setFeaturesMatcher(featuresMatcher);
-        stitcher.setWarper(new SphericalWarper());
-        stitcher.setRegistrationResol(WORK_MEGAPIX);
-
-        startTimer();
-        stitcher.stitch(imgs, pano);
-        stopTimer();
-    }
-}
-
-PERF_TEST_P(stitch, b12, TEST_DETECTORS)
-{
-    Mat pano;
-
-    vector<Mat> imgs;
-    imgs.push_back( imread( getDataPath("stitching/b1.jpg") ) );
-    imgs.push_back( imread( getDataPath("stitching/b2.jpg") ) );
-
-    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
-            ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder()
-            : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder();
-
-    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
-            ? new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE)
-            : new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
-
-    declare.time(30 * 20).iterations(20);
-
-    while(next())
-    {
-        Stitcher stitcher = Stitcher::createDefault();
-        stitcher.setFeaturesFinder(featuresFinder);
-        stitcher.setFeaturesMatcher(featuresMatcher);
-        stitcher.setWarper(new SphericalWarper());
-        stitcher.setRegistrationResol(WORK_MEGAPIX);
-
-        startTimer();
-        stitcher.stitch(imgs, pano);
-        stopTimer();
-    }
-}
-
-PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS)
-{
-    Mat img1, img1_full = imread( getDataPath("stitching/b1.jpg") );
-    Mat img2, img2_full = imread( getDataPath("stitching/b2.jpg") );
-    float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
-    float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
-    resize(img1_full, img1, Size(), scale1, scale1);
-    resize(img2_full, img2, Size(), scale2, scale2);
-
-    Ptr<detail::FeaturesFinder> finder;
-    Ptr<detail::FeaturesMatcher> matcher;
-    if (GetParam() == "surf")
-    {
-        finder = new detail::SurfFeaturesFinder();
-        matcher = new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
-    }
-    else if (GetParam() == "orb")
-    {
-        finder = new detail::OrbFeaturesFinder();
-        matcher = new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE);
-    }
-    else
-    {
-        FAIL() << "Unknown 2D features type: " << GetParam();
-    }
-
-    detail::ImageFeatures features1, features2;
-    (*finder)(img1, features1);
-    (*finder)(img2, features2);
-
-    detail::MatchesInfo pairwise_matches;
-
-    declare.in(features1.descriptors, features2.descriptors)
-            .iterations(100);
-
-    while(next())
-    {
-        cvflann::seed_random(42);//for predictive FlannBasedMatcher
-        startTimer();
-        (*matcher)(features1, features2, pairwise_matches);
-        stopTimer();
-        matcher->collectGarbage();
-    }
-}
+#include "perf_precomp.hpp"
+#include "opencv2/highgui/highgui.hpp"
+#include "opencv2/core/internal.hpp"
+#include "opencv2/flann/flann.hpp"
+#include "opencv2/opencv_modules.hpp"
+
+using namespace std;
+using namespace cv;
+using namespace perf;
+using std::tr1::make_tuple;
+using std::tr1::get;
+
+#define SURF_MATCH_CONFIDENCE 0.65f
+#define ORB_MATCH_CONFIDENCE  0.3f
+#define WORK_MEGAPIX 0.6
+
+typedef TestBaseWithParam<String> stitch;
+typedef TestBaseWithParam<String> match;
+
+#ifdef HAVE_OPENCV_NONFREE
+#define TEST_DETECTORS testing::Values("surf", "orb")
+#else
+#define TEST_DETECTORS testing::Values<String>("orb")
+#endif
+
+PERF_TEST_P(stitch, a123, TEST_DETECTORS)
+{
+    Mat pano;
+
+    vector<Mat> imgs;
+    imgs.push_back( imread( getDataPath("stitching/a1.jpg") ) );
+    imgs.push_back( imread( getDataPath("stitching/a2.jpg") ) );
+    imgs.push_back( imread( getDataPath("stitching/a3.jpg") ) );
+
+    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
+            ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder()
+            : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder();
+
+    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
+            ? new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE)
+            : new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
+
+    declare.time(30 * 20).iterations(20);
+
+    while(next())
+    {
+        Stitcher stitcher = Stitcher::createDefault();
+        stitcher.setFeaturesFinder(featuresFinder);
+        stitcher.setFeaturesMatcher(featuresMatcher);
+        stitcher.setWarper(new SphericalWarper());
+        stitcher.setRegistrationResol(WORK_MEGAPIX);
+
+        startTimer();
+        stitcher.stitch(imgs, pano);
+        stopTimer();
+    }
+}
+
+PERF_TEST_P(stitch, b12, TEST_DETECTORS)
+{
+    Mat pano;
+
+    vector<Mat> imgs;
+    imgs.push_back( imread( getDataPath("stitching/b1.jpg") ) );
+    imgs.push_back( imread( getDataPath("stitching/b2.jpg") ) );
+
+    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
+            ? (detail::FeaturesFinder*)new detail::OrbFeaturesFinder()
+            : (detail::FeaturesFinder*)new detail::SurfFeaturesFinder();
+
+    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
+            ? new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE)
+            : new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
+
+    declare.time(30 * 20).iterations(20);
+
+    while(next())
+    {
+        Stitcher stitcher = Stitcher::createDefault();
+        stitcher.setFeaturesFinder(featuresFinder);
+        stitcher.setFeaturesMatcher(featuresMatcher);
+        stitcher.setWarper(new SphericalWarper());
+        stitcher.setRegistrationResol(WORK_MEGAPIX);
+
+        startTimer();
+        stitcher.stitch(imgs, pano);
+        stopTimer();
+    }
+}
+
+PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS)
+{
+    Mat img1, img1_full = imread( getDataPath("stitching/b1.jpg") );
+    Mat img2, img2_full = imread( getDataPath("stitching/b2.jpg") );
+    float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
+    float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
+    resize(img1_full, img1, Size(), scale1, scale1);
+    resize(img2_full, img2, Size(), scale2, scale2);
+
+    Ptr<detail::FeaturesFinder> finder;
+    Ptr<detail::FeaturesMatcher> matcher;
+    if (GetParam() == "surf")
+    {
+        finder = new detail::SurfFeaturesFinder();
+        matcher = new detail::BestOf2NearestMatcher(false, SURF_MATCH_CONFIDENCE);
+    }
+    else if (GetParam() == "orb")
+    {
+        finder = new detail::OrbFeaturesFinder();
+        matcher = new detail::BestOf2NearestMatcher(false, ORB_MATCH_CONFIDENCE);
+    }
+    else
+    {
+        FAIL() << "Unknown 2D features type: " << GetParam();
+    }
+
+    detail::ImageFeatures features1, features2;
+    (*finder)(img1, features1);
+    (*finder)(img2, features2);
+
+    detail::MatchesInfo pairwise_matches;
+
+    declare.in(features1.descriptors, features2.descriptors)
+            .iterations(100);
+
+    while(next())
+    {
+        cvflann::seed_random(42);//for predictive FlannBasedMatcher
+        startTimer();
+        (*matcher)(features1, features2, pairwise_matches);
+        stopTimer();
+        matcher->collectGarbage();
+    }
+}
diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp
index 52934c4a0..cd389f1d8 100644
--- a/modules/ts/src/ts_perf.cpp
+++ b/modules/ts/src/ts_perf.cpp
@@ -1,1155 +1,1155 @@
-#include "precomp.hpp"
-
-#ifdef ANDROID
-# include <sys/time.h>
-#endif
-
-using namespace perf;
-
-int64 TestBase::timeLimitDefault = 0;
-unsigned int TestBase::iterationsLimitDefault = (unsigned int)(-1);
-int64 TestBase::_timeadjustment = 0;
-
-const char *command_line_keys =
-{
-    "{   |perf_max_outliers   |8        |percent of allowed outliers}"
-    "{   |perf_min_samples    |10       |minimal required numer of samples}"
-    "{   |perf_force_samples  |100      |force set maximum number of samples for all tests}"
-    "{   |perf_seed           |809564   |seed for random numbers generator}"
-    "{   |perf_tbb_nthreads   |-1       |if TBB is enabled, the number of TBB threads}"
-    "{   |perf_write_sanity   |false    |allow to create new records for sanity checks}"
-    #ifdef ANDROID
-    "{   |perf_time_limit     |6.0      |default time limit for a single test (in seconds)}"
-    "{   |perf_affinity_mask  |0        |set affinity mask for the main thread}"
-    "{   |perf_log_power_checkpoints  |false    |additional xml logging for power measurement}"
-    #else
-    "{   |perf_time_limit     |3.0      |default time limit for a single test (in seconds)}"
-    #endif
-    "{   |perf_max_deviation  |1.0      |}"
-    "{h  |help                |false    |}"
-};
-
-static double       param_max_outliers;
-static double       param_max_deviation;
-static unsigned int param_min_samples;
-static unsigned int param_force_samples;
-static uint64       param_seed;
-static double       param_time_limit;
-static int          param_tbb_nthreads;
-static bool         param_write_sanity;
-#ifdef ANDROID
-static int          param_affinity_mask;
-static bool         log_power_checkpoints;
-
-#include <sys/syscall.h>
-#include <pthread.h>
-static void setCurrentThreadAffinityMask(int mask)
-{
-    pid_t pid=gettid();
-    int syscallres=syscall(__NR_sched_setaffinity, pid, sizeof(mask), &mask);
-    if (syscallres)
-    {
-        int err=errno;
-        err=err;//to avoid warnings about unused variables
-        LOGE("Error in the syscall setaffinity: mask=%d=0x%x err=%d=0x%x", mask, mask, err, err);
-    }
-}
-
-#endif
-
-static void randu(cv::Mat& m)
-{
-    const int bigValue = 0x00000FFF;
-    if (m.depth() < CV_32F)
-    {
-        int minmax[] = {0, 256};
-        cv::Mat mr = cv::Mat(m.rows, (int)(m.cols * m.elemSize()), CV_8U, m.ptr(), m.step[0]);
-        cv::randu(mr, cv::Mat(1, 1, CV_32S, minmax), cv::Mat(1, 1, CV_32S, minmax + 1));
-    }
-    else if (m.depth() == CV_32F)
-    {
-        //float minmax[] = {-FLT_MAX, FLT_MAX};
-        float minmax[] = {-bigValue, bigValue};
-        cv::Mat mr = m.reshape(1);
-        cv::randu(mr, cv::Mat(1, 1, CV_32F, minmax), cv::Mat(1, 1, CV_32F, minmax + 1));
-    }
-    else
-    {
-        //double minmax[] = {-DBL_MAX, DBL_MAX};
-        double minmax[] = {-bigValue, bigValue};
-        cv::Mat mr = m.reshape(1);
-        cv::randu(mr, cv::Mat(1, 1, CV_64F, minmax), cv::Mat(1, 1, CV_64F, minmax + 1));
-    }
-}
-
-/*****************************************************************************************\
-*                       inner exception class for early termination
-\*****************************************************************************************/
-
-class PerfEarlyExitException: public cv::Exception {};
-
-/*****************************************************************************************\
-*                                   ::perf::Regression
-\*****************************************************************************************/
-
-Regression& Regression::instance()
-{
-    static Regression single;
-    return single;
-}
-
-Regression& Regression::add(const std::string& name, cv::InputArray array, double eps, ERROR_TYPE err)
-{
-    return instance()(name, array, eps, err);
-}
-
-void Regression::Init(const std::string& testSuitName, const std::string& ext)
-{
-    instance().init(testSuitName, ext);
-}
-
-void Regression::init(const std::string& testSuitName, const std::string& ext)
-{
-    if (!storageInPath.empty())
-    {
-        LOGE("Subsequent initialisation of Regression utility is not allowed.");
-        return;
-    }
-
-    const char *data_path_dir = getenv("OPENCV_TEST_DATA_PATH");
-    const char *path_separator = "/";
-
-    if (data_path_dir)
-    {
-        int len = (int)strlen(data_path_dir)-1;
-        if (len < 0) len = 0;
-        std::string path_base = (data_path_dir[0] == 0 ? std::string(".") : std::string(data_path_dir))
-                + (data_path_dir[len] == '/' || data_path_dir[len] == '\\' ? "" : path_separator)
-                + "perf"
-                + path_separator;
-
-        storageInPath = path_base + testSuitName + ext;
-        storageOutPath = path_base + testSuitName;
-    }
-    else
-    {
-        storageInPath = testSuitName + ext;
-        storageOutPath = testSuitName;
-    }
-
-    try
-    {
-        if (storageIn.open(storageInPath, cv::FileStorage::READ))
-        {
-            rootIn = storageIn.root();
-            if (storageInPath.length() > 3 && storageInPath.substr(storageInPath.length()-3) == ".gz")
-                storageOutPath += "_new";
-            storageOutPath += ext;
-        }
-    }
-    catch(cv::Exception&)
-    {
-        LOGE("Failed to open sanity data for reading: %s", storageInPath.c_str());
-    }
-
-    if(!storageIn.isOpened())
-        storageOutPath = storageInPath;
-}
-
-Regression::Regression() : regRNG(cv::getTickCount())//this rng should be really random
-{
-}
-
-Regression::~Regression()
-{
-    if (storageIn.isOpened())
-        storageIn.release();
-    if (storageOut.isOpened())
-    {
-        if (!currentTestNodeName.empty())
-            storageOut << "}";
-        storageOut.release();
-    }
-}
-
-cv::FileStorage& Regression::write()
-{
-    if (!storageOut.isOpened() && !storageOutPath.empty())
-    {
-        int mode = (storageIn.isOpened() && storageInPath == storageOutPath)
-                ? cv::FileStorage::APPEND : cv::FileStorage::WRITE;
-        storageOut.open(storageOutPath, mode);
-        if (!storageOut.isOpened())
-        {
-            LOGE("Could not open \"%s\" file for writing", storageOutPath.c_str());
-            storageOutPath.clear();
-        }
-        else if (mode == cv::FileStorage::WRITE && !rootIn.empty())
-        {
-            //TODO: write content of rootIn node into the storageOut
-        }
-    }
-    return storageOut;
-}
-
-std::string Regression::getCurrentTestNodeName()
-{
-    const ::testing::TestInfo* const test_info =
-      ::testing::UnitTest::GetInstance()->current_test_info();
-
-    if (test_info == 0)
-        return "undefined";
-
-    std::string nodename = std::string(test_info->test_case_name()) + "--" + test_info->name();
-    size_t idx = nodename.find_first_of('/');
-    if (idx != std::string::npos)
-        nodename.erase(idx);
-
-    const char* type_param = test_info->type_param();
-    if (type_param != 0)
-        (nodename += "--") += type_param;
-
-    const char* value_param = test_info->value_param();
-    if (value_param != 0)
-        (nodename += "--") += value_param;
-
-    for(size_t i = 0; i < nodename.length(); ++i)
-        if (!isalnum(nodename[i]) && '_' != nodename[i])
-            nodename[i] = '-';
-
-    return nodename;
-}
-
-bool Regression::isVector(cv::InputArray a)
-{
-    return a.kind() == cv::_InputArray::STD_VECTOR_MAT || a.kind() == cv::_InputArray::STD_VECTOR_VECTOR;
-}
-
-double Regression::getElem(cv::Mat& m, int y, int x, int cn)
-{
-    switch (m.depth())
-    {
-    case CV_8U: return *(m.ptr<unsigned char>(y, x) + cn);
-    case CV_8S: return *(m.ptr<signed char>(y, x) + cn);
-    case CV_16U: return *(m.ptr<unsigned short>(y, x) + cn);
-    case CV_16S: return *(m.ptr<signed short>(y, x) + cn);
-    case CV_32S: return *(m.ptr<signed int>(y, x) + cn);
-    case CV_32F: return *(m.ptr<float>(y, x) + cn);
-    case CV_64F: return *(m.ptr<double>(y, x) + cn);
-    default: return 0;
-    }
-}
-
-void Regression::write(cv::Mat m)
-{
-    double min, max;
-    cv::minMaxLoc(m, &min, &max);
-    write() << "min" << min << "max" << max;
-
-    write() << "last" << "{" << "x" << m.cols-1 << "y" << m.rows-1
-        << "val" << getElem(m, m.rows-1, m.cols-1, m.channels()-1) << "}";
-
-    int x, y, cn;
-    x = regRNG.uniform(0, m.cols);
-    y = regRNG.uniform(0, m.rows);
-    cn = regRNG.uniform(0, m.channels());
-    write() << "rng1" << "{" << "x" << x << "y" << y;
-    if(cn > 0) write() << "cn" << cn;
-    write() << "val" << getElem(m, y, x, cn) << "}";
-
-    x = regRNG.uniform(0, m.cols);
-    y = regRNG.uniform(0, m.rows);
-    cn = regRNG.uniform(0, m.channels());
-    write() << "rng2" << "{" << "x" << x << "y" << y;
-    if (cn > 0) write() << "cn" << cn;
-    write() << "val" << getElem(m, y, x, cn) << "}";
-}
-
-static double evalEps(double expected, double actual, double _eps, ERROR_TYPE err)
-{
-    if (err == ERROR_ABSOLUTE)
-        return _eps;
-    else if (err == ERROR_RELATIVE)
-        return std::max(std::abs(expected), std::abs(actual)) * err;
-    return 0;
-}
-
-void Regression::verify(cv::FileNode node, cv::Mat actual, double _eps, std::string argname, ERROR_TYPE err)
-{
-    double actual_min, actual_max;
-    cv::minMaxLoc(actual, &actual_min, &actual_max);
-
-    double eps = evalEps((double)node["min"], actual_min, _eps, err);
-    ASSERT_NEAR((double)node["min"], actual_min, eps)
-            << "  " << argname << " has unexpected minimal value";
-
-    eps = evalEps((double)node["max"], actual_max, _eps, err);
-    ASSERT_NEAR((double)node["max"], actual_max, eps)
-            << "  " << argname << " has unexpected maximal value";
-
-    cv::FileNode last = node["last"];
-    double actualLast = getElem(actual, actual.rows - 1, actual.cols - 1, actual.channels() - 1);
-    ASSERT_EQ((int)last["x"], actual.cols - 1)
-            << "  " << argname << " has unexpected number of columns";
-    ASSERT_EQ((int)last["y"], actual.rows - 1)
-            << "  " << argname << " has unexpected number of rows";
-
-    eps = evalEps((double)last["val"], actualLast, _eps, err);
-    ASSERT_NEAR((double)last["val"], actualLast, eps)
-            << "  " << argname << " has unexpected value of last element";
-
-    cv::FileNode rng1 = node["rng1"];
-    int x1 = rng1["x"];
-    int y1 = rng1["y"];
-    int cn1 = rng1["cn"];
-
-    eps = evalEps((double)rng1["val"], getElem(actual, y1, x1, cn1), _eps, err);
-    ASSERT_NEAR((double)rng1["val"], getElem(actual, y1, x1, cn1), eps)
-            << "  " << argname << " has unexpected value of ["<< x1 << ":" << y1 << ":" << cn1 <<"] element";
-
-    cv::FileNode rng2 = node["rng2"];
-    int x2 = rng2["x"];
-    int y2 = rng2["y"];
-    int cn2 = rng2["cn"];
-
-    eps = evalEps((double)rng2["val"], getElem(actual, y2, x2, cn2), _eps, err);
-    ASSERT_NEAR((double)rng2["val"], getElem(actual, y2, x2, cn2), eps)
-            << "  " << argname << " has unexpected value of ["<< x2 << ":" << y2 << ":" << cn2 <<"] element";
-}
-
-void Regression::write(cv::InputArray array)
-{
-    write() << "kind" << array.kind();
-    write() << "type" << array.type();
-    if (isVector(array))
-    {
-        int total = (int)array.total();
-        int idx = regRNG.uniform(0, total);
-        write() << "len" << total;
-        write() << "idx" << idx;
-
-        cv::Mat m = array.getMat(idx);
-
-        if (m.total() * m.channels() < 26) //5x5 or smaller
-            write() << "val" << m;
-        else
-            write(m);
-    }
-    else
-    {
-        if (array.total() * array.channels() < 26) //5x5 or smaller
-            write() << "val" << array.getMat();
-        else
-            write(array.getMat());
-    }
-}
-
-static int countViolations(const cv::Mat& expected, const cv::Mat& actual, const cv::Mat& diff, double eps, double* max_violation = 0, double* max_allowed = 0)
-{
-    cv::Mat diff64f;
-    diff.reshape(1).convertTo(diff64f, CV_64F);
-
-    cv::Mat expected_abs = cv::abs(expected.reshape(1));
-    cv::Mat actual_abs = cv::abs(actual.reshape(1));
-    cv::Mat maximum, mask;
-    cv::max(expected_abs, actual_abs, maximum);
-    cv::multiply(maximum, cv::Vec<double, 1>(eps), maximum, CV_64F);
-    cv::compare(diff64f, maximum, mask, cv::CMP_GT);
-
-    int v = cv::countNonZero(mask);
-
-    if (v > 0 && max_violation != 0 && max_allowed != 0)
-    {
-        int loc[10];
-        cv::minMaxIdx(maximum, 0, max_allowed, 0, loc, mask);
-        *max_violation = diff64f.at<double>(loc[1], loc[0]);
-    }
-
-    return v;
-}
-
-void Regression::verify(cv::FileNode node, cv::InputArray array, double eps, ERROR_TYPE err)
-{
-    ASSERT_EQ((int)node["kind"], array.kind()) << "  Argument \"" << node.name() << "\" has unexpected kind";
-    ASSERT_EQ((int)node["type"], array.type()) << "  Argument \"" << node.name() << "\" has unexpected type";
-
-    cv::FileNode valnode = node["val"];
-    if (isVector(array))
-    {
-        ASSERT_EQ((int)node["len"], (int)array.total()) << "  Vector \"" << node.name() << "\" has unexpected length";
-        int idx = node["idx"];
-
-        cv::Mat actual = array.getMat(idx);
-
-        if (valnode.isNone())
-        {
-            ASSERT_LE((size_t)26, actual.total() * (size_t)actual.channels())
-                    << "  \"" << node.name() << "[" <<  idx << "]\" has unexpected number of elements";
-            verify(node, actual, eps, cv::format("%s[%d]", node.name().c_str(), idx), err);
-        }
-        else
-        {
-            cv::Mat expected;
-            valnode >> expected;
-
-            ASSERT_EQ(expected.size(), actual.size())
-                    << "  " << node.name() << "[" <<  idx<< "] has unexpected size";
-
-            cv::Mat diff;
-            cv::absdiff(expected, actual, diff);
-
-            if (err == ERROR_ABSOLUTE)
-            {
-                if (!cv::checkRange(diff, true, 0, 0, eps))
-                {
-                    double max;
-                    cv::minMaxLoc(diff.reshape(1), 0, &max);
-                    FAIL() << "  Absolute difference (=" << max << ") between argument \""
-                           << node.name() << "[" <<  idx << "]\" and expected value is bugger than " << eps;
-                }
-            }
-            else if (err == ERROR_RELATIVE)
-            {
-                double maxv, maxa;
-                int violations = countViolations(expected, actual, diff, eps, &maxv, &maxa);
-                if (violations > 0)
-                {
-                    FAIL() << "  Relative difference (" << maxv << " of " << maxa << " allowed) between argument \""
-                           << node.name() << "[" <<  idx << "]\" and expected value is bugger than " << eps << " in " << violations << " points";
-                }
-            }
-        }
-    }
-    else
-    {
-        if (valnode.isNone())
-        {
-            ASSERT_LE((size_t)26, array.total() * (size_t)array.channels())
-                    << "  Argument \"" << node.name() << "\" has unexpected number of elements";
-            verify(node, array.getMat(), eps, "Argument " + node.name(), err);
-        }
-        else
-        {
-            cv::Mat expected;
-            valnode >> expected;
-            cv::Mat actual = array.getMat();
-
-            ASSERT_EQ(expected.size(), actual.size())
-                    << "  Argument \"" << node.name() << "\" has unexpected size";
-
-            cv::Mat diff;
-            cv::absdiff(expected, actual, diff);
-
-            if (err == ERROR_ABSOLUTE)
-            {
-                if (!cv::checkRange(diff, true, 0, 0, eps))
-                {
-                    double max;
-                    cv::minMaxLoc(diff.reshape(1), 0, &max);
-                    FAIL() << "  Difference (=" << max << ") between argument \"" << node.name()
-                           << "\" and expected value is bugger than " << eps;
-                }
-            }
-            else if (err == ERROR_RELATIVE)
-            {
-                double maxv, maxa;
-                int violations = countViolations(expected, actual, diff, eps, &maxv, &maxa);
-                if (violations > 0)
-                {
-                    FAIL() << "  Relative difference (" << maxv << " of " << maxa << " allowed) between argument \"" << node.name()
-                           << "\" and expected value is bugger than " << eps << " in " << violations << " points";
-                }
-            }
-        }
-    }
-}
-
-Regression& Regression::operator() (const std::string& name, cv::InputArray array, double eps, ERROR_TYPE err)
-{
-    std::string nodename = getCurrentTestNodeName();
-
-    cv::FileNode n = rootIn[nodename];
-    if(n.isNone())
-    {
-        if(param_write_sanity)
-        {
-            if (nodename != currentTestNodeName)
-            {
-                if (!currentTestNodeName.empty())
-                    write() << "}";
-                currentTestNodeName = nodename;
-
-                write() << nodename << "{";
-            }
-            write() << name << "{";
-            write(array);
-            write() << "}";
-        }
-    }
-    else
-    {
-        cv::FileNode this_arg = n[name];
-        if (!this_arg.isMap())
-            ADD_FAILURE() << "  No regression data for " << name << " argument";
-        else
-            verify(this_arg, array, eps, err);
-    }
-    return *this;
-}
-
-
-/*****************************************************************************************\
-*                                ::perf::performance_metrics
-\*****************************************************************************************/
-performance_metrics::performance_metrics()
-{
-    bytesIn = 0;
-    bytesOut = 0;
-    samples = 0;
-    outliers = 0;
-    gmean = 0;
-    gstddev = 0;
-    mean = 0;
-    stddev = 0;
-    median = 0;
-    min = 0;
-    frequency = 0;
-    terminationReason = TERM_UNKNOWN;
-}
-
-
-/*****************************************************************************************\
-*                                   ::perf::TestBase
-\*****************************************************************************************/
-
-
-void TestBase::Init(int argc, const char* const argv[])
-{
-    cv::CommandLineParser args(argc, argv, command_line_keys);
-    param_max_outliers = std::min(100., std::max(0., args.get<double>("perf_max_outliers")));
-    param_min_samples  = std::max(1u, args.get<unsigned int>("perf_min_samples"));
-    param_max_deviation = std::max(0., args.get<double>("perf_max_deviation"));
-    param_seed = args.get<uint64>("perf_seed");
-    param_time_limit = std::max(0., args.get<double>("perf_time_limit"));
-    param_force_samples = args.get<unsigned int>("perf_force_samples");
-    param_write_sanity = args.get<bool>("perf_write_sanity");
-    param_tbb_nthreads  = args.get<int>("perf_tbb_nthreads");
-#ifdef ANDROID
-    param_affinity_mask = args.get<int>("perf_affinity_mask");
-    log_power_checkpoints = args.get<bool>("perf_log_power_checkpoints");
-#endif
-
-    if (args.get<bool>("help"))
-    {
-        args.printParams();
-        printf("\n\n");
-        return;
-    }
-
-    timeLimitDefault = param_time_limit == 0.0 ? 1 : (int64)(param_time_limit * cv::getTickFrequency());
-    iterationsLimitDefault = param_force_samples == 0 ? (unsigned)(-1) : param_force_samples;
-    _timeadjustment = _calibrate();
-}
-
-int64 TestBase::_calibrate()
-{
-    class _helper : public ::perf::TestBase
-    {
-        public:
-        performance_metrics& getMetrics() { return calcMetrics(); }
-        virtual void TestBody() {}
-        virtual void PerfTestBody()
-        {
-            //the whole system warmup
-            SetUp();
-            cv::Mat a(2048, 2048, CV_32S, cv::Scalar(1));
-            cv::Mat b(2048, 2048, CV_32S, cv::Scalar(2));
-            declare.time(30);
-            double s = 0;
-            for(declare.iterations(20); startTimer(), next(); stopTimer())
-                s+=a.dot(b);
-            declare.time(s);
-
-            //self calibration
-            SetUp();
-            for(declare.iterations(1000); startTimer(), next(); stopTimer()){}
-        }
-    };
-
-    _timeadjustment = 0;
-    _helper h;
-    h.PerfTestBody();
-    double compensation = h.getMetrics().min;
-    LOGD("Time compensation is %.0f", compensation);
-    return (int64)compensation;
-}
-
-#ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable:4355)  // 'this' : used in base member initializer list
-#endif
-TestBase::TestBase(): declare(this)
-{
-}
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
-
-
-void TestBase::declareArray(SizeVector& sizes, cv::InputOutputArray a, int wtype)
-{
-    if (!a.empty())
-    {
-        sizes.push_back(std::pair<int, cv::Size>(getSizeInBytes(a), getSize(a)));
-        warmup(a, wtype);
-    }
-    else if (a.kind() != cv::_InputArray::NONE)
-        ADD_FAILURE() << "  Uninitialized input/output parameters are not allowed for performance tests";
-}
-
-void TestBase::warmup(cv::InputOutputArray a, int wtype)
-{
-    if (a.empty()) return;
-    if (a.kind() != cv::_InputArray::STD_VECTOR_MAT && a.kind() != cv::_InputArray::STD_VECTOR_VECTOR)
-        warmup_impl(a.getMat(), wtype);
-    else
-    {
-        size_t total = a.total();
-        for (size_t i = 0; i < total; ++i)
-            warmup_impl(a.getMat((int)i), wtype);
-    }
-}
-
-int TestBase::getSizeInBytes(cv::InputArray a)
-{
-    if (a.empty()) return 0;
-    int total = (int)a.total();
-    if (a.kind() != cv::_InputArray::STD_VECTOR_MAT && a.kind() != cv::_InputArray::STD_VECTOR_VECTOR)
-        return total * CV_ELEM_SIZE(a.type());
-
-    int size = 0;
-    for (int i = 0; i < total; ++i)
-        size += (int)a.total(i) * CV_ELEM_SIZE(a.type(i));
-
-    return size;
-}
-
-cv::Size TestBase::getSize(cv::InputArray a)
-{
-    if (a.kind() != cv::_InputArray::STD_VECTOR_MAT && a.kind() != cv::_InputArray::STD_VECTOR_VECTOR)
-        return a.size();
-    return cv::Size();
-}
-
-bool TestBase::next()
-{
-    bool has_next = ++currentIter < nIters && totalTime < timeLimit;
-#ifdef ANDROID
-    if (log_power_checkpoints)
-    {
-        timeval tim;
-        gettimeofday(&tim, NULL);
-        unsigned long long t1 = tim.tv_sec * 1000LLU + (unsigned long long)(tim.tv_usec / 1000.f);
-
-        if (currentIter == 1) RecordProperty("test_start", cv::format("%llu",t1).c_str());
-        if (!has_next) RecordProperty("test_complete", cv::format("%llu",t1).c_str());
-    }
-#endif
-    return has_next;
-}
-
-void TestBase::warmup_impl(cv::Mat m, int wtype)
-{
-    switch(wtype)
-    {
-    case WARMUP_READ:
-        cv::sum(m.reshape(1));
-        return;
-    case WARMUP_WRITE:
-        m.reshape(1).setTo(cv::Scalar::all(0));
-        return;
-    case WARMUP_RNG:
-        randu(m);
-        return;
-    default:
-        return;
-    }
-}
-
-unsigned int TestBase::getTotalInputSize() const
-{
-    unsigned int res = 0;
-    for (SizeVector::const_iterator i = inputData.begin(); i != inputData.end(); ++i)
-        res += i->first;
-    return res;
-}
-
-unsigned int TestBase::getTotalOutputSize() const
-{
-    unsigned int res = 0;
-    for (SizeVector::const_iterator i = outputData.begin(); i != outputData.end(); ++i)
-        res += i->first;
-    return res;
-}
-
-void TestBase::startTimer()
-{
-    lastTime = cv::getTickCount();
-}
-
-void TestBase::stopTimer()
-{
-    int64 time = cv::getTickCount();
-    if (lastTime == 0)
-        ADD_FAILURE() << "  stopTimer() is called before startTimer()";
-    lastTime = time - lastTime;
-    totalTime += lastTime;
-    lastTime -= _timeadjustment;
-    if (lastTime < 0) lastTime = 0;
-    times.push_back(lastTime);
-    lastTime = 0;
-}
-
-performance_metrics& TestBase::calcMetrics()
-{
-    if ((metrics.samples == (unsigned int)currentIter) || times.size() == 0)
-        return metrics;
-
-    metrics.bytesIn = getTotalInputSize();
-    metrics.bytesOut = getTotalOutputSize();
-    metrics.frequency = cv::getTickFrequency();
-    metrics.samples = (unsigned int)times.size();
-    metrics.outliers = 0;
-
-    if (metrics.terminationReason != performance_metrics::TERM_INTERRUPT && metrics.terminationReason != performance_metrics::TERM_EXCEPTION)
-    {
-        if (currentIter == nIters)
-            metrics.terminationReason = performance_metrics::TERM_ITERATIONS;
-        else if (totalTime >= timeLimit)
-            metrics.terminationReason = performance_metrics::TERM_TIME;
-        else
-            metrics.terminationReason = performance_metrics::TERM_UNKNOWN;
-    }
-
-    std::sort(times.begin(), times.end());
-
-    //estimate mean and stddev for log(time)
-    double gmean = 0;
-    double gstddev = 0;
-    int n = 0;
-    for(TimeVector::const_iterator i = times.begin(); i != times.end(); ++i)
-    {
-        double x = static_cast<double>(*i)/runsPerIteration;
-        if (x < DBL_EPSILON) continue;
-        double lx = log(x);
-
-        ++n;
-        double delta = lx - gmean;
-        gmean += delta / n;
-        gstddev += delta * (lx - gmean);
-    }
-
-    gstddev = n > 1 ? sqrt(gstddev / (n - 1)) : 0;
-
-    TimeVector::const_iterator start = times.begin();
-    TimeVector::const_iterator end = times.end();
-
-    //filter outliers assuming log-normal distribution
-    //http://stackoverflow.com/questions/1867426/modeling-distribution-of-performance-measurements
-    int offset = 0;
-    if (gstddev > DBL_EPSILON)
-    {
-        double minout = exp(gmean - 3 * gstddev) * runsPerIteration;
-        double maxout = exp(gmean + 3 * gstddev) * runsPerIteration;
-        while(*start < minout) ++start, ++metrics.outliers, ++offset;
-        do --end, ++metrics.outliers; while(*end > maxout);
-        ++end, --metrics.outliers;
-    }
-
-    metrics.min = static_cast<double>(*start)/runsPerIteration;
-    //calc final metrics
-    n = 0;
-    gmean = 0;
-    gstddev = 0;
-    double mean = 0;
-    double stddev = 0;
-    int m = 0;
-    for(; start != end; ++start)
-    {
-        double x = static_cast<double>(*start)/runsPerIteration;
-        if (x > DBL_EPSILON)
-        {
-            double lx = log(x);
-            ++m;
-            double gdelta = lx - gmean;
-            gmean += gdelta / m;
-            gstddev += gdelta * (lx - gmean);
-        }
-        ++n;
-        double delta = x - mean;
-        mean += delta / n;
-        stddev += delta * (x - mean);
-    }
-
-    metrics.mean = mean;
-    metrics.gmean = exp(gmean);
-    metrics.gstddev = m > 1 ? sqrt(gstddev / (m - 1)) : 0;
-    metrics.stddev = n > 1 ? sqrt(stddev / (n - 1)) : 0;
-    metrics.median = n % 2
-            ? (double)times[offset + n / 2]
-            : 0.5 * (times[offset + n / 2] + times[offset + n / 2 - 1]);
-
-    metrics.median /= runsPerIteration;
-
-    return metrics;
-}
-
-void TestBase::validateMetrics()
-{
-    performance_metrics& m = calcMetrics();
-
-    if (HasFailure()) return;
-
-    ASSERT_GE(m.samples, 1u)
-      << "  No time measurements was performed.\nstartTimer() and stopTimer() commands are required for performance tests.";
-
-    EXPECT_GE(m.samples, param_min_samples)
-      << "  Only a few samples are collected.\nPlease increase number of iterations or/and time limit to get reliable performance measurements.";
-
-    if (m.gstddev > DBL_EPSILON)
-    {
-        EXPECT_GT(/*m.gmean * */1., /*m.gmean * */ 2 * sinh(m.gstddev * param_max_deviation))
-          << "  Test results are not reliable ((mean-sigma,mean+sigma) deviation interval is bigger than measured time interval).";
-    }
-
-    EXPECT_LE(m.outliers, std::max((unsigned int)cvCeil(m.samples * param_max_outliers / 100.), 1u))
-      << "  Test results are not reliable (too many outliers).";
-}
-
-void TestBase::reportMetrics(bool toJUnitXML)
-{
-    performance_metrics& m = calcMetrics();
-
-    if (toJUnitXML)
-    {
-        RecordProperty("bytesIn", (int)m.bytesIn);
-        RecordProperty("bytesOut", (int)m.bytesOut);
-        RecordProperty("term", m.terminationReason);
-        RecordProperty("samples", (int)m.samples);
-        RecordProperty("outliers", (int)m.outliers);
-        RecordProperty("frequency", cv::format("%.0f", m.frequency).c_str());
-        RecordProperty("min", cv::format("%.0f", m.min).c_str());
-        RecordProperty("median", cv::format("%.0f", m.median).c_str());
-        RecordProperty("gmean", cv::format("%.0f", m.gmean).c_str());
-        RecordProperty("gstddev", cv::format("%.6f", m.gstddev).c_str());
-        RecordProperty("mean", cv::format("%.0f", m.mean).c_str());
-        RecordProperty("stddev", cv::format("%.0f", m.stddev).c_str());
-    }
-    else
-    {
-        const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info();
-        const char* type_param = test_info->type_param();
-        const char* value_param = test_info->value_param();
-
-#if defined(ANDROID) && defined(USE_ANDROID_LOGGING)
-        LOGD("[ FAILED   ] %s.%s", test_info->test_case_name(), test_info->name());
-#endif
-
-        if (type_param)  LOGD("type      = %11s", type_param);
-        if (value_param) LOGD("params    = %11s", value_param);
-
-        switch (m.terminationReason)
-        {
-        case performance_metrics::TERM_ITERATIONS:
-            LOGD("termination reason:  reached maximum number of iterations");
-            break;
-        case performance_metrics::TERM_TIME:
-            LOGD("termination reason:  reached time limit");
-            break;
-        case performance_metrics::TERM_INTERRUPT:
-            LOGD("termination reason:  aborted by the performance testing framework");
-            break;
-        case performance_metrics::TERM_EXCEPTION:
-            LOGD("termination reason:  unhandled exception");
-            break;
-        case performance_metrics::TERM_UNKNOWN:
-        default:
-            LOGD("termination reason:  unknown");
-            break;
-        };
-
-        LOGD("bytesIn   =%11lu", (unsigned long)m.bytesIn);
-        LOGD("bytesOut  =%11lu", (unsigned long)m.bytesOut);
-        if (nIters == (unsigned int)-1 || m.terminationReason == performance_metrics::TERM_ITERATIONS)
-            LOGD("samples   =%11u",  m.samples);
-        else
-            LOGD("samples   =%11u of %u", m.samples, nIters);
-        LOGD("outliers  =%11u", m.outliers);
-        LOGD("frequency =%11.0f", m.frequency);
-        if (m.samples > 0)
-        {
-            LOGD("min       =%11.0f = %.2fms", m.min, m.min * 1e3 / m.frequency);
-            LOGD("median    =%11.0f = %.2fms", m.median, m.median * 1e3 / m.frequency);
-            LOGD("gmean     =%11.0f = %.2fms", m.gmean, m.gmean * 1e3 / m.frequency);
-            LOGD("gstddev   =%11.8f = %.2fms for 97%% dispersion interval", m.gstddev, m.gmean * 2 * sinh(m.gstddev * 3) * 1e3 / m.frequency);
-            LOGD("mean      =%11.0f = %.2fms", m.mean, m.mean * 1e3 / m.frequency);
-            LOGD("stddev    =%11.0f = %.2fms", m.stddev, m.stddev * 1e3 / m.frequency);
-        }
-    }
-}
-
-void TestBase::SetUp()
-{
-#ifdef HAVE_TBB
-    if (param_tbb_nthreads > 0) {
-        p_tbb_initializer.release();
-        p_tbb_initializer=new tbb::task_scheduler_init(param_tbb_nthreads);
-    }
-#endif
-#ifdef ANDROID
-    if (param_affinity_mask)
-        setCurrentThreadAffinityMask(param_affinity_mask);
-#endif
-    lastTime = 0;
-    totalTime = 0;
-    runsPerIteration = 1;
-    nIters = iterationsLimitDefault;
-    currentIter = (unsigned int)-1;
-    timeLimit = timeLimitDefault;
-    times.clear();
-    cv::theRNG().state = param_seed;//this rng should generate same numbers for each run
-}
-
-void TestBase::TearDown()
-{
-    validateMetrics();
-    if (HasFailure())
-        reportMetrics(false);
-    else
-    {
-        const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info();
-        const char* type_param = test_info->type_param();
-        const char* value_param = test_info->value_param();
-        if (value_param) printf("[ VALUE    ] \t%s\n", value_param), fflush(stdout);
-        if (type_param)  printf("[ TYPE     ] \t%s\n", type_param), fflush(stdout);
-        reportMetrics(true);
-    }
-#ifdef HAVE_TBB
-    p_tbb_initializer.release();
-#endif
-}
-
-std::string TestBase::getDataPath(const std::string& relativePath)
-{
-    if (relativePath.empty())
-    {
-        ADD_FAILURE() << "  Bad path to test resource";
-        throw PerfEarlyExitException();
-    }
-
-    const char *data_path_dir = getenv("OPENCV_TEST_DATA_PATH");
-    const char *path_separator = "/";
-
-    std::string path;
-    if (data_path_dir)
-    {
-        int len = (int)strlen(data_path_dir) - 1;
-        if (len < 0) len = 0;
-        path = (data_path_dir[0] == 0 ? std::string(".") : std::string(data_path_dir))
-                + (data_path_dir[len] == '/' || data_path_dir[len] == '\\' ? "" : path_separator);
-    }
-    else
-    {
-        path = ".";
-        path += path_separator;
-    }
-
-    if (relativePath[0] == '/' || relativePath[0] == '\\')
-        path += relativePath.substr(1);
-    else
-        path += relativePath;
-
-    FILE* fp = fopen(path.c_str(), "r");
-    if (fp)
-        fclose(fp);
-    else
-    {
-        ADD_FAILURE() << "  Requested file \"" << path << "\" does not exist.";
-        throw PerfEarlyExitException();
-    }
-    return path;
-}
-
-void TestBase::RunPerfTestBody()
-{
-    try
-    {
-        this->PerfTestBody();
-    }
-    catch(PerfEarlyExitException)
-    {
-        metrics.terminationReason = performance_metrics::TERM_INTERRUPT;
-        return;//no additional failure logging
-    }
-    catch(cv::Exception e)
-    {
-        metrics.terminationReason = performance_metrics::TERM_EXCEPTION;
-        FAIL() << "Expected: PerfTestBody() doesn't throw an exception.\n  Actual: it throws:\n  " << e.what();
-    }
-    catch(...)
-    {
-        metrics.terminationReason = performance_metrics::TERM_EXCEPTION;
-        FAIL() << "Expected: PerfTestBody() doesn't throw an exception.\n  Actual: it throws.";
-    }
-}
-
-/*****************************************************************************************\
-*                          ::perf::TestBase::_declareHelper
-\*****************************************************************************************/
-TestBase::_declareHelper& TestBase::_declareHelper::iterations(unsigned int n)
-{
-    test->times.clear();
-    test->times.reserve(n);
-    test->nIters = std::min(n, TestBase::iterationsLimitDefault);
-    test->currentIter = (unsigned int)-1;
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::time(double timeLimitSecs)
-{
-    test->times.clear();
-    test->currentIter = (unsigned int)-1;
-    test->timeLimit = (int64)(timeLimitSecs * cv::getTickFrequency());
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::tbb_threads(int n)
-{
-#ifdef HAVE_TBB
-    test->p_tbb_initializer.release();
-    if (n > 0)
-        test->p_tbb_initializer=new tbb::task_scheduler_init(n);
-#endif
-    (void)n;
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::runs(unsigned int runsNumber)
-{
-    test->runsPerIteration = runsNumber;
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::in(cv::InputOutputArray a1, int wtype)
-{
-    if (!test->times.empty()) return *this;
-    TestBase::declareArray(test->inputData, a1, wtype);
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::in(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype)
-{
-    if (!test->times.empty()) return *this;
-    TestBase::declareArray(test->inputData, a1, wtype);
-    TestBase::declareArray(test->inputData, a2, wtype);
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype)
-{
-    if (!test->times.empty()) return *this;
-    TestBase::declareArray(test->inputData, a1, wtype);
-    TestBase::declareArray(test->inputData, a2, wtype);
-    TestBase::declareArray(test->inputData, a3, wtype);
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype)
-{
-    if (!test->times.empty()) return *this;
-    TestBase::declareArray(test->inputData, a1, wtype);
-    TestBase::declareArray(test->inputData, a2, wtype);
-    TestBase::declareArray(test->inputData, a3, wtype);
-    TestBase::declareArray(test->inputData, a4, wtype);
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::out(cv::InputOutputArray a1, int wtype)
-{
-    if (!test->times.empty()) return *this;
-    TestBase::declareArray(test->outputData, a1, wtype);
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::out(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype)
-{
-    if (!test->times.empty()) return *this;
-    TestBase::declareArray(test->outputData, a1, wtype);
-    TestBase::declareArray(test->outputData, a2, wtype);
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype)
-{
-    if (!test->times.empty()) return *this;
-    TestBase::declareArray(test->outputData, a1, wtype);
-    TestBase::declareArray(test->outputData, a2, wtype);
-    TestBase::declareArray(test->outputData, a3, wtype);
-    return *this;
-}
-
-TestBase::_declareHelper& TestBase::_declareHelper::out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype)
-{
-    if (!test->times.empty()) return *this;
-    TestBase::declareArray(test->outputData, a1, wtype);
-    TestBase::declareArray(test->outputData, a2, wtype);
-    TestBase::declareArray(test->outputData, a3, wtype);
-    TestBase::declareArray(test->outputData, a4, wtype);
-    return *this;
-}
-
-TestBase::_declareHelper::_declareHelper(TestBase* t) : test(t)
-{
-}
-
-/*****************************************************************************************\
-*                                  ::perf::PrintTo
-\*****************************************************************************************/
-namespace perf
-{
-
-void PrintTo(const MatType& t, ::std::ostream* os)
-{
-    switch( CV_MAT_DEPTH((int)t) )
-    {
-        case CV_8U:  *os << "8U";  break;
-        case CV_8S:  *os << "8S";  break;
-        case CV_16U: *os << "16U"; break;
-        case CV_16S: *os << "16S"; break;
-        case CV_32S: *os << "32S"; break;
-        case CV_32F: *os << "32F"; break;
-        case CV_64F: *os << "64F"; break;
-        case CV_USRTYPE1: *os << "USRTYPE1"; break;
-        default: *os << "INVALID_TYPE"; break;
-    }
-    *os << 'C' << CV_MAT_CN((int)t);
-}
-
-} //namespace perf
-
-/*****************************************************************************************\
-*                                  ::cv::PrintTo
-\*****************************************************************************************/
-namespace cv {
-
-void PrintTo(const Size& sz, ::std::ostream* os)
-{
-    *os << /*"Size:" << */sz.width << "x" << sz.height;
-}
-
-}  // namespace cv
-
-
-/*****************************************************************************************\
-*                                  ::cv::PrintTo
-\*****************************************************************************************/
+#include "precomp.hpp"
+
+#ifdef ANDROID
+# include <sys/time.h>
+#endif
+
+using namespace perf;
+
+int64 TestBase::timeLimitDefault = 0;
+unsigned int TestBase::iterationsLimitDefault = (unsigned int)(-1);
+int64 TestBase::_timeadjustment = 0;
+
+const char *command_line_keys =
+{
+    "{   |perf_max_outliers   |8        |percent of allowed outliers}"
+    "{   |perf_min_samples    |10       |minimal required numer of samples}"
+    "{   |perf_force_samples  |100      |force set maximum number of samples for all tests}"
+    "{   |perf_seed           |809564   |seed for random numbers generator}"
+    "{   |perf_tbb_nthreads   |-1       |if TBB is enabled, the number of TBB threads}"
+    "{   |perf_write_sanity   |false    |allow to create new records for sanity checks}"
+    #ifdef ANDROID
+    "{   |perf_time_limit     |6.0      |default time limit for a single test (in seconds)}"
+    "{   |perf_affinity_mask  |0        |set affinity mask for the main thread}"
+    "{   |perf_log_power_checkpoints  |false    |additional xml logging for power measurement}"
+    #else
+    "{   |perf_time_limit     |3.0      |default time limit for a single test (in seconds)}"
+    #endif
+    "{   |perf_max_deviation  |1.0      |}"
+    "{h  |help                |false    |}"
+};
+
+static double       param_max_outliers;
+static double       param_max_deviation;
+static unsigned int param_min_samples;
+static unsigned int param_force_samples;
+static uint64       param_seed;
+static double       param_time_limit;
+static int          param_tbb_nthreads;
+static bool         param_write_sanity;
+#ifdef ANDROID
+static int          param_affinity_mask;
+static bool         log_power_checkpoints;
+
+#include <sys/syscall.h>
+#include <pthread.h>
+static void setCurrentThreadAffinityMask(int mask)
+{
+    pid_t pid=gettid();
+    int syscallres=syscall(__NR_sched_setaffinity, pid, sizeof(mask), &mask);
+    if (syscallres)
+    {
+        int err=errno;
+        err=err;//to avoid warnings about unused variables
+        LOGE("Error in the syscall setaffinity: mask=%d=0x%x err=%d=0x%x", mask, mask, err, err);
+    }
+}
+
+#endif
+
+static void randu(cv::Mat& m)
+{
+    const int bigValue = 0x00000FFF;
+    if (m.depth() < CV_32F)
+    {
+        int minmax[] = {0, 256};
+        cv::Mat mr = cv::Mat(m.rows, (int)(m.cols * m.elemSize()), CV_8U, m.ptr(), m.step[0]);
+        cv::randu(mr, cv::Mat(1, 1, CV_32S, minmax), cv::Mat(1, 1, CV_32S, minmax + 1));
+    }
+    else if (m.depth() == CV_32F)
+    {
+        //float minmax[] = {-FLT_MAX, FLT_MAX};
+        float minmax[] = {-bigValue, bigValue};
+        cv::Mat mr = m.reshape(1);
+        cv::randu(mr, cv::Mat(1, 1, CV_32F, minmax), cv::Mat(1, 1, CV_32F, minmax + 1));
+    }
+    else
+    {
+        //double minmax[] = {-DBL_MAX, DBL_MAX};
+        double minmax[] = {-bigValue, bigValue};
+        cv::Mat mr = m.reshape(1);
+        cv::randu(mr, cv::Mat(1, 1, CV_64F, minmax), cv::Mat(1, 1, CV_64F, minmax + 1));
+    }
+}
+
+/*****************************************************************************************\
+*                       inner exception class for early termination
+\*****************************************************************************************/
+
+class PerfEarlyExitException: public cv::Exception {};
+
+/*****************************************************************************************\
+*                                   ::perf::Regression
+\*****************************************************************************************/
+
+Regression& Regression::instance()
+{
+    static Regression single;
+    return single;
+}
+
+Regression& Regression::add(const std::string& name, cv::InputArray array, double eps, ERROR_TYPE err)
+{
+    return instance()(name, array, eps, err);
+}
+
+void Regression::Init(const std::string& testSuitName, const std::string& ext)
+{
+    instance().init(testSuitName, ext);
+}
+
+void Regression::init(const std::string& testSuitName, const std::string& ext)
+{
+    if (!storageInPath.empty())
+    {
+        LOGE("Subsequent initialisation of Regression utility is not allowed.");
+        return;
+    }
+
+    const char *data_path_dir = getenv("OPENCV_TEST_DATA_PATH");
+    const char *path_separator = "/";
+
+    if (data_path_dir)
+    {
+        int len = (int)strlen(data_path_dir)-1;
+        if (len < 0) len = 0;
+        std::string path_base = (data_path_dir[0] == 0 ? std::string(".") : std::string(data_path_dir))
+                + (data_path_dir[len] == '/' || data_path_dir[len] == '\\' ? "" : path_separator)
+                + "perf"
+                + path_separator;
+
+        storageInPath = path_base + testSuitName + ext;
+        storageOutPath = path_base + testSuitName;
+    }
+    else
+    {
+        storageInPath = testSuitName + ext;
+        storageOutPath = testSuitName;
+    }
+
+    try
+    {
+        if (storageIn.open(storageInPath, cv::FileStorage::READ))
+        {
+            rootIn = storageIn.root();
+            if (storageInPath.length() > 3 && storageInPath.substr(storageInPath.length()-3) == ".gz")
+                storageOutPath += "_new";
+            storageOutPath += ext;
+        }
+    }
+    catch(cv::Exception&)
+    {
+        LOGE("Failed to open sanity data for reading: %s", storageInPath.c_str());
+    }
+
+    if(!storageIn.isOpened())
+        storageOutPath = storageInPath;
+}
+
+Regression::Regression() : regRNG(cv::getTickCount())//this rng should be really random
+{
+}
+
+Regression::~Regression()
+{
+    if (storageIn.isOpened())
+        storageIn.release();
+    if (storageOut.isOpened())
+    {
+        if (!currentTestNodeName.empty())
+            storageOut << "}";
+        storageOut.release();
+    }
+}
+
+cv::FileStorage& Regression::write()
+{
+    if (!storageOut.isOpened() && !storageOutPath.empty())
+    {
+        int mode = (storageIn.isOpened() && storageInPath == storageOutPath)
+                ? cv::FileStorage::APPEND : cv::FileStorage::WRITE;
+        storageOut.open(storageOutPath, mode);
+        if (!storageOut.isOpened())
+        {
+            LOGE("Could not open \"%s\" file for writing", storageOutPath.c_str());
+            storageOutPath.clear();
+        }
+        else if (mode == cv::FileStorage::WRITE && !rootIn.empty())
+        {
+            //TODO: write content of rootIn node into the storageOut
+        }
+    }
+    return storageOut;
+}
+
+std::string Regression::getCurrentTestNodeName()
+{
+    const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+
+    if (test_info == 0)
+        return "undefined";
+
+    std::string nodename = std::string(test_info->test_case_name()) + "--" + test_info->name();
+    size_t idx = nodename.find_first_of('/');
+    if (idx != std::string::npos)
+        nodename.erase(idx);
+
+    const char* type_param = test_info->type_param();
+    if (type_param != 0)
+        (nodename += "--") += type_param;
+
+    const char* value_param = test_info->value_param();
+    if (value_param != 0)
+        (nodename += "--") += value_param;
+
+    for(size_t i = 0; i < nodename.length(); ++i)
+        if (!isalnum(nodename[i]) && '_' != nodename[i])
+            nodename[i] = '-';
+
+    return nodename;
+}
+
+bool Regression::isVector(cv::InputArray a)
+{
+    return a.kind() == cv::_InputArray::STD_VECTOR_MAT || a.kind() == cv::_InputArray::STD_VECTOR_VECTOR;
+}
+
+double Regression::getElem(cv::Mat& m, int y, int x, int cn)
+{
+    switch (m.depth())
+    {
+    case CV_8U: return *(m.ptr<unsigned char>(y, x) + cn);
+    case CV_8S: return *(m.ptr<signed char>(y, x) + cn);
+    case CV_16U: return *(m.ptr<unsigned short>(y, x) + cn);
+    case CV_16S: return *(m.ptr<signed short>(y, x) + cn);
+    case CV_32S: return *(m.ptr<signed int>(y, x) + cn);
+    case CV_32F: return *(m.ptr<float>(y, x) + cn);
+    case CV_64F: return *(m.ptr<double>(y, x) + cn);
+    default: return 0;
+    }
+}
+
+void Regression::write(cv::Mat m)
+{
+    double min, max;
+    cv::minMaxLoc(m, &min, &max);
+    write() << "min" << min << "max" << max;
+
+    write() << "last" << "{" << "x" << m.cols-1 << "y" << m.rows-1
+        << "val" << getElem(m, m.rows-1, m.cols-1, m.channels()-1) << "}";
+
+    int x, y, cn;
+    x = regRNG.uniform(0, m.cols);
+    y = regRNG.uniform(0, m.rows);
+    cn = regRNG.uniform(0, m.channels());
+    write() << "rng1" << "{" << "x" << x << "y" << y;
+    if(cn > 0) write() << "cn" << cn;
+    write() << "val" << getElem(m, y, x, cn) << "}";
+
+    x = regRNG.uniform(0, m.cols);
+    y = regRNG.uniform(0, m.rows);
+    cn = regRNG.uniform(0, m.channels());
+    write() << "rng2" << "{" << "x" << x << "y" << y;
+    if (cn > 0) write() << "cn" << cn;
+    write() << "val" << getElem(m, y, x, cn) << "}";
+}
+
+static double evalEps(double expected, double actual, double _eps, ERROR_TYPE err)
+{
+    if (err == ERROR_ABSOLUTE)
+        return _eps;
+    else if (err == ERROR_RELATIVE)
+        return std::max(std::abs(expected), std::abs(actual)) * err;
+    return 0;
+}
+
+void Regression::verify(cv::FileNode node, cv::Mat actual, double _eps, std::string argname, ERROR_TYPE err)
+{
+    double actual_min, actual_max;
+    cv::minMaxLoc(actual, &actual_min, &actual_max);
+
+    double eps = evalEps((double)node["min"], actual_min, _eps, err);
+    ASSERT_NEAR((double)node["min"], actual_min, eps)
+            << "  " << argname << " has unexpected minimal value";
+
+    eps = evalEps((double)node["max"], actual_max, _eps, err);
+    ASSERT_NEAR((double)node["max"], actual_max, eps)
+            << "  " << argname << " has unexpected maximal value";
+
+    cv::FileNode last = node["last"];
+    double actualLast = getElem(actual, actual.rows - 1, actual.cols - 1, actual.channels() - 1);
+    ASSERT_EQ((int)last["x"], actual.cols - 1)
+            << "  " << argname << " has unexpected number of columns";
+    ASSERT_EQ((int)last["y"], actual.rows - 1)
+            << "  " << argname << " has unexpected number of rows";
+
+    eps = evalEps((double)last["val"], actualLast, _eps, err);
+    ASSERT_NEAR((double)last["val"], actualLast, eps)
+            << "  " << argname << " has unexpected value of last element";
+
+    cv::FileNode rng1 = node["rng1"];
+    int x1 = rng1["x"];
+    int y1 = rng1["y"];
+    int cn1 = rng1["cn"];
+
+    eps = evalEps((double)rng1["val"], getElem(actual, y1, x1, cn1), _eps, err);
+    ASSERT_NEAR((double)rng1["val"], getElem(actual, y1, x1, cn1), eps)
+            << "  " << argname << " has unexpected value of ["<< x1 << ":" << y1 << ":" << cn1 <<"] element";
+
+    cv::FileNode rng2 = node["rng2"];
+    int x2 = rng2["x"];
+    int y2 = rng2["y"];
+    int cn2 = rng2["cn"];
+
+    eps = evalEps((double)rng2["val"], getElem(actual, y2, x2, cn2), _eps, err);
+    ASSERT_NEAR((double)rng2["val"], getElem(actual, y2, x2, cn2), eps)
+            << "  " << argname << " has unexpected value of ["<< x2 << ":" << y2 << ":" << cn2 <<"] element";
+}
+
+void Regression::write(cv::InputArray array)
+{
+    write() << "kind" << array.kind();
+    write() << "type" << array.type();
+    if (isVector(array))
+    {
+        int total = (int)array.total();
+        int idx = regRNG.uniform(0, total);
+        write() << "len" << total;
+        write() << "idx" << idx;
+
+        cv::Mat m = array.getMat(idx);
+
+        if (m.total() * m.channels() < 26) //5x5 or smaller
+            write() << "val" << m;
+        else
+            write(m);
+    }
+    else
+    {
+        if (array.total() * array.channels() < 26) //5x5 or smaller
+            write() << "val" << array.getMat();
+        else
+            write(array.getMat());
+    }
+}
+
+static int countViolations(const cv::Mat& expected, const cv::Mat& actual, const cv::Mat& diff, double eps, double* max_violation = 0, double* max_allowed = 0)
+{
+    cv::Mat diff64f;
+    diff.reshape(1).convertTo(diff64f, CV_64F);
+
+    cv::Mat expected_abs = cv::abs(expected.reshape(1));
+    cv::Mat actual_abs = cv::abs(actual.reshape(1));
+    cv::Mat maximum, mask;
+    cv::max(expected_abs, actual_abs, maximum);
+    cv::multiply(maximum, cv::Vec<double, 1>(eps), maximum, CV_64F);
+    cv::compare(diff64f, maximum, mask, cv::CMP_GT);
+
+    int v = cv::countNonZero(mask);
+
+    if (v > 0 && max_violation != 0 && max_allowed != 0)
+    {
+        int loc[10];
+        cv::minMaxIdx(maximum, 0, max_allowed, 0, loc, mask);
+        *max_violation = diff64f.at<double>(loc[1], loc[0]);
+    }
+
+    return v;
+}
+
+void Regression::verify(cv::FileNode node, cv::InputArray array, double eps, ERROR_TYPE err)
+{
+    ASSERT_EQ((int)node["kind"], array.kind()) << "  Argument \"" << node.name() << "\" has unexpected kind";
+    ASSERT_EQ((int)node["type"], array.type()) << "  Argument \"" << node.name() << "\" has unexpected type";
+
+    cv::FileNode valnode = node["val"];
+    if (isVector(array))
+    {
+        ASSERT_EQ((int)node["len"], (int)array.total()) << "  Vector \"" << node.name() << "\" has unexpected length";
+        int idx = node["idx"];
+
+        cv::Mat actual = array.getMat(idx);
+
+        if (valnode.isNone())
+        {
+            ASSERT_LE((size_t)26, actual.total() * (size_t)actual.channels())
+                    << "  \"" << node.name() << "[" <<  idx << "]\" has unexpected number of elements";
+            verify(node, actual, eps, cv::format("%s[%d]", node.name().c_str(), idx), err);
+        }
+        else
+        {
+            cv::Mat expected;
+            valnode >> expected;
+
+            ASSERT_EQ(expected.size(), actual.size())
+                    << "  " << node.name() << "[" <<  idx<< "] has unexpected size";
+
+            cv::Mat diff;
+            cv::absdiff(expected, actual, diff);
+
+            if (err == ERROR_ABSOLUTE)
+            {
+                if (!cv::checkRange(diff, true, 0, 0, eps))
+                {
+                    double max;
+                    cv::minMaxLoc(diff.reshape(1), 0, &max);
+                    FAIL() << "  Absolute difference (=" << max << ") between argument \""
+                           << node.name() << "[" <<  idx << "]\" and expected value is bugger than " << eps;
+                }
+            }
+            else if (err == ERROR_RELATIVE)
+            {
+                double maxv, maxa;
+                int violations = countViolations(expected, actual, diff, eps, &maxv, &maxa);
+                if (violations > 0)
+                {
+                    FAIL() << "  Relative difference (" << maxv << " of " << maxa << " allowed) between argument \""
+                           << node.name() << "[" <<  idx << "]\" and expected value is bugger than " << eps << " in " << violations << " points";
+                }
+            }
+        }
+    }
+    else
+    {
+        if (valnode.isNone())
+        {
+            ASSERT_LE((size_t)26, array.total() * (size_t)array.channels())
+                    << "  Argument \"" << node.name() << "\" has unexpected number of elements";
+            verify(node, array.getMat(), eps, "Argument " + node.name(), err);
+        }
+        else
+        {
+            cv::Mat expected;
+            valnode >> expected;
+            cv::Mat actual = array.getMat();
+
+            ASSERT_EQ(expected.size(), actual.size())
+                    << "  Argument \"" << node.name() << "\" has unexpected size";
+
+            cv::Mat diff;
+            cv::absdiff(expected, actual, diff);
+
+            if (err == ERROR_ABSOLUTE)
+            {
+                if (!cv::checkRange(diff, true, 0, 0, eps))
+                {
+                    double max;
+                    cv::minMaxLoc(diff.reshape(1), 0, &max);
+                    FAIL() << "  Difference (=" << max << ") between argument \"" << node.name()
+                           << "\" and expected value is bugger than " << eps;
+                }
+            }
+            else if (err == ERROR_RELATIVE)
+            {
+                double maxv, maxa;
+                int violations = countViolations(expected, actual, diff, eps, &maxv, &maxa);
+                if (violations > 0)
+                {
+                    FAIL() << "  Relative difference (" << maxv << " of " << maxa << " allowed) between argument \"" << node.name()
+                           << "\" and expected value is bugger than " << eps << " in " << violations << " points";
+                }
+            }
+        }
+    }
+}
+
+Regression& Regression::operator() (const std::string& name, cv::InputArray array, double eps, ERROR_TYPE err)
+{
+    std::string nodename = getCurrentTestNodeName();
+
+    cv::FileNode n = rootIn[nodename];
+    if(n.isNone())
+    {
+        if(param_write_sanity)
+        {
+            if (nodename != currentTestNodeName)
+            {
+                if (!currentTestNodeName.empty())
+                    write() << "}";
+                currentTestNodeName = nodename;
+
+                write() << nodename << "{";
+            }
+            write() << name << "{";
+            write(array);
+            write() << "}";
+        }
+    }
+    else
+    {
+        cv::FileNode this_arg = n[name];
+        if (!this_arg.isMap())
+            ADD_FAILURE() << "  No regression data for " << name << " argument";
+        else
+            verify(this_arg, array, eps, err);
+    }
+    return *this;
+}
+
+
+/*****************************************************************************************\
+*                                ::perf::performance_metrics
+\*****************************************************************************************/
+performance_metrics::performance_metrics()
+{
+    bytesIn = 0;
+    bytesOut = 0;
+    samples = 0;
+    outliers = 0;
+    gmean = 0;
+    gstddev = 0;
+    mean = 0;
+    stddev = 0;
+    median = 0;
+    min = 0;
+    frequency = 0;
+    terminationReason = TERM_UNKNOWN;
+}
+
+
+/*****************************************************************************************\
+*                                   ::perf::TestBase
+\*****************************************************************************************/
+
+
+void TestBase::Init(int argc, const char* const argv[])
+{
+    cv::CommandLineParser args(argc, argv, command_line_keys);
+    param_max_outliers = std::min(100., std::max(0., args.get<double>("perf_max_outliers")));
+    param_min_samples  = std::max(1u, args.get<unsigned int>("perf_min_samples"));
+    param_max_deviation = std::max(0., args.get<double>("perf_max_deviation"));
+    param_seed = args.get<uint64>("perf_seed");
+    param_time_limit = std::max(0., args.get<double>("perf_time_limit"));
+    param_force_samples = args.get<unsigned int>("perf_force_samples");
+    param_write_sanity = args.get<bool>("perf_write_sanity");
+    param_tbb_nthreads  = args.get<int>("perf_tbb_nthreads");
+#ifdef ANDROID
+    param_affinity_mask = args.get<int>("perf_affinity_mask");
+    log_power_checkpoints = args.get<bool>("perf_log_power_checkpoints");
+#endif
+
+    if (args.get<bool>("help"))
+    {
+        args.printParams();
+        printf("\n\n");
+        return;
+    }
+
+    timeLimitDefault = param_time_limit == 0.0 ? 1 : (int64)(param_time_limit * cv::getTickFrequency());
+    iterationsLimitDefault = param_force_samples == 0 ? (unsigned)(-1) : param_force_samples;
+    _timeadjustment = _calibrate();
+}
+
+int64 TestBase::_calibrate()
+{
+    class _helper : public ::perf::TestBase
+    {
+        public:
+        performance_metrics& getMetrics() { return calcMetrics(); }
+        virtual void TestBody() {}
+        virtual void PerfTestBody()
+        {
+            //the whole system warmup
+            SetUp();
+            cv::Mat a(2048, 2048, CV_32S, cv::Scalar(1));
+            cv::Mat b(2048, 2048, CV_32S, cv::Scalar(2));
+            declare.time(30);
+            double s = 0;
+            for(declare.iterations(20); startTimer(), next(); stopTimer())
+                s+=a.dot(b);
+            declare.time(s);
+
+            //self calibration
+            SetUp();
+            for(declare.iterations(1000); startTimer(), next(); stopTimer()){}
+        }
+    };
+
+    _timeadjustment = 0;
+    _helper h;
+    h.PerfTestBody();
+    double compensation = h.getMetrics().min;
+    LOGD("Time compensation is %.0f", compensation);
+    return (int64)compensation;
+}
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4355)  // 'this' : used in base member initializer list
+#endif
+TestBase::TestBase(): declare(this)
+{
+}
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+
+void TestBase::declareArray(SizeVector& sizes, cv::InputOutputArray a, int wtype)
+{
+    if (!a.empty())
+    {
+        sizes.push_back(std::pair<int, cv::Size>(getSizeInBytes(a), getSize(a)));
+        warmup(a, wtype);
+    }
+    else if (a.kind() != cv::_InputArray::NONE)
+        ADD_FAILURE() << "  Uninitialized input/output parameters are not allowed for performance tests";
+}
+
+void TestBase::warmup(cv::InputOutputArray a, int wtype)
+{
+    if (a.empty()) return;
+    if (a.kind() != cv::_InputArray::STD_VECTOR_MAT && a.kind() != cv::_InputArray::STD_VECTOR_VECTOR)
+        warmup_impl(a.getMat(), wtype);
+    else
+    {
+        size_t total = a.total();
+        for (size_t i = 0; i < total; ++i)
+            warmup_impl(a.getMat((int)i), wtype);
+    }
+}
+
+int TestBase::getSizeInBytes(cv::InputArray a)
+{
+    if (a.empty()) return 0;
+    int total = (int)a.total();
+    if (a.kind() != cv::_InputArray::STD_VECTOR_MAT && a.kind() != cv::_InputArray::STD_VECTOR_VECTOR)
+        return total * CV_ELEM_SIZE(a.type());
+
+    int size = 0;
+    for (int i = 0; i < total; ++i)
+        size += (int)a.total(i) * CV_ELEM_SIZE(a.type(i));
+
+    return size;
+}
+
+cv::Size TestBase::getSize(cv::InputArray a)
+{
+    if (a.kind() != cv::_InputArray::STD_VECTOR_MAT && a.kind() != cv::_InputArray::STD_VECTOR_VECTOR)
+        return a.size();
+    return cv::Size();
+}
+
+bool TestBase::next()
+{
+    bool has_next = ++currentIter < nIters && totalTime < timeLimit;
+#ifdef ANDROID
+    if (log_power_checkpoints)
+    {
+        timeval tim;
+        gettimeofday(&tim, NULL);
+        unsigned long long t1 = tim.tv_sec * 1000LLU + (unsigned long long)(tim.tv_usec / 1000.f);
+
+        if (currentIter == 1) RecordProperty("test_start", cv::format("%llu",t1).c_str());
+        if (!has_next) RecordProperty("test_complete", cv::format("%llu",t1).c_str());
+    }
+#endif
+    return has_next;
+}
+
+void TestBase::warmup_impl(cv::Mat m, int wtype)
+{
+    switch(wtype)
+    {
+    case WARMUP_READ:
+        cv::sum(m.reshape(1));
+        return;
+    case WARMUP_WRITE:
+        m.reshape(1).setTo(cv::Scalar::all(0));
+        return;
+    case WARMUP_RNG:
+        randu(m);
+        return;
+    default:
+        return;
+    }
+}
+
+unsigned int TestBase::getTotalInputSize() const
+{
+    unsigned int res = 0;
+    for (SizeVector::const_iterator i = inputData.begin(); i != inputData.end(); ++i)
+        res += i->first;
+    return res;
+}
+
+unsigned int TestBase::getTotalOutputSize() const
+{
+    unsigned int res = 0;
+    for (SizeVector::const_iterator i = outputData.begin(); i != outputData.end(); ++i)
+        res += i->first;
+    return res;
+}
+
+void TestBase::startTimer()
+{
+    lastTime = cv::getTickCount();
+}
+
+void TestBase::stopTimer()
+{
+    int64 time = cv::getTickCount();
+    if (lastTime == 0)
+        ADD_FAILURE() << "  stopTimer() is called before startTimer()";
+    lastTime = time - lastTime;
+    totalTime += lastTime;
+    lastTime -= _timeadjustment;
+    if (lastTime < 0) lastTime = 0;
+    times.push_back(lastTime);
+    lastTime = 0;
+}
+
+performance_metrics& TestBase::calcMetrics()
+{
+    if ((metrics.samples == (unsigned int)currentIter) || times.size() == 0)
+        return metrics;
+
+    metrics.bytesIn = getTotalInputSize();
+    metrics.bytesOut = getTotalOutputSize();
+    metrics.frequency = cv::getTickFrequency();
+    metrics.samples = (unsigned int)times.size();
+    metrics.outliers = 0;
+
+    if (metrics.terminationReason != performance_metrics::TERM_INTERRUPT && metrics.terminationReason != performance_metrics::TERM_EXCEPTION)
+    {
+        if (currentIter == nIters)
+            metrics.terminationReason = performance_metrics::TERM_ITERATIONS;
+        else if (totalTime >= timeLimit)
+            metrics.terminationReason = performance_metrics::TERM_TIME;
+        else
+            metrics.terminationReason = performance_metrics::TERM_UNKNOWN;
+    }
+
+    std::sort(times.begin(), times.end());
+
+    //estimate mean and stddev for log(time)
+    double gmean = 0;
+    double gstddev = 0;
+    int n = 0;
+    for(TimeVector::const_iterator i = times.begin(); i != times.end(); ++i)
+    {
+        double x = static_cast<double>(*i)/runsPerIteration;
+        if (x < DBL_EPSILON) continue;
+        double lx = log(x);
+
+        ++n;
+        double delta = lx - gmean;
+        gmean += delta / n;
+        gstddev += delta * (lx - gmean);
+    }
+
+    gstddev = n > 1 ? sqrt(gstddev / (n - 1)) : 0;
+
+    TimeVector::const_iterator start = times.begin();
+    TimeVector::const_iterator end = times.end();
+
+    //filter outliers assuming log-normal distribution
+    //http://stackoverflow.com/questions/1867426/modeling-distribution-of-performance-measurements
+    int offset = 0;
+    if (gstddev > DBL_EPSILON)
+    {
+        double minout = exp(gmean - 3 * gstddev) * runsPerIteration;
+        double maxout = exp(gmean + 3 * gstddev) * runsPerIteration;
+        while(*start < minout) ++start, ++metrics.outliers, ++offset;
+        do --end, ++metrics.outliers; while(*end > maxout);
+        ++end, --metrics.outliers;
+    }
+
+    metrics.min = static_cast<double>(*start)/runsPerIteration;
+    //calc final metrics
+    n = 0;
+    gmean = 0;
+    gstddev = 0;
+    double mean = 0;
+    double stddev = 0;
+    int m = 0;
+    for(; start != end; ++start)
+    {
+        double x = static_cast<double>(*start)/runsPerIteration;
+        if (x > DBL_EPSILON)
+        {
+            double lx = log(x);
+            ++m;
+            double gdelta = lx - gmean;
+            gmean += gdelta / m;
+            gstddev += gdelta * (lx - gmean);
+        }
+        ++n;
+        double delta = x - mean;
+        mean += delta / n;
+        stddev += delta * (x - mean);
+    }
+
+    metrics.mean = mean;
+    metrics.gmean = exp(gmean);
+    metrics.gstddev = m > 1 ? sqrt(gstddev / (m - 1)) : 0;
+    metrics.stddev = n > 1 ? sqrt(stddev / (n - 1)) : 0;
+    metrics.median = n % 2
+            ? (double)times[offset + n / 2]
+            : 0.5 * (times[offset + n / 2] + times[offset + n / 2 - 1]);
+
+    metrics.median /= runsPerIteration;
+
+    return metrics;
+}
+
+void TestBase::validateMetrics()
+{
+    performance_metrics& m = calcMetrics();
+
+    if (HasFailure()) return;
+
+    ASSERT_GE(m.samples, 1u)
+      << "  No time measurements was performed.\nstartTimer() and stopTimer() commands are required for performance tests.";
+
+    EXPECT_GE(m.samples, param_min_samples)
+      << "  Only a few samples are collected.\nPlease increase number of iterations or/and time limit to get reliable performance measurements.";
+
+    if (m.gstddev > DBL_EPSILON)
+    {
+        EXPECT_GT(/*m.gmean * */1., /*m.gmean * */ 2 * sinh(m.gstddev * param_max_deviation))
+          << "  Test results are not reliable ((mean-sigma,mean+sigma) deviation interval is bigger than measured time interval).";
+    }
+
+    EXPECT_LE(m.outliers, std::max((unsigned int)cvCeil(m.samples * param_max_outliers / 100.), 1u))
+      << "  Test results are not reliable (too many outliers).";
+}
+
+void TestBase::reportMetrics(bool toJUnitXML)
+{
+    performance_metrics& m = calcMetrics();
+
+    if (toJUnitXML)
+    {
+        RecordProperty("bytesIn", (int)m.bytesIn);
+        RecordProperty("bytesOut", (int)m.bytesOut);
+        RecordProperty("term", m.terminationReason);
+        RecordProperty("samples", (int)m.samples);
+        RecordProperty("outliers", (int)m.outliers);
+        RecordProperty("frequency", cv::format("%.0f", m.frequency).c_str());
+        RecordProperty("min", cv::format("%.0f", m.min).c_str());
+        RecordProperty("median", cv::format("%.0f", m.median).c_str());
+        RecordProperty("gmean", cv::format("%.0f", m.gmean).c_str());
+        RecordProperty("gstddev", cv::format("%.6f", m.gstddev).c_str());
+        RecordProperty("mean", cv::format("%.0f", m.mean).c_str());
+        RecordProperty("stddev", cv::format("%.0f", m.stddev).c_str());
+    }
+    else
+    {
+        const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info();
+        const char* type_param = test_info->type_param();
+        const char* value_param = test_info->value_param();
+
+#if defined(ANDROID) && defined(USE_ANDROID_LOGGING)
+        LOGD("[ FAILED   ] %s.%s", test_info->test_case_name(), test_info->name());
+#endif
+
+        if (type_param)  LOGD("type      = %11s", type_param);
+        if (value_param) LOGD("params    = %11s", value_param);
+
+        switch (m.terminationReason)
+        {
+        case performance_metrics::TERM_ITERATIONS:
+            LOGD("termination reason:  reached maximum number of iterations");
+            break;
+        case performance_metrics::TERM_TIME:
+            LOGD("termination reason:  reached time limit");
+            break;
+        case performance_metrics::TERM_INTERRUPT:
+            LOGD("termination reason:  aborted by the performance testing framework");
+            break;
+        case performance_metrics::TERM_EXCEPTION:
+            LOGD("termination reason:  unhandled exception");
+            break;
+        case performance_metrics::TERM_UNKNOWN:
+        default:
+            LOGD("termination reason:  unknown");
+            break;
+        };
+
+        LOGD("bytesIn   =%11lu", (unsigned long)m.bytesIn);
+        LOGD("bytesOut  =%11lu", (unsigned long)m.bytesOut);
+        if (nIters == (unsigned int)-1 || m.terminationReason == performance_metrics::TERM_ITERATIONS)
+            LOGD("samples   =%11u",  m.samples);
+        else
+            LOGD("samples   =%11u of %u", m.samples, nIters);
+        LOGD("outliers  =%11u", m.outliers);
+        LOGD("frequency =%11.0f", m.frequency);
+        if (m.samples > 0)
+        {
+            LOGD("min       =%11.0f = %.2fms", m.min, m.min * 1e3 / m.frequency);
+            LOGD("median    =%11.0f = %.2fms", m.median, m.median * 1e3 / m.frequency);
+            LOGD("gmean     =%11.0f = %.2fms", m.gmean, m.gmean * 1e3 / m.frequency);
+            LOGD("gstddev   =%11.8f = %.2fms for 97%% dispersion interval", m.gstddev, m.gmean * 2 * sinh(m.gstddev * 3) * 1e3 / m.frequency);
+            LOGD("mean      =%11.0f = %.2fms", m.mean, m.mean * 1e3 / m.frequency);
+            LOGD("stddev    =%11.0f = %.2fms", m.stddev, m.stddev * 1e3 / m.frequency);
+        }
+    }
+}
+
+void TestBase::SetUp()
+{
+#ifdef HAVE_TBB
+    if (param_tbb_nthreads > 0) {
+        p_tbb_initializer.release();
+        p_tbb_initializer=new tbb::task_scheduler_init(param_tbb_nthreads);
+    }
+#endif
+#ifdef ANDROID
+    if (param_affinity_mask)
+        setCurrentThreadAffinityMask(param_affinity_mask);
+#endif
+    lastTime = 0;
+    totalTime = 0;
+    runsPerIteration = 1;
+    nIters = iterationsLimitDefault;
+    currentIter = (unsigned int)-1;
+    timeLimit = timeLimitDefault;
+    times.clear();
+    cv::theRNG().state = param_seed;//this rng should generate same numbers for each run
+}
+
+void TestBase::TearDown()
+{
+    validateMetrics();
+    if (HasFailure())
+        reportMetrics(false);
+    else
+    {
+        const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info();
+        const char* type_param = test_info->type_param();
+        const char* value_param = test_info->value_param();
+        if (value_param) printf("[ VALUE    ] \t%s\n", value_param), fflush(stdout);
+        if (type_param)  printf("[ TYPE     ] \t%s\n", type_param), fflush(stdout);
+        reportMetrics(true);
+    }
+#ifdef HAVE_TBB
+    p_tbb_initializer.release();
+#endif
+}
+
+std::string TestBase::getDataPath(const std::string& relativePath)
+{
+    if (relativePath.empty())
+    {
+        ADD_FAILURE() << "  Bad path to test resource";
+        throw PerfEarlyExitException();
+    }
+
+    const char *data_path_dir = getenv("OPENCV_TEST_DATA_PATH");
+    const char *path_separator = "/";
+
+    std::string path;
+    if (data_path_dir)
+    {
+        int len = (int)strlen(data_path_dir) - 1;
+        if (len < 0) len = 0;
+        path = (data_path_dir[0] == 0 ? std::string(".") : std::string(data_path_dir))
+                + (data_path_dir[len] == '/' || data_path_dir[len] == '\\' ? "" : path_separator);
+    }
+    else
+    {
+        path = ".";
+        path += path_separator;
+    }
+
+    if (relativePath[0] == '/' || relativePath[0] == '\\')
+        path += relativePath.substr(1);
+    else
+        path += relativePath;
+
+    FILE* fp = fopen(path.c_str(), "r");
+    if (fp)
+        fclose(fp);
+    else
+    {
+        ADD_FAILURE() << "  Requested file \"" << path << "\" does not exist.";
+        throw PerfEarlyExitException();
+    }
+    return path;
+}
+
+void TestBase::RunPerfTestBody()
+{
+    try
+    {
+        this->PerfTestBody();
+    }
+    catch(PerfEarlyExitException)
+    {
+        metrics.terminationReason = performance_metrics::TERM_INTERRUPT;
+        return;//no additional failure logging
+    }
+    catch(cv::Exception e)
+    {
+        metrics.terminationReason = performance_metrics::TERM_EXCEPTION;
+        FAIL() << "Expected: PerfTestBody() doesn't throw an exception.\n  Actual: it throws:\n  " << e.what();
+    }
+    catch(...)
+    {
+        metrics.terminationReason = performance_metrics::TERM_EXCEPTION;
+        FAIL() << "Expected: PerfTestBody() doesn't throw an exception.\n  Actual: it throws.";
+    }
+}
+
+/*****************************************************************************************\
+*                          ::perf::TestBase::_declareHelper
+\*****************************************************************************************/
+TestBase::_declareHelper& TestBase::_declareHelper::iterations(unsigned int n)
+{
+    test->times.clear();
+    test->times.reserve(n);
+    test->nIters = std::min(n, TestBase::iterationsLimitDefault);
+    test->currentIter = (unsigned int)-1;
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::time(double timeLimitSecs)
+{
+    test->times.clear();
+    test->currentIter = (unsigned int)-1;
+    test->timeLimit = (int64)(timeLimitSecs * cv::getTickFrequency());
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::tbb_threads(int n)
+{
+#ifdef HAVE_TBB
+    test->p_tbb_initializer.release();
+    if (n > 0)
+        test->p_tbb_initializer=new tbb::task_scheduler_init(n);
+#endif
+    (void)n;
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::runs(unsigned int runsNumber)
+{
+    test->runsPerIteration = runsNumber;
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::in(cv::InputOutputArray a1, int wtype)
+{
+    if (!test->times.empty()) return *this;
+    TestBase::declareArray(test->inputData, a1, wtype);
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::in(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype)
+{
+    if (!test->times.empty()) return *this;
+    TestBase::declareArray(test->inputData, a1, wtype);
+    TestBase::declareArray(test->inputData, a2, wtype);
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype)
+{
+    if (!test->times.empty()) return *this;
+    TestBase::declareArray(test->inputData, a1, wtype);
+    TestBase::declareArray(test->inputData, a2, wtype);
+    TestBase::declareArray(test->inputData, a3, wtype);
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::in(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype)
+{
+    if (!test->times.empty()) return *this;
+    TestBase::declareArray(test->inputData, a1, wtype);
+    TestBase::declareArray(test->inputData, a2, wtype);
+    TestBase::declareArray(test->inputData, a3, wtype);
+    TestBase::declareArray(test->inputData, a4, wtype);
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::out(cv::InputOutputArray a1, int wtype)
+{
+    if (!test->times.empty()) return *this;
+    TestBase::declareArray(test->outputData, a1, wtype);
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::out(cv::InputOutputArray a1, cv::InputOutputArray a2, int wtype)
+{
+    if (!test->times.empty()) return *this;
+    TestBase::declareArray(test->outputData, a1, wtype);
+    TestBase::declareArray(test->outputData, a2, wtype);
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, int wtype)
+{
+    if (!test->times.empty()) return *this;
+    TestBase::declareArray(test->outputData, a1, wtype);
+    TestBase::declareArray(test->outputData, a2, wtype);
+    TestBase::declareArray(test->outputData, a3, wtype);
+    return *this;
+}
+
+TestBase::_declareHelper& TestBase::_declareHelper::out(cv::InputOutputArray a1, cv::InputOutputArray a2, cv::InputOutputArray a3, cv::InputOutputArray a4, int wtype)
+{
+    if (!test->times.empty()) return *this;
+    TestBase::declareArray(test->outputData, a1, wtype);
+    TestBase::declareArray(test->outputData, a2, wtype);
+    TestBase::declareArray(test->outputData, a3, wtype);
+    TestBase::declareArray(test->outputData, a4, wtype);
+    return *this;
+}
+
+TestBase::_declareHelper::_declareHelper(TestBase* t) : test(t)
+{
+}
+
+/*****************************************************************************************\
+*                                  ::perf::PrintTo
+\*****************************************************************************************/
+namespace perf
+{
+
+void PrintTo(const MatType& t, ::std::ostream* os)
+{
+    switch( CV_MAT_DEPTH((int)t) )
+    {
+        case CV_8U:  *os << "8U";  break;
+        case CV_8S:  *os << "8S";  break;
+        case CV_16U: *os << "16U"; break;
+        case CV_16S: *os << "16S"; break;
+        case CV_32S: *os << "32S"; break;
+        case CV_32F: *os << "32F"; break;
+        case CV_64F: *os << "64F"; break;
+        case CV_USRTYPE1: *os << "USRTYPE1"; break;
+        default: *os << "INVALID_TYPE"; break;
+    }
+    *os << 'C' << CV_MAT_CN((int)t);
+}
+
+} //namespace perf
+
+/*****************************************************************************************\
+*                                  ::cv::PrintTo
+\*****************************************************************************************/
+namespace cv {
+
+void PrintTo(const Size& sz, ::std::ostream* os)
+{
+    *os << /*"Size:" << */sz.width << "x" << sz.height;
+}
+
+}  // namespace cv
+
+
+/*****************************************************************************************\
+*                                  ::cv::PrintTo
+\*****************************************************************************************/