From 3bd364fce3b87e3218630f9eb9cd6b1db11ff80a Mon Sep 17 00:00:00 2001 From: Adil Ibragimov Date: Fri, 25 Apr 2014 17:37:31 +0400 Subject: [PATCH 001/136] fixing accum_dist and operator() mismatching for HellingerDistance and KL_Divergence --- modules/flann/include/opencv2/flann/dist.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/flann/include/opencv2/flann/dist.h b/modules/flann/include/opencv2/flann/dist.h index 6a03b48a12..5d941e67fc 100644 --- a/modules/flann/include/opencv2/flann/dist.h +++ b/modules/flann/include/opencv2/flann/dist.h @@ -595,7 +595,7 @@ struct HellingerDistance typedef typename Accumulator::Type ResultType; /** - * Compute the histogram intersection distance + * Compute the Hellinger distance */ template ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const @@ -628,7 +628,8 @@ struct HellingerDistance template inline ResultType accum_dist(const U& a, const V& b, int) const { - return sqrt(static_cast(a)) - sqrt(static_cast(b)); + ResultType diff = sqrt(static_cast(a)) - sqrt(static_cast(b)); + return diff * diff; } }; @@ -729,9 +730,11 @@ struct KL_Divergence inline ResultType accum_dist(const U& a, const V& b, int) const { ResultType result = ResultType(); - ResultType ratio = (ResultType)(a / b); - if (ratio>0) { - result = a * log(ratio); + if( *b != 0 ) { + ResultType ratio = (ResultType)(a / b); + if (ratio>0) { + result = a * log(ratio); + } } return result; } From c5b4b99350d570117801a2274e84beb78773307c Mon Sep 17 00:00:00 2001 From: pradeep Date: Sat, 17 May 2014 23:44:31 +0800 Subject: [PATCH 002/136] Implemented Kullback-Leibler divergence --- modules/imgproc/doc/histograms.rst | 8 ++++++++ modules/imgproc/include/opencv2/imgproc.hpp | 3 ++- .../imgproc/include/opencv2/imgproc/types_c.h | 3 ++- modules/imgproc/src/histogram.cpp | 12 ++++++++++++ modules/imgproc/test/test_histograms.cpp | 17 +++++++++++++++-- 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/modules/imgproc/doc/histograms.rst b/modules/imgproc/doc/histograms.rst index 91199f3781..5ebf168611 100644 --- a/modules/imgproc/doc/histograms.rst +++ b/modules/imgproc/doc/histograms.rst @@ -181,6 +181,8 @@ Compares two histograms. * **CV_COMP_HELLINGER** Synonym for ``CV_COMP_BHATTACHARYYA`` + * **CV_COMP_KL_DIV** Kullback-Leibler divergence + The functions ``compareHist`` compare two dense or two sparse histograms using the specified method: * Correlation (``method=CV_COMP_CORREL``) @@ -224,6 +226,12 @@ The functions ``compareHist`` compare two dense or two sparse histograms using t d(H_1,H_2) = \sqrt{1 - \frac{1}{\sqrt{\bar{H_1} \bar{H_2} N^2}} \sum_I \sqrt{H_1(I) \cdot H_2(I)}} +* Kullback-Leibler divergence (``method=CV_COMP_KL_DIV``). + + .. math:: + + d(H_1,H_2) = \sum _I H_1(I) \log \left(\frac{H_1(I)}{H_2(I)}\right) + The function returns :math:`d(H_1, H_2)` . diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 7928ae0fe8..76d65c2802 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -204,7 +204,8 @@ enum { HISTCMP_CORREL = 0, HISTCMP_INTERSECT = 2, HISTCMP_BHATTACHARYYA = 3, HISTCMP_HELLINGER = HISTCMP_BHATTACHARYYA, - HISTCMP_CHISQR_ALT = 4 + HISTCMP_CHISQR_ALT = 4, + HISTCMP_KL_DIV = 5 }; //! the color conversion code diff --git a/modules/imgproc/include/opencv2/imgproc/types_c.h b/modules/imgproc/include/opencv2/imgproc/types_c.h index dd0d8b8a6e..de8fb62038 100644 --- a/modules/imgproc/include/opencv2/imgproc/types_c.h +++ b/modules/imgproc/include/opencv2/imgproc/types_c.h @@ -509,7 +509,8 @@ enum CV_COMP_INTERSECT =2, CV_COMP_BHATTACHARYYA =3, CV_COMP_HELLINGER =CV_COMP_BHATTACHARYYA, - CV_COMP_CHISQR_ALT =4 + CV_COMP_CHISQR_ALT =4, + CV_COMP_KL_DIV =5 }; /* Mask size for distance transform */ diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index e7e03ceeb2..1be7315acb 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -2323,6 +2323,18 @@ double cv::compareHist( InputArray _H1, InputArray _H2, int method ) s2 += b; } } + else if( method == CV_COMP_KL_DIV ) + { + for( j = 0; j < len; j++ ){ + double p = h1[j]; + double q = h2[j]; + if( p == 0.0 ) + continue; + if( q == 0.0 ) + q += 1e-10; + result += p * cv::log( p / q ); + } + } else CV_Error( CV_StsBadArg, "Unknown comparison method" ); } diff --git a/modules/imgproc/test/test_histograms.cpp b/modules/imgproc/test/test_histograms.cpp index 19ccc656b5..55f4df03c1 100644 --- a/modules/imgproc/test/test_histograms.cpp +++ b/modules/imgproc/test/test_histograms.cpp @@ -948,7 +948,7 @@ int CV_ThreshHistTest::validate_test_results( int /*test_case_idx*/ ) class CV_CompareHistTest : public CV_BaseHistTest { public: - enum { MAX_METHOD = 5 }; + enum { MAX_METHOD = 6 }; CV_CompareHistTest(); protected: @@ -1021,6 +1021,12 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ ) sq0 += v0*v0; sq1 += v1*v1; result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1); + if( fabs(v0) > DBL_EPSILON ) + { + if( fabs(v1) < DBL_EPSILON ) + v1 += 1e-10; + result0[CV_COMP_KL_DIV] += v0 * cv::log( v0 / v1 ); + } } } else @@ -1046,6 +1052,12 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ ) s0 += v0; sq0 += v0*v0; result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1); + if( fabs(v0) > DBL_EPSILON ) + { + if( fabs(v1) < DBL_EPSILON ) + v1 += 1e-10; + result0[CV_COMP_KL_DIV] += v0 * cv::log( v0 / v1 ); + } } for( node = cvInitSparseMatIterator( sparse1, &iterator ); @@ -1076,7 +1088,8 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ ) i == CV_COMP_CHISQR_ALT ? "Alternative Chi-Square" : i == CV_COMP_CORREL ? "Correlation" : i == CV_COMP_INTERSECT ? "Intersection" : - i == CV_COMP_BHATTACHARYYA ? "Bhattacharyya" : "Unknown"; + i == CV_COMP_BHATTACHARYYA ? "Bhattacharyya" : + i == CV_COMP_KL_DIV ? "Kullback-Leibler" : "Unknown"; if( cvIsNaN(v) || cvIsInf(v) ) { From e1e243588e73aa96a458f8f585f4ed055fc685d4 Mon Sep 17 00:00:00 2001 From: Sancho McCann Date: Wed, 11 Jun 2014 17:25:22 -0700 Subject: [PATCH 003/136] Bugfix: Memory leak in deletion of er_stack nodes of ERFilter. --- modules/objdetect/src/erfilter.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/objdetect/src/erfilter.cpp b/modules/objdetect/src/erfilter.cpp index e942094b1d..6651a00933 100644 --- a/modules/objdetect/src/erfilter.cpp +++ b/modules/objdetect/src/erfilter.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #include +#include #if defined _MSC_VER && _MSC_VER == 1500 typedef int int_fast32_t; @@ -57,6 +58,27 @@ using namespace std; namespace cv { +// Deletes a tree of ERStat regions starting at root. Used only +// internally to this implementation. +static void deleteERStatTree(ERStat* root) { + queue to_delete; + to_delete.push(root); + while (!to_delete.empty()) { + ERStat* n = to_delete.front(); + to_delete.pop(); + ERStat* c = n->child; + if (c != NULL) { + to_delete.push(c); + ERStat* sibling = c->next; + while (sibling != NULL) { + to_delete.push(sibling); + sibling = sibling->next; + } + } + delete n; + } +} + ERStat::ERStat(int init_level, int init_pixel, int init_x, int init_y) : pixel(init_pixel), level(init_level), area(0), perimeter(0), euler(0), probability(1.0), parent(0), child(0), next(0), prev(0), local_maxima(0), @@ -497,7 +519,7 @@ void ERFilterNM::er_tree_extract( InputArray image ) delete(stat->crossings); stat->crossings = NULL; } - delete stat; + deleteERStatTree(stat); } er_stack.clear(); From 6dd658a0af53be2de01cf9906ae39a6e314e1858 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 11 Jun 2014 16:50:38 +0400 Subject: [PATCH 004/136] optimized cv::setIdentity --- modules/core/src/matrix.cpp | 23 ++++++++++----- modules/core/src/opencl/set_identity.cl | 38 +++++++++++++++++++++---- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 653efe63ae..7023b391ad 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2758,21 +2758,30 @@ namespace cv { static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s ) { - int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), - sctype = CV_MAKE_TYPE(depth, cn == 3 ? 4 : cn), + int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), kercn = cn; + if (cn == 1) + { + kercn = std::min(ocl::predictOptimalVectorWidth(_m), 4); + if (kercn != 4) + kercn = 1; + } + int sctype = CV_MAKE_TYPE(depth, cn == 3 ? 4 : cn), rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1; ocl::Kernel k("setIdentity", ocl::core::set_identity_oclsrc, - format("-D T=%s -D T1=%s -D cn=%d -D ST=%s", ocl::memopTypeToStr(type), - ocl::memopTypeToStr(depth), cn, ocl::memopTypeToStr(sctype))); + format("-D T=%s -D T1=%s -D cn=%d -D ST=%s -D kercn=%d -D rowsPerWI=%d", + ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)), + ocl::memopTypeToStr(depth), cn, + ocl::memopTypeToStr(sctype), + kercn, rowsPerWI)); if (k.empty()) return false; UMat m = _m.getUMat(); - k.args(ocl::KernelArg::WriteOnly(m), ocl::KernelArg::Constant(Mat(1, 1, sctype, s)), - rowsPerWI); + k.args(ocl::KernelArg::WriteOnly(m, cn, kercn), + ocl::KernelArg::Constant(Mat(1, 1, sctype, s))); - size_t globalsize[2] = { m.cols, (m.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { m.cols * cn / kercn, (m.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/core/src/opencl/set_identity.cl b/modules/core/src/opencl/set_identity.cl index 6b277fe0e4..952204d3ff 100644 --- a/modules/core/src/opencl/set_identity.cl +++ b/modules/core/src/opencl/set_identity.cl @@ -43,20 +43,18 @@ // //M*/ -#if cn != 3 -#define loadpix(addr) *(__global const T *)(addr) +#if kercn != 3 #define storepix(val, addr) *(__global T *)(addr) = val #define TSIZE (int)sizeof(T) #define scalar scalar_ #else -#define loadpix(addr) vload3(0, (__global const T1 *)(addr)) #define storepix(val, addr) vstore3(val, 0, (__global T1 *)(addr)) #define TSIZE ((int)sizeof(T1)*3) #define scalar (T)(scalar_.x, scalar_.y, scalar_.z) #endif __kernel void setIdentity(__global uchar * srcptr, int src_step, int src_offset, int rows, int cols, - ST scalar_, int rowsPerWI) + ST scalar_) { int x = get_global_id(0); int y0 = get_global_id(1) * rowsPerWI; @@ -65,7 +63,35 @@ __kernel void setIdentity(__global uchar * srcptr, int src_step, int src_offset, { int src_index = mad24(y0, src_step, mad24(x, TSIZE, src_offset)); - for (int y = y0, y1 = min(rows, y0 + rowsPerWI); y < y1; ++y, src_index += src_step) - storepix(x == y ? scalar : (T)(0), srcptr + src_index); +#if kercn == cn + #pragma unroll + for (int y = y0, i = 0, y1 = min(rows, y0 + rowsPerWI); i < rowsPerWI; ++y, ++i, src_index += src_step) + if (y < y1) + storepix(x == y ? scalar : (T)(0), srcptr + src_index); +#elif kercn == 4 && cn == 1 + if (y0 < rows) + { + storepix(x == y0 >> 2 ? (T)(scalar, 0, 0, 0) : (T)(0), srcptr + src_index); + if (++y0 < rows) + { + src_index += src_step; + storepix(x == y0 >> 2 ? (T)(0, scalar, 0, 0) : (T)(0), srcptr + src_index); + + if (++y0 < rows) + { + src_index += src_step; + storepix(x == y0 >> 2 ? (T)(0, 0, scalar, 0) : (T)(0), srcptr + src_index); + + if (++y0 < rows) + { + src_index += src_step; + storepix(x == y0 >> 2 ? (T)(0, 0, 0, scalar) : (T)(0), srcptr + src_index); + } + } + } + } +#else +#error "Incorrect combination of cn && kercn" +#endif } } From 93712e913a2af63e4954df206659618d8af5ebba Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 12 Jun 2014 20:10:16 +0400 Subject: [PATCH 005/136] optimization of cv::warpAffine INTER_CUBIC --- modules/imgproc/src/imgwarp.cpp | 3 +- modules/imgproc/src/opencl/warp_affine.cl | 140 ++++++++++++++++++---- 2 files changed, 122 insertions(+), 21 deletions(-) diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index c946afc97a..34cd2c8eee 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -4187,7 +4187,8 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0, const char * const kernelName = op_type == OCL_OP_AFFINE ? "warpAffine" : "warpPerspective"; int scalarcn = cn == 3 ? 4 : cn; - int wdepth = interpolation == INTER_NEAREST ? depth : std::max(CV_32S, depth); + bool is32f = !dev.isAMD() && (interpolation == INTER_CUBIC || interpolation == INTER_LINEAR); + int wdepth = interpolation == INTER_NEAREST ? depth : std::max(is32f ? CV_32F : CV_32S, depth); int sctype = CV_MAKETYPE(wdepth, scalarcn); ocl::Kernel k; diff --git a/modules/imgproc/src/opencl/warp_affine.cl b/modules/imgproc/src/opencl/warp_affine.cl index bb041d1601..8ee34d0d65 100644 --- a/modules/imgproc/src/opencl/warp_affine.cl +++ b/modules/imgproc/src/opencl/warp_affine.cl @@ -61,6 +61,7 @@ #define AB_SCALE (1 << AB_BITS) #define INTER_REMAP_COEF_BITS 15 #define INTER_REMAP_COEF_SCALE (1 << INTER_REMAP_COEF_BITS) +#define ROUND_DELTA (1 << (AB_BITS - INTER_BITS - 1)) #define noconvert @@ -122,6 +123,14 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of #elif defined INTER_LINEAR +__constant float coeffs[64] = +{ 1.000000f, 0.000000f, 0.968750f, 0.031250f, 0.937500f, 0.062500f, 0.906250f, 0.093750f, 0.875000f, 0.125000f, 0.843750f, 0.156250f, + 0.812500f, 0.187500f, 0.781250f, 0.218750f, 0.750000f, 0.250000f, 0.718750f, 0.281250f, 0.687500f, 0.312500f, 0.656250f, 0.343750f, + 0.625000f, 0.375000f, 0.593750f, 0.406250f, 0.562500f, 0.437500f, 0.531250f, 0.468750f, 0.500000f, 0.500000f, 0.468750f, 0.531250f, + 0.437500f, 0.562500f, 0.406250f, 0.593750f, 0.375000f, 0.625000f, 0.343750f, 0.656250f, 0.312500f, 0.687500f, 0.281250f, 0.718750f, + 0.250000f, 0.750000f, 0.218750f, 0.781250f, 0.187500f, 0.812500f, 0.156250f, 0.843750f, 0.125000f, 0.875000f, 0.093750f, 0.906250f, + 0.062500f, 0.937500f, 0.031250f, 0.968750f }; + __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols, __global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols, __constant CT * M, ST scalar_) @@ -131,24 +140,21 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of if (dx < dst_cols) { - int round_delta = AB_SCALE/INTER_TAB_SIZE/2; - - int tmp = (dx << AB_BITS); + int tmp = dx << AB_BITS; int X0_ = rint(M[0] * tmp); int Y0_ = rint(M[3] * tmp); for (int dy = dy0, dy1 = min(dst_rows, dy0 + rowsPerWI); dy < dy1; ++dy) { - int X0 = X0_ + rint(fma(M[1], dy, M[2]) * AB_SCALE) + round_delta; - int Y0 = Y0_ + rint(fma(M[4], dy, M[5]) * AB_SCALE) + round_delta; + int X0 = X0_ + rint(fma(M[1], dy, M[2]) * AB_SCALE) + ROUND_DELTA; + int Y0 = Y0_ + rint(fma(M[4], dy, M[5]) * AB_SCALE) + ROUND_DELTA; X0 = X0 >> (AB_BITS - INTER_BITS); Y0 = Y0 >> (AB_BITS - INTER_BITS); - short sx = convert_short_sat(X0 >> INTER_BITS); - short sy = convert_short_sat(Y0 >> INTER_BITS); - short ax = convert_short(X0 & (INTER_TAB_SIZE-1)); - short ay = convert_short(Y0 & (INTER_TAB_SIZE-1)); + short sx = convert_short_sat(X0 >> INTER_BITS), sy = convert_short_sat(Y0 >> INTER_BITS); + short ax = convert_short(X0 & (INTER_TAB_SIZE-1)), ay = convert_short(Y0 & (INTER_TAB_SIZE-1)); +#if defined AMD_DEVICE || depth > 4 WT v0 = scalar, v1 = scalar, v2 = scalar, v3 = scalar; if (sx >= 0 && sx < src_cols) { @@ -180,8 +186,48 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of storepix(convertToT((val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS), dstptr + dst_index); #else float tabx2 = 1.0f - tabx, taby2 = 1.0f - taby; - WT val = fma(v0, tabx2 * taby2, fma(v1, tabx * taby2, fma(v2, tabx2 * taby, v3 * tabx * taby))); + WT val = fma(tabx2, fma(v0, taby2, v2 * taby), tabx * fma(v1, taby2, v3 * taby)); storepix(convertToT(val), dstptr + dst_index); +#endif +#else // INTEL_DEVICE + __constant float * coeffs_y = coeffs + (ay << 1), * coeffs_x = coeffs + (ax << 1); + + int src_index0 = mad24(sy, src_step, mad24(sx, pixsize, src_offset)), src_index; + int dst_index = mad24(dy, dst_step, mad24(dx, pixsize, dst_offset)); + + WT sum = (WT)(0), xsum; + #pragma unroll + for (int y = 0; y < 2; y++) + { + src_index = mad24(y, src_step, src_index0); + if (sy + y >= 0 && sy + y < src_rows) + { + xsum = (WT)(0); + if (sx >= 0 && sx + 2 < src_cols) + { +#if depth == 0 && cn == 1 + uchar2 value = vload2(0, srcptr + src_index); + xsum = dot(convert_float2(value), (float2)(coeffs_x[0], coeffs_x[1])); +#else + #pragma unroll + for (int x = 0; x < 2; x++) + xsum = fma(convertToWT(loadpix(srcptr + mad24(x, pixsize, src_index))), coeffs_x[x], xsum); +#endif + } + else + { + #pragma unroll + for (int x = 0; x < 2; x++) + xsum = fma(sx + x >= 0 && sx + x < src_cols ? + convertToWT(loadpix(srcptr + mad24(x, pixsize, src_index))) : scalar, coeffs_x[x], xsum); + } + sum = fma(xsum, coeffs_y[y], sum); + } + else + sum = fma(scalar, coeffs_y[y], sum); + } + + storepix(convertToT(sum), dstptr + dst_index); #endif } } @@ -189,6 +235,8 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of #elif defined INTER_CUBIC +#ifdef AMD_DEVICE + inline void interpolateCubic( float x, float* coeffs ) { const float A = -0.75f; @@ -199,6 +247,23 @@ inline void interpolateCubic( float x, float* coeffs ) coeffs[3] = 1.f - coeffs[0] - coeffs[1] - coeffs[2]; } +#else + +__constant float coeffs[128] = + { 0.000000f, 1.000000f, 0.000000f, 0.000000f, -0.021996f, 0.997841f, 0.024864f, -0.000710f, -0.041199f, 0.991516f, 0.052429f, -0.002747f, + -0.057747f, 0.981255f, 0.082466f, -0.005974f, -0.071777f, 0.967285f, 0.114746f, -0.010254f, -0.083427f, 0.949837f, 0.149040f, -0.015450f, + -0.092834f, 0.929138f, 0.185120f, -0.021423f, -0.100136f, 0.905418f, 0.222755f, -0.028038f, -0.105469f, 0.878906f, 0.261719f, -0.035156f, + -0.108971f, 0.849831f, 0.301781f, -0.042641f, -0.110779f, 0.818420f, 0.342712f, -0.050354f, -0.111031f, 0.784904f, 0.384285f, -0.058159f, + -0.109863f, 0.749512f, 0.426270f, -0.065918f, -0.107414f, 0.712471f, 0.468437f, -0.073494f, -0.103821f, 0.674011f, 0.510559f, -0.080750f, + -0.099220f, 0.634361f, 0.552406f, -0.087547f, -0.093750f, 0.593750f, 0.593750f, -0.093750f, -0.087547f, 0.552406f, 0.634361f, -0.099220f, + -0.080750f, 0.510559f, 0.674011f, -0.103821f, -0.073494f, 0.468437f, 0.712471f, -0.107414f, -0.065918f, 0.426270f, 0.749512f, -0.109863f, + -0.058159f, 0.384285f, 0.784904f, -0.111031f, -0.050354f, 0.342712f, 0.818420f, -0.110779f, -0.042641f, 0.301781f, 0.849831f, -0.108971f, + -0.035156f, 0.261719f, 0.878906f, -0.105469f, -0.028038f, 0.222755f, 0.905418f, -0.100136f, -0.021423f, 0.185120f, 0.929138f, -0.092834f, + -0.015450f, 0.149040f, 0.949837f, -0.083427f, -0.010254f, 0.114746f, 0.967285f, -0.071777f, -0.005974f, 0.082466f, 0.981255f, -0.057747f, + -0.002747f, 0.052429f, 0.991516f, -0.041199f, -0.000710f, 0.024864f, 0.997841f, -0.021996f }; + +#endif + __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols, __global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols, __constant CT * M, ST scalar_) @@ -208,22 +273,17 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of if (dx < dst_cols && dy < dst_rows) { - int round_delta = ((AB_SCALE>>INTER_BITS)>>1); - int tmp = (dx << AB_BITS); - int X0 = rint(M[0] * tmp); - int Y0 = rint(M[3] * tmp); + int X0 = rint(M[0] * tmp) + rint(fma(M[1], dy, M[2]) * AB_SCALE) + ROUND_DELTA; + int Y0 = rint(M[3] * tmp) + rint(fma(M[4], dy, M[5]) * AB_SCALE) + ROUND_DELTA; - X0 += rint(fma(M[1], dy, M[2]) * AB_SCALE) + round_delta; - Y0 += rint(fma(M[4], dy, M[5]) * AB_SCALE) + round_delta; X0 = X0 >> (AB_BITS - INTER_BITS); Y0 = Y0 >> (AB_BITS - INTER_BITS); - int sx = (short)(X0 >> INTER_BITS) - 1; - int sy = (short)(Y0 >> INTER_BITS) - 1; - int ay = (short)(Y0 & (INTER_TAB_SIZE-1)); - int ax = (short)(X0 & (INTER_TAB_SIZE-1)); + int sx = (short)(X0 >> INTER_BITS) - 1, sy = (short)(Y0 >> INTER_BITS) - 1; + int ay = (short)(Y0 & (INTER_TAB_SIZE - 1)), ax = (short)(X0 & (INTER_TAB_SIZE - 1)); +#ifdef AMD_DEVICE WT v[16]; #pragma unroll for (int y = 0; y < 4; y++) @@ -269,6 +329,46 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of for (int i = 0; i < 16; i++) sum = fma(v[i], tab1y[(i>>2)] * tab1x[(i&3)], sum); storepix(convertToT( sum ), dstptr + dst_index); +#endif +#else // INTEL_DEVICE + __constant float * coeffs_y = coeffs + (ay << 2), * coeffs_x = coeffs + (ax << 2); + + int src_index0 = mad24(sy, src_step, mad24(sx, pixsize, src_offset)), src_index; + int dst_index = mad24(dy, dst_step, mad24(dx, pixsize, dst_offset)); + + WT sum = (WT)(0), xsum; + #pragma unroll + for (int y = 0; y < 4; y++) + { + src_index = mad24(y, src_step, src_index0); + if (sy + y >= 0 && sy + y < src_rows) + { + xsum = (WT)(0); + if (sx >= 0 && sx + 4 < src_cols) + { +#if depth == 0 && cn == 1 + uchar4 value = vload4(0, srcptr + src_index); + xsum = dot(convert_float4(value), (float4)(coeffs_x[0], coeffs_x[1], coeffs_x[2], coeffs_x[3])); +#else + #pragma unroll + for (int x = 0; x < 4; x++) + xsum = fma(convertToWT(loadpix(srcptr + mad24(x, pixsize, src_index))), coeffs_x[x], xsum); +#endif + } + else + { + #pragma unroll + for (int x = 0; x < 4; x++) + xsum = fma(sx + x >= 0 && sx + x < src_cols ? + convertToWT(loadpix(srcptr + mad24(x, pixsize, src_index))) : scalar, coeffs_x[x], xsum); + } + sum = fma(xsum, coeffs_y[y], sum); + } + else + sum = fma(scalar, coeffs_y[y], sum); + } + + storepix(convertToT(sum), dstptr + dst_index); #endif } } From c41a13439424ad67f49b9407335e0710749541b7 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 17 Jun 2014 19:24:25 +0400 Subject: [PATCH 006/136] increased number of rows per work-item --- modules/imgproc/src/imgwarp.cpp | 12 +- modules/imgproc/src/opencl/remap.cl | 517 +++++++++++++++------------- 2 files changed, 286 insertions(+), 243 deletions(-) diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index c946afc97a..c6d6b1fae1 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -3582,7 +3582,9 @@ private: static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, InputArray _map2, int interpolation, int borderType, const Scalar& borderValue) { - int cn = _src.channels(), type = _src.type(), depth = _src.depth(); + const ocl::Device & dev = ocl::Device::getDefault(); + int cn = _src.channels(), type = _src.type(), depth = _src.depth(), + rowsPerWI = dev.isIntel() ? 4 : 1; if (borderType == BORDER_TRANSPARENT || !(interpolation == INTER_LINEAR || interpolation == INTER_NEAREST) || _map1.type() == CV_16SC1 || _map2.type() == CV_16SC1) @@ -3619,12 +3621,14 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input static const char * const interMap[] = { "INTER_NEAREST", "INTER_LINEAR", "INTER_CUBIC", "INTER_LINEAR", "INTER_LANCZOS" }; static const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101", "BORDER_TRANSPARENT" }; - String buildOptions = format("-D %s -D %s -D T=%s", interMap[interpolation], borderMap[borderType], ocl::typeToStr(type)); + String buildOptions = format("-D %s -D %s -D T=%s -D rowsPerWI=%d", + interMap[interpolation], borderMap[borderType], + ocl::typeToStr(type), rowsPerWI); if (interpolation != INTER_NEAREST) { char cvt[3][40]; - int wdepth = std::max(CV_32F, dst.depth()); + int wdepth = std::max(CV_32F, depth); buildOptions = buildOptions + format(" -D WT=%s -D convertToT=%s -D convertToWT=%s" " -D convertToWT2=%s -D WT2=%s", @@ -3653,7 +3657,7 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input else k.args(srcarg, dstarg, map1arg, ocl::KernelArg::ReadOnlyNoSize(map2), scalararg); - size_t globalThreads[2] = { dst.cols, dst.rows }; + size_t globalThreads[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalThreads, NULL, false); } diff --git a/modules/imgproc/src/opencl/remap.cl b/modules/imgproc/src/opencl/remap.cl index bd043c5e4b..76b5c33ac8 100644 --- a/modules/imgproc/src/opencl/remap.cl +++ b/modules/imgproc/src/opencl/remap.cl @@ -147,37 +147,43 @@ __kernel void remap_2_32FC1(__global const uchar * srcptr, int src_step, int src ST nVal) { int x = get_global_id(0); - int y = get_global_id(1); - - T scalar = convertScalar(nVal); + int y = get_global_id(1) * rowsPerWI; - if (x < dst_cols && y < dst_rows) + if (x < dst_cols) { - int map1_index = mad24(y, map1_step, x * (int)sizeof(float) + map1_offset); - int map2_index = mad24(y, map2_step, x * (int)sizeof(float) + map2_offset); - int dst_index = mad24(y, dst_step, x * TSIZE + dst_offset); - - __global const float * map1 = (__global const float *)(map1ptr + map1_index); - __global const float * map2 = (__global const float *)(map2ptr + map2_index); - __global T * dst = (__global T *)(dstptr + dst_index); - - int gx = convert_int_sat_rte(map1[0]); - int gy = convert_int_sat_rte(map2[0]); - - if (NEED_EXTRAPOLATION(gx, gy)) - { + T scalar = convertScalar(nVal); + + int map1_index = mad24(y, map1_step, mad24(x, (int)sizeof(float), map1_offset)); + int map2_index = mad24(y, map2_step, mad24(x, (int)sizeof(float), map2_offset)); + int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); + + #pragma unroll + for (int i = 0; i < rowsPerWI; ++i, ++y, + map1_index += map1_step, map2_index += map2_step, dst_index += dst_step) + if (y < dst_rows) + { + __global const float * map1 = (__global const float *)(map1ptr + map1_index); + __global const float * map2 = (__global const float *)(map2ptr + map2_index); + __global T * dst = (__global T *)(dstptr + dst_index); + + int gx = convert_int_sat_rte(map1[0]); + int gy = convert_int_sat_rte(map2[0]); + + if (NEED_EXTRAPOLATION(gx, gy)) + { #ifndef BORDER_CONSTANT - int2 gxy = (int2)(gx, gy); + int2 gxy = (int2)(gx, gy); #endif - T v; - EXTRAPOLATE(gxy, v) - storepix(v, dst); - } - else - { - int src_index = mad24(gy, src_step, gx * TSIZE + src_offset); - storepix(loadpix((__global const T*)(srcptr + src_index)), dst); - } + T v; + EXTRAPOLATE(gxy, v) + storepix(v, dst); + } + else + { + int src_index = mad24(gy, src_step, mad24(gx, TSIZE, src_offset)); + storepix(loadpix((__global const T*)(srcptr + src_index)), dst); + } + } } } @@ -187,31 +193,36 @@ __kernel void remap_32FC2(__global const uchar * srcptr, int src_step, int src_o ST nVal) { int x = get_global_id(0); - int y = get_global_id(1); - - T scalar = convertScalar(nVal); + int y = get_global_id(1) * rowsPerWI; - if (x < dst_cols && y < dst_rows) + if (x < dst_cols) { - int dst_index = mad24(y, dst_step, x * TSIZE + dst_offset); - int map_index = mad24(y, map_step, x * (int)sizeof(float2) + map_offset); - - __global const float2 * map = (__global const float2 *)(mapptr + map_index); - __global T * dst = (__global T *)(dstptr + dst_index); - - int2 gxy = convert_int2_sat_rte(map[0]); - int gx = gxy.x, gy = gxy.y; - - if (NEED_EXTRAPOLATION(gx, gy)) - { - T v; - EXTRAPOLATE(gxy, v) - storepix(v, dst); - } - else - { - int src_index = mad24(gy, src_step, gx * TSIZE + src_offset); - storepix(loadpix((__global const T *)(srcptr + src_index)), dst); + T scalar = convertScalar(nVal); + int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); + int map_index = mad24(y, map_step, mad24(x, (int)sizeof(float2), map_offset)); + + #pragma unroll + for (int i = 0; i < rowsPerWI; ++i, ++y, + map_index += map_step, dst_index += dst_step) + if (y < dst_rows) + { + __global const float2 * map = (__global const float2 *)(mapptr + map_index); + __global T * dst = (__global T *)(dstptr + dst_index); + + int2 gxy = convert_int2_sat_rte(map[0]); + int gx = gxy.x, gy = gxy.y; + + if (NEED_EXTRAPOLATION(gx, gy)) + { + T v; + EXTRAPOLATE(gxy, v) + storepix(v, dst); + } + else + { + int src_index = mad24(gy, src_step, mad24(gx, TSIZE, src_offset)); + storepix(loadpix((__global const T *)(srcptr + src_index)), dst); + } } } } @@ -222,32 +233,37 @@ __kernel void remap_16SC2(__global const uchar * srcptr, int src_step, int src_o ST nVal) { int x = get_global_id(0); - int y = get_global_id(1); - - T scalar = convertScalar(nVal); + int y = get_global_id(1) * rowsPerWI; - if (x < dst_cols && y < dst_rows) + if (x < dst_cols) { - int dst_index = mad24(y, dst_step, x * TSIZE + dst_offset); - int map_index = mad24(y, map_step, x * (int)sizeof(short2) + map_offset); - - __global const short2 * map = (__global const short2 *)(mapptr + map_index); - __global T * dst = (__global T *)(dstptr + dst_index); - - int2 gxy = convert_int2(map[0]); - int gx = gxy.x, gy = gxy.y; - - if (NEED_EXTRAPOLATION(gx, gy)) - { - T v; - EXTRAPOLATE(gxy, v) - storepix(v, dst); - } - else - { - int src_index = mad24(gy, src_step, gx * TSIZE + src_offset); - storepix(loadpix((__global const T *)(srcptr + src_index)), dst); - } + T scalar = convertScalar(nVal); + int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); + int map_index = mad24(y, map_step, mad24(x, (int)sizeof(short2), map_offset)); + + #pragma unroll + for (int i = 0; i < rowsPerWI; ++i, ++y, + map_index += map_step, dst_index += dst_step) + if (y < dst_rows) + { + __global const short2 * map = (__global const short2 *)(mapptr + map_index); + __global T * dst = (__global T *)(dstptr + dst_index); + + int2 gxy = convert_int2(map[0]); + int gx = gxy.x, gy = gxy.y; + + if (NEED_EXTRAPOLATION(gx, gy)) + { + T v; + EXTRAPOLATE(gxy, v) + storepix(v, dst); + } + else + { + int src_index = mad24(gy, src_step, mad24(gx, TSIZE, src_offset)); + storepix(loadpix((__global const T *)(srcptr + src_index)), dst); + } + } } } @@ -260,35 +276,40 @@ __kernel void remap_16SC2_16UC1(__global const uchar * srcptr, int src_step, int int x = get_global_id(0); int y = get_global_id(1); - T scalar = convertScalar(nVal); - - if (x < dst_cols && y < dst_rows) + if (x < dst_cols) { - int dst_index = mad24(y, dst_step, x * TSIZE + dst_offset); - int map1_index = mad24(y, map1_step, x * (int)sizeof(short2) + map1_offset); - int map2_index = mad24(y, map2_step, x * (int)sizeof(ushort) + map2_offset); - - __global const short2 * map1 = (__global const short2 *)(map1ptr + map1_index); - __global const ushort * map2 = (__global const ushort *)(map2ptr + map2_index); - __global T * dst = (__global T *)(dstptr + dst_index); - - int map2Value = convert_int(map2[0]) & (INTER_TAB_SIZE2 - 1); - int dx = (map2Value & (INTER_TAB_SIZE - 1)) < (INTER_TAB_SIZE >> 1) ? 1 : 0; - int dy = (map2Value >> INTER_BITS) < (INTER_TAB_SIZE >> 1) ? 1 : 0; - int2 gxy = convert_int2(map1[0]) + (int2)(dx, dy); - int gx = gxy.x, gy = gxy.y; - - if (NEED_EXTRAPOLATION(gx, gy)) - { - T v; - EXTRAPOLATE(gxy, v) - storepix(v, dst); - } - else - { - int src_index = mad24(gy, src_step, gx * TSIZE + src_offset); - storepix(loadpix((__global const T *)(srcptr + src_index)), dst); - } + T scalar = convertScalar(nVal); + int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); + int map1_index = mad24(y, map1_step, mad24(x, (int)sizeof(short2), map1_offset)); + int map2_index = mad24(y, map2_step, mad24(x, (int)sizeof(ushort), map2_offset)); + + #pragma unroll + for (int i = 0; i < rowsPerWI; ++i, ++y, + map1_index += map1_step, map2_index += map2_step, dst_index += dst_step) + if (y < dst_rows) + { + __global const short2 * map1 = (__global const short2 *)(map1ptr + map1_index); + __global const ushort * map2 = (__global const ushort *)(map2ptr + map2_index); + __global T * dst = (__global T *)(dstptr + dst_index); + + int map2Value = convert_int(map2[0]) & (INTER_TAB_SIZE2 - 1); + int dx = (map2Value & (INTER_TAB_SIZE - 1)) < (INTER_TAB_SIZE >> 1) ? 1 : 0; + int dy = (map2Value >> INTER_BITS) < (INTER_TAB_SIZE >> 1) ? 1 : 0; + int2 gxy = convert_int2(map1[0]) + (int2)(dx, dy); + int gx = gxy.x, gy = gxy.y; + + if (NEED_EXTRAPOLATION(gx, gy)) + { + T v; + EXTRAPOLATE(gxy, v) + storepix(v, dst); + } + else + { + int src_index = mad24(gy, src_step, mad24(gx, TSIZE, src_offset)); + storepix(loadpix((__global const T *)(srcptr + src_index)), dst); + } + } } } @@ -301,54 +322,60 @@ __kernel void remap_16SC2_16UC1(__global const uchar * srcptr, int src_step, int ST nVal) { int x = get_global_id(0); - int y = get_global_id(1); + int y = get_global_id(1) * rowsPerWI; - if (x < dst_cols && y < dst_rows) + if (x < dst_cols) { - int dst_index = mad24(y, dst_step, x * TSIZE + dst_offset); - int map1_index = mad24(y, map1_step, x * (int)sizeof(short2) + map1_offset); - int map2_index = mad24(y, map2_step, x * (int)sizeof(ushort) + map2_offset); - - __global const short2 * map1 = (__global const short2 *)(map1ptr + map1_index); - __global const ushort * map2 = (__global const ushort *)(map2ptr + map2_index); - __global T * dst = (__global T *)(dstptr + dst_index); - - int2 map_dataA = convert_int2(map1[0]); - int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y); - int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1); - int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1); - - ushort map2Value = (ushort)(map2[0] & (INTER_TAB_SIZE2 - 1)); - WT2 u = (WT2)(map2Value & (INTER_TAB_SIZE - 1), map2Value >> INTER_BITS) / (WT2)(INTER_TAB_SIZE); - - WT scalar = convertToWT(convertScalar(nVal)); - WT a = scalar, b = scalar, c = scalar, d = scalar; - - if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) - a = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataA.y, src_step, map_dataA.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataA, a); - - if (!NEED_EXTRAPOLATION(map_dataB.x, map_dataB.y)) - b = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataB.y, src_step, map_dataB.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataB, b); - - if (!NEED_EXTRAPOLATION(map_dataC.x, map_dataC.y)) - c = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataC.y, src_step, map_dataC.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataC, c); - - if (!NEED_EXTRAPOLATION(map_dataD.x, map_dataD.y)) - d = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataD.y, src_step, map_dataD.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataD, d); - - WT dst_data = a * (1 - u.x) * (1 - u.y) + - b * (u.x) * (1 - u.y) + - c * (1 - u.x) * (u.y) + - d * (u.x) * (u.y); - storepix(convertToT(dst_data), dst); + int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); + int map1_index = mad24(y, map1_step, mad24(x, (int)sizeof(short2), map1_offset)); + int map2_index = mad24(y, map2_step, mad24(x, (int)sizeof(ushort), map2_offset)); + + #pragma unroll + for (int i = 0; i < rowsPerWI; ++i, ++y, + map1_index += map1_step, map2_index += map2_step, dst_index += dst_step) + if (y < dst_rows) + { + __global const short2 * map1 = (__global const short2 *)(map1ptr + map1_index); + __global const ushort * map2 = (__global const ushort *)(map2ptr + map2_index); + __global T * dst = (__global T *)(dstptr + dst_index); + + int2 map_dataA = convert_int2(map1[0]); + int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y); + int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1); + int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1); + + ushort map2Value = (ushort)(map2[0] & (INTER_TAB_SIZE2 - 1)); + WT2 u = (WT2)(map2Value & (INTER_TAB_SIZE - 1), map2Value >> INTER_BITS) / (WT2)(INTER_TAB_SIZE); + + WT scalar = convertToWT(convertScalar(nVal)); + WT a = scalar, b = scalar, c = scalar, d = scalar; + + if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) + a = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataA.y, src_step, map_dataA.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataA, a); + + if (!NEED_EXTRAPOLATION(map_dataB.x, map_dataB.y)) + b = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataB.y, src_step, map_dataB.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataB, b); + + if (!NEED_EXTRAPOLATION(map_dataC.x, map_dataC.y)) + c = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataC.y, src_step, map_dataC.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataC, c); + + if (!NEED_EXTRAPOLATION(map_dataD.x, map_dataD.y)) + d = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataD.y, src_step, map_dataD.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataD, d); + + WT dst_data = a * (1 - u.x) * (1 - u.y) + + b * (u.x) * (1 - u.y) + + c * (1 - u.x) * (u.y) + + d * (u.x) * (u.y); + storepix(convertToT(dst_data), dst); + } } } @@ -359,55 +386,61 @@ __kernel void remap_2_32FC1(__global const uchar * srcptr, int src_step, int src ST nVal) { int x = get_global_id(0); - int y = get_global_id(1); + int y = get_global_id(1) * rowsPerWI; - if (x < dst_cols && y < dst_rows) + if (x < dst_cols) { - int dst_index = mad24(y, dst_step, x * TSIZE + dst_offset); - int map1_index = mad24(y, map1_step, x * (int)sizeof(float) + map1_offset); - int map2_index = mad24(y, map2_step, x * (int)sizeof(float) + map2_offset); - - __global const float * map1 = (__global const float *)(map1ptr + map1_index); - __global const float * map2 = (__global const float *)(map2ptr + map2_index); - __global T * dst = (__global T *)(dstptr + dst_index); - - float2 map_data = (float2)(map1[0], map2[0]); - - int2 map_dataA = convert_int2_sat_rtn(map_data); - int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y); - int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1); - int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1); - - float2 _u = map_data - convert_float2(map_dataA); - WT2 u = convertToWT2(convert_int2_rte(convertToWT2(_u) * (WT2)INTER_TAB_SIZE)) / (WT2)INTER_TAB_SIZE; - WT scalar = convertToWT(convertScalar(nVal)); - WT a = scalar, b = scalar, c = scalar, d = scalar; - - if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) - a = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataA.y, src_step, map_dataA.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataA, a); - - if (!NEED_EXTRAPOLATION(map_dataB.x, map_dataB.y)) - b = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataB.y, src_step, map_dataB.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataB, b); - - if (!NEED_EXTRAPOLATION(map_dataC.x, map_dataC.y)) - c = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataC.y, src_step, map_dataC.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataC, c); - - if (!NEED_EXTRAPOLATION(map_dataD.x, map_dataD.y)) - d = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataD.y, src_step, map_dataD.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataD, d); - - WT dst_data = a * (1 - u.x) * (1 - u.y) + - b * (u.x) * (1 - u.y) + - c * (1 - u.x) * (u.y) + - d * (u.x) * (u.y); - storepix(convertToT(dst_data), dst); + int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); + int map1_index = mad24(y, map1_step, mad24(x, (int)sizeof(float), map1_offset)); + int map2_index = mad24(y, map2_step, mad24(x, (int)sizeof(float), map2_offset)); + + #pragma unroll + for (int i = 0; i < rowsPerWI; ++i, ++y, + map1_index += map1_step, map2_index += map2_step, dst_index += dst_step) + if (y < dst_rows) + { + __global const float * map1 = (__global const float *)(map1ptr + map1_index); + __global const float * map2 = (__global const float *)(map2ptr + map2_index); + __global T * dst = (__global T *)(dstptr + dst_index); + + float2 map_data = (float2)(map1[0], map2[0]); + + int2 map_dataA = convert_int2_sat_rtn(map_data); + int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y); + int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1); + int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1); + + float2 _u = map_data - convert_float2(map_dataA); + WT2 u = convertToWT2(convert_int2_rte(convertToWT2(_u) * (WT2)INTER_TAB_SIZE)) / (WT2)INTER_TAB_SIZE; + WT scalar = convertToWT(convertScalar(nVal)); + WT a = scalar, b = scalar, c = scalar, d = scalar; + + if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) + a = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataA.y, src_step, map_dataA.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataA, a); + + if (!NEED_EXTRAPOLATION(map_dataB.x, map_dataB.y)) + b = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataB.y, src_step, map_dataB.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataB, b); + + if (!NEED_EXTRAPOLATION(map_dataC.x, map_dataC.y)) + c = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataC.y, src_step, map_dataC.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataC, c); + + if (!NEED_EXTRAPOLATION(map_dataD.x, map_dataD.y)) + d = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataD.y, src_step, map_dataD.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataD, d); + + WT dst_data = a * (1 - u.x) * (1 - u.y) + + b * (u.x) * (1 - u.y) + + c * (1 - u.x) * (u.y) + + d * (u.x) * (u.y); + storepix(convertToT(dst_data), dst); + } } } @@ -417,52 +450,58 @@ __kernel void remap_32FC2(__global const uchar * srcptr, int src_step, int src_o ST nVal) { int x = get_global_id(0); - int y = get_global_id(1); + int y = get_global_id(1) * rowsPerWI; - if (x < dst_cols && y < dst_rows) + if (x < dst_cols) { - int dst_index = mad24(y, dst_step, x * TSIZE + dst_offset); - int map_index = mad24(y, map_step, x * (int)sizeof(float2) + map_offset); - - __global const float2 * map = (__global const float2 *)(mapptr + map_index); - __global T * dst = (__global T *)(dstptr + dst_index); - - float2 map_data = map[0]; - int2 map_dataA = convert_int2_sat_rtn(map_data); - int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y); - int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1); - int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1); - - float2 _u = map_data - convert_float2(map_dataA); - WT2 u = convertToWT2(convert_int2_rte(convertToWT2(_u) * (WT2)INTER_TAB_SIZE)) / (WT2)INTER_TAB_SIZE; - WT scalar = convertToWT(convertScalar(nVal)); - WT a = scalar, b = scalar, c = scalar, d = scalar; - - if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) - a = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataA.y, src_step, map_dataA.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataA, a); - - if (!NEED_EXTRAPOLATION(map_dataB.x, map_dataB.y)) - b = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataB.y, src_step, map_dataB.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataB, b); - - if (!NEED_EXTRAPOLATION(map_dataC.x, map_dataC.y)) - c = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataC.y, src_step, map_dataC.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataC, c); - - if (!NEED_EXTRAPOLATION(map_dataD.x, map_dataD.y)) - d = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataD.y, src_step, map_dataD.x * TSIZE + src_offset)))); - else - EXTRAPOLATE(map_dataD, d); - - WT dst_data = a * (1 - u.x) * (1 - u.y) + - b * (u.x) * (1 - u.y) + - c * (1 - u.x) * (u.y) + - d * (u.x) * (u.y); - storepix(convertToT(dst_data), dst); + int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); + int map_index = mad24(y, map_step, mad24(x, (int)sizeof(float2), map_offset)); + + #pragma unroll + for (int i = 0; i < rowsPerWI; ++i, ++y, + map_index += map_step, dst_index += dst_step) + if (y < dst_rows) + { + __global const float2 * map = (__global const float2 *)(mapptr + map_index); + __global T * dst = (__global T *)(dstptr + dst_index); + + float2 map_data = map[0]; + int2 map_dataA = convert_int2_sat_rtn(map_data); + int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y); + int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1); + int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1); + + float2 _u = map_data - convert_float2(map_dataA); + WT2 u = convertToWT2(convert_int2_rte(convertToWT2(_u) * (WT2)INTER_TAB_SIZE)) / (WT2)INTER_TAB_SIZE; + WT scalar = convertToWT(convertScalar(nVal)); + WT a = scalar, b = scalar, c = scalar, d = scalar; + + if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) + a = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataA.y, src_step, map_dataA.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataA, a); + + if (!NEED_EXTRAPOLATION(map_dataB.x, map_dataB.y)) + b = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataB.y, src_step, map_dataB.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataB, b); + + if (!NEED_EXTRAPOLATION(map_dataC.x, map_dataC.y)) + c = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataC.y, src_step, map_dataC.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataC, c); + + if (!NEED_EXTRAPOLATION(map_dataD.x, map_dataD.y)) + d = convertToWT(loadpix((__global const T *)(srcptr + mad24(map_dataD.y, src_step, map_dataD.x * TSIZE + src_offset)))); + else + EXTRAPOLATE(map_dataD, d); + + WT dst_data = a * (1 - u.x) * (1 - u.y) + + b * (u.x) * (1 - u.y) + + c * (1 - u.x) * (u.y) + + d * (u.x) * (u.y); + storepix(convertToT(dst_data), dst); + } } } From eeddda4701042b6708645544b46b086e653f5668 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Fri, 20 Jun 2014 15:38:15 +0400 Subject: [PATCH 007/136] Optimization of cv::pyrDown for 8UC1. --- modules/imgproc/src/opencl/pyr_down.cl | 185 ++++++++++++++++++------- modules/imgproc/src/pyramids.cpp | 21 +-- 2 files changed, 150 insertions(+), 56 deletions(-) diff --git a/modules/imgproc/src/opencl/pyr_down.cl b/modules/imgproc/src/opencl/pyr_down.cl index b8b06b712b..4babf54a13 100644 --- a/modules/imgproc/src/opencl/pyr_down.cl +++ b/modules/imgproc/src/opencl/pyr_down.cl @@ -79,12 +79,16 @@ #define SRC(_x,_y) convertToFT(loadpix(srcData + mad24(_y, src_step, PIXSIZE * _x))) +#if kercn == 4 +#define SRC4(_x,_y) convert_float4(*(__global const uchar4*)(srcData + mad24(_y, src_step, PIXSIZE * _x))) +#endif + #define noconvert __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, int src_rows, int src_cols, __global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols) { - const int x = get_global_id(0); + const int x = get_global_id(0)*kercn; const int y = get_group_id(1); __local FT smem[LOCAL_SIZE + 4]; @@ -97,98 +101,185 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, FT co3 = 0.0625f; const int src_y = 2*y; + int col; - if (src_y >= 2 && src_y < src_rows - 2 && x >= 2 && x < src_cols - 2) + if (src_y >= 2 && src_y < src_rows - 2) { - sum = co3 * SRC(x, src_y - 2); - sum = sum + co2 * SRC(x, src_y - 1); - sum = sum + co1 * SRC(x, src_y ); - sum = sum + co2 * SRC(x, src_y + 1); - sum = sum + co3 * SRC(x, src_y + 2); +#if kercn == 1 + col = EXTRAPOLATE(x, src_cols); + + sum = co3* SRC(col, src_y - 2); + sum = fma(co2, SRC(col, src_y - 1), sum); + sum = fma(co1, SRC(col, src_y ), sum); + sum = fma(co2, SRC(col, src_y + 1), sum); + sum = fma(co3, SRC(col, src_y + 2), sum); smem[2 + get_local_id(0)] = sum; +#else + if (x < src_cols-4) + { + float4 sum4; + sum4 = co3* SRC4(x, src_y - 2); + sum4 = fma(co2, SRC4(x, src_y - 1), sum4); + sum4 = fma(co1, SRC4(x, src_y ), sum4); + sum4 = fma(co2, SRC4(x, src_y + 1), sum4); + sum4 = fma(co3, SRC4(x, src_y + 2), sum4); + vstore4(sum4, get_local_id(0), (__local float*) &smem[2]); + } + else + { + for (int i=0; i<4; i++) + { + col = EXTRAPOLATE(x+i, src_cols); + sum = co3* SRC(col, src_y - 2); + sum = fma(co2, SRC(col, src_y - 1), sum); + sum = fma(co1, SRC(col, src_y ), sum); + sum = fma(co2, SRC(col, src_y + 1), sum); + sum = fma(co3, SRC(col, src_y + 2), sum); + + smem[2 + 4*get_local_id(0)+i] = sum; + } + } +#endif if (get_local_id(0) < 2) { - const int left_x = x - 2; + col = EXTRAPOLATE((int)(get_group_id(0)*LOCAL_SIZE + get_local_id(0) - 2), src_cols); - sum = co3 * SRC(left_x, src_y - 2); - sum = sum + co2 * SRC(left_x, src_y - 1); - sum = sum + co1 * SRC(left_x, src_y ); - sum = sum + co2 * SRC(left_x, src_y + 1); - sum = sum + co3 * SRC(left_x, src_y + 2); + sum = co3* SRC(col, src_y - 2); + sum = fma(co2, SRC(col, src_y - 1), sum); + sum = fma(co1, SRC(col, src_y ), sum); + sum = fma(co2, SRC(col, src_y + 1), sum); + sum = fma(co3, SRC(col, src_y + 2), sum); smem[get_local_id(0)] = sum; } - if (get_local_id(0) > LOCAL_SIZE - 3) + if (get_local_id(0) > 1 && get_local_id(0) < 4) { - const int right_x = x + 2; + col = EXTRAPOLATE((int)((get_group_id(0)+1)*LOCAL_SIZE + get_local_id(0) - 2), src_cols); - sum = co3 * SRC(right_x, src_y - 2); - sum = sum + co2 * SRC(right_x, src_y - 1); - sum = sum + co1 * SRC(right_x, src_y ); - sum = sum + co2 * SRC(right_x, src_y + 1); - sum = sum + co3 * SRC(right_x, src_y + 2); + sum = co3* SRC(col, src_y - 2); + sum = fma(co2, SRC(col, src_y - 1), sum); + sum = fma(co1, SRC(col, src_y ), sum); + sum = fma(co2, SRC(col, src_y + 1), sum); + sum = fma(co3, SRC(col, src_y + 2), sum); - smem[4 + get_local_id(0)] = sum; + smem[LOCAL_SIZE + get_local_id(0)] = sum; } } - else + else // need extrapolate y { - int col = EXTRAPOLATE(x, src_cols); +#if kercn == 1 + col = EXTRAPOLATE(x, src_cols); - sum = co3 * SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); - sum = sum + co2 * SRC(col, EXTRAPOLATE(src_y - 1, src_rows)); - sum = sum + co1 * SRC(col, EXTRAPOLATE(src_y , src_rows)); - sum = sum + co2 * SRC(col, EXTRAPOLATE(src_y + 1, src_rows)); - sum = sum + co3 * SRC(col, EXTRAPOLATE(src_y + 2, src_rows)); + sum = co3* SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); + sum = fma(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); + sum = fma(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); + sum = fma(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); + sum = fma(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); smem[2 + get_local_id(0)] = sum; +#else + if (x < src_cols-4) + { + float4 sum4; + sum4 = co3* SRC4(x, EXTRAPOLATE(src_y - 2, src_rows)); + sum4 = fma(co2, SRC4(x, EXTRAPOLATE(src_y - 1, src_rows)), sum4); + sum4 = fma(co1, SRC4(x, EXTRAPOLATE(src_y , src_rows)), sum4); + sum4 = fma(co2, SRC4(x, EXTRAPOLATE(src_y + 1, src_rows)), sum4); + sum4 = fma(co3, SRC4(x, EXTRAPOLATE(src_y + 2, src_rows)), sum4); + + vstore4(sum4, get_local_id(0), (__local float*) &smem[2]); + } + else + { + for (int i=0; i<4; i++) + { + col = EXTRAPOLATE(x+i, src_cols); + sum = co3* SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); + sum = fma(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); + sum = fma(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); + sum = fma(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); + sum = fma(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); + smem[2 + 4*get_local_id(0)+i] = sum; + } + } +#endif if (get_local_id(0) < 2) { - col = EXTRAPOLATE(x - 2, src_cols); + col = EXTRAPOLATE((int)(get_group_id(0)*LOCAL_SIZE + get_local_id(0) - 2), src_cols); - sum = co3 * SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); - sum = sum + co2 * SRC(col, EXTRAPOLATE(src_y - 1, src_rows)); - sum = sum + co1 * SRC(col, EXTRAPOLATE(src_y , src_rows)); - sum = sum + co2 * SRC(col, EXTRAPOLATE(src_y + 1, src_rows)); - sum = sum + co3 * SRC(col, EXTRAPOLATE(src_y + 2, src_rows)); + sum = co3* SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); + sum = fma(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); + sum = fma(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); + sum = fma(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); + sum = fma(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); smem[get_local_id(0)] = sum; } - if (get_local_id(0) > LOCAL_SIZE - 3) + if (get_local_id(0) > 1 && get_local_id(0) < 4) { - col = EXTRAPOLATE(x + 2, src_cols); + col = EXTRAPOLATE((int)((get_group_id(0)+1)*LOCAL_SIZE + get_local_id(0) - 2), src_cols); - sum = co3 * SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); - sum = sum + co2 * SRC(col, EXTRAPOLATE(src_y - 1, src_rows)); - sum = sum + co1 * SRC(col, EXTRAPOLATE(src_y , src_rows)); - sum = sum + co2 * SRC(col, EXTRAPOLATE(src_y + 1, src_rows)); - sum = sum + co3 * SRC(col, EXTRAPOLATE(src_y + 2, src_rows)); + sum = co3* SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); + sum = fma(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); + sum = fma(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); + sum = fma(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); + sum = fma(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); - smem[4 + get_local_id(0)] = sum; + smem[LOCAL_SIZE + get_local_id(0)] = sum; } } barrier(CLK_LOCAL_MEM_FENCE); +#if kercn == 1 if (get_local_id(0) < LOCAL_SIZE / 2) { const int tid2 = get_local_id(0) * 2; - sum = co3 * smem[2 + tid2 - 2]; - sum = sum + co2 * smem[2 + tid2 - 1]; - sum = sum + co1 * smem[2 + tid2 ]; - sum = sum + co2 * smem[2 + tid2 + 1]; - sum = sum + co3 * smem[2 + tid2 + 2]; + sum = co3* smem[2 + tid2 + 2]; +#if cn == 1 + sum = sum + dot(vload4(0, (__local float*) (&smem)+tid2), (float4)(co3, co2, co1, co2)); +#else + sum = fma(co3, smem[2 + tid2 - 2], sum); + sum = fma(co2, smem[2 + tid2 - 1], sum); + sum = fma(co1, smem[2 + tid2 ], sum); + sum = fma(co2, smem[2 + tid2 + 1], sum); +#endif const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; if (dst_x < dst_cols) storepix(convertToT(sum), dstData + y * dst_step + dst_x * PIXSIZE); } +#else + int tid4 = get_local_id(0) * 4; + sum = co3* smem[2 + tid4 + 2]; + sum = fma(co3, smem[2 + tid4 - 2], sum); + sum = fma(co2, smem[2 + tid4 - 1], sum); + sum = fma(co1, smem[2 + tid4 ], sum); + sum = fma(co2, smem[2 + tid4 + 1], sum); + + int dst_x = (get_group_id(0) * LOCAL_SIZE + tid4) / 2; + + if (dst_x < dst_cols) + storepix(convertToT(sum), dstData + mad24(y, dst_step, dst_x * PIXSIZE)); + + tid4 += 2; + dst_x += 1; + + sum = co3* smem[2 + tid4 + 2]; + sum = fma(co3, smem[2 + tid4 - 2], sum); + sum = fma(co2, smem[2 + tid4 - 1], sum); + sum = fma(co1, smem[2 + tid4 ], sum); + sum = fma(co2, smem[2 + tid4 + 1], sum); + + if (dst_x < dst_cols) + storepix(convertToT(sum), dstData + mad24(y, dst_step, dst_x * PIXSIZE)); +#endif } diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index d1ed92d5d9..418d20ff45 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -405,10 +405,10 @@ typedef void (*PyrFunc)(const Mat&, Mat&, int); static bool ocl_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType) { - int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type); + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - if (channels > 4 || (depth == CV_64F && !doubleSupport)) + if (cn > 4 || (depth == CV_64F && !doubleSupport)) return false; Size ssize = _src.size(); @@ -423,17 +423,20 @@ static bool ocl_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, in int float_depth = depth == CV_64F ? CV_64F : CV_32F; const int local_size = 256; + int kercn = 1; + if (depth == CV_8U && cn == 1 && float_depth == CV_32F) + kercn = 4; const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" }; char cvt[2][50]; String buildOptions = format( "-D T=%s -D FT=%s -D convertToT=%s -D convertToFT=%s%s " - "-D T1=%s -D cn=%d -D %s -D LOCAL_SIZE=%d", - ocl::typeToStr(type), ocl::typeToStr(CV_MAKETYPE(float_depth, channels)), - ocl::convertTypeStr(float_depth, depth, channels, cvt[0]), - ocl::convertTypeStr(depth, float_depth, channels, cvt[1]), + "-D T1=%s -D cn=%d -D kercn=%d -D %s -D LOCAL_SIZE=%d", + ocl::typeToStr(type), ocl::typeToStr(CV_MAKETYPE(float_depth, cn)), + ocl::convertTypeStr(float_depth, depth, cn, cvt[0]), + ocl::convertTypeStr(depth, float_depth, cn, cvt[1]), doubleSupport ? " -D DOUBLE_SUPPORT" : "", - ocl::typeToStr(depth), channels, borderMap[borderType], local_size + ocl::typeToStr(depth), cn, kercn, borderMap[borderType], local_size ); ocl::Kernel k("pyrDown", ocl::imgproc::pyr_down_oclsrc, buildOptions); if (k.empty()) @@ -441,8 +444,8 @@ static bool ocl_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, in k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst)); - size_t localThreads[2] = { local_size, 1 }; - size_t globalThreads[2] = { src.cols, dst.rows }; + size_t localThreads[2] = { local_size/kercn, 1 }; + size_t globalThreads[2] = { (src.cols + (kercn-1))/kercn, dst.rows }; return k.run(2, globalThreads, localThreads, false); } From 007593cab796a878cac5f24242b25f17daada932 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 4 Jun 2014 15:24:29 +0400 Subject: [PATCH 008/136] cvtColor - optimized index calculations; usage of build-in functions --- modules/imgproc/src/color.cpp | 18 +- modules/imgproc/src/opencl/cvtcolor.cl | 892 ++++++++++++++---------- modules/imgproc/test/ocl/test_color.cpp | 6 +- 3 files changed, 524 insertions(+), 392 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 94401781ee..fe460ee75a 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -2730,8 +2730,6 @@ struct mRGBA2RGBA #ifdef HAVE_OPENCL -#define DIVUP(total, grain) (((total) + (grain) - 1) / (grain)) - static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) { bool ok = false; @@ -2739,23 +2737,17 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) Size sz = src.size(), dstSz = sz; int scn = src.channels(), depth = src.depth(), bidx; int dims = 2, stripeSize = 1; - size_t globalsize[] = { src.cols, src.rows }; ocl::Kernel k; if (depth != CV_8U && depth != CV_16U && depth != CV_32F) return false; - cv::String opts = format("-D depth=%d -D scn=%d ", depth, scn); - ocl::Device dev = ocl::Device::getDefault(); - int pxPerWIy = 1; - if (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU) && - !(code == CV_BGR2Luv || code == CV_RGB2Luv || code == CV_LBGR2Luv || code == CV_LRGB2Luv || - code == CV_Luv2BGR || code == CV_Luv2RGB || code == CV_Luv2LBGR || code == CV_Luv2LRGB)) - pxPerWIy = 4; - - globalsize[1] = DIVUP(globalsize[1], pxPerWIy); - opts += format("-D PIX_PER_WI_Y=%d ", pxPerWIy); + int pxPerWIy = dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU) ? 4 : 1; + + size_t globalsize[] = { src.cols, (src.rows + pxPerWIy - 1) / pxPerWIy }; + cv::String opts = format("-D depth=%d -D scn=%d -D PIX_PER_WI_Y=%d ", + depth, scn, pxPerWIy); switch (code) { diff --git a/modules/imgproc/src/opencl/cvtcolor.cl b/modules/imgproc/src/opencl/cvtcolor.cl index 5bad3eee61..da835e08f3 100644 --- a/modules/imgproc/src/opencl/cvtcolor.cl +++ b/modules/imgproc/src/opencl/cvtcolor.cl @@ -71,10 +71,6 @@ #error "invalid depth: should be 0 (CV_8U), 2 (CV_16U) or 5 (CV_32F)" #endif -#ifndef STRIPE_SIZE -#define STRIPE_SIZE 1 -#endif - #define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) enum @@ -122,8 +118,8 @@ enum ///////////////////////////////////// RGB <-> GRAY ////////////////////////////////////// -__kernel void RGB2Gray(__global const uchar* srcptr, int srcstep, int srcoffset, - __global uchar* dstptr, int dststep, int dstoffset, +__kernel void RGB2Gray(__global const uchar * srcptr, int src_step, int src_offset, + __global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols) { int x = get_global_id(0); @@ -131,27 +127,32 @@ __kernel void RGB2Gray(__global const uchar* srcptr, int srcstep, int srcoffset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + mad24(y, srcstep, srcoffset + x * scnbytes)); - __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + mad24(y, dststep, dstoffset + x * dcnbytes)); + __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + src_index); + __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + dst_index); DATA_TYPE_4 src_pix = vload4(0, src); #ifdef DEPTH_5 - dst[0] = src_pix.B_COMP * 0.114f + src_pix.G_COMP * 0.587f + src_pix.R_COMP * 0.299f; + dst[0] = fma(src_pix.B_COMP, 0.114f, fma(src_pix.G_COMP, 0.587f, src_pix.R_COMP * 0.299f)); #else - dst[0] = (DATA_TYPE)CV_DESCALE((src_pix.B_COMP * B2Y + src_pix.G_COMP * G2Y + src_pix.R_COMP * R2Y), yuv_shift); + dst[0] = (DATA_TYPE)CV_DESCALE(mad24(src_pix.B_COMP, B2Y, mad24(src_pix.G_COMP, G2Y, src_pix.R_COMP * R2Y)), yuv_shift); #endif + ++y; + src_index += src_step; + dst_index += dst_step; } - ++y; } } } -__kernel void Gray2RGB(__global const uchar* srcptr, int srcstep, int srcoffset, - __global uchar* dstptr, int dststep, int dstoffset, +__kernel void Gray2RGB(__global const uchar * srcptr, int src_step, int src_offset, + __global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols) { int x = get_global_id(0); @@ -159,20 +160,29 @@ __kernel void Gray2RGB(__global const uchar* srcptr, int srcstep, int srcoffset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + mad24(y, srcstep, srcoffset + x * scnbytes)); - __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + mad24(y, dststep, dstoffset + x * dcnbytes)); + __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + src_index); + __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + dst_index); DATA_TYPE val = src[0]; +#if dcn == 3 || defined DEPTH_5 dst[0] = dst[1] = dst[2] = val; #if dcn == 4 dst[3] = MAX_NUM; #endif +#else + *(__global DATA_TYPE_4 *)dst = (DATA_TYPE_4)(val, val, val, MAX_NUM); +#endif + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -182,8 +192,8 @@ __kernel void Gray2RGB(__global const uchar* srcptr, int srcstep, int srcoffset, __constant float c_RGB2YUVCoeffs_f[5] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f }; __constant int c_RGB2YUVCoeffs_i[5] = { B2Y, G2Y, R2Y, 8061, 14369 }; -__kernel void RGB2YUV(__global const uchar* srcptr, int srcstep, int srcoffset, - __global uchar* dstptr, int dststep, int dstoffset, +__kernel void RGB2YUV(__global const uchar* srcptr, int src_step, int src_offset, + __global uchar* dstptr, int dst_step, int dt_offset, int rows, int cols) { int x = get_global_id(0); @@ -191,34 +201,40 @@ __kernel void RGB2YUV(__global const uchar* srcptr, int srcstep, int srcoffset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dt_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + mad24(y, srcstep, srcoffset + x * scnbytes)); - __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + mad24(y, dststep, dstoffset + x * dcnbytes)); + __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + src_index); + __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + dst_index); DATA_TYPE_4 src_pix = vload4(0, src); - DATA_TYPE b=src_pix.B_COMP, g=src_pix.G_COMP, r=src_pix.R_COMP; + DATA_TYPE b = src_pix.B_COMP, g = src_pix.G_COMP, r = src_pix.R_COMP; #ifdef DEPTH_5 __constant float * coeffs = c_RGB2YUVCoeffs_f; - const DATA_TYPE Y = b * coeffs[0] + g * coeffs[1] + r * coeffs[2]; - const DATA_TYPE U = (b - Y) * coeffs[3] + HALF_MAX; - const DATA_TYPE V = (r - Y) * coeffs[4] + HALF_MAX; + const DATA_TYPE Y = fma(b, coeffs[0], fma(g, coeffs[1], r * coeffs[2])); + const DATA_TYPE U = fma(b - Y, coeffs[3], HALF_MAX); + const DATA_TYPE V = fma(r - Y, coeffs[4], HALF_MAX); #else __constant int * coeffs = c_RGB2YUVCoeffs_i; const int delta = HALF_MAX * (1 << yuv_shift); - const int Y = CV_DESCALE(b * coeffs[0] + g * coeffs[1] + r * coeffs[2], yuv_shift); - const int U = CV_DESCALE((b - Y) * coeffs[3] + delta, yuv_shift); - const int V = CV_DESCALE((r - Y) * coeffs[4] + delta, yuv_shift); + const int Y = CV_DESCALE(mad24(b, coeffs[0], mad24(g, coeffs[1], r * coeffs[2])), yuv_shift); + const int U = CV_DESCALE(mad24(b - Y, coeffs[3], delta), yuv_shift); + const int V = CV_DESCALE(mad24(r - Y, coeffs[4], delta), yuv_shift); #endif dst[0] = SAT_CAST( Y ); dst[1] = SAT_CAST( U ); dst[2] = SAT_CAST( V ); + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -226,8 +242,8 @@ __kernel void RGB2YUV(__global const uchar* srcptr, int srcstep, int srcoffset, __constant float c_YUV2RGBCoeffs_f[5] = { 2.032f, -0.395f, -0.581f, 1.140f }; __constant int c_YUV2RGBCoeffs_i[5] = { 33292, -6472, -9519, 18678 }; -__kernel void YUV2RGB(__global const uchar* srcptr, int srcstep, int srcoffset, - __global uchar* dstptr, int dststep, int dstoffset, +__kernel void YUV2RGB(__global const uchar* srcptr, int src_step, int src_offset, + __global uchar* dstptr, int dst_step, int dt_offset, int rows, int cols) { int x = get_global_id(0); @@ -235,25 +251,28 @@ __kernel void YUV2RGB(__global const uchar* srcptr, int srcstep, int srcoffset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dt_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + mad24(y, srcstep, srcoffset + x * scnbytes)); - __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + mad24(y, dststep, dstoffset + x * dcnbytes)); + __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + src_index); + __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + dst_index); DATA_TYPE_4 src_pix = vload4(0, src); DATA_TYPE Y = src_pix.x, U = src_pix.y, V = src_pix.z; #ifdef DEPTH_5 __constant float * coeffs = c_YUV2RGBCoeffs_f; - const float r = Y + (V - HALF_MAX) * coeffs[3]; - const float g = Y + (V - HALF_MAX) * coeffs[2] + (U - HALF_MAX) * coeffs[1]; - const float b = Y + (U - HALF_MAX) * coeffs[0]; + float r = fma(V - HALF_MAX, coeffs[3], Y); + float g = fma(V - HALF_MAX, coeffs[2], fma(U - HALF_MAX, coeffs[1], Y)); + float b = fma(U - HALF_MAX, coeffs[0], Y); #else __constant int * coeffs = c_YUV2RGBCoeffs_i; const int r = Y + CV_DESCALE((V - HALF_MAX) * coeffs[3], yuv_shift); - const int g = Y + CV_DESCALE((V - HALF_MAX) * coeffs[2] + (U - HALF_MAX) * coeffs[1], yuv_shift); + const int g = Y + CV_DESCALE(mad24(V - HALF_MAX, coeffs[2], (U - HALF_MAX) * coeffs[1]), yuv_shift); const int b = Y + CV_DESCALE((U - HALF_MAX) * coeffs[0], yuv_shift); #endif @@ -263,8 +282,10 @@ __kernel void YUV2RGB(__global const uchar* srcptr, int srcstep, int srcoffset, #if dcn == 4 dst[3] = MAX_NUM; #endif + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -276,8 +297,8 @@ __constant int ITUR_BT_601_CVG = 852492; __constant int ITUR_BT_601_CVR = 1673527; __constant int ITUR_BT_601_SHIFT = 20; -__kernel void YUV2RGB_NV12(__global const uchar* srcptr, int srcstep, int srcoffset, - __global uchar* dstptr, int dststep, int dstoffset, +__kernel void YUV2RGB_NV12(__global const uchar* srcptr, int src_step, int src_offset, + __global uchar* dstptr, int dst_step, int dt_offset, int rows, int cols) { int x = get_global_id(0); @@ -290,15 +311,15 @@ __kernel void YUV2RGB_NV12(__global const uchar* srcptr, int srcstep, int srcoff { if (y < rows / 2 ) { - __global const uchar* ysrc = srcptr + mad24(y << 1, srcstep, (x << 1) + srcoffset); - __global const uchar* usrc = srcptr + mad24(rows + y, srcstep, (x << 1) + srcoffset); - __global uchar* dst1 = dstptr + mad24(y << 1, dststep, x * (dcn<<1) + dstoffset); - __global uchar* dst2 = dstptr + mad24((y << 1) + 1, dststep, x * (dcn<<1) + dstoffset); + __global const uchar* ysrc = srcptr + mad24(y << 1, src_step, (x << 1) + src_offset); + __global const uchar* usrc = srcptr + mad24(rows + y, src_step, (x << 1) + src_offset); + __global uchar* dst1 = dstptr + mad24(y << 1, dst_step, x * (dcn<<1) + dt_offset); + __global uchar* dst2 = dstptr + mad24((y << 1) + 1, dst_step, x * (dcn<<1) + dt_offset); int Y1 = ysrc[0]; int Y2 = ysrc[1]; - int Y3 = ysrc[srcstep]; - int Y4 = ysrc[srcstep + 1]; + int Y3 = ysrc[src_step]; + int Y4 = ysrc[src_step + 1]; int U = usrc[0] - 128; int V = usrc[1] - 128; @@ -349,8 +370,8 @@ __kernel void YUV2RGB_NV12(__global const uchar* srcptr, int srcstep, int srcoff __constant float c_RGB2YCrCbCoeffs_f[5] = {0.299f, 0.587f, 0.114f, 0.713f, 0.564f}; __constant int c_RGB2YCrCbCoeffs_i[5] = {R2Y, G2Y, B2Y, 11682, 9241}; -__kernel void RGB2YCrCb(__global const uchar* srcptr, int srcstep, int srcoffset, - __global uchar* dstptr, int dststep, int dstoffset, +__kernel void RGB2YCrCb(__global const uchar* srcptr, int src_step, int src_offset, + __global uchar* dstptr, int dst_step, int dt_offset, int rows, int cols) { int x = get_global_id(0); @@ -358,34 +379,40 @@ __kernel void RGB2YCrCb(__global const uchar* srcptr, int srcstep, int srcoffset if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dt_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + mad24(y, srcstep, srcoffset + x * scnbytes)); - __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + mad24(y, dststep, dstoffset + x * dcnbytes)); + __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + src_index); + __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + dst_index); DATA_TYPE_4 src_pix = vload4(0, src); - DATA_TYPE b=src_pix.B_COMP, g=src_pix.G_COMP, r=src_pix.R_COMP; + DATA_TYPE b = src_pix.B_COMP, g = src_pix.G_COMP, r = src_pix.R_COMP; #ifdef DEPTH_5 __constant float * coeffs = c_RGB2YCrCbCoeffs_f; - DATA_TYPE Y = b * coeffs[2] + g * coeffs[1] + r * coeffs[0]; - DATA_TYPE Cr = (r - Y) * coeffs[3] + HALF_MAX; - DATA_TYPE Cb = (b - Y) * coeffs[4] + HALF_MAX; + DATA_TYPE Y = fma(b, coeffs[2], fma(g, coeffs[1], r * coeffs[0])); + DATA_TYPE Cr = fma(r - Y, coeffs[3], HALF_MAX); + DATA_TYPE Cb = fma(b - Y, coeffs[4], HALF_MAX); #else __constant int * coeffs = c_RGB2YCrCbCoeffs_i; int delta = HALF_MAX * (1 << yuv_shift); - int Y = CV_DESCALE(b * coeffs[2] + g * coeffs[1] + r * coeffs[0], yuv_shift); - int Cr = CV_DESCALE((r - Y) * coeffs[3] + delta, yuv_shift); - int Cb = CV_DESCALE((b - Y) * coeffs[4] + delta, yuv_shift); + int Y = CV_DESCALE(mad24(b, coeffs[2], mad24(g, coeffs[1], r * coeffs[0])), yuv_shift); + int Cr = CV_DESCALE(mad24(r - Y, coeffs[3], delta), yuv_shift); + int Cb = CV_DESCALE(mad24(b - Y, coeffs[4], delta), yuv_shift); #endif dst[0] = SAT_CAST( Y ); dst[1] = SAT_CAST( Cr ); dst[2] = SAT_CAST( Cb ); + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -402,28 +429,29 @@ __kernel void YCrCb2RGB(__global const uchar* src, int src_step, int src_offset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - __global const DATA_TYPE * srcptr = (__global const DATA_TYPE*)(src + src_idx); - __global DATA_TYPE * dstptr = (__global DATA_TYPE*)(dst + dst_idx); + __global const DATA_TYPE * srcptr = (__global const DATA_TYPE*)(src + src_index); + __global DATA_TYPE * dstptr = (__global DATA_TYPE*)(dst + dst_index); DATA_TYPE_4 src_pix = vload4(0, srcptr); DATA_TYPE y = src_pix.x, cr = src_pix.y, cb = src_pix.z; #ifdef DEPTH_5 __constant float * coeff = c_YCrCb2RGBCoeffs_f; - float r = y + coeff[0] * (cr - HALF_MAX); - float g = y + coeff[1] * (cr - HALF_MAX) + coeff[2] * (cb - HALF_MAX); - float b = y + coeff[3] * (cb - HALF_MAX); + float r = fma(coeff[0], cr - HALF_MAX, y); + float g = fma(coeff[1], cr - HALF_MAX, fma(coeff[2], cb - HALF_MAX, y)); + float b = fma(coeff[3], cb - HALF_MAX, y); #else __constant int * coeff = c_YCrCb2RGBCoeffs_i; int r = y + CV_DESCALE(coeff[0] * (cr - HALF_MAX), yuv_shift); - int g = y + CV_DESCALE(coeff[1] * (cr - HALF_MAX) + coeff[2] * (cb - HALF_MAX), yuv_shift); + int g = y + CV_DESCALE(mad24(coeff[1], cr - HALF_MAX, coeff[2] * (cb - HALF_MAX)), yuv_shift); int b = y + CV_DESCALE(coeff[3] * (cb - HALF_MAX), yuv_shift); #endif @@ -433,8 +461,11 @@ __kernel void YCrCb2RGB(__global const uchar* src, int src_step, int src_offset, #if dcn == 4 dstptr[3] = MAX_NUM; #endif + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -450,34 +481,37 @@ __kernel void RGB2XYZ(__global const uchar * srcptr, int src_step, int src_offse if (dx < cols) { + int src_index = mad24(dy, src_step, mad24(dx, scnbytes, src_offset)); + int dst_index = mad24(dy, dst_step, mad24(dx, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (dy < rows) { - int src_idx = mad24(dy, src_step, src_offset + dx * scnbytes); - int dst_idx = mad24(dy, dst_step, dst_offset + dx * dcnbytes); - - __global const DATA_TYPE * src = (__global const DATA_TYPE *)(srcptr + src_idx); - __global DATA_TYPE * dst = (__global DATA_TYPE *)(dstptr + dst_idx); + __global const DATA_TYPE * src = (__global const DATA_TYPE *)(srcptr + src_index); + __global DATA_TYPE * dst = (__global DATA_TYPE *)(dstptr + dst_index); DATA_TYPE_4 src_pix = vload4(0, src); DATA_TYPE r = src_pix.x, g = src_pix.y, b = src_pix.z; #ifdef DEPTH_5 - float x = r * coeffs[0] + g * coeffs[1] + b * coeffs[2]; - float y = r * coeffs[3] + g * coeffs[4] + b * coeffs[5]; - float z = r * coeffs[6] + g * coeffs[7] + b * coeffs[8]; + float x = fma(r, coeffs[0], fma(g, coeffs[1], b * coeffs[2])); + float y = fma(r, coeffs[3], fma(g, coeffs[4], b * coeffs[5])); + float z = fma(r, coeffs[6], fma(g, coeffs[7], b * coeffs[8])); #else - int x = CV_DESCALE(r * coeffs[0] + g * coeffs[1] + b * coeffs[2], xyz_shift); - int y = CV_DESCALE(r * coeffs[3] + g * coeffs[4] + b * coeffs[5], xyz_shift); - int z = CV_DESCALE(r * coeffs[6] + g * coeffs[7] + b * coeffs[8], xyz_shift); + int x = CV_DESCALE(mad24(r, coeffs[0], mad24(g, coeffs[1], b * coeffs[2])), xyz_shift); + int y = CV_DESCALE(mad24(r, coeffs[3], mad24(g, coeffs[4], b * coeffs[5])), xyz_shift); + int z = CV_DESCALE(mad24(r, coeffs[6], mad24(g, coeffs[7], b * coeffs[8])), xyz_shift); #endif dst[0] = SAT_CAST(x); dst[1] = SAT_CAST(y); dst[2] = SAT_CAST(z); + + ++dy; + dst_index += dst_step; + src_index += src_step; } - ++dy; } } } @@ -491,37 +525,48 @@ __kernel void XYZ2RGB(__global const uchar * srcptr, int src_step, int src_offse if (dx < cols) { + int src_index = mad24(dy, src_step, mad24(dx, scnbytes, src_offset)); + int dst_index = mad24(dy, dst_step, mad24(dx, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (dy < rows) { - int src_idx = mad24(dy, src_step, src_offset + dx * scnbytes); - int dst_idx = mad24(dy, dst_step, dst_offset + dx * dcnbytes); - - __global const DATA_TYPE * src = (__global const DATA_TYPE *)(srcptr + src_idx); - __global DATA_TYPE * dst = (__global DATA_TYPE *)(dstptr + dst_idx); + __global const DATA_TYPE * src = (__global const DATA_TYPE *)(srcptr + src_index); + __global DATA_TYPE * dst = (__global DATA_TYPE *)(dstptr + dst_index); DATA_TYPE_4 src_pix = vload4(0, src); DATA_TYPE x = src_pix.x, y = src_pix.y, z = src_pix.z; #ifdef DEPTH_5 - float b = x * coeffs[0] + y * coeffs[1] + z * coeffs[2]; - float g = x * coeffs[3] + y * coeffs[4] + z * coeffs[5]; - float r = x * coeffs[6] + y * coeffs[7] + z * coeffs[8]; + float b = fma(x, coeffs[0], fma(y, coeffs[1], z * coeffs[2])); + float g = fma(x, coeffs[3], fma(y, coeffs[4], z * coeffs[5])); + float r = fma(x, coeffs[6], fma(y, coeffs[7], z * coeffs[8])); #else - int b = CV_DESCALE(x * coeffs[0] + y * coeffs[1] + z * coeffs[2], xyz_shift); - int g = CV_DESCALE(x * coeffs[3] + y * coeffs[4] + z * coeffs[5], xyz_shift); - int r = CV_DESCALE(x * coeffs[6] + y * coeffs[7] + z * coeffs[8], xyz_shift); + int b = CV_DESCALE(mad24(x, coeffs[0], mad24(y, coeffs[1], z * coeffs[2])), xyz_shift); + int g = CV_DESCALE(mad24(x, coeffs[3], mad24(y, coeffs[4], z * coeffs[5])), xyz_shift); + int r = CV_DESCALE(mad24(x, coeffs[6], mad24(y, coeffs[7], z * coeffs[8])), xyz_shift); #endif - dst[0] = SAT_CAST(b); - dst[1] = SAT_CAST(g); - dst[2] = SAT_CAST(r); + + DATA_TYPE dst0 = SAT_CAST(b); + DATA_TYPE dst1 = SAT_CAST(g); + DATA_TYPE dst2 = SAT_CAST(r); +#if dcn == 3 || defined DEPTH_5 + dst[0] = dst0; + dst[1] = dst1; + dst[2] = dst2; #if dcn == 4 dst[3] = MAX_NUM; #endif +#else + *(__global DATA_TYPE_4 *)dst = (DATA_TYPE_4)(dst0, dst1, dst2, MAX_NUM); +#endif + + ++dy; + dst_index += dst_step; + src_index += src_step; } - ++dy; } } } @@ -537,16 +582,16 @@ __kernel void RGB(__global const uchar* srcptr, int src_step, int src_offset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - - __global const DATA_TYPE * src = (__global const DATA_TYPE *)(srcptr + src_idx); - __global DATA_TYPE * dst = (__global DATA_TYPE *)(dstptr + dst_idx); + __global const DATA_TYPE * src = (__global const DATA_TYPE *)(srcptr + src_index); + __global DATA_TYPE * dst = (__global DATA_TYPE *)(dstptr + dst_index); DATA_TYPE_4 src_pix = vload4(0, src); #ifdef REVERSE @@ -566,8 +611,11 @@ __kernel void RGB(__global const uchar* srcptr, int src_step, int src_offset, dst[3] = src[3]; #endif #endif + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -583,34 +631,38 @@ __kernel void RGB5x52RGB(__global const uchar* src, int src_step, int src_offset if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - ushort t = *((__global const ushort*)(src + src_idx)); + ushort t = *((__global const ushort*)(src + src_index)); #if greenbits == 6 - dst[dst_idx + bidx] = (uchar)(t << 3); - dst[dst_idx + 1] = (uchar)((t >> 3) & ~3); - dst[dst_idx + (bidx^2)] = (uchar)((t >> 8) & ~7); + dst[dst_index + bidx] = (uchar)(t << 3); + dst[dst_index + 1] = (uchar)((t >> 3) & ~3); + dst[dst_index + (bidx^2)] = (uchar)((t >> 8) & ~7); #else - dst[dst_idx + bidx] = (uchar)(t << 3); - dst[dst_idx + 1] = (uchar)((t >> 2) & ~7); - dst[dst_idx + (bidx^2)] = (uchar)((t >> 7) & ~7); + dst[dst_index + bidx] = (uchar)(t << 3); + dst[dst_index + 1] = (uchar)((t >> 2) & ~7); + dst[dst_index + (bidx^2)] = (uchar)((t >> 7) & ~7); #endif #if dcn == 4 #if greenbits == 6 - dst[dst_idx + 3] = 255; + dst[dst_index + 3] = 255; #else - dst[dst_idx + 3] = t & 0x8000 ? 255 : 0; + dst[dst_index + 3] = t & 0x8000 ? 255 : 0; #endif #endif + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -624,25 +676,29 @@ __kernel void RGB2RGB5x5(__global const uchar* src, int src_step, int src_offset if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - uchar4 src_pix = vload4(0, src + src_idx); + uchar4 src_pix = vload4(0, src + src_index); #if greenbits == 6 - *((__global ushort*)(dst + dst_idx)) = (ushort)((src_pix.B_COMP >> 3)|((src_pix.G_COMP&~3) << 3)|((src_pix.R_COMP&~7) << 8)); + *((__global ushort*)(dst + dst_index)) = (ushort)((src_pix.B_COMP >> 3)|((src_pix.G_COMP&~3) << 3)|((src_pix.R_COMP&~7) << 8)); #elif scn == 3 - *((__global ushort*)(dst + dst_idx)) = (ushort)((src_pix.B_COMP >> 3)|((src_pix.G_COMP&~7) << 2)|((src_pix.R_COMP&~7) << 7)); + *((__global ushort*)(dst + dst_index)) = (ushort)((src_pix.B_COMP >> 3)|((src_pix.G_COMP&~7) << 2)|((src_pix.R_COMP&~7) << 7)); #else - *((__global ushort*)(dst + dst_idx)) = (ushort)((src_pix.B_COMP >> 3)|((src_pix.G_COMP&~7) << 2)| + *((__global ushort*)(dst + dst_index)) = (ushort)((src_pix.B_COMP >> 3)|((src_pix.G_COMP&~7) << 2)| ((src_pix.R_COMP&~7) << 7)|(src_pix.w ? 0x8000 : 0)); #endif + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -658,26 +714,25 @@ __kernel void BGR5x52Gray(__global const uchar* src, int src_step, int src_offse if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, dst_offset + x); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x); - int t = *((__global const ushort*)(src + src_idx)); + int t = *((__global const ushort*)(src + src_index)); #if greenbits == 6 - dst[dst_idx] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y + - ((t >> 3) & 0xfc)*G2Y + - ((t >> 8) & 0xf8)*R2Y, yuv_shift); + dst[dst_index] = (uchar)CV_DESCALE(mad24((t << 3) & 0xf8, B2Y, mad24((t >> 3) & 0xfc, G2Y, ((t >> 8) & 0xf8) * R2Y)), yuv_shift); #else - dst[dst_idx] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y + - ((t >> 2) & 0xf8)*G2Y + - ((t >> 7) & 0xf8)*R2Y, yuv_shift); + dst[dst_index] = (uchar)CV_DESCALE(mad24((t << 3) & 0xf8, B2Y, mad24((t >> 2) & 0xf8, G2Y, ((t >> 7) & 0xf8) * R2Y)), yuv_shift); #endif + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -691,23 +746,26 @@ __kernel void Gray2BGR5x5(__global const uchar* src, int src_step, int src_offse if (x < cols) { + int src_index = mad24(y, src_step, src_offset + x); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - int t = src[src_idx]; + int t = src[src_index]; #if greenbits == 6 - *((__global ushort*)(dst + dst_idx)) = (ushort)((t >> 3) | ((t & ~3) << 3) | ((t & ~7) << 8)); + *((__global ushort*)(dst + dst_index)) = (ushort)((t >> 3) | ((t & ~3) << 3) | ((t & ~7) << 8)); #else t >>= 3; - *((__global ushort*)(dst + dst_idx)) = (ushort)(t|(t << 5)|(t << 10)); + *((__global ushort*)(dst + dst_index)) = (ushort)(t|(t << 5)|(t << 10)); #endif + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -733,40 +791,44 @@ __kernel void RGB2HSV(__global const uchar* src, int src_step, int src_offset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - uchar4 src_pix = vload4(0, src + src_idx); + uchar4 src_pix = vload4(0, src + src_index); int b = src_pix.B_COMP, g = src_pix.G_COMP, r = src_pix.R_COMP; int h, s, v = b; int vmin = b, diff; int vr, vg; - v = max( v, g ); - v = max( v, r ); - vmin = min( vmin, g ); - vmin = min( vmin, r ); + v = max(v, g); + v = max(v, r); + vmin = min(vmin, g); + vmin = min(vmin, r); diff = v - vmin; vr = v == r ? -1 : 0; vg = v == g ? -1 : 0; - s = (diff * sdiv_table[v] + (1 << (hsv_shift-1))) >> hsv_shift; + s = mad24(diff, sdiv_table[v], (1 << (hsv_shift-1))) >> hsv_shift; h = (vr & (g - b)) + - (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff)))); - h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift; + (~vr & ((vg & mad24(diff, 2, b - r)) + ((~vg) & mad24(4, diff, r - g)))); + h = mad24(h, hdiv_table[diff], (1 << (hsv_shift-1))) >> hsv_shift; h += h < 0 ? hrange : 0; - dst[dst_idx] = convert_uchar_sat_rte(h); - dst[dst_idx + 1] = (uchar)s; - dst[dst_idx + 2] = (uchar)v; + dst[dst_index] = convert_uchar_sat_rte(h); + dst[dst_index + 1] = (uchar)s; + dst[dst_index + 2] = (uchar)v; + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -780,14 +842,15 @@ __kernel void HSV2RGB(__global const uchar* src, int src_step, int src_offset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - uchar4 src_pix = vload4(0, src + src_idx); + uchar4 src_pix = vload4(0, src + src_index); float h = src_pix.x, s = src_pix.y*(1/255.f), v = src_pix.z*(1/255.f); float b, g, r; @@ -821,14 +884,17 @@ __kernel void HSV2RGB(__global const uchar* src, int src_step, int src_offset, else b = g = r = v; - dst[dst_idx + bidx] = convert_uchar_sat_rte(b*255.f); - dst[dst_idx + 1] = convert_uchar_sat_rte(g*255.f); - dst[dst_idx + (bidx^2)] = convert_uchar_sat_rte(r*255.f); + dst[dst_index + bidx] = convert_uchar_sat_rte(b*255.f); + dst[dst_index + 1] = convert_uchar_sat_rte(g*255.f); + dst[dst_index + (bidx^2)] = convert_uchar_sat_rte(r*255.f); #if dcn == 4 - dst[dst_idx + 3] = MAX_NUM; + dst[dst_index + 3] = MAX_NUM; #endif + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -844,16 +910,16 @@ __kernel void RGB2HSV(__global const uchar* srcptr, int src_step, int src_offset if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - - __global const float * src = (__global const float *)(srcptr + src_idx); - __global float * dst = (__global float *)(dstptr + dst_idx); + __global const float * src = (__global const float *)(srcptr + src_index); + __global float * dst = (__global float *)(dstptr + dst_index); float4 src_pix = vload4(0, src); float b = src_pix.B_COMP, g = src_pix.G_COMP, r = src_pix.R_COMP; @@ -873,17 +939,21 @@ __kernel void RGB2HSV(__global const uchar* srcptr, int src_step, int src_offset if( v == r ) h = (g - b)*diff; else if( v == g ) - h = (b - r)*diff + 120.f; + h = fma(b - r, diff, 120.f); else - h = (r - g)*diff + 240.f; + h = fma(r - g, diff, 240.f); - if( h < 0 ) h += 360.f; + if( h < 0 ) + h += 360.f; dst[0] = h*hscale; dst[1] = s; dst[2] = v; + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -897,16 +967,17 @@ __kernel void HSV2RGB(__global const uchar* srcptr, int src_step, int src_offset if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - __global const float * src = (__global const float *)(srcptr + src_idx); - __global float * dst = (__global float *)(dstptr + dst_idx); + __global const float * src = (__global const float *)(srcptr + src_index); + __global float * dst = (__global float *)(dstptr + dst_index); float4 src_pix = vload4(0, src); float h = src_pix.x, s = src_pix.y, v = src_pix.z; @@ -947,8 +1018,11 @@ __kernel void HSV2RGB(__global const uchar* srcptr, int src_step, int src_offset #if dcn == 4 dst[3] = MAX_NUM; #endif + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -968,14 +1042,15 @@ __kernel void RGB2HLS(__global const uchar* src, int src_step, int src_offset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - uchar4 src_pix = vload4(0, src + src_idx); + uchar4 src_pix = vload4(0, src + src_index); float b = src_pix.B_COMP*(1/255.f), g = src_pix.G_COMP*(1/255.f), r = src_pix.R_COMP*(1/255.f); float h = 0.f, s = 0.f, l; @@ -998,18 +1073,22 @@ __kernel void RGB2HLS(__global const uchar* src, int src_step, int src_offset, if( vmax == r ) h = (g - b)*diff; else if( vmax == g ) - h = (b - r)*diff + 120.f; + h = fma(b - r, diff, 120.f); else - h = (r - g)*diff + 240.f; + h = fma(r - g, diff, 240.f); - if( h < 0.f ) h += 360.f; + if( h < 0.f ) + h += 360.f; } - dst[dst_idx] = convert_uchar_sat_rte(h*hscale); - dst[dst_idx + 1] = convert_uchar_sat_rte(l*255.f); - dst[dst_idx + 2] = convert_uchar_sat_rte(s*255.f); + dst[dst_index] = convert_uchar_sat_rte(h*hscale); + dst[dst_index + 1] = convert_uchar_sat_rte(l*255.f); + dst[dst_index + 2] = convert_uchar_sat_rte(s*255.f); + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1023,14 +1102,15 @@ __kernel void HLS2RGB(__global const uchar* src, int src_step, int src_offset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - uchar4 src_pix = vload4(0, src + src_idx); + uchar4 src_pix = vload4(0, src + src_index); float h = src_pix.x, l = src_pix.y*(1.f/255.f), s = src_pix.z*(1.f/255.f); float b, g, r; @@ -1053,8 +1133,8 @@ __kernel void HLS2RGB(__global const uchar* src, int src_step, int src_offset, tab[0] = p2; tab[1] = p1; - tab[2] = p1 + (p2 - p1)*(1-h); - tab[3] = p1 + (p2 - p1)*h; + tab[2] = fma(p2 - p1, 1-h, p1); + tab[3] = fma(p2 - p1, h, p1); b = tab[sector_data[sector][0]]; g = tab[sector_data[sector][1]]; @@ -1063,14 +1143,17 @@ __kernel void HLS2RGB(__global const uchar* src, int src_step, int src_offset, else b = g = r = l; - dst[dst_idx + bidx] = convert_uchar_sat_rte(b*255.f); - dst[dst_idx + 1] = convert_uchar_sat_rte(g*255.f); - dst[dst_idx + (bidx^2)] = convert_uchar_sat_rte(r*255.f); + dst[dst_index + bidx] = convert_uchar_sat_rte(b*255.f); + dst[dst_index + 1] = convert_uchar_sat_rte(g*255.f); + dst[dst_index + (bidx^2)] = convert_uchar_sat_rte(r*255.f); #if dcn == 4 - dst[dst_idx + 3] = MAX_NUM; + dst[dst_index + 3] = MAX_NUM; #endif + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1086,16 +1169,16 @@ __kernel void RGB2HLS(__global const uchar* srcptr, int src_step, int src_offset if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - - __global const float * src = (__global const float *)(srcptr + src_idx); - __global float * dst = (__global float *)(dstptr + dst_idx); + __global const float * src = (__global const float *)(srcptr + src_index); + __global float * dst = (__global float *)(dstptr + dst_index); float4 src_pix = vload4(0, src); float b = src_pix.B_COMP, g = src_pix.G_COMP, r = src_pix.R_COMP; @@ -1119,9 +1202,9 @@ __kernel void RGB2HLS(__global const uchar* srcptr, int src_step, int src_offset if( vmax == r ) h = (g - b)*diff; else if( vmax == g ) - h = (b - r)*diff + 120.f; + h = fma(b - r, diff, 120.f); else - h = (r - g)*diff + 240.f; + h = fma(r - g, diff, 240.f); if( h < 0.f ) h += 360.f; } @@ -1129,8 +1212,11 @@ __kernel void RGB2HLS(__global const uchar* srcptr, int src_step, int src_offset dst[0] = h*hscale; dst[1] = l; dst[2] = s; + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1144,16 +1230,16 @@ __kernel void HLS2RGB(__global const uchar* srcptr, int src_step, int src_offset if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - - __global const float * src = (__global const float *)(srcptr + src_idx); - __global float * dst = (__global float *)(dstptr + dst_idx); + __global const float * src = (__global const float *)(srcptr + src_index); + __global float * dst = (__global float *)(dstptr + dst_index); float4 src_pix = vload4(0, src); float h = src_pix.x, l = src_pix.y, s = src_pix.z; @@ -1178,8 +1264,8 @@ __kernel void HLS2RGB(__global const uchar* srcptr, int src_step, int src_offset tab[0] = p2; tab[1] = p1; - tab[2] = p1 + (p2 - p1)*(1-h); - tab[3] = p1 + (p2 - p1)*h; + tab[2] = fma(p2 - p1, 1-h, p1); + tab[3] = fma(p2 - p1, h, p1); b = tab[sector_data[sector][0]]; g = tab[sector_data[sector][1]]; @@ -1194,8 +1280,11 @@ __kernel void HLS2RGB(__global const uchar* srcptr, int src_step, int src_offset #if dcn == 4 dst[3] = MAX_NUM; #endif + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1215,24 +1304,25 @@ __kernel void RGBA2mRGBA(__global const uchar* src, int src_step, int src_offset if (x < cols) { + int src_index = mad24(y, src_step, src_offset + (x << 2)); + int dst_index = mad24(y, dst_step, dst_offset + (x << 2)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + (x << 2)); - int dst_idx = mad24(y, dst_step, dst_offset + (x << 2)); - uchar4 src_pix = vload4(0, src + src_idx); + uchar4 src_pix = *(__global const uchar4 *)(src + src_index); - uchar v0 = src_pix.x, v1 = src_pix.y; - uchar v2 = src_pix.z, v3 = src_pix.w; + *(__global uchar4 *)(dst + dst_index) = + (uchar4)(mad24(src_pix.x, src_pix.w, HALF_MAX) / MAX_NUM, + mad24(src_pix.y, src_pix.w, HALF_MAX) / MAX_NUM, + mad24(src_pix.z, src_pix.w, HALF_MAX) / MAX_NUM, src_pix.w); - dst[dst_idx] = (v0 * v3 + HALF_MAX) / MAX_NUM; - dst[dst_idx + 1] = (v1 * v3 + HALF_MAX) / MAX_NUM; - dst[dst_idx + 2] = (v2 * v3 + HALF_MAX) / MAX_NUM; - dst[dst_idx + 3] = v3; + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1246,25 +1336,29 @@ __kernel void mRGBA2RGBA(__global const uchar* src, int src_step, int src_offset if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, 4, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, 4, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + (x << 2)); - int dst_idx = mad24(y, dst_step, dst_offset + (x << 2)); - uchar4 src_pix = vload4(0, src + src_idx); - - uchar v0 = src_pix.x, v1 = src_pix.y; - uchar v2 = src_pix.z, v3 = src_pix.w; - uchar v3_half = v3 / 2; - - dst[dst_idx] = v3 == 0 ? 0 : (v0 * MAX_NUM + v3_half) / v3; - dst[dst_idx + 1] = v3 == 0 ? 0 : (v1 * MAX_NUM + v3_half) / v3; - dst[dst_idx + 2] = v3 == 0 ? 0 : (v2 * MAX_NUM + v3_half) / v3; - dst[dst_idx + 3] = v3; + uchar4 src_pix = *(__global const uchar4 *)(src + src_index); + uchar v3 = src_pix.w, v3_half = v3 / 2; + + if (v3 == 0) + *(__global uchar4 *)(dst + dst_index) = (uchar4)(0, 0, 0, 0); + else + *(__global uchar4 *)(dst + dst_index) = + (uchar4)(mad24(src_pix.x, MAX_NUM, v3_half) / v3, + mad24(src_pix.y, MAX_NUM, v3_half) / v3, + mad24(src_pix.z, MAX_NUM, v3_half) / v3, v3); + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1283,8 +1377,8 @@ inline float splineInterpolate(float x, __global const float * tab, int n) { int ix = clamp(convert_int_sat_rtn(x), 0, n-1); x -= ix; - tab += ix*4; - return ((tab[3]*x + tab[2])*x + tab[1])*x + tab[0]; + tab += ix << 2; + return fma(fma(fma(tab[3], x, tab[2]), x, tab[1]), x, tab[0]); } #ifdef DEPTH_0 @@ -1299,16 +1393,16 @@ __kernel void BGR2Lab(__global const uchar * src, int src_step, int src_offset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - - __global const uchar* src_ptr = src + src_idx; - __global uchar* dst_ptr = dst + dst_idx; + __global const uchar* src_ptr = src + src_index; + __global uchar* dst_ptr = dst + dst_index; uchar4 src_pix = vload4(0, src_ptr); int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], @@ -1316,19 +1410,22 @@ __kernel void BGR2Lab(__global const uchar * src, int src_step, int src_offset, C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8]; int R = gammaTab[src_pix.x], G = gammaTab[src_pix.y], B = gammaTab[src_pix.z]; - int fX = LabCbrtTab_b[CV_DESCALE(R*C0 + G*C1 + B*C2, lab_shift)]; - int fY = LabCbrtTab_b[CV_DESCALE(R*C3 + G*C4 + B*C5, lab_shift)]; - int fZ = LabCbrtTab_b[CV_DESCALE(R*C6 + G*C7 + B*C8, lab_shift)]; + int fX = LabCbrtTab_b[CV_DESCALE(mad24(R, C0, mad24(G, C1, B*C2)), lab_shift)]; + int fY = LabCbrtTab_b[CV_DESCALE(mad24(R, C3, mad24(G, C4, B*C5)), lab_shift)]; + int fZ = LabCbrtTab_b[CV_DESCALE(mad24(R, C6, mad24(G, C7, B*C8)), lab_shift)]; int L = CV_DESCALE( Lscale*fY + Lshift, lab_shift2 ); - int a = CV_DESCALE( 500*(fX - fY) + 128*(1 << lab_shift2), lab_shift2 ); - int b = CV_DESCALE( 200*(fY - fZ) + 128*(1 << lab_shift2), lab_shift2 ); + int a = CV_DESCALE( mad24(500, fX - fY, 128*(1 << lab_shift2)), lab_shift2 ); + int b = CV_DESCALE( mad24(200, fY - fZ, 128*(1 << lab_shift2)), lab_shift2 ); dst_ptr[0] = SAT_CAST(L); dst_ptr[1] = SAT_CAST(a); dst_ptr[2] = SAT_CAST(b); + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1347,16 +1444,16 @@ __kernel void BGR2Lab(__global const uchar * srcptr, int src_step, int src_offse if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - - __global const float * src = (__global const float *)(srcptr + src_idx); - __global float * dst = (__global float *)(dstptr + dst_idx); + __global const float * src = (__global const float *)(srcptr + src_index); + __global float * dst = (__global float *)(dstptr + dst_index); float4 src_pix = vload4(0, src); float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], @@ -1373,23 +1470,26 @@ __kernel void BGR2Lab(__global const uchar * srcptr, int src_step, int src_offse B = splineInterpolate(B * GammaTabScale, gammaTab, GAMMA_TAB_SIZE); #endif - float X = R*C0 + G*C1 + B*C2; - float Y = R*C3 + G*C4 + B*C5; - float Z = R*C6 + G*C7 + B*C8; + float X = fma(R, C0, fma(G, C1, B*C2)); + float Y = fma(R, C3, fma(G, C4, B*C5)); + float Z = fma(R, C6, fma(G, C7, B*C8)); - float FX = X > 0.008856f ? pow(X, _1_3) : (7.787f * X + _a); - float FY = Y > 0.008856f ? pow(Y, _1_3) : (7.787f * Y + _a); - float FZ = Z > 0.008856f ? pow(Z, _1_3) : (7.787f * Z + _a); + float FX = X > 0.008856f ? rootn(X, 3) : fma(7.787f, X, _a); + float FY = Y > 0.008856f ? rootn(Y, 3) : fma(7.787f, Y, _a); + float FZ = Z > 0.008856f ? rootn(Z, 3) : fma(7.787f, Z, _a); - float L = Y > 0.008856f ? (116.f * FY - 16.f) : (903.3f * Y); + float L = Y > 0.008856f ? fma(116.f, FY, -16.f) : (903.3f * Y); float a = 500.f * (FX - FY); float b = 200.f * (FY - FZ); dst[0] = L; dst[1] = a; dst[2] = b; + + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1412,7 +1512,7 @@ inline void Lab2BGR_f(const float * srcbuf, float * dstbuf, if (li <= lThresh) { y = li / 903.3f; - fy = 7.787f * y + 16.0f / 116.0f; + fy = fma(7.787f, y, 16.0f / 116.0f); } else { @@ -1422,6 +1522,7 @@ inline void Lab2BGR_f(const float * srcbuf, float * dstbuf, float fxz[] = { ai / 500.0f + fy, fy - bi / 200.0f }; + #pragma unroll for (int j = 0; j < 2; j++) if (fxz[j] <= fThresh) fxz[j] = (fxz[j] - 16.0f / 116.0f) / 7.787f; @@ -1429,9 +1530,9 @@ inline void Lab2BGR_f(const float * srcbuf, float * dstbuf, fxz[j] = fxz[j] * fxz[j] * fxz[j]; float x = fxz[0], z = fxz[1]; - float ro = clamp(C0 * x + C1 * y + C2 * z, 0.0f, 1.0f); - float go = clamp(C3 * x + C4 * y + C5 * z, 0.0f, 1.0f); - float bo = clamp(C6 * x + C7 * y + C8 * z, 0.0f, 1.0f); + float ro = clamp(fma(C0, x, fma(C1, y, C2 * z)), 0.0f, 1.0f); + float go = clamp(fma(C3, x, fma(C4, y, C5 * z)), 0.0f, 1.0f); + float bo = clamp(fma(C6, x, fma(C7, y, C8 * z)), 0.0f, 1.0f); #ifdef SRGB ro = splineInterpolate(ro * GammaTabScale, gammaTab, GAMMA_TAB_SIZE); @@ -1456,16 +1557,16 @@ __kernel void Lab2BGR(__global const uchar * src, int src_step, int src_offset, if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - - __global const uchar* src_ptr = src + src_idx; - __global uchar* dst_ptr = dst + dst_idx; + __global const uchar* src_ptr = src + src_index; + __global uchar * dst_ptr = dst + dst_index; uchar4 src_pix = vload4(0, src_ptr); float srcbuf[3], dstbuf[3]; @@ -1479,14 +1580,18 @@ __kernel void Lab2BGR(__global const uchar * src, int src_step, int src_offset, #endif coeffs, lThresh, fThresh); +#if dcn == 3 dst_ptr[0] = SAT_CAST(dstbuf[0] * 255.0f); dst_ptr[1] = SAT_CAST(dstbuf[1] * 255.0f); dst_ptr[2] = SAT_CAST(dstbuf[2] * 255.0f); -#if dcn == 4 - dst_ptr[3] = MAX_NUM; +#else + *(__global uchar4 *)dst_ptr = (uchar4)(SAT_CAST(dstbuf[0] * 255.0f), + SAT_CAST(dstbuf[1] * 255.0f), SAT_CAST(dstbuf[2] * 255.0f), MAX_NUM); #endif + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1505,16 +1610,16 @@ __kernel void Lab2BGR(__global const uchar * srcptr, int src_step, int src_offse if (x < cols) { + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + #pragma unroll for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) { if (y < rows) { - int src_idx = mad24(y, src_step, src_offset + x * scnbytes); - int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes); - - __global const float * src = (__global const float *)(srcptr + src_idx); - __global float * dst = (__global float *)(dstptr + dst_idx); + __global const float * src = (__global const float *)(srcptr + src_index); + __global float * dst = (__global float *)(dstptr + dst_index); float4 src_pix = vload4(0, src); float srcbuf[3], dstbuf[3]; @@ -1530,8 +1635,10 @@ __kernel void Lab2BGR(__global const uchar * srcptr, int src_step, int src_offse #if dcn == 4 dst[3] = MAX_NUM; #endif + ++y; + dst_index += dst_step; + src_index += src_step; } - ++y; } } } @@ -1555,37 +1662,46 @@ __kernel void BGR2Luv(__global const uchar * srcptr, int src_step, int src_offse __global const float * LabCbrtTab, __constant float * coeffs, float _un, float _vn) { int x = get_global_id(0); - int y = get_global_id(1); + int y = get_global_id(1) * PIX_PER_WI_Y; - if (x < cols && y < rows) + if (x < cols) { - int src_idx = mad24(y, src_step, mad24(x, scnbytes, src_offset)); - int dst_idx = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); - __global const float * src = (__global const float *)(srcptr + src_idx); - __global float * dst = (__global float *)(dstptr + dst_idx); + #pragma unroll + for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) + if (y < rows) + { + __global const float * src = (__global const float *)(srcptr + src_index); + __global float * dst = (__global float *)(dstptr + dst_index); - float R = src[0], G = src[1], B = src[2]; + float R = src[0], G = src[1], B = src[2]; #ifdef SRGB - R = splineInterpolate(R*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); - G = splineInterpolate(G*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); - B = splineInterpolate(B*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + B = splineInterpolate(B*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); #endif - float X = R*coeffs[0] + G*coeffs[1] + B*coeffs[2]; - float Y = R*coeffs[3] + G*coeffs[4] + B*coeffs[5]; - float Z = R*coeffs[6] + G*coeffs[7] + B*coeffs[8]; + float X = fma(R, coeffs[0], fma(G, coeffs[1], B*coeffs[2])); + float Y = fma(R, coeffs[3], fma(G, coeffs[4], B*coeffs[5])); + float Z = fma(R, coeffs[6], fma(G, coeffs[7], B*coeffs[8])); - float L = splineInterpolate(Y*LabCbrtTabScale, LabCbrtTab, LAB_CBRT_TAB_SIZE); - L = 116.f*L - 16.f; + float L = splineInterpolate(Y*LabCbrtTabScale, LabCbrtTab, LAB_CBRT_TAB_SIZE); + L = fma(116.f, L, -16.f); - float d = (4*13) / max(X + 15 * Y + 3 * Z, FLT_EPSILON); - float u = L*(X*d - _un); - float v = L*((9*0.25f)*Y*d - _vn); + float d = 52.0f / fmax(fma(15.0f, Y, fma(3.0f, Z, X)), FLT_EPSILON); + float u = L*fma(X, d, -_un); + float v = L*fma(2.25f, Y*d, -_vn); - dst[0] = L; - dst[1] = u; - dst[2] = v; + dst[0] = L; + dst[1] = u; + dst[2] = v; + + ++y; + dst_index += dst_step; + src_index += src_step; + } } } @@ -1599,38 +1715,44 @@ __kernel void BGR2Luv(__global const uchar * src, int src_step, int src_offset, __global const float * LabCbrtTab, __constant float * coeffs, float _un, float _vn) { int x = get_global_id(0); - int y = get_global_id(1); + int y = get_global_id(1) * PIX_PER_WI_Y; - if (x < cols && y < rows) + if (x < cols) { - int src_idx = mad24(y, src_step, mad24(x, scnbytes, src_offset)); - int dst_idx = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + src += mad24(y, src_step, mad24(x, scnbytes, src_offset)); + dst += mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); - src += src_idx; - dst += dst_idx; - - float scale = 1.0f / 255.0f; - float R = src[0]*scale, G = src[1]*scale, B = src[2]*scale; + #pragma unroll + for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) + if (y < rows) + { + float scale = 1.0f / 255.0f; + float R = src[0]*scale, G = src[1]*scale, B = src[2]*scale; #ifdef SRGB - R = splineInterpolate(R*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); - G = splineInterpolate(G*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); - B = splineInterpolate(B*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + B = splineInterpolate(B*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); #endif - float X = R*coeffs[0] + G*coeffs[1] + B*coeffs[2]; - float Y = R*coeffs[3] + G*coeffs[4] + B*coeffs[5]; - float Z = R*coeffs[6] + G*coeffs[7] + B*coeffs[8]; + float X = fma(R, coeffs[0], fma(G, coeffs[1], B*coeffs[2])); + float Y = fma(R, coeffs[3], fma(G, coeffs[4], B*coeffs[5])); + float Z = fma(R, coeffs[6], fma(G, coeffs[7], B*coeffs[8])); + + float L = splineInterpolate(Y*LabCbrtTabScale, LabCbrtTab, LAB_CBRT_TAB_SIZE); + L = 116.f*L - 16.f; - float L = splineInterpolate(Y*LabCbrtTabScale, LabCbrtTab, LAB_CBRT_TAB_SIZE); - L = 116.f*L - 16.f; + float d = (4*13) / fmax(fma(15.0f, Y, fma(3.0f, Z, X)), FLT_EPSILON); + float u = L*(X*d - _un); + float v = L*fma(2.25f, Y*d, -_vn); - float d = (4*13) / max(X + 15 * Y + 3 * Z, FLT_EPSILON); - float u = L*(X*d - _un); - float v = L*((9*0.25f)*Y*d - _vn); + dst[0] = SAT_CAST(L * 2.55f); + dst[1] = SAT_CAST(fma(u, 0.72033898305084743f, 96.525423728813564f)); + dst[2] = SAT_CAST(fma(v, 0.99609375f, 139.453125f)); - dst[0] = SAT_CAST(L * 2.55f); - dst[1] = SAT_CAST(mad(u, 0.72033898305084743f, 96.525423728813564f)); - dst[2] = SAT_CAST(mad(v, 0.99609375f, 139.453125f)); + ++y; + dst += dst_step; + src += src_step; + } } } @@ -1646,42 +1768,50 @@ __kernel void Luv2BGR(__global const uchar * srcptr, int src_step, int src_offse __constant float * coeffs, float _un, float _vn) { int x = get_global_id(0); - int y = get_global_id(1); + int y = get_global_id(1) * PIX_PER_WI_Y; - if (x < cols && y < rows) + if (x < cols) { - int src_idx = mad24(y, src_step, mad24(x, scnbytes, src_offset)); - int dst_idx = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); - - __global const float * src = (__global const float *)(srcptr + src_idx); - __global float * dst = (__global float *)(dstptr + dst_idx); - - float L = src[0], u = src[1], v = src[2], d, X, Y, Z; - Y = (L + 16.f) * (1.f/116.f); - Y = Y*Y*Y; - d = (1.f/13.f)/L; - u = u*d + _un; - v = v*d + _vn; - float iv = 1.f/v; - X = 2.25f * u * Y * iv ; - Z = (12 - 3 * u - 20 * v) * Y * 0.25f * iv; - - float R = X*coeffs[0] + Y*coeffs[1] + Z*coeffs[2]; - float G = X*coeffs[3] + Y*coeffs[4] + Z*coeffs[5]; - float B = X*coeffs[6] + Y*coeffs[7] + Z*coeffs[8]; + int src_index = mad24(y, src_step, mad24(x, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + + #pragma unroll + for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) + if (y < rows) + { + __global const float * src = (__global const float *)(srcptr + src_index); + __global float * dst = (__global float *)(dstptr + dst_index); + + float L = src[0], u = src[1], v = src[2], d, X, Y, Z; + Y = (L + 16.f) * (1.f/116.f); + Y = Y*Y*Y; + d = (1.f/13.f)/L; + u = fma(u, d, _un); + v = fma(v, d, _vn); + float iv = 1.f/v; + X = 2.25f * u * Y * iv; + Z = (12 - fma(3.0f, u, 20.0f * v)) * Y * 0.25f * iv; + + float R = fma(X, coeffs[0], fma(Y, coeffs[1], Z * coeffs[2])); + float G = fma(X, coeffs[3], fma(Y, coeffs[4], Z * coeffs[5])); + float B = fma(X, coeffs[6], fma(Y, coeffs[7], Z * coeffs[8])); #ifdef SRGB - R = splineInterpolate(R*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); - G = splineInterpolate(G*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); - B = splineInterpolate(B*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + B = splineInterpolate(B*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); #endif - dst[0] = R; - dst[1] = G; - dst[2] = B; + dst[0] = R; + dst[1] = G; + dst[2] = B; #if dcn == 4 - dst[3] = MAX_NUM; + dst[3] = MAX_NUM; #endif + ++y; + dst_index += dst_step; + src_index += src_step; + } } } @@ -1695,46 +1825,56 @@ __kernel void Luv2BGR(__global const uchar * src, int src_step, int src_offset, __constant float * coeffs, float _un, float _vn) { int x = get_global_id(0); - int y = get_global_id(1); + int y = get_global_id(1) * PIX_PER_WI_Y; - if (x < cols && y < rows) + if (x < cols) { - int src_idx = mad24(y, src_step, mad24(x, scnbytes, src_offset)); - int dst_idx = mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); - - src += src_idx; - dst += dst_idx; - - float d, X, Y, Z; - float L = src[0]*(100.f/255.f); - float u = (float)(src[1]*1.388235294117647f - 134.f); - float v = (float)(src[2]*1.003921568627451f - 140.f); - Y = (L + 16.f) * (1.f/116.f); - Y = Y*Y*Y; - d = (1.f/13.f)/L; - u = u*d + _un; - v = v*d + _vn; - float iv = 1.f/v; - X = 2.25f * u * Y * iv ; - Z = (12 - 3 * u - 20 * v) * Y * 0.25f * iv; - - float R = X*coeffs[0] + Y*coeffs[1] + Z*coeffs[2]; - float G = X*coeffs[3] + Y*coeffs[4] + Z*coeffs[5]; - float B = X*coeffs[6] + Y*coeffs[7] + Z*coeffs[8]; + src += mad24(y, src_step, mad24(x, scnbytes, src_offset)); + dst += mad24(y, dst_step, mad24(x, dcnbytes, dst_offset)); + + #pragma unroll + for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) + if (y < rows) + { + float d, X, Y, Z; + float L = src[0]*(100.f/255.f); + float u = fma(convert_float(src[1]), 1.388235294117647f, -134.f); + float v = fma(convert_float(src[2]), 1.003921568627451f, - 140.f); + Y = (L + 16.f) * (1.f/116.f); + Y = Y*Y*Y; + d = (1.f/13.f)/L; + u = fma(u, d, _un); + v = fma(v, d, _vn); + float iv = 1.f/v; + X = 2.25f * u * Y * iv ; + Z = (12 - fma(3.0f, u, 20.0f * v)) * Y * 0.25f * iv; + + float R = fma(X, coeffs[0], fma(Y, coeffs[1], Z * coeffs[2])); + float G = fma(X, coeffs[3], fma(Y, coeffs[4], Z * coeffs[5])); + float B = fma(X, coeffs[6], fma(Y, coeffs[7], Z * coeffs[8])); #ifdef SRGB - R = splineInterpolate(R*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); - G = splineInterpolate(G*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); - B = splineInterpolate(B*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); + B = splineInterpolate(B*GammaTabScale, gammaTab, GAMMA_TAB_SIZE); #endif - dst[0] = SAT_CAST(R * 255.0f); - dst[1] = SAT_CAST(G * 255.0f); - dst[2] = SAT_CAST(B * 255.0f); + uchar dst0 = SAT_CAST(R * 255.0f); + uchar dst1 = SAT_CAST(G * 255.0f); + uchar dst2 = SAT_CAST(B * 255.0f); #if dcn == 4 - dst[3] = MAX_NUM; + *(__global uchar4 *)dst = (uchar4)(dst0, dst1, dst2, MAX_NUM); +#else + dst[0] = dst0; + dst[1] = dst1; + dst[2] = dst2; #endif + + ++y; + dst += dst_step; + src += src_step; + } } } diff --git a/modules/imgproc/test/ocl/test_color.cpp b/modules/imgproc/test/ocl/test_color.cpp index e9fb0d3896..82bf2c06f1 100644 --- a/modules/imgproc/test/ocl/test_color.cpp +++ b/modules/imgproc/test/ocl/test_color.cpp @@ -305,11 +305,11 @@ OCL_TEST_P(CvtColor8u32f, Lab2LRGBA) { performTest(3, 4, CVTCODE(Lab2LRGB), dept OCL_TEST_P(CvtColor8u32f, BGR2Luv) { performTest(3, 3, CVTCODE(BGR2Luv), depth == CV_8U ? 1 : 1e-2); } OCL_TEST_P(CvtColor8u32f, RGB2Luv) { performTest(3, 3, CVTCODE(RGB2Luv), depth == CV_8U ? 1 : 1e-2); } OCL_TEST_P(CvtColor8u32f, LBGR2Luv) { performTest(3, 3, CVTCODE(LBGR2Luv), depth == CV_8U ? 1 : 4e-3); } -OCL_TEST_P(CvtColor8u32f, LRGB2Luv) { performTest(3, 3, CVTCODE(LRGB2Luv), depth == CV_8U ? 1 : 4e-3); } +OCL_TEST_P(CvtColor8u32f, LRGB2Luv) { performTest(3, 3, CVTCODE(LRGB2Luv), depth == CV_8U ? 1 : 5e-3); } OCL_TEST_P(CvtColor8u32f, BGRA2Luv) { performTest(4, 3, CVTCODE(BGR2Luv), depth == CV_8U ? 1 : 8e-3); } OCL_TEST_P(CvtColor8u32f, RGBA2Luv) { performTest(4, 3, CVTCODE(RGB2Luv), depth == CV_8U ? 1 : 9e-3); } -OCL_TEST_P(CvtColor8u32f, LBGRA2Luv) { performTest(4, 3, CVTCODE(LBGR2Luv), depth == CV_8U ? 1 : 4e-3); } -OCL_TEST_P(CvtColor8u32f, LRGBA2Luv) { performTest(4, 3, CVTCODE(LRGB2Luv), depth == CV_8U ? 1 : 4e-3); } +OCL_TEST_P(CvtColor8u32f, LBGRA2Luv) { performTest(4, 3, CVTCODE(LBGR2Luv), depth == CV_8U ? 1 : 5e-3); } +OCL_TEST_P(CvtColor8u32f, LRGBA2Luv) { performTest(4, 3, CVTCODE(LRGB2Luv), depth == CV_8U ? 1 : 5e-3); } OCL_TEST_P(CvtColor8u32f, Luv2BGR) { performTest(3, 3, CVTCODE(Luv2BGR), depth == CV_8U ? 1 : 7e-5); } OCL_TEST_P(CvtColor8u32f, Luv2RGB) { performTest(3, 3, CVTCODE(Luv2RGB), depth == CV_8U ? 1 : 7e-5); } From e89cee35e5821377a75b3de6d92d1c33391bc31e Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 21 Jun 2014 19:17:03 +0400 Subject: [PATCH 009/136] optimized cv::inRange --- modules/core/src/arithm.cpp | 17 ++++++--- modules/core/src/opencl/inrange.cl | 57 +++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 7ca8b4b48d..197ebc1de4 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -3130,9 +3130,16 @@ static bool ocl_inRange( InputArray _src, InputArray _lowerb, (!haveScalar && (sdepth != ldepth || sdepth != udepth)) ) return false; - ocl::Kernel ker("inrange", ocl::core::inrange_oclsrc, - format("%s-D cn=%d -D T=%s%s", haveScalar ? "-D HAVE_SCALAR " : "", - cn, ocl::typeToStr(sdepth), doubleSupport ? " -D DOUBLE_SUPPORT" : "")); + int kercn = haveScalar ? cn : std::max(std::min(ocl::predictOptimalVectorWidth(_src, _lowerb, _upperb, _dst), 4), cn); + if (kercn % cn != 0) + kercn = cn; + int colsPerWI = kercn / cn; + String opts = format("%s-D cn=%d -D srcT=%s -D srcT1=%s -D dstT=%s -D kercn=%d -D depth=%d%s -D colsPerWI=%d", + haveScalar ? "-D HAVE_SCALAR " : "", cn, ocl::typeToStr(CV_MAKE_TYPE(sdepth, kercn)), + ocl::typeToStr(sdepth), ocl::typeToStr(CV_8UC(colsPerWI)), kercn, sdepth, + doubleSupport ? " -D DOUBLE_SUPPORT" : "", colsPerWI); + + ocl::Kernel ker("inrange", ocl::core::inrange_oclsrc, opts); if (ker.empty()) return false; @@ -3180,7 +3187,7 @@ static bool ocl_inRange( InputArray _src, InputArray _lowerb, } ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src), - dstarg = ocl::KernelArg::WriteOnly(dst); + dstarg = ocl::KernelArg::WriteOnly(dst, 1, colsPerWI); if (haveScalar) { @@ -3194,7 +3201,7 @@ static bool ocl_inRange( InputArray _src, InputArray _lowerb, ker.args(srcarg, dstarg, ocl::KernelArg::ReadOnlyNoSize(lscalaru), ocl::KernelArg::ReadOnlyNoSize(uscalaru), rowsPerWI); - size_t globalsize[2] = { ssize.width, (ssize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { ssize.width / colsPerWI, (ssize.height + rowsPerWI - 1) / rowsPerWI }; return ker.run(2, globalsize, NULL, false); } diff --git a/modules/core/src/opencl/inrange.cl b/modules/core/src/opencl/inrange.cl index 0de561f5f2..538259539a 100644 --- a/modules/core/src/opencl/inrange.cl +++ b/modules/core/src/opencl/inrange.cl @@ -52,7 +52,7 @@ __kernel void inrange(__global const uchar * src1ptr, int src1_step, int src1_offset, __global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols, #ifdef HAVE_SCALAR - __global const T * src2, __global const T * src3, + __global const srcT1 * src2, __global const srcT1 * src3, #else __global const uchar * src2ptr, int src2_step, int src2_offset, __global const uchar * src3ptr, int src3_step, int src3_offset, @@ -64,31 +64,56 @@ __kernel void inrange(__global const uchar * src1ptr, int src1_step, int src1_of if (x < dst_cols) { - int src1_index = mad24(y0, src1_step, mad24(x, (int)sizeof(T) * cn, src1_offset)); - int dst_index = mad24(y0, dst_step, x + dst_offset); + int src1_index = mad24(y0, src1_step, mad24(x, (int)sizeof(srcT1) * kercn, src1_offset)); + int dst_index = mad24(y0, dst_step, mad24(x, colsPerWI, dst_offset)); #ifndef HAVE_SCALAR - int src2_index = mad24(y0, src2_step, mad24(x, (int)sizeof(T) * cn, src2_offset)); - int src3_index = mad24(y0, src3_step, mad24(x, (int)sizeof(T) * cn, src3_offset)); + int src2_index = mad24(y0, src2_step, mad24(x, (int)sizeof(srcT1) * kercn, src2_offset)); + int src3_index = mad24(y0, src3_step, mad24(x, (int)sizeof(srcT1) * kercn, src3_offset)); #endif for (int y = y0, y1 = min(dst_rows, y0 + rowsPerWI); y < y1; ++y, src1_index += src1_step, dst_index += dst_step) { - __global const T * src1 = (__global const T *)(src1ptr + src1_index); +#if kercn >= cn && kercn == 4 && depth <= 4 && !defined HAVE_SCALAR + srcT src1 = *(__global const srcT *)(src1ptr + src1_index); + srcT src2 = *(__global const srcT *)(src2ptr + src2_index); + srcT src3 = *(__global const srcT *)(src3ptr + src3_index); + __global dstT * dst = (__global dstT *)(dstptr + dst_index); +#if cn == 1 + dst[0] = src2 > src1 || src3 < src1 ? (dstT)(0) : (dstT)(255); +#elif cn == 2 + dst[0] = (dstT)(src2.xy > src1.xy || src3.xy < src1.xy || + src2.zw > src1.zw || src3.zw < src1.zw ? (dstT)(0) : (dstT)(255); +#elif cn == 4 + dst[0] = (dstT)(src2.x > src1.x || src3.x < src1.x || + src2.y > src1.y || src3.y < src1.y || + src2.z > src1.z || src3.z < src1.z || + src2.w > src1.w || src3.w < src1.w ? 0 : 255); +#endif +#else + __global const srcT1 * src1 = (__global const srcT1 *)(src1ptr + src1_index); __global uchar * dst = dstptr + dst_index; #ifndef HAVE_SCALAR - __global const T * src2 = (__global const T *)(src2ptr + src2_index); - __global const T * src3 = (__global const T *)(src3ptr + src3_index); + __global const srcT1 * src2 = (__global const srcT1 *)(src2ptr + src2_index); + __global const srcT1 * src3 = (__global const srcT1 *)(src3ptr + src3_index); #endif - dst[0] = 255; - - for (int c = 0; c < cn; ++c) - if (src2[c] > src1[c] || src3[c] < src1[c]) - { - dst[0] = 0; - break; - } + #pragma unroll + for (int px = 0; px < colsPerWI; ++px, src1 += cn +#ifndef HAVE_SCALAR + , src2 += cn, src3 += cn +#endif + ) + { + dst[px] = 255; + for (int c = 0; c < cn; ++c) + if (src2[c] > src1[c] || src3[c] < src1[c]) + { + dst[px] = 0; + break; + } + } +#endif // kercn >= cn #ifndef HAVE_SCALAR src2_index += src2_step; src3_index += src3_step; From 87f4b47a4fd0b73d8f58252e81d96a8a0044adcc Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 17 Jun 2014 19:41:53 +0400 Subject: [PATCH 010/136] optimized INTER_LINEAR mode --- modules/imgproc/src/imgwarp.cpp | 5 +-- modules/imgproc/src/opencl/remap.cl | 61 ++++++++++++++++++++++++-- modules/imgproc/test/ocl/test_warp.cpp | 2 +- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index c6d6b1fae1..7c970d0ff2 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -3640,10 +3640,9 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input } int scalarcn = cn == 3 ? 4 : cn; int sctype = CV_MAKETYPE(depth, scalarcn); - buildOptions += format(" -D T=%s -D T1=%s" - " -D cn=%d -D ST=%s", + buildOptions += format(" -D T=%s -D T1=%s -D cn=%d -D ST=%s -D depth=%d", ocl::typeToStr(type), ocl::typeToStr(depth), - cn, ocl::typeToStr(sctype)); + cn, ocl::typeToStr(sctype), depth); ocl::Kernel k(kernelName.c_str(), ocl::imgproc::remap_oclsrc, buildOptions); diff --git a/modules/imgproc/src/opencl/remap.cl b/modules/imgproc/src/opencl/remap.cl index 76b5c33ac8..4e45b40bd3 100644 --- a/modules/imgproc/src/opencl/remap.cl +++ b/modules/imgproc/src/opencl/remap.cl @@ -274,7 +274,7 @@ __kernel void remap_16SC2_16UC1(__global const uchar * srcptr, int src_step, int ST nVal) { int x = get_global_id(0); - int y = get_global_id(1); + int y = get_global_id(1) * rowsPerWI; if (x < dst_cols) { @@ -313,7 +313,15 @@ __kernel void remap_16SC2_16UC1(__global const uchar * srcptr, int src_step, int } } -#elif INTER_LINEAR +#elif defined INTER_LINEAR + +__constant float coeffs[64] = +{ 1.000000f, 0.000000f, 0.968750f, 0.031250f, 0.937500f, 0.062500f, 0.906250f, 0.093750f, 0.875000f, 0.125000f, 0.843750f, 0.156250f, + 0.812500f, 0.187500f, 0.781250f, 0.218750f, 0.750000f, 0.250000f, 0.718750f, 0.281250f, 0.687500f, 0.312500f, 0.656250f, 0.343750f, + 0.625000f, 0.375000f, 0.593750f, 0.406250f, 0.562500f, 0.437500f, 0.531250f, 0.468750f, 0.500000f, 0.500000f, 0.468750f, 0.531250f, + 0.437500f, 0.562500f, 0.406250f, 0.593750f, 0.375000f, 0.625000f, 0.343750f, 0.656250f, 0.312500f, 0.687500f, 0.281250f, 0.718750f, + 0.250000f, 0.750000f, 0.218750f, 0.781250f, 0.187500f, 0.812500f, 0.156250f, 0.843750f, 0.125000f, 0.875000f, 0.093750f, 0.906250f, + 0.062500f, 0.937500f, 0.031250f, 0.968750f }; __kernel void remap_16SC2_16UC1(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols, __global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols, @@ -326,6 +334,7 @@ __kernel void remap_16SC2_16UC1(__global const uchar * srcptr, int src_step, int if (x < dst_cols) { + WT scalar = convertToWT(convertScalar(nVal)); int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); int map1_index = mad24(y, map1_step, mad24(x, (int)sizeof(short2), map1_offset)); int map2_index = mad24(y, map2_step, mad24(x, (int)sizeof(ushort), map2_offset)); @@ -347,7 +356,6 @@ __kernel void remap_16SC2_16UC1(__global const uchar * srcptr, int src_step, int ushort map2Value = (ushort)(map2[0] & (INTER_TAB_SIZE2 - 1)); WT2 u = (WT2)(map2Value & (INTER_TAB_SIZE - 1), map2Value >> INTER_BITS) / (WT2)(INTER_TAB_SIZE); - WT scalar = convertToWT(convertScalar(nVal)); WT a = scalar, b = scalar, c = scalar, d = scalar; if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) @@ -390,6 +398,7 @@ __kernel void remap_2_32FC1(__global const uchar * srcptr, int src_step, int src if (x < dst_cols) { + WT scalar = convertToWT(convertScalar(nVal)); int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); int map1_index = mad24(y, map1_step, mad24(x, (int)sizeof(float), map1_offset)); int map2_index = mad24(y, map2_step, mad24(x, (int)sizeof(float), map2_offset)); @@ -403,6 +412,49 @@ __kernel void remap_2_32FC1(__global const uchar * srcptr, int src_step, int src __global const float * map2 = (__global const float *)(map2ptr + map2_index); __global T * dst = (__global T *)(dstptr + dst_index); +#if defined BORDER_CONSTANT + + float xf = map1[0], yf = map2[0]; + int sx = convert_int_sat_rtn(xf), sy = convert_int_sat_rtn(yf); + + __constant float * coeffs_x = coeffs + ((convert_int_rte(xf * INTER_TAB_SIZE) & (INTER_TAB_SIZE - 1)) << 1); + __constant float * coeffs_y = coeffs + ((convert_int_rte(yf * INTER_TAB_SIZE) & (INTER_TAB_SIZE - 1)) << 1); + + WT sum = (WT)(0), xsum; + int src_index = mad24(sy, src_step, mad24(sx, TSIZE, src_offset)); + + #pragma unroll + for (int yp = 0; yp < 2; ++yp, src_index += src_step) + { + if (sy + yp >= 0 && sy + yp < src_rows) + { + xsum = (WT)(0); + if (sx >= 0 && sx + 2 < src_cols) + { +#if depth == 0 && cn == 1 + uchar2 value = vload2(0, srcptr + src_index); + xsum = dot(convert_float2(value), (float2)(coeffs_x[0], coeffs_x[1])); +#else + #pragma unroll + for (int xp = 0; xp < 2; ++xp) + xsum = fma(convertToWT(loadpix(srcptr + mad24(xp, TSIZE, src_index))), coeffs_x[xp], xsum); +#endif + } + else + { + #pragma unroll + for (int xp = 0; xp < 2; ++xp) + xsum = fma(sx + xp >= 0 && sx + xp < src_cols ? + convertToWT(loadpix(srcptr + mad24(xp, TSIZE, src_index))) : scalar, coeffs_x[xp], xsum); + } + sum = fma(xsum, coeffs_y[yp], sum); + } + else + sum = fma(scalar, coeffs_y[yp], sum); + } + + storepix(convertToT(sum), dst); +#else float2 map_data = (float2)(map1[0], map2[0]); int2 map_dataA = convert_int2_sat_rtn(map_data); @@ -440,6 +492,7 @@ __kernel void remap_2_32FC1(__global const uchar * srcptr, int src_step, int src c * (1 - u.x) * (u.y) + d * (u.x) * (u.y); storepix(convertToT(dst_data), dst); +#endif } } } @@ -454,6 +507,7 @@ __kernel void remap_32FC2(__global const uchar * srcptr, int src_step, int src_o if (x < dst_cols) { + WT scalar = convertToWT(convertScalar(nVal)); int dst_index = mad24(y, dst_step, mad24(x, TSIZE, dst_offset)); int map_index = mad24(y, map_step, mad24(x, (int)sizeof(float2), map_offset)); @@ -473,7 +527,6 @@ __kernel void remap_32FC2(__global const uchar * srcptr, int src_step, int src_o float2 _u = map_data - convert_float2(map_dataA); WT2 u = convertToWT2(convert_int2_rte(convertToWT2(_u) * (WT2)INTER_TAB_SIZE)) / (WT2)INTER_TAB_SIZE; - WT scalar = convertToWT(convertScalar(nVal)); WT a = scalar, b = scalar, c = scalar, d = scalar; if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) diff --git a/modules/imgproc/test/ocl/test_warp.cpp b/modules/imgproc/test/ocl/test_warp.cpp index 416bd523ed..53d82187f9 100644 --- a/modules/imgproc/test/ocl/test_warp.cpp +++ b/modules/imgproc/test/ocl/test_warp.cpp @@ -267,7 +267,7 @@ PARAM_TEST_CASE(Remap, MatDepth, Channels, std::pair, BorderTy Border map1Border = randomBorder(0, useRoi ? MAX_VALUE : 0); randomSubMat(map1, map1_roi, dstROISize, map1Border, map1Type, -mapMaxValue, mapMaxValue); - Border map2Border = randomBorder(0, useRoi ? MAX_VALUE : 0); + Border map2Border = randomBorder(0, useRoi ? MAX_VALUE + 1 : 0); if (map2Type != noType) { int mapMinValue = -mapMaxValue; From 09bcc061dd32361b4864c3b1e62ef5d7121571e5 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 19 Jun 2014 14:39:49 +0400 Subject: [PATCH 011/136] Change kernel for optimization. Remove restriction to align data Fix kernel compilation errors on AMD system Fix licanse information in cl file Support CV_64F destination type Change build options of the kernel Optimize sum of square Remove separate kernel for integral square Increase epsilon for perfomance tests Increase epsilon for perfomance tests Test double support on AMD devices Fix some issues Try to fix problems with AMD device Try to solve problem with AMD device Fix error of destination size in kernel Fix warnings --- modules/imgproc/perf/opencl/perf_imgproc.cpp | 6 +- modules/imgproc/src/opencl/integral_sqrsum.cl | 512 ------------------ modules/imgproc/src/opencl/integral_sum.cl | 374 +++++-------- modules/imgproc/src/sumpixels.cpp | 120 ++-- 4 files changed, 193 insertions(+), 819 deletions(-) delete mode 100644 modules/imgproc/src/opencl/integral_sqrsum.cl diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index 1b3ba7f19e..7f0770853d 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -231,7 +231,7 @@ OCL_PERF_TEST_P(IntegralFixture, Integral1, ::testing::Combine(OCL_TEST_SIZES, O OCL_TEST_CYCLE() cv::integral(src, dst, ddepth); - SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); + SANITY_CHECK(dst, 2e-6, ERROR_RELATIVE); } OCL_PERF_TEST_P(IntegralFixture, Integral2, ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(CV_32S, CV_32F))) @@ -243,11 +243,11 @@ OCL_PERF_TEST_P(IntegralFixture, Integral2, ::testing::Combine(OCL_TEST_SIZES, O checkDeviceMaxMemoryAllocSize(srcSize, ddepth); UMat src(srcSize, CV_8UC1), sum(srcSize + Size(1, 1), ddepth), sqsum(srcSize + Size(1, 1), CV_32F); - declare.in(src, WARMUP_RNG).out(sum).out(sqsum); + declare.in(src, WARMUP_RNG).out(sum, sqsum); OCL_TEST_CYCLE() cv::integral(src, sum, sqsum, ddepth, CV_32F); - SANITY_CHECK(sum, 1e-6, ERROR_RELATIVE); + SANITY_CHECK(sum, 2e-4, ERROR_RELATIVE); SANITY_CHECK(sqsum, 5e-5, ERROR_RELATIVE); } diff --git a/modules/imgproc/src/opencl/integral_sqrsum.cl b/modules/imgproc/src/opencl/integral_sqrsum.cl deleted file mode 100644 index 8b5d2452b8..0000000000 --- a/modules/imgproc/src/opencl/integral_sqrsum.cl +++ /dev/null @@ -1,512 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.com -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors as is and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#if sqdepth == 6 -#define CONVERT(step) ((step)>>1) -#else -#define CONVERT(step) ((step)) -#endif - -#define LSIZE 256 -#define LSIZE_1 255 -#define LSIZE_2 254 -#define HF_LSIZE 128 -#define LOG_LSIZE 8 -#define LOG_NUM_BANKS 5 -#define NUM_BANKS 32 -#define GET_CONFLICT_OFFSET(lid) ((lid) >> LOG_NUM_BANKS) - -#define noconvert - -#if sdepth == 4 - -kernel void integral_cols(__global uchar4 *src, __global int *sum, __global TYPE *sqsum, - int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step, int dst1_step) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int4 src_t[2], sum_t[2]; - TYPE4 sqsum_t[2]; - __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; - __local int* sum_p; - __local TYPE* sqsum_p; - src_step = src_step >> 2; - gid = gid << 1; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + min(gid, cols - 1)]) : 0); - src_t[1] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + min(gid + 1, cols - 1)]) : 0); - - sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - lm_sqsum[0][bf_loc] = convert_TYPE4(src_t[0] * src_t[0]); - - lm_sum[1][bf_loc] = src_t[1]; - lm_sqsum[1][bf_loc] = convert_TYPE4(src_t[1] * src_t[1]); - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step /4, loc_s1 = loc_s0 + dst_step ; - int loc_sq0 = gid * CONVERT(dst1_step) + i + lid - 1 - pre_invalid * dst1_step / sizeof(TYPE),loc_sq1 = loc_sq0 + CONVERT(dst1_step); - if(lid > 0 && (i+lid) <= rows) - { - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - lm_sqsum[0][bf_loc] += sqsum_t[0]; - lm_sqsum[1][bf_loc] += sqsum_t[1]; - sum_p = (__local int*)(&(lm_sum[0][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; - sum[loc_s0 + k * dst_step / 4] = sum_p[k]; - sqsum[loc_sq0 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; - } - sum_p = (__local int*)(&(lm_sum[1][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k + 4 >= cols + pre_invalid) break; - sum[loc_s1 + k * dst_step / 4] = sum_p[k]; - sqsum[loc_sq1 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - -kernel void integral_rows(__global int4 *srcsum, __global TYPE4 * srcsqsum,__global int *sum, - __global TYPE *sqsum, int rows, int cols, int src_step, int src1_step, int sum_step, - int sqsum_step, int sum_offset, int sqsum_offset) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int4 src_t[2], sum_t[2]; - TYPE4 sqsrc_t[2],sqsum_t[2]; - __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; - __local int *sum_p; - __local TYPE *sqsum_p; - src_step = src_step >> 4; - src1_step = (src1_step / sizeof(TYPE)) >> 2 ; - gid <<= 1; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid ] : (int4)0; - sqsrc_t[0] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid ] : (TYPE4)0; - src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid + 1] : (int4)0; - sqsrc_t[1] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid + 1] : (TYPE4)0; - - sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - lm_sqsum[0][bf_loc] = sqsrc_t[0]; - - lm_sum[1][bf_loc] = src_t[1]; - lm_sqsum[1][bf_loc] = sqsrc_t[1]; - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - if(gid == 0 && (i + lid) <= rows) - { - sum[sum_offset + i + lid] = 0; - sqsum[sqsum_offset + i + lid] = 0; - } - if(i + lid == 0) - { - int loc0 = gid * sum_step; - int loc1 = gid * CONVERT(sqsum_step); - for(int k = 1; k <= 8; k++) - { - if(gid * 4 + k > cols) break; - sum[sum_offset + loc0 + k * sum_step / 4] = 0; - sqsum[sqsum_offset + loc1 + k * sqsum_step / sizeof(TYPE)] = 0; - } - } - int loc_s0 = sum_offset + gid * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; - int loc_sq0 = sqsum_offset + gid * CONVERT(sqsum_step) + sqsum_step / sizeof(TYPE) + i + lid, loc_sq1 = loc_sq0 + CONVERT(sqsum_step) ; - - if(lid > 0 && (i+lid) <= rows) - { - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - lm_sqsum[0][bf_loc] += sqsum_t[0]; - lm_sqsum[1][bf_loc] += sqsum_t[1]; - sum_p = (__local int*)(&(lm_sum[0][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k >= cols) break; - sum[loc_s0 + k * sum_step / 4] = sum_p[k]; - sqsum[loc_sq0 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; - } - sum_p = (__local int*)(&(lm_sum[1][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + 4 + k >= cols) break; - sum[loc_s1 + k * sum_step / 4] = sum_p[k]; - sqsum[loc_sq1 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - -#elif sdepth == 5 - -kernel void integral_cols(__global uchar4 *src, __global float *sum, __global TYPE *sqsum, - int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step, int dst1_step) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - float4 src_t[2], sum_t[2]; - TYPE4 sqsum_t[2]; - __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; - __local float* sum_p; - __local TYPE* sqsum_p; - src_step = src_step >> 2; - gid = gid << 1; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + min(gid, cols - 1)]) : (float4)0); - src_t[1] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + min(gid + 1, cols - 1)]) : (float4)0); - - sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - lm_sqsum[0][bf_loc] = convert_TYPE4(src_t[0] * src_t[0]); -// printf("%f\n", src_t[0].s0); - - lm_sum[1][bf_loc] = src_t[1]; - lm_sqsum[1][bf_loc] = convert_TYPE4(src_t[1] * src_t[1]); - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ; - int loc_sq0 = gid * CONVERT(dst1_step) + i + lid - 1 - pre_invalid * dst1_step / sizeof(TYPE), loc_sq1 = loc_sq0 + CONVERT(dst1_step); - if(lid > 0 && (i+lid) <= rows) - { - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - lm_sqsum[0][bf_loc] += sqsum_t[0]; - lm_sqsum[1][bf_loc] += sqsum_t[1]; - sum_p = (__local float*)(&(lm_sum[0][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; - sum[loc_s0 + k * dst_step / 4] = sum_p[k]; - sqsum[loc_sq0 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; - } - sum_p = (__local float*)(&(lm_sum[1][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k + 4 >= cols + pre_invalid) break; - sum[loc_s1 + k * dst_step / 4] = sum_p[k]; - sqsum[loc_sq1 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - -kernel void integral_rows(__global float4 *srcsum, __global TYPE4 * srcsqsum, __global float *sum , - __global TYPE *sqsum, int rows, int cols, int src_step, int src1_step, int sum_step, - int sqsum_step, int sum_offset, int sqsum_offset) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - float4 src_t[2], sum_t[2]; - TYPE4 sqsrc_t[2],sqsum_t[2]; - __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; - __local float *sum_p; - __local TYPE *sqsum_p; - src_step = src_step >> 4; - src1_step = (src1_step / sizeof(TYPE)) >> 2; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : (float4)0; - sqsrc_t[0] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid * 2] : (TYPE4)0; - src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : (float4)0; - sqsrc_t[1] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid * 2 + 1] : (TYPE4)0; - - sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - lm_sqsum[0][bf_loc] = sqsrc_t[0]; - - lm_sum[1][bf_loc] = src_t[1]; - lm_sqsum[1][bf_loc] = sqsrc_t[1]; - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - if(gid == 0 && (i + lid) <= rows) - { - sum[sum_offset + i + lid] = 0; - sqsum[sqsum_offset + i + lid] = 0; - } - if(i + lid == 0) - { - int loc0 = gid * 2 * sum_step; - int loc1 = gid * 2 * CONVERT(sqsum_step); - for(int k = 1; k <= 8; k++) - { - if(gid * 8 + k > cols) break; - sum[sum_offset + loc0 + k * sum_step / 4] = 0; - sqsum[sqsum_offset + loc1 + k * sqsum_step / sizeof(TYPE)] = 0; - } - } - int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; - int loc_sq0 = sqsum_offset + gid * 2 * CONVERT(sqsum_step) + sqsum_step / sizeof(TYPE) + i + lid, loc_sq1 = loc_sq0 + CONVERT(sqsum_step) ; - if(lid > 0 && (i+lid) <= rows) - { - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - lm_sqsum[0][bf_loc] += sqsum_t[0]; - lm_sqsum[1][bf_loc] += sqsum_t[1]; - sum_p = (__local float*)(&(lm_sum[0][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 8 + k >= cols) break; - sum[loc_s0 + k * sum_step / 4] = sum_p[k]; - sqsum[loc_sq0 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; - } - sum_p = (__local float*)(&(lm_sum[1][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 8 + 4 + k >= cols) break; - sum[loc_s1 + k * sum_step / 4] = sum_p[k]; - sqsum[loc_sq1 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - -#endif diff --git a/modules/imgproc/src/opencl/integral_sum.cl b/modules/imgproc/src/opencl/integral_sum.cl index 333c7121cb..49a3bde955 100644 --- a/modules/imgproc/src/opencl/integral_sum.cl +++ b/modules/imgproc/src/opencl/integral_sum.cl @@ -1,46 +1,9 @@ /*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// Copyright (C) 2014, Itseez, Inc., all rights reserved. // Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.com -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors as is and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// //M*/ #ifdef DOUBLE_SUPPORT @@ -51,237 +14,170 @@ #endif #endif -#define LSIZE 256 -#define LSIZE_1 255 -#define LSIZE_2 254 -#define HF_LSIZE 128 -#define LOG_LSIZE 8 -#define LOG_NUM_BANKS 5 -#define NUM_BANKS 32 -#define GET_CONFLICT_OFFSET(lid) ((lid) >> LOG_NUM_BANKS) - -#if sdepth == 4 -#define sumT int -#define vecSumT int4 -#define convertToSum4 convert_int4 -#elif sdepth == 5 -#define sumT float -#define vecSumT float4 -#define convertToSum4 convert_float4 +#ifndef LOCAL_SUM_SIZE +#define LOCAL_SUM_SIZE 16 #endif +#define LOCAL_SUM_STRIDE (LOCAL_SUM_SIZE + 1) + -kernel void integral_sum_cols(__global const uchar4 *src, __global uchar *sum_ptr, - int src_offset, int rows, int cols, int src_step, int dst_step) +kernel void integral_sum_cols(__global const uchar *src_ptr, int src_step, int src_offset, int rows, int cols, + __global uchar *buf_ptr, int buf_step, int buf_offset +#ifdef SUM_SQUARE + ,__global uchar *buf_sq_ptr, int buf_sq_step, int buf_sq_offset +#endif + ) { - __global sumT *sum = (__global sumT *)sum_ptr; + __local sumT lm_sum[LOCAL_SUM_STRIDE * LOCAL_SUM_SIZE]; +#ifdef SUM_SQUARE + __local sumSQT lm_sum_sq[LOCAL_SUM_STRIDE * LOCAL_SUM_SIZE]; +#endif int lid = get_local_id(0); int gid = get_group_id(0); - vecSumT src_t[2], sum_t[2]; - __local vecSumT lm_sum[2][LSIZE + LOG_LSIZE]; - __local sumT* sum_p; - src_step = src_step >> 2; - gid = gid << 1; - int lid_prim = ((lid & 127) << 1) + 1; - for (int i = 0; i < rows; i += LSIZE_1) - { - if (i + lid < rows) - { - int src_index = mad24((lid+i), src_step, gid + src_offset); - src_t[0] = convertToSum4(src[src_index]); - src_t[1] = convertToSum4(src[src_index + 1]); - } - else - { - src_t[0] = (vecSumT)0; - src_t[1] = (vecSumT)0; - } - if (i == 0) - { - sum_t[0] = (vecSumT)0; - sum_t[1] = (vecSumT)0; - } - else - { - sum_t[0] = lm_sum[0][LSIZE_2 + LOG_LSIZE]; - sum_t[1] = lm_sum[1][LSIZE_2 + LOG_LSIZE]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - - lm_sum[0][bf_loc] = src_t[0]; - lm_sum[1][bf_loc] = src_t[1]; + int x = get_global_id(0); + int src_index = x + src_offset; - int offset = 1; - for (int d = LSIZE >> 1 ; d > 0; d>>=1) + sumT accum = 0; +#ifdef SUM_SQUARE + sumSQT accum_sq = 0; +#endif + for (int y = 0; y < rows; y += LOCAL_SUM_SIZE) + { + int lsum_index = lid; + #pragma unroll + for (int yin = 0; yin < LOCAL_SUM_SIZE; yin++, src_index+=src_step, lsum_index += LOCAL_SUM_STRIDE) { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * lid_prim - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) + if ((x < cols) && (y + yin < rows)) { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + __global const uchar *src = src_ptr + src_index; + accum += src[0]; +#ifdef SUM_SQUARE + sumSQT temp = src[0] * src[0]; + accum_sq += temp; +#endif } - offset <<= 1; + lm_sum[lsum_index] = accum; +#ifdef SUM_SQUARE + lm_sum_sq[lsum_index] = accum_sq; +#endif } barrier(CLK_LOCAL_MEM_FENCE); - if (lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for (int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * lid_prim - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - if (lid > 0 && (i+lid) <= rows) - { - int loc_s0 = mad24(gid, dst_step, i + lid - 1), loc_s1 = loc_s0 + dst_step; - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - sum_p = (__local sumT*)(&(lm_sum[0][bf_loc])); - for (int k = 0; k < 4; k++) - { - if (gid * 4 + k >= cols) - break; - sum[loc_s0 + k * dst_step / 4] = sum_p[k]; - } - sum_p = (__local sumT*)(&(lm_sum[1][bf_loc])); - for (int k = 0; k < 4; k++) - { - if (gid * 4 + k + 4 >= cols) - break; - sum[loc_s1 + k * dst_step / 4] = sum_p[k]; - } + //int buf_index = buf_offset + buf_step * LOCAL_SUM_COLS * gid + sizeof(sumT) * y + sizeof(sumT) * lid; + int buf_index = mad24(buf_step, LOCAL_SUM_SIZE * gid, mad24((int)sizeof(sumT), y + lid, buf_offset)); +#ifdef SUM_SQUARE + int buf_sq_index = mad24(buf_sq_step, LOCAL_SUM_SIZE * gid, mad24((int)sizeof(sumSQT), y + lid, buf_sq_offset)); +#endif + + lsum_index = LOCAL_SUM_STRIDE * lid; + #pragma unroll + for (int yin = 0; yin < LOCAL_SUM_SIZE; yin++, lsum_index ++) + { + __global sumT *buf = (__global sumT *)(buf_ptr + buf_index); + buf[0] = lm_sum[lsum_index]; + buf_index += buf_step; +#ifdef SUM_SQUARE + __global sumSQT *bufsq = (__global sumSQT *)(buf_sq_ptr + buf_sq_index); + bufsq[0] = lm_sum_sq[lsum_index]; + buf_sq_index += buf_sq_step; +#endif } barrier(CLK_LOCAL_MEM_FENCE); } } - -kernel void integral_sum_rows(__global const uchar *srcsum_ptr, __global uchar *sum_ptr, - int rows, int cols, int src_step, int sum_step, int sum_offset) +kernel void integral_sum_rows(__global const uchar *buf_ptr, int buf_step, int buf_offset, +#ifdef SUM_SQUARE + __global uchar *buf_sq_ptr, int buf_sq_step, int buf_sq_offset, +#endif + __global uchar *dst_ptr, int dst_step, int dst_offset, int rows, int cols +#ifdef SUM_SQUARE + ,__global uchar *dst_sq_ptr, int dst_sq_step, int dst_sq_offset +#endif + ) { - __global const vecSumT *srcsum = (__global const vecSumT *)srcsum_ptr; - __global sumT *sum = (__global sumT *)sum_ptr; + __local sumT lm_sum[LOCAL_SUM_STRIDE * LOCAL_SUM_SIZE]; +#ifdef SUM_SQUARE + __local sumSQT lm_sum_sq[LOCAL_SUM_STRIDE * LOCAL_SUM_SIZE]; +#endif int lid = get_local_id(0); int gid = get_group_id(0); - vecSumT src_t[2], sum_t[2]; - __local vecSumT lm_sum[2][LSIZE + LOG_LSIZE]; - __local sumT *sum_p; - src_step = src_step >> 4; - int lid_prim = ((lid & 127) << 1) + 1; - for (int i = 0; i < rows; i += LSIZE_1) + + int gs = get_global_size(0); + + int x = get_global_id(0); + + __global sumT *dst = (__global sumT *)(dst_ptr + dst_offset); + for (int xin = x; xin < cols; xin += gs) { - if (i + lid < rows) - { - int sum_idx = mad24(lid + i, src_step, gid * 2); - src_t[0] = srcsum[sum_idx]; - src_t[1] = srcsum[sum_idx + 1]; - } - else - { - src_t[0] = 0; - src_t[1] = 0; - } - if (i == 0) - { - sum_t[0] = 0; - sum_t[1] = 0; - } - else - { - sum_t[0] = lm_sum[0][LSIZE_2 + LOG_LSIZE]; - sum_t[1] = lm_sum[1][LSIZE_2 + LOG_LSIZE]; - } - barrier(CLK_LOCAL_MEM_FENCE); + dst[xin] = 0; + } + dst_offset += dst_step; - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); + if (x < rows - 1) + { + dst = (__global sumT *)(dst_ptr + mad24(x, dst_step, dst_offset)); + dst[0] = 0; + } - lm_sum[0][bf_loc] = src_t[0]; - lm_sum[1][bf_loc] = src_t[1]; + int buf_index = mad24((int)sizeof(sumT), x, buf_offset); + sumT accum = 0; - int offset = 1; - for (int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * lid_prim - 1, bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); +#ifdef SUM_SQUARE + __global sumSQT *dst_sq = (__global sumT *)(dst_sq_ptr + dst_sq_offset); + for (int xin = x; xin < cols; xin += gs) + { + dst_sq[xin] = 0; + } + dst_sq_offset += dst_sq_step; - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if (lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for (int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * lid_prim - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); + dst_sq = (__global sumSQT *)(dst_sq_ptr + mad24(x, dst_sq_step, dst_sq_offset)); + dst_sq[0] = 0; - if ((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - } + int buf_sq_index = mad24((int)sizeof(sumSQT), x, buf_sq_offset); + sumSQT accum_sq = 0; +#endif + + for (int y = 1; y < cols; y += LOCAL_SUM_SIZE) + { + int lsum_index = lid; + #pragma unroll + for (int yin = 0; yin < LOCAL_SUM_SIZE; yin++, lsum_index += LOCAL_SUM_STRIDE) + { + __global const sumT *buf = (__global const sumT *)(buf_ptr + buf_index); + accum += buf[0]; + lm_sum[lsum_index] = accum; + buf_index += buf_step; +#ifdef SUM_SQUARE + __global const sumSQT *buf_sq = (__global const sumSQT *)(buf_sq_ptr + buf_sq_index); + accum_sq += buf_sq[0]; + lm_sum_sq[lsum_index] = accum_sq; + buf_sq_index += buf_sq_step; +#endif } barrier(CLK_LOCAL_MEM_FENCE); - if (gid == 0 && (i + lid) <= rows) - { - sum[sum_offset + i + lid] = 0; - } - if (i + lid == 0) - { - int loc0 = gid * 2 * sum_step; - for(int k = 1; k <= 8; k++) - { - if (gid * 8 + k > cols) - break; - sum[sum_offset + loc0 + k * sum_step / 4] = 0; - } - } - if (lid > 0 && (i+lid) <= rows) + if (y + lid < cols) { - int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - sum_p = (__local sumT*)(&(lm_sum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if (gid * 8 + k >= cols) - break; - sum[loc_s0 + k * sum_step / 4] = sum_p[k]; - } - sum_p = (__local sumT*)(&(lm_sum[1][bf_loc])); - for(int k = 0; k < 4; k++) + //int dst_index = dst_offset + dst_step * LOCAL_SUM_COLS * gid + sizeof(sumT) * y + sizeof(sumT) * lid; + int dst_index = mad24(dst_step, LOCAL_SUM_SIZE * gid, mad24((int)sizeof(sumT), y + lid, dst_offset)); +#ifdef SUM_SQUARE + int dst_sq_index = mad24(dst_sq_step, LOCAL_SUM_SIZE * gid, mad24((int)sizeof(sumSQT), y + lid, dst_sq_offset)); +#endif + lsum_index = LOCAL_SUM_STRIDE * lid; + int yin_max = min(rows - 1 - LOCAL_SUM_SIZE * gid, LOCAL_SUM_SIZE); + #pragma unroll + for (int yin = 0; yin < yin_max; yin++, lsum_index++) { - if (gid * 8 + 4 + k >= cols) - break; - sum[loc_s1 + k * sum_step / 4] = sum_p[k]; + dst = (__global sumT *)(dst_ptr + dst_index); + dst[0] = lm_sum[lsum_index]; + dst_index += dst_step; +#ifdef SUM_SQUARE + dst_sq = (__global sumSQT *)(dst_sq_ptr + dst_sq_index); + dst_sq[0] = lm_sum_sq[lsum_index]; + dst_sq_index += dst_sq_step; +#endif } } barrier(CLK_LOCAL_MEM_FENCE); diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index 1d246ec7bc..e7694b01a9 100755 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -235,97 +235,87 @@ typedef void (*IntegralFunc)(const uchar* src, size_t srcstep, uchar* sum, size_ #ifdef HAVE_OPENCL -enum { vlen = 4 }; - static bool ocl_integral( InputArray _src, OutputArray _sum, int sdepth ) { - if ( _src.type() != CV_8UC1 || _src.step() % vlen != 0 || _src.offset() % vlen != 0 || - !(sdepth == CV_32S || sdepth == CV_32F) ) - return false; + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - ocl::Kernel k1("integral_sum_cols", ocl::imgproc::integral_sum_oclsrc, - format("-D sdepth=%d", sdepth)); - if (k1.empty()) + if ( (_src.type() != CV_8UC1) || + !(sdepth == CV_32S || sdepth == CV_32F || (doubleSupport && sdepth == CV_64F))) return false; - Size size = _src.size(), t_size = Size(((size.height + vlen - 1) / vlen) * vlen, size.width), - ssize(size.width + 1, size.height + 1); - _sum.create(ssize, sdepth); - UMat src = _src.getUMat(), t_sum(t_size, sdepth), sum = _sum.getUMat(); - t_sum = t_sum(Range::all(), Range(0, size.height)); + static const int tileSize = 16; + + String build_opt = format("-D sumT=%s -D LOCAL_SUM_SIZE=%d%s", + ocl::typeToStr(sdepth), tileSize, + doubleSupport ? " -D DOUBLE_SUPPORT" : ""); + + ocl::Kernel kcols("integral_sum_cols", ocl::imgproc::integral_sum_oclsrc, build_opt); + if (kcols.empty()) + return false; - int offset = (int)src.offset / vlen; - int vcols = (src.cols + vlen - 1) / vlen; - int sum_offset = (int)sum.offset / vlen; + UMat src = _src.getUMat(); + Size src_size = src.size(); + Size bufsize(((src_size.height + tileSize - 1) / tileSize) * tileSize, ((src_size.width + tileSize - 1) / tileSize) * tileSize); + UMat buf(bufsize, sdepth); + kcols.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnlyNoSize(buf)); + size_t gt = src.cols, lt = tileSize; + if (!kcols.run(1, >, <, false)) + return false; - k1.args(ocl::KernelArg::PtrReadOnly(src), ocl::KernelArg::PtrWriteOnly(t_sum), - offset, src.rows, src.cols, (int)src.step, (int)t_sum.step); - size_t gt = ((vcols + 1) / 2) * 256, lt = 256; - if (!k1.run(1, >, <, false)) + ocl::Kernel krows("integral_sum_rows", ocl::imgproc::integral_sum_oclsrc, build_opt); + if (krows.empty()) return false; - ocl::Kernel k2("integral_sum_rows", ocl::imgproc::integral_sum_oclsrc, - format("-D sdepth=%d", sdepth)); - k2.args(ocl::KernelArg::PtrReadOnly(t_sum), ocl::KernelArg::PtrWriteOnly(sum), - t_sum.rows, t_sum.cols, (int)t_sum.step, (int)sum.step, sum_offset); + Size sumsize(src_size.width + 1, src_size.height + 1); + _sum.create(sumsize, sdepth); + UMat sum = _sum.getUMat(); - size_t gt2 = t_sum.cols * 32, lt2 = 256; - return k2.run(1, >2, <2, false); + krows.args(ocl::KernelArg::ReadOnlyNoSize(buf), ocl::KernelArg::WriteOnly(sum)); + gt = src.rows; + return krows.run(1, >, <, false); } static bool ocl_integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, int sdepth, int sqdepth ) { bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - if ( _src.type() != CV_8UC1 || _src.step() % vlen != 0 || _src.offset() % vlen != 0 || - (!doubleSupport && (sdepth == CV_64F || sqdepth == CV_64F)) ) - return false; - - char cvt[40]; - String opts = format("-D sdepth=%d -D sqdepth=%d -D TYPE=%s -D TYPE4=%s4 -D convert_TYPE4=%s%s", - sdepth, sqdepth, ocl::typeToStr(sqdepth), ocl::typeToStr(sqdepth), - ocl::convertTypeStr(sdepth, sqdepth, 4, cvt), - doubleSupport ? " -D DOUBLE_SUPPORT" : ""); - - ocl::Kernel k1("integral_cols", ocl::imgproc::integral_sqrsum_oclsrc, opts); - if (k1.empty()) + if ( _src.type() != CV_8UC1 || (!doubleSupport && (sdepth == CV_64F || sqdepth == CV_64F)) ) return false; - Size size = _src.size(), dsize = Size(size.width + 1, size.height + 1), - t_size = Size(((size.height + vlen - 1) / vlen) * vlen, size.width); - UMat src = _src.getUMat(), t_sum(t_size, sdepth), t_sqsum(t_size, sqdepth); - t_sum = t_sum(Range::all(), Range(0, size.height)); - t_sqsum = t_sqsum(Range::all(), Range(0, size.height)); - - _sum.create(dsize, sdepth); - _sqsum.create(dsize, sqdepth); - UMat sum = _sum.getUMat(), sqsum = _sqsum.getUMat(); + static const int tileSize = 16; - int offset = (int)src.offset / vlen; - int pre_invalid = src.offset % vlen; - int vcols = (pre_invalid + src.cols + vlen - 1) / vlen; - int sum_offset = (int)(sum.offset / sum.elemSize()); - int sqsum_offset = (int)(sqsum.offset / sqsum.elemSize()); + String build_opt = format("-D SUM_SQUARE -D sumT=%s -D sumSQT=%s -D LOCAL_SUM_SIZE=%d%s", + ocl::typeToStr(sdepth), ocl::typeToStr(sqdepth), + tileSize, + doubleSupport ? " -D DOUBLE_SUPPORT" : ""); - k1.args(ocl::KernelArg::PtrReadOnly(src), ocl::KernelArg::PtrWriteOnly(t_sum), - ocl::KernelArg::PtrWriteOnly(t_sqsum), offset, pre_invalid, src.rows, - src.cols, (int)src.step, (int)t_sum.step, (int)t_sqsum.step); + ocl::Kernel kcols("integral_sum_cols", ocl::imgproc::integral_sum_oclsrc, build_opt); + if (kcols.empty()) + return false; - size_t gt = ((vcols + 1) / 2) * 256, lt = 256; - if (!k1.run(1, >, <, false)) + UMat src = _src.getUMat(); + Size src_size = src.size(); + Size bufsize(((src_size.height + tileSize - 1) / tileSize) * tileSize, ((src_size.width + tileSize - 1) / tileSize) * tileSize); + UMat buf(bufsize, sdepth); + UMat buf_sq(bufsize, sqdepth); + kcols.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnlyNoSize(buf), ocl::KernelArg::WriteOnlyNoSize(buf_sq)); + size_t gt = src.cols, lt = tileSize; + if (!kcols.run(1, >, <, false)) return false; - ocl::Kernel k2("integral_rows", ocl::imgproc::integral_sqrsum_oclsrc, opts); - if (k2.empty()) + ocl::Kernel krows("integral_sum_rows", ocl::imgproc::integral_sum_oclsrc, build_opt); + if (krows.empty()) return false; - k2.args(ocl::KernelArg::PtrReadOnly(t_sum), ocl::KernelArg::PtrReadOnly(t_sqsum), - ocl::KernelArg::PtrWriteOnly(sum), ocl::KernelArg::PtrWriteOnly(sqsum), - t_sum.rows, t_sum.cols, (int)t_sum.step, (int)t_sqsum.step, - (int)sum.step, (int)sqsum.step, sum_offset, sqsum_offset); + Size sumsize(src_size.width + 1, src_size.height + 1); + _sum.create(sumsize, sdepth); + UMat sum = _sum.getUMat(); + _sqsum.create(sumsize, sqdepth); + UMat sum_sq = _sqsum.getUMat(); - size_t gt2 = t_sum.cols * 32, lt2 = 256; - return k2.run(1, >2, <2, false); + krows.args(ocl::KernelArg::ReadOnlyNoSize(buf), ocl::KernelArg::ReadOnlyNoSize(buf_sq), ocl::KernelArg::WriteOnly(sum), ocl::KernelArg::WriteOnlyNoSize(sum_sq)); + gt = src.rows; + return krows.run(1, >, <, false); } #endif From a73809e6fc986ca84f1b7c58492ba7433396b5e6 Mon Sep 17 00:00:00 2001 From: "Fco. Javier Delgado del Hoyo" Date: Wed, 25 Jun 2014 11:46:05 +0200 Subject: [PATCH 012/136] Fix GCC 4.9 compiler warning --- modules/imgproc/src/morph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 3ab495d75f..f05c5afc15 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1257,7 +1257,7 @@ static bool IPPMorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kerne } #undef IPP_MORPH_CASE -#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8 +#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 8 return false; /// It disables false positive warning in GCC 4.8.2 #endif } From 47e345bcb6177ee701baf27357abeb2d3ab6aa9a Mon Sep 17 00:00:00 2001 From: "Fco. Javier Delgado del Hoyo" Date: Wed, 25 Jun 2014 11:49:26 +0200 Subject: [PATCH 013/136] Change comment according to fix --- modules/imgproc/src/morph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index f05c5afc15..eaae9b6d0c 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1258,7 +1258,7 @@ static bool IPPMorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kerne #undef IPP_MORPH_CASE #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 8 - return false; /// It disables false positive warning in GCC 4.8.2 + return false; /// It disables false positive warning in GCC 4.8 and further #endif } } From 730ead44fedeabb6f30f31f2219dc30007d7c6e2 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 26 Jun 2014 12:46:03 +0400 Subject: [PATCH 014/136] Optimize OpenCL version of sepFilter2D --- modules/imgproc/src/filter.cpp | 2 +- .../src/opencl/filterSep_singlePass.cl | 90 ++++++++++++------- 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index e51986c394..d23de91ea1 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3492,7 +3492,7 @@ static bool ocl_sepFilter2D_SinglePass(InputArray _src, OutputArray _dst, return false; size_t lt2[2] = { optimizedSepFilterLocalSize, optimizedSepFilterLocalSize }; - size_t gt2[2] = { lt2[0] * (1 + (size.width - 1) / lt2[0]), lt2[1] * (1 + (size.height - 1) / lt2[1]) }; + size_t gt2[2] = { lt2[0] * (1 + (size.width - 1) / lt2[0]), optimizedSepFilterLocalSize}; char cvt[2][40]; const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", diff --git a/modules/imgproc/src/opencl/filterSep_singlePass.cl b/modules/imgproc/src/opencl/filterSep_singlePass.cl index 3952577d77..6c3bbdc161 100644 --- a/modules/imgproc/src/opencl/filterSep_singlePass.cl +++ b/modules/imgproc/src/opencl/filterSep_singlePass.cl @@ -119,17 +119,15 @@ __kernel void sep_filter(__global uchar* Src, int src_step, int srcOffsetX, int int liy = get_local_id(1); int x = get_global_id(0); - int y = get_global_id(1); // calculate pixel position in source image taking image offset into account int srcX = x + srcOffsetX - RADIUSX; - int srcY = y + srcOffsetY - RADIUSY; // extrapolate coordinates, if needed // and read my own source pixel into local memory // with account for extra border pixels, which will be read by starting workitems int clocY = liy; - int cSrcY = srcY; + int cSrcY = liy + srcOffsetY - RADIUSY; do { int yb = cSrcY; @@ -154,48 +152,76 @@ __kernel void sep_filter(__global uchar* Src, int src_step, int srcOffsetX, int while (clocY < BLK_Y+(RADIUSY*2)); barrier(CLK_LOCAL_MEM_FENCE); - // do vertical filter pass - // and store intermediate results to second local memory array - int i, clocX = lix; - WT sum = (WT) 0; - do + for (int y = 0; y < dst_rows; y+=BLK_Y) { - sum = (WT) 0; - for (i=0; i<=2*RADIUSY; i++) + // do vertical filter pass + // and store intermediate results to second local memory array + int i, clocX = lix; + WT sum = (WT) 0; + do + { + sum = (WT) 0; + for (i=0; i<=2*RADIUSY; i++) #if (defined(INTEGER_ARITHMETIC) && !INTEL_DEVICE) - sum = mad24(lsmem[liy+i][clocX], mat_kernelY[i], sum); + sum = mad24(lsmem[liy + i][clocX], mat_kernelY[i], sum); #else - sum = mad(lsmem[liy+i][clocX], mat_kernelY[i], sum); + sum = mad(lsmem[liy + i][clocX], mat_kernelY[i], sum); #endif - lsmemDy[liy][clocX] = sum; - clocX += BLK_X; - } - while(clocX < BLK_X+(RADIUSX*2)); - barrier(CLK_LOCAL_MEM_FENCE); - - // if this pixel happened to be out of image borders because of global size rounding, - // then just return - if( x >= dst_cols || y >=dst_rows ) - return; + lsmemDy[liy][clocX] = sum; + clocX += BLK_X; + } + while(clocX < BLK_X+(RADIUSX*2)); + barrier(CLK_LOCAL_MEM_FENCE); - // do second horizontal filter pass - // and calculate final result - sum = 0.0f; - for (i=0; i<=2*RADIUSX; i++) + // if this pixel happened to be out of image borders because of global size rounding, + // then just return + if ((x < dst_cols) && (y + liy < dst_rows)) + { + // do second horizontal filter pass + // and calculate final result + sum = 0.0f; + for (i=0; i<=2*RADIUSX; i++) #if (defined(INTEGER_ARITHMETIC) && !INTEL_DEVICE) - sum = mad24(lsmemDy[liy][lix+i], mat_kernelX[i], sum); + sum = mad24(lsmemDy[liy][lix+i], mat_kernelX[i], sum); #else - sum = mad(lsmemDy[liy][lix+i], mat_kernelX[i], sum); + sum = mad(lsmemDy[liy][lix+i], mat_kernelX[i], sum); #endif #ifdef INTEGER_ARITHMETIC #ifdef INTEL_DEVICE - sum = (sum + (1 << (SHIFT_BITS-1))) / (1 << SHIFT_BITS); + sum = (sum + (1 << (SHIFT_BITS-1))) / (1 << SHIFT_BITS); #else - sum = (sum + (1 << (SHIFT_BITS-1))) >> SHIFT_BITS; + sum = (sum + (1 << (SHIFT_BITS-1))) >> SHIFT_BITS; #endif #endif + // store result into destination image + storepix(convertToDstT(sum + (WT)(delta)), Dst + mad24(y + liy, dst_step, mad24(x, DSTSIZE, dst_offset))); + } + + for (int i = liy * BLK_X + lix; i < (RADIUSY*2) * (BLK_X+(RADIUSX*2)); i += BLK_X * BLK_Y) + { + int clocX = i % (BLK_X+(RADIUSX*2)); + int clocY = i / (BLK_X+(RADIUSX*2)); + lsmem[clocY][clocX] = lsmem[clocY + BLK_Y][clocX]; + } + barrier(CLK_LOCAL_MEM_FENCE); + + int cSrcY = y + BLK_Y + liy + srcOffsetY + RADIUSY; + EXTRAPOLATE(cSrcY, (height)); + + clocX = lix; + int cSrcX = x + srcOffsetX - RADIUSX; + do + { + int xb = cSrcX; + EXTRAPOLATE(xb,(width)); + lsmem[liy + 2*RADIUSY][clocX] = ELEM(xb, cSrcY, (width), (height), 0 ); + + clocX += BLK_X; + cSrcX += BLK_X; + } + while(clocX < BLK_X+(RADIUSX*2)); + barrier(CLK_LOCAL_MEM_FENCE); + } - // store result into destination image - storepix(convertToDstT(sum + (WT)(delta)), Dst + mad24(y, dst_step, mad24(x, DSTSIZE, dst_offset))); } From 6f2fea7ea5f3f61cee860168700537165f3a77db Mon Sep 17 00:00:00 2001 From: mlyashko Date: Wed, 25 Jun 2014 16:07:33 +0400 Subject: [PATCH 015/136] added perftest for moments --- modules/imgproc/perf/perf_moments.cpp | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 modules/imgproc/perf/perf_moments.cpp diff --git a/modules/imgproc/perf/perf_moments.cpp b/modules/imgproc/perf/perf_moments.cpp new file mode 100644 index 0000000000..9b3c5428f3 --- /dev/null +++ b/modules/imgproc/perf/perf_moments.cpp @@ -0,0 +1,38 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// Copyright (C) 2014, Itseez, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. + +#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; + +typedef std::tr1::tuple MomentsParams_t; +typedef perf::TestBaseWithParam MomentsFixture_val; + +PERF_TEST_P(MomentsFixture_val, Moments1, + ::testing::Combine( + testing::Values(TYPICAL_MAT_SIZES), + testing::Values(CV_16U, CV_16S, CV_32F, CV_64F), + testing::Bool())) +{ + const MomentsParams_t params = GetParam(); + const Size srcSize = get<0>(params); + const MatDepth srcDepth = get<1>(params); + const bool binaryImage = get<2>(params); + + cv::Moments m; + Mat src(srcSize, srcDepth); + declare.in(src, WARMUP_RNG); + + TEST_CYCLE() m = cv::moments(src, binaryImage); + + SANITY_CHECK_MOMENTS(m, 1e-4, ERROR_RELATIVE); +} From ad9272e83652f8c21eaaa89840e00898107b9778 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 26 Jun 2014 13:13:01 +0400 Subject: [PATCH 016/136] reverted to original plain C++ code --- modules/imgproc/src/morph.cpp | 93 +++++++++-------------------------- 1 file changed, 22 insertions(+), 71 deletions(-) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 3ab495d75f..6e31673a5f 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1545,93 +1545,44 @@ void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, InputArray kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { - int src_type = _src.type(), dst_type = _dst.type(), - src_cn = CV_MAT_CN(src_type), src_depth = CV_MAT_DEPTH(src_type); - - bool use_opencl = cv::ocl::useOpenCL() && _src.isUMat() && _src.size() == _dst.size() && src_type == dst_type && - _src.dims()<=2 && (src_cn == 1 || src_cn == 4) && (anchor.x == -1) && (anchor.y == -1) && - (src_depth == CV_8U || src_depth == CV_32F || src_depth == CV_64F ) && - (borderType == cv::BORDER_CONSTANT) && (borderValue == morphologyDefaultBorderValue()); - - _dst.create(_src.size(), _src.type()); - Mat src, dst, temp; - UMat usrc, udst, utemp; + Mat src = _src.getMat(), temp; + _dst.create(src.size(), src.type()); + Mat dst = _dst.getMat(); switch( op ) { case MORPH_ERODE: - erode( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); + erode( src, dst, kernel, anchor, iterations, borderType, borderValue ); break; case MORPH_DILATE: - dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); + dilate( src, dst, kernel, anchor, iterations, borderType, borderValue ); break; case MORPH_OPEN: - erode( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); - dilate( _dst, _dst, kernel, anchor, iterations, borderType, borderValue ); + erode( src, dst, kernel, anchor, iterations, borderType, borderValue ); + dilate( dst, dst, kernel, anchor, iterations, borderType, borderValue ); break; case CV_MOP_CLOSE: - dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); - erode( _dst, _dst, kernel, anchor, iterations, borderType, borderValue ); + dilate( src, dst, kernel, anchor, iterations, borderType, borderValue ); + erode( dst, dst, kernel, anchor, iterations, borderType, borderValue ); break; case CV_MOP_GRADIENT: - erode( _src, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, anchor, iterations, borderType, borderValue ); - dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); - if(use_opencl) - { - udst = _dst.getUMat(); - subtract(udst, utemp, udst); - } - else - { - dst = _dst.getMat(); - dst -= temp; - } + erode( src, temp, kernel, anchor, iterations, borderType, borderValue ); + dilate( src, dst, kernel, anchor, iterations, borderType, borderValue ); + dst -= temp; break; case CV_MOP_TOPHAT: - if(use_opencl) - { - usrc = _src.getUMat(); - udst = _dst.getUMat(); - if( usrc.u != udst.u ) - utemp = udst; - } - else - { - src = _src.getMat(); - dst = _dst.getMat(); - if( src.data != dst.data ) - temp = dst; - } - erode( _src, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, anchor, iterations, borderType, borderValue ); - dilate( use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, - anchor, iterations, borderType, borderValue ); - if(use_opencl) - subtract(usrc, utemp, udst); - else - dst = src - temp; + if( src.data != dst.data ) + temp = dst; + erode( src, temp, kernel, anchor, iterations, borderType, borderValue ); + dilate( temp, temp, kernel, anchor, iterations, borderType, borderValue ); + dst = src - temp; break; case CV_MOP_BLACKHAT: - if(use_opencl) - { - usrc = _src.getUMat(); - udst = _dst.getUMat(); - if( usrc.u != udst.u ) - utemp = udst; - } - else - { - src = _src.getMat(); - dst = _dst.getMat(); - if( src.data != dst.data ) - temp = dst; - } - dilate( _src, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, anchor, iterations, borderType, borderValue ); - erode( use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, - anchor, iterations, borderType, borderValue ); - if(use_opencl) - subtract(utemp, usrc, udst); - else - dst = temp - src; + if( src.data != dst.data ) + temp = dst; + dilate( src, temp, kernel, anchor, iterations, borderType, borderValue ); + erode( temp, temp, kernel, anchor, iterations, borderType, borderValue ); + dst = temp - src; break; default: CV_Error( CV_StsBadArg, "unknown morphological operation" ); From a3592cd068231d6cf7dfcfb092cfbcaaa2d4c41f Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 26 Jun 2014 13:18:03 +0400 Subject: [PATCH 017/136] added ocl_** function --- modules/imgproc/src/morph.cpp | 58 +++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 6e31673a5f..097179f99e 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1541,10 +1541,68 @@ void cv::dilate( InputArray src, OutputArray dst, InputArray kernel, morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue ); } +#ifdef HAVE_OPENCL + +static void ocl_morphologyEx(InputArray _src, OutputArray _dst, int op, + InputArray kernel, Point anchor, int iterations, + int borderType, const Scalar& borderValue) +{ + int type = _src.type(), cn = CV_MAT_CN(type); + Size ksize = kernel.size(); + + _dst.create(_src.size(), type); + UMat temp; + + switch( op ) + { + case MORPH_ERODE: + erode( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); + break; + case MORPH_DILATE: + dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); + break; + case MORPH_OPEN: + erode( _src, temp, kernel, anchor, iterations, borderType, borderValue ); + dilate( temp, _dst, kernel, anchor, iterations, borderType, borderValue ); + break; + case CV_MOP_CLOSE: + dilate( _src, temp, kernel, anchor, iterations, borderType, borderValue ); + erode( temp, _dst, kernel, anchor, iterations, borderType, borderValue ); + break; + case CV_MOP_GRADIENT: + // ?? + erode( _src, temp, kernel, anchor, iterations, borderType, borderValue ); + dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); + subtract(_dst, temp, _dst); + break; + case CV_MOP_TOPHAT: + // ?? + erode( _src, temp, kernel, anchor, iterations, borderType, borderValue ); + dilate( temp, _dst, kernel, anchor, iterations, borderType, borderValue ); + subtract(_src, _dst, _dst); + break; + case CV_MOP_BLACKHAT: + // ?? + dilate( _src, temp, kernel, anchor, iterations, borderType, borderValue ); + erode( temp, _dst, kernel, anchor, iterations, borderType, borderValue ); + subtract(_dst, _src, _dst); + break; + default: + CV_Error( CV_StsBadArg, "unknown morphological operation" ); + } +} + +#endif + void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, InputArray kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && cn <= 4 && + anchor.x == ksize.width >> 1 && anchor.y == ksize.height >> 1 && + borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue(), + ocl_morphologyEx(_src, _dst, op, kernel, anchor, iterations, borderType, borderValue)) + Mat src = _src.getMat(), temp; _dst.create(src.size(), src.type()); Mat dst = _dst.getMat(); From 16ab6ec534a6c45b9d8090d3146d70b27c87348c Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 26 Jun 2014 13:25:24 +0400 Subject: [PATCH 018/136] ported changes from PR #2867 --- modules/imgproc/src/morph.cpp | 167 +++++++++++++++------------- modules/imgproc/src/opencl/morph.cl | 87 +++++++-------- 2 files changed, 134 insertions(+), 120 deletions(-) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 097179f99e..c1a5d28245 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1342,58 +1342,80 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, #ifdef HAVE_OPENCL -static bool ocl_morphology_op(InputArray _src, OutputArray _dst, Mat kernel, - const Size & ksize, const Point & anchor, int iterations, int op) +static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel, + Point anchor, int iterations, int op, int borderType, + const Scalar& borderValue) { - CV_Assert(op == MORPH_ERODE || op == MORPH_DILATE); - - int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - - if (depth == CV_64F && !doubleSupport) + if (borderType != BORDER_CONSTANT) return false; - UMat kernel8U; - kernel.convertTo(kernel8U, CV_8U); - kernel8U = kernel8U.reshape(1, 1); + Mat kernel = _kernel.getMat(); + Size ksize = kernel.data ? kernel.size() : Size(3,3); + anchor = normalizeAnchor(anchor, ksize); - bool rectKernel = true; + if (iterations == 0 || kernel.rows*kernel.cols == 1) { - Mat m = kernel.reshape(1, 1); - for (int i = 0; i < m.size().area(); ++i) - if (m.at(i) != 1) - { - rectKernel = false; - break; - } + _src.copyTo(_dst); + return true; + } + + if (!kernel.data) + { + kernel = getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2)); + anchor = Point(iterations, iterations); + iterations = 1; } + else if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols ) + { + anchor = Point(anchor.x*iterations, anchor.y*iterations); + kernel = getStructuringElement(MORPH_RECT, + Size(ksize.width + (iterations-1)*(ksize.width-1), + ksize.height + (iterations-1)*(ksize.height-1)), + anchor); + iterations = 1; + } + + const ocl::Device & dev = ocl::Device::getDefault(); + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + bool doubleSupport = dev.doubleFPConfig() > 0; + + if (depth == CV_64F && !doubleSupport) + return false; UMat src = _src.getUMat(); #ifdef ANDROID - size_t localThreads[3] = {16, 8, 1}; + size_t localThreads[2] = { 16, 8 }; #else - size_t localThreads[3] = {16, 16, 1}; + size_t localThreads[2] = { 16, 16 }; #endif - size_t globalThreads[3] = {(src.cols + localThreads[0] - 1) / localThreads[0] *localThreads[0], (src.rows + localThreads[1] - 1) / localThreads[1] *localThreads[1], 1}; + size_t globalThreads[2] = { src.cols, src.rows }; if (localThreads[0]*localThreads[1] * 2 < (localThreads[0] + ksize.width - 1) * (localThreads[1] + ksize.height - 1)) return false; + // build processing + String processing; + Mat kernel8u; + kernel.convertTo(kernel8u, CV_8U); + for (int y = 0; y < kernel8u.rows; ++y) + for (int x = 0; x < kernel8u.cols; ++x) + if (kernel8u.at(y, x) != 0) + processing += format("PROCESS(%d,%d)", y, x); + static const char * const op2str[] = { "ERODE", "DILATE" }; - String buildOptions = format("-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D %s%s%s" - " -D T=%s -D DEPTH_%d -D cn=%d -D T1=%s", anchor.x, anchor.y, + String buildOptions = format("-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D %s%s" + " -D PROCESS_ELEMS=%s -D T=%s -D DEPTH_%d -D cn=%d -D T1=%s", anchor.x, anchor.y, (int)localThreads[0], (int)localThreads[1], op2str[op], - doubleSupport ? " -D DOUBLE_SUPPORT" : "", rectKernel ? " -D RECTKERNEL" : "", - ocl::typeToStr(_src.type()), _src.depth(), cn, ocl::typeToStr(depth)); + doubleSupport ? " -D DOUBLE_SUPPORT" : "", processing.c_str(), + ocl::typeToStr(type), depth, cn, ocl::typeToStr(depth)); - std::vector kernels; + std::vector kernels(iterations); for (int i = 0; i < iterations; i++) { - ocl::Kernel k("morph", ocl::imgproc::morph_oclsrc, buildOptions); - if (k.empty()) + kernels[i].create("morph", ocl::imgproc::morph_oclsrc, buildOptions); + if (kernels[i].empty()) return false; - kernels.push_back(k); } _dst.create(src.size(), src.type()); @@ -1407,8 +1429,7 @@ static bool ocl_morphology_op(InputArray _src, OutputArray _dst, Mat kernel, int wholecols = wholesize.width, wholerows = wholesize.height; kernels[0].args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), - ofs.x, ofs.y, src.cols, src.rows, ocl::KernelArg::PtrReadOnly(kernel8U), - wholecols, wholerows); + ofs.x, ofs.y, src.cols, src.rows, wholecols, wholerows); return kernels[0].run(2, globalThreads, localThreads, false); } @@ -1422,19 +1443,20 @@ static bool ocl_morphology_op(InputArray _src, OutputArray _dst, Mat kernel, if (i == 0) { int cols = src.cols, rows = src.rows; - src.locateROI(wholesize,ofs); + src.locateROI(wholesize, ofs); src.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x); if(src.u != dst.u) source = src; else src.copyTo(source); + src.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x); source.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x); } else { int cols = dst.cols, rows = dst.rows; - dst.locateROI(wholesize,ofs); + dst.locateROI(wholesize, ofs); dst.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x); dst.copyTo(source); dst.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x); @@ -1443,12 +1465,12 @@ static bool ocl_morphology_op(InputArray _src, OutputArray _dst, Mat kernel, source.locateROI(wholesize, ofs); kernels[i].args(ocl::KernelArg::ReadOnlyNoSize(source), ocl::KernelArg::WriteOnlyNoSize(dst), - ofs.x, ofs.y, source.cols, source.rows, ocl::KernelArg::PtrReadOnly(kernel8U), - wholesize.width, wholesize.height); + ofs.x, ofs.y, source.cols, source.rows, wholesize.width, wholesize.height); if (!kernels[i].run(2, globalThreads, localThreads, false)) return false; } + return true; } @@ -1459,10 +1481,10 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { -#ifdef HAVE_OPENCL - int src_type = _src.type(), - src_cn = CV_MAT_CN(src_type), src_depth = CV_MAT_DEPTH(src_type); -#endif + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && _src.channels() <= 4 && + borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() && + (op == MORPH_ERODE || op == MORPH_DILATE), + ocl_morphOp(_src, _dst, _kernel, anchor, iterations, op, borderType, borderValue) ) Mat kernel = _kernel.getMat(); Size ksize = kernel.data ? kernel.size() : Size(3,3); @@ -1490,12 +1512,6 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, iterations = 1; } - CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && src_cn <= 4 && - (src_depth == CV_8U || src_depth == CV_32F || src_depth == CV_64F ) && - borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() && - (op == MORPH_ERODE || op == MORPH_DILATE), - ocl_morphology_op(_src, _dst, kernel, ksize, anchor, iterations, op) ) - #if IPP_VERSION_X100 >= 801 if( IPPMorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue) ) return; @@ -1515,13 +1531,6 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, parallel_for_(Range(0, nStripes), MorphologyRunner(src, dst, nStripes, iterations, op, kernel, anchor, borderType, borderType, borderValue)); - - //Ptr f = createMorphologyFilter(op, src.type(), - // kernel, anchor, borderType, borderType, borderValue ); - - //f->apply( src, dst ); - //for( int i = 1; i < iterations; i++ ) - // f->apply( dst, dst ); } } @@ -1543,53 +1552,56 @@ void cv::dilate( InputArray src, OutputArray dst, InputArray kernel, #ifdef HAVE_OPENCL -static void ocl_morphologyEx(InputArray _src, OutputArray _dst, int op, +namespace cv { + +static bool ocl_morphologyEx(InputArray _src, OutputArray _dst, int op, InputArray kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue) { - int type = _src.type(), cn = CV_MAT_CN(type); - Size ksize = kernel.size(); - - _dst.create(_src.size(), type); + _dst.createSameSize(_src, _src.type()); UMat temp; switch( op ) { case MORPH_ERODE: - erode( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); + ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); break; case MORPH_DILATE: - dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); + ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); break; case MORPH_OPEN: - erode( _src, temp, kernel, anchor, iterations, borderType, borderValue ); - dilate( temp, _dst, kernel, anchor, iterations, borderType, borderValue ); + ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); + ocl_morphOp( temp, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); break; - case CV_MOP_CLOSE: - dilate( _src, temp, kernel, anchor, iterations, borderType, borderValue ); - erode( temp, _dst, kernel, anchor, iterations, borderType, borderValue ); + case MORPH_CLOSE: + ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); + ocl_morphOp( temp, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); break; - case CV_MOP_GRADIENT: + case MORPH_GRADIENT: // ?? - erode( _src, temp, kernel, anchor, iterations, borderType, borderValue ); - dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); + ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); + ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); subtract(_dst, temp, _dst); break; - case CV_MOP_TOPHAT: + case MORPH_TOPHAT: // ?? - erode( _src, temp, kernel, anchor, iterations, borderType, borderValue ); - dilate( temp, _dst, kernel, anchor, iterations, borderType, borderValue ); + ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); + ocl_morphOp( temp, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); subtract(_src, _dst, _dst); break; - case CV_MOP_BLACKHAT: + case MORPH_BLACKHAT: // ?? - dilate( _src, temp, kernel, anchor, iterations, borderType, borderValue ); - erode( temp, _dst, kernel, anchor, iterations, borderType, borderValue ); + ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); + ocl_morphOp( temp, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); subtract(_dst, _src, _dst); break; default: CV_Error( CV_StsBadArg, "unknown morphological operation" ); } + + return true; +} + } #endif @@ -1598,10 +1610,13 @@ void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, InputArray kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { - CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && cn <= 4 && +#ifdef HAVE_OPENCL + Size ksize = kernel.size(); + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && _src.channels() <= 4 && anchor.x == ksize.width >> 1 && anchor.y == ksize.height >> 1 && - borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue(), + borderType == cv::BORDER_CONSTANT, ocl_morphologyEx(_src, _dst, op, kernel, anchor, iterations, borderType, borderValue)) +#endif Mat src = _src.getMat(), temp; _dst.create(src.size(), src.type()); diff --git a/modules/imgproc/src/opencl/morph.cl b/modules/imgproc/src/opencl/morph.cl index a7611c50f9..7df09ec61e 100644 --- a/modules/imgproc/src/opencl/morph.cl +++ b/modules/imgproc/src/opencl/morph.cl @@ -54,59 +54,70 @@ #endif #ifdef DEPTH_0 -#ifdef ERODE -#define VAL 255 -#endif -#ifdef DILATE -#define VAL 0 -#endif +#define MIN_VAL 0 +#define MAX_VAL UCHAR_MAX +#elif defined DEPTH_1 +#define MIN_VAL SCHAR_MIN +#define MAX_VAL SCHAR_MAX +#elif defined DEPTH_2 +#define MIN_VAL 0 +#define MAX_VAL USHRT_MAX +#elif defined DEPTH_3 +#define MIN_VAL SHRT_MIN +#define MAX_VAL SHRT_MAX +#elif defined DEPTH_4 +#define MIN_VAL INT_MIN +#define MAX_VAL INT_MAX #elif defined DEPTH_5 -#ifdef ERODE -#define VAL FLT_MAX -#endif -#ifdef DILATE -#define VAL -FLT_MAX -#endif +#define MIN_VAL (-FLT_MAX) +#define MAX_VAL FLT_MAX #elif defined DEPTH_6 -#ifdef ERODE -#define VAL DBL_MAX -#endif -#ifdef DILATE -#define VAL -DBL_MAX +#define MIN_VAL (-DBL_MAX) +#define MAX_VAL DBL_MAX #endif + +#ifdef OP_ERODE +#define VAL MAX_VAL +#elif defined OP_DILATE +#define VAL MIN_VAL +#else +#error "Unknown operation" #endif -#ifdef ERODE -#if defined(INTEL_DEVICE) && (DEPTH_0) +#ifdef OP_ERODE +#if defined INTEL_DEVICE && defined DEPTH_0 // workaround for bug in Intel HD graphics drivers (10.18.10.3496 or older) #define __CAT(x, y) x##y #define CAT(x, y) __CAT(x, y) #define WA_CONVERT_1 CAT(convert_uint, cn) #define WA_CONVERT_2 CAT(convert_, T) #define convert_uint1 convert_uint -#define MORPH_OP(A,B) WA_CONVERT_2(min(WA_CONVERT_1(A),WA_CONVERT_1(B))) +#define MORPH_OP(A, B) WA_CONVERT_2(min(WA_CONVERT_1(A), WA_CONVERT_1(B))) #else -#define MORPH_OP(A,B) min((A),(B)) +#define MORPH_OP(A, B) min((A), (B)) #endif #endif -#ifdef DILATE -#define MORPH_OP(A,B) max((A),(B)) +#ifdef OP_DILATE +#define MORPH_OP(A, B) max((A), (B)) #endif +#define PROCESS(y, x) \ + res = MORPH_OP(res, LDS_DAT[mad24(l_y + y, width, l_x + x)]); + // BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii #define ELEM(i, l_edge, r_edge, elem1, elem2) (i) < (l_edge) | (i) >= (r_edge) ? (elem1) : (elem2) + __kernel void morph(__global const uchar * srcptr, int src_step, int src_offset, __global uchar * dstptr, int dst_step, int dst_offset, int src_offset_x, int src_offset_y, int cols, int rows, - __constant uchar * mat_kernel, int src_whole_cols, int src_whole_rows) + int src_whole_cols, int src_whole_rows EXTRA_PARAMS) { int gidx = get_global_id(0), gidy = get_global_id(1); int l_x = get_local_id(0), l_y = get_local_id(1); int x = get_group_id(0) * LSIZE0, y = get_group_id(1) * LSIZE1; int start_x = x + src_offset_x - RADIUSX; - int end_x = x + src_offset_x + LSIZE0 + RADIUSX; - int width = end_x - (x + src_offset_x - RADIUSX) + 1; + int width = mad24(RADIUSX, 2, LSIZE0 + 1); int start_y = y + src_offset_y - RADIUSY; int point1 = mad24(l_y, LSIZE0, l_x); int point2 = point1 + LSIZE0 * LSIZE1; @@ -117,7 +128,7 @@ __kernel void morph(__global const uchar * srcptr, int src_step, int src_offset, int start_addr = mad24(cur_y, src_step, cur_x * TSIZE); int start_addr2 = mad24(cur_y2, src_step, cur_x2 * TSIZE); - __local T LDS_DAT[2*LSIZE1*LSIZE0]; + __local T LDS_DAT[2 * LSIZE1 * LSIZE0]; // read pixels from src int end_addr = mad24(src_whole_rows - 1, src_step, src_whole_cols * TSIZE); @@ -128,8 +139,8 @@ __kernel void morph(__global const uchar * srcptr, int src_step, int src_offset, T temp1 = loadpix(srcptr + start_addr2); // judge if read out of boundary - temp0 = ELEM(cur_x, 0, src_whole_cols, (T)(VAL),temp0); - temp0 = ELEM(cur_y, 0, src_whole_rows, (T)(VAL),temp0); + temp0 = ELEM(cur_x, 0, src_whole_cols, (T)(VAL), temp0); + temp0 = ELEM(cur_y, 0, src_whole_rows, (T)(VAL), temp0); temp1 = ELEM(cur_x2, 0, src_whole_cols, (T)(VAL), temp1); temp1 = ELEM(cur_y2, 0, src_whole_rows, (T)(VAL), temp1); @@ -138,23 +149,11 @@ __kernel void morph(__global const uchar * srcptr, int src_step, int src_offset, LDS_DAT[point2] = temp1; barrier(CLK_LOCAL_MEM_FENCE); - T res = (T)(VAL); - for (int i = 0, sizey = 2 * RADIUSY + 1; i < sizey; i++) - for (int j = 0, sizex = 2 * RADIUSX + 1; j < sizex; j++) - { - res = -#ifndef RECTKERNEL - mat_kernel[i*(2*RADIUSX+1)+j] ? -#endif - MORPH_OP(res, LDS_DAT[mad24(l_y + i, width, l_x + j)]) -#ifndef RECTKERNEL - : res -#endif - ; - } - if (gidx < cols && gidy < rows) { + T res = (T)(VAL); + PROCESS_ELEMS; + int dst_index = mad24(gidy, dst_step, mad24(gidx, TSIZE, dst_offset)); storepix(res, dstptr + dst_index); } From 1a73aa1f6a3e25cdbe749e4ceaf1a75ece0fb6fb Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 26 Jun 2014 15:43:40 +0400 Subject: [PATCH 019/136] Change local size --- modules/imgproc/src/filter.cpp | 11 ++++++----- modules/imgproc/src/opencl/filterSep_singlePass.cl | 10 ++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index d23de91ea1..6c0da79ccf 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3471,7 +3471,8 @@ static bool ocl_sepColFilter2D(const UMat & buf, UMat & dst, const Mat & kernelY return k.run(2, globalsize, localsize, false); } -const int optimizedSepFilterLocalSize = 16; +const int optimizedSepFilterLocalWidth = 16; +const int optimizedSepFilterLocalHeight = 8; static bool ocl_sepFilter2D_SinglePass(InputArray _src, OutputArray _dst, Mat row_kernel, Mat col_kernel, @@ -3491,8 +3492,8 @@ static bool ocl_sepFilter2D_SinglePass(InputArray _src, OutputArray _dst, borderType == BORDER_REFLECT_101)) return false; - size_t lt2[2] = { optimizedSepFilterLocalSize, optimizedSepFilterLocalSize }; - size_t gt2[2] = { lt2[0] * (1 + (size.width - 1) / lt2[0]), optimizedSepFilterLocalSize}; + size_t lt2[2] = { optimizedSepFilterLocalWidth, optimizedSepFilterLocalHeight }; + size_t gt2[2] = { lt2[0] * (1 + (size.width - 1) / lt2[0]), lt2[1]}; char cvt[2][40]; const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", @@ -3584,8 +3585,8 @@ static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, } CV_OCL_RUN_(kernelY.cols <= 21 && kernelX.cols <= 21 && - imgSize.width > optimizedSepFilterLocalSize + anchor.x && - imgSize.height > optimizedSepFilterLocalSize + anchor.y && + imgSize.width > optimizedSepFilterLocalWidth + anchor.x && + imgSize.height > optimizedSepFilterLocalHeight + anchor.y && (!(borderType & BORDER_ISOLATED) || _src.offset() == 0) && anchor == Point(kernelX.cols >> 1, kernelY.cols >> 1) && (d.isIntel() || (d.isAMD() && !d.hostUnifiedMemory())), diff --git a/modules/imgproc/src/opencl/filterSep_singlePass.cl b/modules/imgproc/src/opencl/filterSep_singlePass.cl index 6c3bbdc161..8c14f2d77e 100644 --- a/modules/imgproc/src/opencl/filterSep_singlePass.cl +++ b/modules/imgproc/src/opencl/filterSep_singlePass.cl @@ -127,10 +127,9 @@ __kernel void sep_filter(__global uchar* Src, int src_step, int srcOffsetX, int // and read my own source pixel into local memory // with account for extra border pixels, which will be read by starting workitems int clocY = liy; - int cSrcY = liy + srcOffsetY - RADIUSY; do { - int yb = cSrcY; + int yb = clocY + srcOffsetY - RADIUSY; EXTRAPOLATE(yb, (height)); int clocX = lix; @@ -147,7 +146,6 @@ __kernel void sep_filter(__global uchar* Src, int src_step, int srcOffsetX, int while(clocX < BLK_X+(RADIUSX*2)); clocY += BLK_Y; - cSrcY += BLK_Y; } while (clocY < BLK_Y+(RADIUSY*2)); barrier(CLK_LOCAL_MEM_FENCE); @@ -206,8 +204,8 @@ __kernel void sep_filter(__global uchar* Src, int src_step, int srcOffsetX, int } barrier(CLK_LOCAL_MEM_FENCE); - int cSrcY = y + BLK_Y + liy + srcOffsetY + RADIUSY; - EXTRAPOLATE(cSrcY, (height)); + int yb = y + liy + BLK_Y + srcOffsetY + RADIUSY; + EXTRAPOLATE(yb, (height)); clocX = lix; int cSrcX = x + srcOffsetX - RADIUSX; @@ -215,7 +213,7 @@ __kernel void sep_filter(__global uchar* Src, int src_step, int srcOffsetX, int { int xb = cSrcX; EXTRAPOLATE(xb,(width)); - lsmem[liy + 2*RADIUSY][clocX] = ELEM(xb, cSrcY, (width), (height), 0 ); + lsmem[liy + 2*RADIUSY][clocX] = ELEM(xb, yb, (width), (height), 0 ); clocX += BLK_X; cSrcX += BLK_X; From 36db85a94dac360d2eb1cd883b3f3693e3ee9453 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 26 Jun 2014 18:15:13 +0400 Subject: [PATCH 020/136] optimized some operations --- modules/imgproc/src/morph.cpp | 130 +++++++++++++--------- modules/imgproc/src/opencl/morph.cl | 21 ++++ modules/imgproc/test/ocl/test_filters.cpp | 32 +++--- 3 files changed, 116 insertions(+), 67 deletions(-) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index c1a5d28245..5eec87cb26 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1333,10 +1333,7 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, if( iterations > 1 ) return false; - if (IPPMorphReplicate( op, src, dst, kernel, ksize, anchor, rectKernel )) - return true; - - return false; + return IPPMorphReplicate( op, src, dst, kernel, ksize, anchor, rectKernel ); } #endif @@ -1344,14 +1341,19 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel, Point anchor, int iterations, int op, int borderType, - const Scalar& borderValue) + const Scalar &, int actual_op = -1, InputArray _extraMat = noArray()) { - if (borderType != BORDER_CONSTANT) + const ocl::Device & dev = ocl::Device::getDefault(); + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + bool doubleSupport = dev.doubleFPConfig() > 0; + + if ((depth == CV_64F && !doubleSupport) || borderType != BORDER_CONSTANT) return false; Mat kernel = _kernel.getMat(); - Size ksize = kernel.data ? kernel.size() : Size(3,3); - anchor = normalizeAnchor(anchor, ksize); + bool haveExtraMat = !_extraMat.empty(); + Size ksize = kernel.data ? kernel.size() : Size(3, 3), ssize = _src.size(); + CV_Assert(actual_op <= 3 || haveExtraMat); if (iterations == 0 || kernel.rows*kernel.cols == 1) { @@ -1375,21 +1377,12 @@ static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel, iterations = 1; } - const ocl::Device & dev = ocl::Device::getDefault(); - int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - bool doubleSupport = dev.doubleFPConfig() > 0; - - if (depth == CV_64F && !doubleSupport) - return false; - - UMat src = _src.getUMat(); - #ifdef ANDROID size_t localThreads[2] = { 16, 8 }; #else size_t localThreads[2] = { 16, 16 }; #endif - size_t globalThreads[2] = { src.cols, src.rows }; + size_t globalThreads[2] = { ssize.width, ssize.height }; if (localThreads[0]*localThreads[1] * 2 < (localThreads[0] + ksize.width - 1) * (localThreads[1] + ksize.height - 1)) return false; @@ -1403,21 +1396,35 @@ static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel, if (kernel8u.at(y, x) != 0) processing += format("PROCESS(%d,%d)", y, x); - static const char * const op2str[] = { "ERODE", "DILATE" }; - String buildOptions = format("-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D %s%s" - " -D PROCESS_ELEMS=%s -D T=%s -D DEPTH_%d -D cn=%d -D T1=%s", anchor.x, anchor.y, - (int)localThreads[0], (int)localThreads[1], op2str[op], - doubleSupport ? " -D DOUBLE_SUPPORT" : "", processing.c_str(), - ocl::typeToStr(type), depth, cn, ocl::typeToStr(depth)); + static const char * const op2str[] = { "OP_ERODE", "OP_DILATE", NULL, NULL, "OP_GRADIENT", "OP_TOPHAT", "OP_BLACKHAT" }; + + char cvt[2][50]; + int wdepth = std::max(depth, CV_32F), scalarcn = cn == 3 ? 4 : cn; + + if (actual_op < 0) + actual_op = op; std::vector kernels(iterations); for (int i = 0; i < iterations; i++) { + int current_op = iterations == i + 1 ? actual_op : op; + String buildOptions = format("-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D %s%s" + " -D PROCESS_ELEMS=%s -D T=%s -D DEPTH_%d -D cn=%d -D T1=%s" + " -D convertToWT=%s -D convertToT=%s -D ST=%s%s", + anchor.x, anchor.y, (int)localThreads[0], (int)localThreads[1], op2str[op], + doubleSupport ? " -D DOUBLE_SUPPORT" : "", processing.c_str(), + ocl::typeToStr(type), depth, cn, ocl::typeToStr(depth), + ocl::convertTypeStr(depth, wdepth, cn, cvt[0]), + ocl::convertTypeStr(wdepth, depth, cn, cvt[1]), + ocl::typeToStr(CV_MAKE_TYPE(depth, scalarcn)), + current_op == op ? "" : cv::format(" -D %s", op2str[current_op]).c_str()); + kernels[i].create("morph", ocl::imgproc::morph_oclsrc, buildOptions); if (kernels[i].empty()) return false; } + UMat src = _src.getUMat(), extraMat = _extraMat.getUMat(); _dst.create(src.size(), src.type()); UMat dst = _dst.getUMat(); @@ -1428,7 +1435,12 @@ static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel, src.locateROI(wholesize, ofs); int wholecols = wholesize.width, wholerows = wholesize.height; - kernels[0].args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), + if (haveExtraMat) + kernels[0].args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), + ofs.x, ofs.y, src.cols, src.rows, wholecols, wholerows, + ocl::KernelArg::ReadOnlyNoSize(extraMat)); + else + kernels[0].args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), ofs.x, ofs.y, src.cols, src.rows, wholecols, wholerows); return kernels[0].run(2, globalThreads, localThreads, false); @@ -1464,8 +1476,13 @@ static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel, } source.locateROI(wholesize, ofs); - kernels[i].args(ocl::KernelArg::ReadOnlyNoSize(source), ocl::KernelArg::WriteOnlyNoSize(dst), - ofs.x, ofs.y, source.cols, source.rows, wholesize.width, wholesize.height); + if (haveExtraMat && iterations == i + 1) + kernels[i].args(ocl::KernelArg::ReadOnlyNoSize(source), ocl::KernelArg::WriteOnlyNoSize(dst), + ofs.x, ofs.y, source.cols, source.rows, wholesize.width, wholesize.height, + ocl::KernelArg::ReadOnlyNoSize(extraMat)); + else + kernels[i].args(ocl::KernelArg::ReadOnlyNoSize(source), ocl::KernelArg::WriteOnlyNoSize(dst), + ofs.x, ofs.y, source.cols, source.rows, wholesize.width, wholesize.height); if (!kernels[i].run(2, globalThreads, localThreads, false)) return false; @@ -1481,15 +1498,16 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { - CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && _src.channels() <= 4 && - borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() && - (op == MORPH_ERODE || op == MORPH_DILATE), - ocl_morphOp(_src, _dst, _kernel, anchor, iterations, op, borderType, borderValue) ) - Mat kernel = _kernel.getMat(); Size ksize = kernel.data ? kernel.size() : Size(3,3); anchor = normalizeAnchor(anchor, ksize); + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && _src.channels() <= 4 && + borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() && + (op == MORPH_ERODE || op == MORPH_DILATE) && + anchor.x == ksize.width >> 1 && anchor.y == ksize.height >> 1, + ocl_morphOp(_src, _dst, kernel, anchor, iterations, op, borderType, borderValue) ) + if (iterations == 0 || kernel.rows*kernel.cols == 1) { _src.copyTo(_dst); @@ -1559,41 +1577,49 @@ static bool ocl_morphologyEx(InputArray _src, OutputArray _dst, int op, int borderType, const Scalar& borderValue) { _dst.createSameSize(_src, _src.type()); + bool submat = _dst.isSubmatrix(); UMat temp; + _OutputArray _temp = submat ? _dst : _OutputArray(temp); switch( op ) { case MORPH_ERODE: - ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); + if (!ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) + return false; break; case MORPH_DILATE: - ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); + if (!ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue )) + return false; break; case MORPH_OPEN: - ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); - ocl_morphOp( temp, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); + if (!ocl_morphOp( _src, _temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) + return false; + if (!ocl_morphOp( _temp, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue )) + return false; break; case MORPH_CLOSE: - ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); - ocl_morphOp( temp, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); + if (!ocl_morphOp( _src, _temp, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue )) + return false; + if (!ocl_morphOp( _temp, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) + return false; break; case MORPH_GRADIENT: - // ?? - ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); - ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); - subtract(_dst, temp, _dst); + if (!ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) + return false; + if (!ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue, MORPH_GRADIENT, temp )) + return false; break; case MORPH_TOPHAT: - // ?? - ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); - ocl_morphOp( temp, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); - subtract(_src, _dst, _dst); + if (!ocl_morphOp( _src, _temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) + return false; + if (!ocl_morphOp( _temp, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue, MORPH_TOPHAT, _src )) + return false; break; case MORPH_BLACKHAT: - // ?? - ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue ); - ocl_morphOp( temp, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue ); - subtract(_dst, _src, _dst); + if (!ocl_morphOp( _src, _temp, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue )) + return false; + if (!ocl_morphOp( _temp, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue, MORPH_BLACKHAT, _src )) + return false; break; default: CV_Error( CV_StsBadArg, "unknown morphological operation" ); @@ -1612,9 +1638,11 @@ void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, { #ifdef HAVE_OPENCL Size ksize = kernel.size(); + anchor = normalizeAnchor(anchor, ksize); + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && _src.channels() <= 4 && anchor.x == ksize.width >> 1 && anchor.y == ksize.height >> 1 && - borderType == cv::BORDER_CONSTANT, + borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue(), ocl_morphologyEx(_src, _dst, op, kernel, anchor, iterations, borderType, borderValue)) #endif diff --git a/modules/imgproc/src/opencl/morph.cl b/modules/imgproc/src/opencl/morph.cl index 7df09ec61e..f78af89c9c 100644 --- a/modules/imgproc/src/opencl/morph.cl +++ b/modules/imgproc/src/opencl/morph.cl @@ -43,6 +43,8 @@ #endif #endif +#define noconvert + #if cn != 3 #define loadpix(addr) *(__global const T *)(addr) #define storepix(val, addr) *(__global T *)(addr) = val @@ -107,6 +109,11 @@ // BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii #define ELEM(i, l_edge, r_edge, elem1, elem2) (i) < (l_edge) | (i) >= (r_edge) ? (elem1) : (elem2) +#if defined OP_GRADIENT || defined OP_TOPHAT || defined OP_BLACKHAT +#define EXTRA_PARAMS , __global const uchar * matptr, int mat_step, int mat_offset +#else +#define EXTRA_PARAMS +#endif __kernel void morph(__global const uchar * srcptr, int src_step, int src_offset, __global uchar * dstptr, int dst_step, int dst_offset, @@ -155,6 +162,20 @@ __kernel void morph(__global const uchar * srcptr, int src_step, int src_offset, PROCESS_ELEMS; int dst_index = mad24(gidy, dst_step, mad24(gidx, TSIZE, dst_offset)); + +#if defined OP_GRADIENT || defined OP_TOPHAT || defined OP_BLACKHAT + int mat_index = mad24(gidy, mat_step, mad24(gidx, TSIZE, mat_offset)); + T value = loadpix(matptr + mat_index); + +#ifdef OP_GRADIENT + storepix(convertToT(convertToWT(res) - convertToWT(value)), dstptr + dst_index); +#elif defined OP_TOPHAT + storepix(convertToT(convertToWT(value) - convertToWT(res)), dstptr + dst_index); +#elif defined OP_BLACKHAT + storepix(convertToT(convertToWT(res) - convertToWT(value)), dstptr + dst_index); +#endif +#else // erode or dilate storepix(res, dstptr + dst_index); +#endif } } diff --git a/modules/imgproc/test/ocl/test_filters.cpp b/modules/imgproc/test/ocl/test_filters.cpp index 46d77285d7..1fe2927886 100644 --- a/modules/imgproc/test/ocl/test_filters.cpp +++ b/modules/imgproc/test/ocl/test_filters.cpp @@ -63,7 +63,7 @@ PARAM_TEST_CASE(FilterTestBase, MatType, BorderType, // border type double, // optional parameter bool, // roi or not - int) //width multiplier + int) // width multiplier { int type, borderType, ksize; Size size; @@ -244,8 +244,8 @@ OCL_TEST_P(Erode, Mat) random_roi(); Mat kernel = randomMat(kernelSize, CV_8UC1, 0, 3); - OCL_OFF(cv::erode(src_roi, dst_roi, kernel, Point(-1,-1), iterations) ); - OCL_ON(cv::erode(usrc_roi, udst_roi, kernel, Point(-1,-1), iterations) ); + OCL_OFF(cv::erode(src_roi, dst_roi, kernel, Point(-1, -1), iterations) ); + OCL_ON(cv::erode(usrc_roi, udst_roi, kernel, Point(-1, -1), iterations) ); Near(); } @@ -266,8 +266,8 @@ OCL_TEST_P(Dilate, Mat) random_roi(); Mat kernel = randomMat(kernelSize, CV_8UC1, 0, 3); - OCL_OFF(cv::dilate(src_roi, dst_roi, kernel, Point(-1,-1), iterations) ); - OCL_ON(cv::dilate(usrc_roi, udst_roi, kernel, Point(-1,-1), iterations) ); + OCL_OFF(cv::dilate(src_roi, dst_roi, kernel, Point(-1, -1), iterations) ); + OCL_ON(cv::dilate(usrc_roi, udst_roi, kernel, Point(-1, -1), iterations) ); Near(); } @@ -289,8 +289,8 @@ OCL_TEST_P(MorphologyEx, Mat) random_roi(); Mat kernel = randomMat(kernelSize, CV_8UC1, 0, 3); - OCL_OFF(cv::morphologyEx(src_roi, dst_roi, op, kernel, Point(-1,-1), iterations) ); - OCL_ON(cv::morphologyEx(usrc_roi, udst_roi, op, kernel, Point(-1,-1), iterations) ); + OCL_OFF(cv::morphologyEx(src_roi, dst_roi, op, kernel, Point(-1, -1), iterations) ); + OCL_ON(cv::morphologyEx(usrc_roi, udst_roi, op, kernel, Point(-1, -1), iterations) ); Near(); } @@ -360,8 +360,8 @@ OCL_INSTANTIATE_TEST_CASE_P(Filter, GaussianBlurTest, Combine( OCL_INSTANTIATE_TEST_CASE_P(Filter, Erode, Combine( Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4, CV_64FC1, CV_64FC4), Values(3, 5, 7), - Values(Size(0,0)),//not used - Values((BorderType)BORDER_CONSTANT),//not used + Values(Size(0, 0)), //not used + Values((BorderType)BORDER_CONSTANT), Values(1.0, 2.0, 3.0), Bool(), Values(1))); // not used @@ -369,20 +369,20 @@ OCL_INSTANTIATE_TEST_CASE_P(Filter, Erode, Combine( OCL_INSTANTIATE_TEST_CASE_P(Filter, Dilate, Combine( Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4, CV_64FC1, CV_64FC4), Values(3, 5, 7), - Values(Size(0,0)),//not used - Values((BorderType)BORDER_CONSTANT),//not used + Values(Size(0, 0)), // not used + Values((BorderType)BORDER_CONSTANT), Values(1.0, 2.0, 3.0), Bool(), - Values(1))); //not used + Values(1))); // not used OCL_INSTANTIATE_TEST_CASE_P(Filter, MorphologyEx, Combine( - Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4, CV_64FC1, CV_64FC4), + Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4), Values(3, 5, 7), - Values(Size(0, 0), Size(0, 1), Size(0, 2), Size(0, 3), Size(0, 4), Size(0, 5), Size(0, 6)), // used as generator of operations - Values((BorderType)BORDER_CONSTANT),// not used + Values(Size(0, 2), Size(0, 3), Size(0, 4), Size(0, 5), Size(0, 6)), // used as generator of operations + Values((BorderType)BORDER_CONSTANT), Values(1.0, 2.0, 3.0), Bool(), - Values(1))); //not used + Values(1))); // not used } } // namespace cvtest::ocl From d5c99a07b673e15fb65f846d04800fb61f8a5d88 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Mon, 23 Jun 2014 10:18:11 +0400 Subject: [PATCH 021/136] Use fma only for Intel devices --- modules/imgproc/src/opencl/pyr_down.cl | 119 ++++++++++++++----------- modules/imgproc/src/pyramids.cpp | 8 +- 2 files changed, 69 insertions(+), 58 deletions(-) diff --git a/modules/imgproc/src/opencl/pyr_down.cl b/modules/imgproc/src/opencl/pyr_down.cl index 4babf54a13..2358775e7a 100644 --- a/modules/imgproc/src/opencl/pyr_down.cl +++ b/modules/imgproc/src/opencl/pyr_down.cl @@ -80,7 +80,13 @@ #define SRC(_x,_y) convertToFT(loadpix(srcData + mad24(_y, src_step, PIXSIZE * _x))) #if kercn == 4 -#define SRC4(_x,_y) convert_float4(*(__global const uchar4*)(srcData + mad24(_y, src_step, PIXSIZE * _x))) +#define SRC4(_x,_y) convert_float4(vload4(0, srcData + mad24(_y, src_step, PIXSIZE * _x))) +#endif + +#ifdef INTEL_DEVICE +#define MAD(x,y,z) fma((x),(y),(z)) +#else +#define MAD(x,y,z) mad((x),(y),(z)) #endif #define noconvert @@ -109,10 +115,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, col = EXTRAPOLATE(x, src_cols); sum = co3* SRC(col, src_y - 2); - sum = fma(co2, SRC(col, src_y - 1), sum); - sum = fma(co1, SRC(col, src_y ), sum); - sum = fma(co2, SRC(col, src_y + 1), sum); - sum = fma(co3, SRC(col, src_y + 2), sum); + sum = MAD(co2, SRC(col, src_y - 1), sum); + sum = MAD(co1, SRC(col, src_y ), sum); + sum = MAD(co2, SRC(col, src_y + 1), sum); + sum = MAD(co3, SRC(col, src_y + 2), sum); smem[2 + get_local_id(0)] = sum; #else @@ -120,10 +126,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, { float4 sum4; sum4 = co3* SRC4(x, src_y - 2); - sum4 = fma(co2, SRC4(x, src_y - 1), sum4); - sum4 = fma(co1, SRC4(x, src_y ), sum4); - sum4 = fma(co2, SRC4(x, src_y + 1), sum4); - sum4 = fma(co3, SRC4(x, src_y + 2), sum4); + sum4 = MAD(co2, SRC4(x, src_y - 1), sum4); + sum4 = MAD(co1, SRC4(x, src_y ), sum4); + sum4 = MAD(co2, SRC4(x, src_y + 1), sum4); + sum4 = MAD(co3, SRC4(x, src_y + 2), sum4); vstore4(sum4, get_local_id(0), (__local float*) &smem[2]); } @@ -133,10 +139,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, { col = EXTRAPOLATE(x+i, src_cols); sum = co3* SRC(col, src_y - 2); - sum = fma(co2, SRC(col, src_y - 1), sum); - sum = fma(co1, SRC(col, src_y ), sum); - sum = fma(co2, SRC(col, src_y + 1), sum); - sum = fma(co3, SRC(col, src_y + 2), sum); + sum = MAD(co2, SRC(col, src_y - 1), sum); + sum = MAD(co1, SRC(col, src_y ), sum); + sum = MAD(co2, SRC(col, src_y + 1), sum); + sum = MAD(co3, SRC(col, src_y + 2), sum); smem[2 + 4*get_local_id(0)+i] = sum; } @@ -147,10 +153,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, col = EXTRAPOLATE((int)(get_group_id(0)*LOCAL_SIZE + get_local_id(0) - 2), src_cols); sum = co3* SRC(col, src_y - 2); - sum = fma(co2, SRC(col, src_y - 1), sum); - sum = fma(co1, SRC(col, src_y ), sum); - sum = fma(co2, SRC(col, src_y + 1), sum); - sum = fma(co3, SRC(col, src_y + 2), sum); + sum = MAD(co2, SRC(col, src_y - 1), sum); + sum = MAD(co1, SRC(col, src_y ), sum); + sum = MAD(co2, SRC(col, src_y + 1), sum); + sum = MAD(co3, SRC(col, src_y + 2), sum); smem[get_local_id(0)] = sum; } @@ -160,10 +166,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, col = EXTRAPOLATE((int)((get_group_id(0)+1)*LOCAL_SIZE + get_local_id(0) - 2), src_cols); sum = co3* SRC(col, src_y - 2); - sum = fma(co2, SRC(col, src_y - 1), sum); - sum = fma(co1, SRC(col, src_y ), sum); - sum = fma(co2, SRC(col, src_y + 1), sum); - sum = fma(co3, SRC(col, src_y + 2), sum); + sum = MAD(co2, SRC(col, src_y - 1), sum); + sum = MAD(co1, SRC(col, src_y ), sum); + sum = MAD(co2, SRC(col, src_y + 1), sum); + sum = MAD(co3, SRC(col, src_y + 2), sum); smem[LOCAL_SIZE + get_local_id(0)] = sum; } @@ -174,10 +180,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, col = EXTRAPOLATE(x, src_cols); sum = co3* SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); - sum = fma(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); - sum = fma(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); - sum = fma(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); - sum = fma(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); + sum = MAD(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); + sum = MAD(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); + sum = MAD(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); + sum = MAD(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); smem[2 + get_local_id(0)] = sum; #else @@ -185,10 +191,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, { float4 sum4; sum4 = co3* SRC4(x, EXTRAPOLATE(src_y - 2, src_rows)); - sum4 = fma(co2, SRC4(x, EXTRAPOLATE(src_y - 1, src_rows)), sum4); - sum4 = fma(co1, SRC4(x, EXTRAPOLATE(src_y , src_rows)), sum4); - sum4 = fma(co2, SRC4(x, EXTRAPOLATE(src_y + 1, src_rows)), sum4); - sum4 = fma(co3, SRC4(x, EXTRAPOLATE(src_y + 2, src_rows)), sum4); + sum4 = MAD(co2, SRC4(x, EXTRAPOLATE(src_y - 1, src_rows)), sum4); + sum4 = MAD(co1, SRC4(x, EXTRAPOLATE(src_y , src_rows)), sum4); + sum4 = MAD(co2, SRC4(x, EXTRAPOLATE(src_y + 1, src_rows)), sum4); + sum4 = MAD(co3, SRC4(x, EXTRAPOLATE(src_y + 2, src_rows)), sum4); vstore4(sum4, get_local_id(0), (__local float*) &smem[2]); } @@ -198,10 +204,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, { col = EXTRAPOLATE(x+i, src_cols); sum = co3* SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); - sum = fma(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); - sum = fma(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); - sum = fma(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); - sum = fma(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); + sum = MAD(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); + sum = MAD(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); + sum = MAD(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); + sum = MAD(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); smem[2 + 4*get_local_id(0)+i] = sum; } @@ -212,10 +218,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, col = EXTRAPOLATE((int)(get_group_id(0)*LOCAL_SIZE + get_local_id(0) - 2), src_cols); sum = co3* SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); - sum = fma(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); - sum = fma(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); - sum = fma(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); - sum = fma(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); + sum = MAD(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); + sum = MAD(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); + sum = MAD(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); + sum = MAD(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); smem[get_local_id(0)] = sum; } @@ -225,10 +231,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, col = EXTRAPOLATE((int)((get_group_id(0)+1)*LOCAL_SIZE + get_local_id(0) - 2), src_cols); sum = co3* SRC(col, EXTRAPOLATE(src_y - 2, src_rows)); - sum = fma(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); - sum = fma(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); - sum = fma(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); - sum = fma(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); + sum = MAD(co2, SRC(col, EXTRAPOLATE(src_y - 1, src_rows)), sum); + sum = MAD(co1, SRC(col, EXTRAPOLATE(src_y , src_rows)), sum); + sum = MAD(co2, SRC(col, EXTRAPOLATE(src_y + 1, src_rows)), sum); + sum = MAD(co3, SRC(col, EXTRAPOLATE(src_y + 2, src_rows)), sum); smem[LOCAL_SIZE + get_local_id(0)] = sum; } @@ -241,15 +247,20 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, { const int tid2 = get_local_id(0) * 2; - sum = co3* smem[2 + tid2 + 2]; + sum = 0.f; #if cn == 1 +#if fdepth <= 5 sum = sum + dot(vload4(0, (__local float*) (&smem)+tid2), (float4)(co3, co2, co1, co2)); #else - sum = fma(co3, smem[2 + tid2 - 2], sum); - sum = fma(co2, smem[2 + tid2 - 1], sum); - sum = fma(co1, smem[2 + tid2 ], sum); - sum = fma(co2, smem[2 + tid2 + 1], sum); + sum = sum + dot(vload4(0, (__local double*) (&smem)+tid2), (double4)(co3, co2, co1, co2)); +#endif +#else + sum = MAD(co3, smem[2 + tid2 - 2], sum); + sum = MAD(co2, smem[2 + tid2 - 1], sum); + sum = MAD(co1, smem[2 + tid2 ], sum); + sum = MAD(co2, smem[2 + tid2 + 1], sum); #endif + sum = MAD(co3, smem[2 + tid2 + 2], sum); const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; @@ -260,10 +271,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, int tid4 = get_local_id(0) * 4; sum = co3* smem[2 + tid4 + 2]; - sum = fma(co3, smem[2 + tid4 - 2], sum); - sum = fma(co2, smem[2 + tid4 - 1], sum); - sum = fma(co1, smem[2 + tid4 ], sum); - sum = fma(co2, smem[2 + tid4 + 1], sum); + sum = MAD(co3, smem[2 + tid4 - 2], sum); + sum = MAD(co2, smem[2 + tid4 - 1], sum); + sum = MAD(co1, smem[2 + tid4 ], sum); + sum = MAD(co2, smem[2 + tid4 + 1], sum); int dst_x = (get_group_id(0) * LOCAL_SIZE + tid4) / 2; @@ -274,10 +285,10 @@ __kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, dst_x += 1; sum = co3* smem[2 + tid4 + 2]; - sum = fma(co3, smem[2 + tid4 - 2], sum); - sum = fma(co2, smem[2 + tid4 - 1], sum); - sum = fma(co1, smem[2 + tid4 ], sum); - sum = fma(co2, smem[2 + tid4 + 1], sum); + sum = MAD(co3, smem[2 + tid4 - 2], sum); + sum = MAD(co2, smem[2 + tid4 - 1], sum); + sum = MAD(co1, smem[2 + tid4 ], sum); + sum = MAD(co2, smem[2 + tid4 + 1], sum); if (dst_x < dst_cols) storepix(convertToT(sum), dstData + mad24(y, dst_step, dst_x * PIXSIZE)); diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index 418d20ff45..f82ab10725 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -424,19 +424,19 @@ static bool ocl_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, in int float_depth = depth == CV_64F ? CV_64F : CV_32F; const int local_size = 256; int kercn = 1; - if (depth == CV_8U && cn == 1 && float_depth == CV_32F) + if (depth == CV_8U && float_depth == CV_32F && cn == 1 && ocl::Device::getDefault().isIntel()) kercn = 4; const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" }; char cvt[2][50]; String buildOptions = format( "-D T=%s -D FT=%s -D convertToT=%s -D convertToFT=%s%s " - "-D T1=%s -D cn=%d -D kercn=%d -D %s -D LOCAL_SIZE=%d", + "-D T1=%s -D cn=%d -D kercn=%d -D fdepth=%d -D %s -D LOCAL_SIZE=%d", ocl::typeToStr(type), ocl::typeToStr(CV_MAKETYPE(float_depth, cn)), ocl::convertTypeStr(float_depth, depth, cn, cvt[0]), ocl::convertTypeStr(depth, float_depth, cn, cvt[1]), - doubleSupport ? " -D DOUBLE_SUPPORT" : "", - ocl::typeToStr(depth), cn, kercn, borderMap[borderType], local_size + doubleSupport ? " -D DOUBLE_SUPPORT" : "", ocl::typeToStr(depth), + cn, kercn, float_depth, borderMap[borderType], local_size ); ocl::Kernel k("pyrDown", ocl::imgproc::pyr_down_oclsrc, buildOptions); if (k.empty()) From 654bdde8ed5ca4fb27de61d63344055958e24ed2 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 30 Jun 2014 01:47:51 +0400 Subject: [PATCH 022/136] SSE2 optimization of cv::preCornerDetect --- modules/imgproc/src/corner.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index eeb20fbc16..923d78b30f 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -608,6 +608,11 @@ void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int bord factor *= 255; factor = 1./(factor * factor * factor); +#if CV_SSE2 + volatile bool haveSSE2 = cv::checkHardwareSupport(CV_CPU_SSE2); + __m128 v_factor = _mm_set1_ps((float)factor), v_m2 = _mm_set1_ps(-2.0f); +#endif + Size size = src.size(); int i, j; for( i = 0; i < size.height; i++ ) @@ -619,7 +624,26 @@ void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int bord const float* d2ydata = (const float*)(D2y.data + i*D2y.step); const float* dxydata = (const float*)(Dxy.data + i*Dxy.step); - for( j = 0; j < size.width; j++ ) + j = 0; + +#if CV_SSE2 + if (haveSSE2) + { + for( ; j <= size.width - 4; j += 4 ) + { + __m128 v_dx = _mm_loadu_ps((const float *)(dxdata + j)); + __m128 v_dy = _mm_loadu_ps((const float *)(dydata + j)); + + __m128 v_s1 = _mm_mul_ps(_mm_mul_ps(v_dx, v_dx), _mm_loadu_ps((const float *)(d2ydata + j))); + __m128 v_s2 = _mm_mul_ps(_mm_mul_ps(v_dy, v_dy), _mm_loadu_ps((const float *)(d2xdata + j))); + __m128 v_s3 = _mm_mul_ps(_mm_mul_ps(v_dx, v_dy), _mm_loadu_ps((const float *)(dxydata + j))); + v_s1 = _mm_mul_ps(v_factor, _mm_add_ps(v_s1, _mm_add_ps(v_s2, _mm_mul_ps(v_s3, v_m2)))); + _mm_storeu_ps(dstdata + j, v_s1); + } + } +#endif + + for( ; j < size.width; j++ ) { float dx = dxdata[j]; float dy = dydata[j]; From 978f7eb44ae983e9689e210ad801bb852997617d Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 27 Jun 2014 14:06:32 +0400 Subject: [PATCH 023/136] added perf test for transpose inplace --- modules/core/perf/opencl/perf_arithm.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/modules/core/perf/opencl/perf_arithm.cpp b/modules/core/perf/opencl/perf_arithm.cpp index 8488c1799b..17badca765 100644 --- a/modules/core/perf/opencl/perf_arithm.cpp +++ b/modules/core/perf/opencl/perf_arithm.cpp @@ -308,6 +308,23 @@ OCL_PERF_TEST_P(TransposeFixture, Transpose, ::testing::Combine( SANITY_CHECK(dst); } +OCL_PERF_TEST_P(TransposeFixture, TransposeInplace, ::testing::Combine( + OCL_PERF_ENUM(Size(640, 640), Size(1280, 1280), Size(2160, 2160)), OCL_TEST_TYPES_134)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type); + declare.in(src, WARMUP_RNG).out(src, WARMUP_NONE); + + OCL_TEST_CYCLE() cv::transpose(src, src); + + SANITY_CHECK_NOTHING(); +} + ///////////// Flip //////////////////////// enum From 9c8b9fc73384ca3945962a7850eb5e58837bab80 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 27 Jun 2014 12:44:32 +0400 Subject: [PATCH 024/136] cv::transpose --- modules/core/src/matrix.cpp | 4 ++-- modules/core/src/opencl/transpose.cl | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 653efe63ae..c27c961077 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -3002,8 +3002,8 @@ static bool ocl_transpose( InputArray _src, OutputArray _dst ) k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnlyNoSize(dst)); - size_t localsize[3] = { TILE_DIM, BLOCK_ROWS, 1 }; - size_t globalsize[3] = { src.cols, inplace ? src.rows : divUp(src.rows, TILE_DIM) * BLOCK_ROWS, 1 }; + size_t localsize[2] = { TILE_DIM, BLOCK_ROWS }; + size_t globalsize[2] = { src.cols, inplace ? src.rows : divUp(src.rows, TILE_DIM) * BLOCK_ROWS }; return k.run(2, globalsize, localsize, false); } diff --git a/modules/core/src/opencl/transpose.cl b/modules/core/src/opencl/transpose.cl index b5ec4b6f95..d56e499099 100644 --- a/modules/core/src/opencl/transpose.cl +++ b/modules/core/src/opencl/transpose.cl @@ -53,7 +53,7 @@ #define TSIZE ((int)sizeof(T1)*3) #endif -#define LDS_STEP TILE_DIM +#define LDS_STEP (TILE_DIM + 1) __kernel void transpose(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols, __global uchar * dstptr, int dst_step, int dst_offset) @@ -90,6 +90,7 @@ __kernel void transpose(__global const uchar * srcptr, int src_step, int src_off { int index_src = mad24(y, src_step, mad24(x, TSIZE, src_offset)); + #pragma unroll for (int i = 0; i < TILE_DIM; i += BLOCK_ROWS) if (y + i < src_rows) { @@ -103,6 +104,7 @@ __kernel void transpose(__global const uchar * srcptr, int src_step, int src_off { int index_dst = mad24(y_index, dst_step, mad24(x_index, TSIZE, dst_offset)); + #pragma unroll for (int i = 0; i < TILE_DIM; i += BLOCK_ROWS) if ((y_index + i) < src_cols) { From 54e4ef657c41a5bb794ebd2a34932cae16a8507b Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 27 Jun 2014 14:03:05 +0400 Subject: [PATCH 025/136] optimized cv::transpose inplace --- modules/core/src/matrix.cpp | 16 ++++++++++++---- modules/core/src/opencl/transpose.cl | 20 +++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index c27c961077..f199cb2534 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2973,8 +2973,10 @@ static inline int divUp(int a, int b) static bool ocl_transpose( InputArray _src, OutputArray _dst ) { + const ocl::Device & dev = ocl::Device::getDefault(); const int TILE_DIM = 32, BLOCK_ROWS = 8; - int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type); + int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type), + rowsPerWI = dev.isIntel() ? 4 : 1; UMat src = _src.getUMat(); _dst.create(src.cols, src.rows, type); @@ -2990,9 +2992,9 @@ static bool ocl_transpose( InputArray _src, OutputArray _dst ) } ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc, - format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d", + format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d", ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth), - cn, TILE_DIM, BLOCK_ROWS)); + cn, TILE_DIM, BLOCK_ROWS, rowsPerWI)); if (k.empty()) return false; @@ -3003,7 +3005,13 @@ static bool ocl_transpose( InputArray _src, OutputArray _dst ) ocl::KernelArg::WriteOnlyNoSize(dst)); size_t localsize[2] = { TILE_DIM, BLOCK_ROWS }; - size_t globalsize[2] = { src.cols, inplace ? src.rows : divUp(src.rows, TILE_DIM) * BLOCK_ROWS }; + size_t globalsize[2] = { src.cols, inplace ? (src.rows + rowsPerWI - 1) / rowsPerWI : (divUp(src.rows, TILE_DIM) * BLOCK_ROWS) }; + + if (inplace && dev.isIntel()) + { + localsize[0] = 16; + localsize[1] = dev.maxWorkGroupSize() / localsize[0]; + } return k.run(2, globalsize, localsize, false); } diff --git a/modules/core/src/opencl/transpose.cl b/modules/core/src/opencl/transpose.cl index d56e499099..cad3616b5d 100644 --- a/modules/core/src/opencl/transpose.cl +++ b/modules/core/src/opencl/transpose.cl @@ -117,18 +117,24 @@ __kernel void transpose(__global const uchar * srcptr, int src_step, int src_off __kernel void transpose_inplace(__global uchar * srcptr, int src_step, int src_offset, int src_rows) { int x = get_global_id(0); - int y = get_global_id(1); + int y = get_global_id(1) * rowsPerWI; - if (y < src_rows && x < y) + if (x < y + rowsPerWI) { int src_index = mad24(y, src_step, mad24(x, TSIZE, src_offset)); int dst_index = mad24(x, src_step, mad24(y, TSIZE, src_offset)); + T tmp; - __global const uchar * src = srcptr + src_index; - __global uchar * dst = srcptr + dst_index; + #pragma unroll + for (int i = 0; i < rowsPerWI; ++i, ++y, src_index += src_step, dst_index += TSIZE) + if (y < src_rows && x < y) + { + __global uchar * src = srcptr + src_index; + __global uchar * dst = srcptr + dst_index; - T tmp = loadpix(dst); - storepix(loadpix(src), dst); - storepix(tmp, src); + tmp = loadpix(dst); + storepix(loadpix(src), dst); + storepix(tmp, src); + } } } From 972119bff3cae561ed9440eba1aa80c85a7a27ca Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sun, 29 Jun 2014 21:03:16 +0400 Subject: [PATCH 026/136] sse2 optimization of cv::convertScaleAbs --- modules/core/src/convert.cpp | 174 ++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 2 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 64d24304cd..7b2684c85e 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -851,6 +851,175 @@ void cv::insertChannel(InputArray _src, InputOutputArray _dst, int coi) namespace cv { +template +struct cvtScaleAbs_SSE2 +{ + int operator () (const T *, DT *, int, WT, WT) const + { + return 0; + } +}; + +#if CV_SSE2 + +template <> +struct cvtScaleAbs_SSE2 +{ + int operator () (const uchar * src, uchar * dst, int width, + float scale, float shift) const + { + int x = 0; + + if (USE_SSE2) + { + __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift), + v_zero_f = _mm_setzero_ps(); + __m128i v_zero_i = _mm_setzero_si128(); + + for ( ; x <= width - 16; x += 16) + { + __m128i v_src = _mm_loadu_si128((const __m128i *)(src + x)); + __m128i v_src12 = _mm_unpacklo_epi8(v_src, v_zero_i), v_src_34 = _mm_unpackhi_epi8(v_src, v_zero_i); + __m128 v_dst1 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src12, v_zero_i)), v_scale), v_shift); + v_dst1 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst1), v_dst1); + __m128 v_dst2 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src12, v_zero_i)), v_scale), v_shift); + v_dst2 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst2), v_dst2); + __m128 v_dst3 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src_34, v_zero_i)), v_scale), v_shift); + v_dst3 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst3), v_dst3); + __m128 v_dst4 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src_34, v_zero_i)), v_scale), v_shift); + v_dst4 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst4), v_dst4); + + __m128i v_dst_i = _mm_packus_epi16(_mm_packs_epi32(_mm_cvtps_epi32(v_dst1), _mm_cvtps_epi32(v_dst2)), + _mm_packs_epi32(_mm_cvtps_epi32(v_dst3), _mm_cvtps_epi32(v_dst4))); + _mm_storeu_si128((__m128i *)(dst + x), v_dst_i); + } + } + + return x; + } +}; + +template <> +struct cvtScaleAbs_SSE2 +{ + int operator () (const ushort * src, uchar * dst, int width, + float scale, float shift) const + { + int x = 0; + + if (USE_SSE2) + { + __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift), + v_zero_f = _mm_setzero_ps(); + __m128i v_zero_i = _mm_setzero_si128(); + + for ( ; x <= width - 8; x += 8) + { + __m128i v_src = _mm_loadu_si128((const __m128i *)(src + x)); + __m128 v_dst1 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src, v_zero_i)), v_scale), v_shift); + v_dst1 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst1), v_dst1); + __m128 v_dst2 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src, v_zero_i)), v_scale), v_shift); + v_dst2 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst2), v_dst2); + + __m128i v_dst_i = _mm_packus_epi16(_mm_packs_epi32(_mm_cvtps_epi32(v_dst1), _mm_cvtps_epi32(v_dst2)), v_zero_i); + _mm_storel_epi64((__m128i *)(dst + x), v_dst_i); + } + } + + return x; + } +}; + +template <> +struct cvtScaleAbs_SSE2 +{ + int operator () (const short * src, uchar * dst, int width, + float scale, float shift) const + { + int x = 0; + + if (USE_SSE2) + { + __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift), + v_zero_f = _mm_setzero_ps(); + __m128i v_zero_i = _mm_setzero_si128(); + + for ( ; x <= width - 8; x += 8) + { + __m128i v_src = _mm_loadu_si128((const __m128i *)(src + x)); + __m128 v_dst1 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(v_src, v_src), 16)), v_scale), v_shift); + v_dst1 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst1), v_dst1); + __m128 v_dst2 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpackhi_epi16(v_src, v_src), 16)), v_scale), v_shift); + v_dst2 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst2), v_dst2); + + __m128i v_dst_i = _mm_packus_epi16(_mm_packs_epi32(_mm_cvtps_epi32(v_dst1), _mm_cvtps_epi32(v_dst2)), v_zero_i); + _mm_storel_epi64((__m128i *)(dst + x), v_dst_i); + } + } + + return x; + } +}; + +template <> +struct cvtScaleAbs_SSE2 +{ + int operator () (const int * src, uchar * dst, int width, + float scale, float shift) const + { + int x = 0; + + if (USE_SSE2) + { + __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift), + v_zero_f = _mm_setzero_ps(); + __m128i v_zero_i = _mm_setzero_si128(); + + for ( ; x <= width - 8; x += 4) + { + __m128i v_src = _mm_loadu_si128((const __m128i *)(src + x)); + __m128 v_dst1 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(v_src), v_scale), v_shift); + v_dst1 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst1), v_dst1); + + __m128i v_dst_i = _mm_packus_epi16(_mm_packs_epi32(_mm_cvtps_epi32(v_dst1), v_zero_i), v_zero_i); + _mm_storel_epi64((__m128i *)(dst + x), v_dst_i); + } + } + + return x; + } +}; + +template <> +struct cvtScaleAbs_SSE2 +{ + int operator () (const float * src, uchar * dst, int width, + float scale, float shift) const + { + int x = 0; + + if (USE_SSE2) + { + __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift), + v_zero_f = _mm_setzero_ps(); + __m128i v_zero_i = _mm_setzero_si128(); + + for ( ; x <= width - 8; x += 4) + { + __m128 v_dst = _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(src + x), v_scale), v_shift); + v_dst = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst), v_dst); + + __m128i v_dst_i = _mm_packs_epi32(_mm_cvtps_epi32(v_dst), v_zero_i); + _mm_storel_epi64((__m128i *)(dst + x), _mm_packus_epi16(v_dst_i, v_zero_i)); + } + } + + return x; + } +}; + +#endif + template static void cvtScaleAbs_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size, @@ -858,10 +1027,12 @@ cvtScaleAbs_( const T* src, size_t sstep, { sstep /= sizeof(src[0]); dstep /= sizeof(dst[0]); + cvtScaleAbs_SSE2 vop; for( ; size.height--; src += sstep, dst += dstep ) { - int x = 0; + int x = vop(src, dst, size.width, scale, shift); + #if CV_ENABLE_UNROLLED for( ; x <= size.width - 4; x += 4 ) { @@ -879,7 +1050,6 @@ cvtScaleAbs_( const T* src, size_t sstep, } } - template static void cvtScale_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size, From 157257b0723e7bfb9f7d929402772aef1966a752 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 1 Jul 2014 14:24:14 +0400 Subject: [PATCH 027/136] ocl: don't use OpenCL CPU device in default setup --- modules/core/src/ocl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 24ca6ee4d3..0b196d9c52 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -2228,7 +2228,8 @@ static cl_device_id selectOpenCLDevice() if (!isID) { deviceTypes.push_back("GPU"); - deviceTypes.push_back("CPU"); + if (configuration) + deviceTypes.push_back("CPU"); } else deviceTypes.push_back("ALL"); From 92ead5fab38aec7715766683b023f96c15ca6f34 Mon Sep 17 00:00:00 2001 From: Ievgen Khvedchenia Date: Tue, 1 Jul 2014 22:31:57 +0300 Subject: [PATCH 028/136] Fix cmake to build OpenCV framework on OSX --- 3rdparty/libjpeg/CMakeLists.txt | 2 +- cmake/OpenCVGenInfoPlist.cmake | 3 + modules/world/CMakeLists.txt | 4 +- platforms/osx/Info.plist.in | 18 +++++ platforms/osx/build_framework.py | 124 +++++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 platforms/osx/Info.plist.in create mode 100755 platforms/osx/build_framework.py diff --git a/3rdparty/libjpeg/CMakeLists.txt b/3rdparty/libjpeg/CMakeLists.txt index 028a583cff..65a9d1c8aa 100644 --- a/3rdparty/libjpeg/CMakeLists.txt +++ b/3rdparty/libjpeg/CMakeLists.txt @@ -9,7 +9,7 @@ ocv_include_directories(${CMAKE_CURRENT_SOURCE_DIR}) file(GLOB lib_srcs *.c) file(GLOB lib_hdrs *.h) -if(ANDROID OR IOS) +if(ANDROID OR IOS OR APPLE) ocv_list_filterout(lib_srcs jmemansi.c) else() ocv_list_filterout(lib_srcs jmemnobs.c) diff --git a/cmake/OpenCVGenInfoPlist.cmake b/cmake/OpenCVGenInfoPlist.cmake index 97c674ceb7..db418d1253 100644 --- a/cmake/OpenCVGenInfoPlist.cmake +++ b/cmake/OpenCVGenInfoPlist.cmake @@ -1,4 +1,7 @@ if(IOS) configure_file("${OpenCV_SOURCE_DIR}/platforms/ios/Info.plist.in" "${CMAKE_BINARY_DIR}/ios/Info.plist") +elseif(APPLE) + configure_file("${OpenCV_SOURCE_DIR}/platforms/osx/Info.plist.in" + "${CMAKE_BINARY_DIR}/osx/Info.plist") endif() diff --git a/modules/world/CMakeLists.txt b/modules/world/CMakeLists.txt index 6a84c1b6ae..33a9304c87 100644 --- a/modules/world/CMakeLists.txt +++ b/modules/world/CMakeLists.txt @@ -106,11 +106,11 @@ macro(ios_include_3party_libs) ocv_list_filterout(objlist jmemansi) # <<= dirty fix endmacro() -if(IOS AND WITH_PNG) +if( (IOS OR APPLE) AND WITH_PNG) ios_include_3party_libs(zlib libpng) endif() -if(IOS AND WITH_JPEG) +if( (IOS OR APPLE) AND WITH_JPEG) ios_include_3party_libs(libjpeg) endif() diff --git a/platforms/osx/Info.plist.in b/platforms/osx/Info.plist.in new file mode 100644 index 0000000000..b2a3baf524 --- /dev/null +++ b/platforms/osx/Info.plist.in @@ -0,0 +1,18 @@ + + + + + CFBundleName + OpenCV + CFBundleIdentifier + org.opencv + CFBundleVersion + ${OPENCV_LIBVERSION} + CFBundleShortVersionString + ${OPENCV_LIBVERSION} + CFBundleSignature + ???? + CFBundlePackageType + FMWK + + diff --git a/platforms/osx/build_framework.py b/platforms/osx/build_framework.py new file mode 100755 index 0000000000..456ea95725 --- /dev/null +++ b/platforms/osx/build_framework.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +""" +The script builds OpenCV.framework for iOS. +The built framework is universal, it can be used to build app and run it on either iOS simulator or real device. + +Usage: + ./build_framework.py + +By cmake conventions (and especially if you work with OpenCV repository), +the output dir should not be a subdirectory of OpenCV source tree. + +Script will create , if it's missing, and a few its subdirectories: + + + build/ + iPhoneOS-*/ + [cmake-generated build tree for an iOS device target] + iPhoneSimulator/ + [cmake-generated build tree for iOS simulator] + opencv2.framework/ + [the framework content] + +The script should handle minor OpenCV updates efficiently +- it does not recompile the library from scratch each time. +However, opencv2.framework directory is erased and recreated on each run. +""" + +import glob, re, os, os.path, shutil, string, sys + +def build_opencv(srcroot, buildroot, target, arch): + "builds OpenCV for device or simulator" + + builddir = os.path.join(buildroot, target + '-' + arch) + if not os.path.isdir(builddir): + os.makedirs(builddir) + currdir = os.getcwd() + os.chdir(builddir) + # for some reason, if you do not specify CMAKE_BUILD_TYPE, it puts libs to "RELEASE" rather than "Release" + cmakeargs = ("-GXcode " + + "-DCMAKE_BUILD_TYPE=Release " + + "-DBUILD_SHARED_LIBS=OFF " + + "-DBUILD_DOCS=OFF " + + "-DBUILD_EXAMPLES=OFF " + + "-DBUILD_TESTS=OFF " + + "-DBUILD_PERF_TESTS=OFF " + + "-DBUILD_opencv_apps=OFF " + + "-DBUILD_opencv_world=ON " + + "-DBUILD_opencv_matlab=OFF " + + "-DWITH_TIFF=OFF -DBUILD_TIFF=OFF " + + "-DWITH_JASPER=OFF -DBUILD_JASPER=OFF " + + "-DWITH_WEBP=OFF -DBUILD_WEBP=OFF " + + "-DWITH_OPENEXR=OFF -DBUILD_OPENEXR=OFF " + + "-DWITH_IPP=OFF -DWITH_IPP_A=OFF " + + "-DCMAKE_C_FLAGS=\"-Wno-implicit-function-declaration\" " + + "-DCMAKE_INSTALL_PREFIX=install") + # if cmake cache exists, just rerun cmake to update OpenCV.xproj if necessary + if os.path.isfile(os.path.join(builddir, "CMakeCache.txt")): + os.system("cmake %s ." % (cmakeargs,)) + else: + os.system("cmake %s %s" % (cmakeargs, srcroot)) + + for wlib in [builddir + "/modules/world/UninstalledProducts/libopencv_world.a", + builddir + "/lib/Release/libopencv_world.a"]: + if os.path.isfile(wlib): + os.remove(wlib) + + os.system("xcodebuild -parallelizeTargets ARCHS=%s -jobs 2 -sdk %s -configuration Release -target ALL_BUILD" % (arch, target.lower())) + os.system("xcodebuild ARCHS=%s -sdk %s -configuration Release -target install install" % (arch, target.lower())) + os.chdir(currdir) + +def put_framework_together(srcroot, dstroot): + "constructs the framework directory after all the targets are built" + + # find the list of targets (basically, ["iPhoneOS", "iPhoneSimulator"]) + targetlist = glob.glob(os.path.join(dstroot, "build", "*")) + targetlist = [os.path.basename(t) for t in targetlist] + + # set the current dir to the dst root + currdir = os.getcwd() + framework_dir = dstroot + "/opencv2.framework" + if os.path.isdir(framework_dir): + shutil.rmtree(framework_dir) + os.makedirs(framework_dir) + os.chdir(framework_dir) + + # form the directory tree + dstdir = "Versions/A" + os.makedirs(dstdir + "/Resources") + + tdir0 = "../build/" + targetlist[0] + # copy headers + shutil.copytree(tdir0 + "/install/include/opencv2", dstdir + "/Headers") + + # make universal static lib + wlist = " ".join(["../build/" + t + "/lib/Release/libopencv_world.a" for t in targetlist]) + os.system("lipo -create " + wlist + " -o " + dstdir + "/opencv2") + + # copy Info.plist + shutil.copyfile(tdir0 + "/osx/Info.plist", dstdir + "/Resources/Info.plist") + + # make symbolic links + os.symlink("A", "Versions/Current") + os.symlink("Versions/Current/Headers", "Headers") + os.symlink("Versions/Current/Resources", "Resources") + os.symlink("Versions/Current/opencv2", "opencv2") + + +def build_framework(srcroot, dstroot): + "main function to do all the work" + + targets = ["MacOSX", "MacOSX" ] + archs = ["x86_64", "i386" ] + for i in range(len(targets)): + build_opencv(srcroot, os.path.join(dstroot, "build"), targets[i], archs[i]) + + put_framework_together(srcroot, dstroot) + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print "Usage:\n\t./build_framework.py \n\n" + sys.exit(0) + + build_framework(os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../..")), os.path.abspath(sys.argv[1])) From d40cb396168697837964ba94242250e4be3afeac Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sun, 29 Jun 2014 18:32:15 +0400 Subject: [PATCH 029/136] SSE2 optimization of magnitude calculation --- modules/imgproc/src/canny.cpp | 48 +++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 3590e290db..2a87ae05b4 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -348,6 +348,10 @@ void cv::Canny( InputArray _src, OutputArray _dst, #define CANNY_PUSH(d) *(d) = uchar(2), *stack_top++ = (d) #define CANNY_POP(d) (d) = *--stack_top +#if CV_SSE2 + bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2); +#endif + // calculate magnitude and angle of gradient, perform non-maxima suppression. // fill the map with one of the following values: // 0 - the pixel might belong to an edge @@ -363,12 +367,52 @@ void cv::Canny( InputArray _src, OutputArray _dst, if (!L2gradient) { - for (int j = 0; j < src.cols*cn; j++) + int j = 0, width = src.cols * cn; +#if CV_SSE2 + if (haveSSE2) + { + __m128i v_zero = _mm_setzero_si128(); + for ( ; j <= width - 8; j += 8) + { + __m128i v_dx = _mm_loadu_si128((const __m128i *)(_dx + j)); + __m128i v_dy = _mm_loadu_si128((const __m128i *)(_dy + j)); + v_dx = _mm_max_epi16(v_dx, _mm_sub_epi16(v_zero, v_dx)); + v_dy = _mm_max_epi16(v_dy, _mm_sub_epi16(v_zero, v_dy)); + + __m128i v_norm = _mm_add_epi32(_mm_unpacklo_epi16(v_dx, v_zero), _mm_unpacklo_epi16(v_dy, v_zero)); + _mm_storeu_si128((__m128i *)(_norm + j), v_norm); + + v_norm = _mm_add_epi32(_mm_unpackhi_epi16(v_dx, v_zero), _mm_unpackhi_epi16(v_dy, v_zero)); + _mm_storeu_si128((__m128i *)(_norm + j + 4), v_norm); + } + } +#endif + for ( ; j < width; ++j) _norm[j] = std::abs(int(_dx[j])) + std::abs(int(_dy[j])); } else { - for (int j = 0; j < src.cols*cn; j++) + int j = 0, width = src.cols * cn; +#if CV_SSE2 + if (haveSSE2) + { + for ( ; j <= width - 8; j += 8) + { + __m128i v_dx = _mm_loadu_si128((const __m128i *)(_dx + j)); + __m128i v_dy = _mm_loadu_si128((const __m128i *)(_dy + j)); + + __m128i v_dx_ml = _mm_mullo_epi16(v_dx, v_dx), v_dx_mh = _mm_mulhi_epi16(v_dx, v_dx); + __m128i v_dy_ml = _mm_mullo_epi16(v_dy, v_dy), v_dy_mh = _mm_mulhi_epi16(v_dy, v_dy); + + __m128i v_norm = _mm_add_epi32(_mm_unpacklo_epi16(v_dx_ml, v_dx_mh), _mm_unpacklo_epi16(v_dy_ml, v_dy_mh)); + _mm_storeu_si128((__m128i *)(_norm + j), v_norm); + + v_norm = _mm_add_epi32(_mm_unpackhi_epi16(v_dx_ml, v_dx_mh), _mm_unpackhi_epi16(v_dy_ml, v_dy_mh)); + _mm_storeu_si128((__m128i *)(_norm + j + 4), v_norm); + } + } +#endif + for ( ; j < width; ++j) _norm[j] = int(_dx[j])*_dx[j] + int(_dy[j])*_dy[j]; } From a3b9884674b112a92c93ba742925030b5887ccfa Mon Sep 17 00:00:00 2001 From: vbystricky Date: Tue, 1 Jul 2014 11:58:58 +0400 Subject: [PATCH 030/136] Change global buffer to local --- modules/core/src/matrix.cpp | 119 +++++++++++++++-------------- modules/core/src/opencl/reduce2.cl | 60 ++++++++++++--- 2 files changed, 112 insertions(+), 67 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index f199cb2534..0db08e884e 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -3441,8 +3441,11 @@ static bool ocl_reduce(InputArray _src, OutputArray _dst, const int min_opt_cols = 128, buf_cols = 32; int sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype), ddepth = CV_MAT_DEPTH(dtype), ddepth0 = ddepth; - bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0, - useOptimized = 1 == dim && _src.cols() > min_opt_cols; + const ocl::Device &defDev = ocl::Device::getDefault(); + bool doubleSupport = defDev.doubleFPConfig() > 0; + + size_t wgs = defDev.maxWorkGroupSize(); + bool useOptimized = 1 == dim && _src.cols() > min_opt_cols && (wgs >= buf_cols); if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F)) return false; @@ -3455,78 +3458,80 @@ static bool ocl_reduce(InputArray _src, OutputArray _dst, const char * const ops[4] = { "OCL_CV_REDUCE_SUM", "OCL_CV_REDUCE_AVG", "OCL_CV_REDUCE_MAX", "OCL_CV_REDUCE_MIN" }; - char cvt[2][40]; - int wdepth = std::max(ddepth, CV_32F); - cv::String build_opt = format("-D %s -D dim=%d -D cn=%d -D ddepth=%d" - " -D srcT=%s -D dstT=%s -D dstT0=%s -D convertToWT=%s" - " -D convertToDT=%s -D convertToDT0=%s%s", - ops[op], dim, cn, ddepth, ocl::typeToStr(useOptimized ? ddepth : sdepth), - ocl::typeToStr(ddepth), ocl::typeToStr(ddepth0), - ocl::convertTypeStr(ddepth, wdepth, 1, cvt[0]), - ocl::convertTypeStr(sdepth, ddepth, 1, cvt[0]), - ocl::convertTypeStr(wdepth, ddepth0, 1, cvt[1]), - doubleSupport ? " -D DOUBLE_SUPPORT" : ""); - if (useOptimized) { - cv::String build_opt_pre = format("-D OP_REDUCE_PRE -D BUF_COLS=%d -D %s -D dim=1" - " -D cn=%d -D ddepth=%d -D srcT=%s -D dstT=%s -D convertToDT=%s%s", - buf_cols, ops[op], cn, ddepth, ocl::typeToStr(sdepth), ocl::typeToStr(ddepth), - ocl::convertTypeStr(sdepth, ddepth, 1, cvt[0]), - doubleSupport ? " -D DOUBLE_SUPPORT" : ""); - ocl::Kernel kpre("reduce_horz_pre", ocl::core::reduce2_oclsrc, build_opt_pre); - if (kpre.empty()) - return false; - - ocl::Kernel kmain("reduce", ocl::core::reduce2_oclsrc, build_opt); - if (kmain.empty()) + size_t tileHeight = (size_t)(wgs / buf_cols); + if (defDev.isIntel()) + { + static const size_t maxItemInGroupCount = 16; + tileHeight = min(tileHeight, defDev.localMemSize() / buf_cols / CV_ELEM_SIZE(CV_MAKETYPE(wdepth, cn)) / maxItemInGroupCount); + } + char cvt[3][40]; + cv::String build_opt = format("-D OP_REDUCE_PRE -D BUF_COLS=%d -D TILE_HEIGHT=%d -D %s -D dim=1" + " -D cn=%d -D ddepth=%d" + " -D srcT=%s -D bufT=%s -D dstT=%s" + " -D convertToWT=%s -D convertToBufT=%s -D convertToDT=%s%s", + buf_cols, tileHeight, ops[op], cn, ddepth, + ocl::typeToStr(sdepth), + ocl::typeToStr(ddepth), + ocl::typeToStr(ddepth0), + ocl::convertTypeStr(ddepth, wdepth, 1, cvt[0]), + ocl::convertTypeStr(sdepth, ddepth, 1, cvt[1]), + ocl::convertTypeStr(wdepth, ddepth0, 1, cvt[2]), + doubleSupport ? " -D DOUBLE_SUPPORT" : ""); + ocl::Kernel k("reduce_horz_opt", ocl::core::reduce2_oclsrc, build_opt); + if (k.empty()) return false; - UMat src = _src.getUMat(); Size dsize(1, src.rows); _dst.create(dsize, dtype); UMat dst = _dst.getUMat(); - UMat buf(src.rows, buf_cols, dst.type()); - - kpre.args(ocl::KernelArg::ReadOnly(src), - ocl::KernelArg::WriteOnlyNoSize(buf)); - - size_t globalSize[2] = { buf_cols, src.rows }; - if (!kpre.run(2, globalSize, NULL, false)) - return false; - if (op0 == CV_REDUCE_AVG) - kmain.args(ocl::KernelArg::ReadOnly(buf), - ocl::KernelArg::WriteOnlyNoSize(dst), 1.0f / src.cols); + k.args(ocl::KernelArg::ReadOnly(src), + ocl::KernelArg::WriteOnlyNoSize(dst), 1.0f / src.cols); else - kmain.args(ocl::KernelArg::ReadOnly(buf), - ocl::KernelArg::WriteOnlyNoSize(dst)); + k.args(ocl::KernelArg::ReadOnly(src), + ocl::KernelArg::WriteOnlyNoSize(dst)); - globalSize[0] = src.rows; - return kmain.run(1, globalSize, NULL, false); + size_t localSize[2] = { buf_cols, tileHeight}; + size_t globalSize[2] = { buf_cols, src.rows }; + return k.run(2, globalSize, localSize, false); } + else + { + char cvt[2][40]; + cv::String build_opt = format("-D %s -D dim=%d -D cn=%d -D ddepth=%d" + " -D srcT=%s -D dstT=%s -D dstT0=%s -D convertToWT=%s" + " -D convertToDT=%s -D convertToDT0=%s%s", + ops[op], dim, cn, ddepth, ocl::typeToStr(useOptimized ? ddepth : sdepth), + ocl::typeToStr(ddepth), ocl::typeToStr(ddepth0), + ocl::convertTypeStr(ddepth, wdepth, 1, cvt[0]), + ocl::convertTypeStr(sdepth, ddepth, 1, cvt[0]), + ocl::convertTypeStr(wdepth, ddepth0, 1, cvt[1]), + doubleSupport ? " -D DOUBLE_SUPPORT" : ""); + + ocl::Kernel k("reduce", ocl::core::reduce2_oclsrc, build_opt); + if (k.empty()) + return false; - ocl::Kernel k("reduce", ocl::core::reduce2_oclsrc, build_opt); - if (k.empty()) - return false; - - UMat src = _src.getUMat(); - Size dsize(dim == 0 ? src.cols : 1, dim == 0 ? 1 : src.rows); - _dst.create(dsize, dtype); - UMat dst = _dst.getUMat(); + UMat src = _src.getUMat(); + Size dsize(dim == 0 ? src.cols : 1, dim == 0 ? 1 : src.rows); + _dst.create(dsize, dtype); + UMat dst = _dst.getUMat(); - ocl::KernelArg srcarg = ocl::KernelArg::ReadOnly(src), - temparg = ocl::KernelArg::WriteOnlyNoSize(dst); + ocl::KernelArg srcarg = ocl::KernelArg::ReadOnly(src), + temparg = ocl::KernelArg::WriteOnlyNoSize(dst); - if (op0 == CV_REDUCE_AVG) - k.args(srcarg, temparg, 1.0f / (dim == 0 ? src.rows : src.cols)); - else - k.args(srcarg, temparg); + if (op0 == CV_REDUCE_AVG) + k.args(srcarg, temparg, 1.0f / (dim == 0 ? src.rows : src.cols)); + else + k.args(srcarg, temparg); - size_t globalsize = std::max(dsize.width, dsize.height); - return k.run(1, &globalsize, NULL, false); + size_t globalsize = std::max(dsize.width, dsize.height); + return k.run(1, &globalsize, NULL, false); + } } } diff --git a/modules/core/src/opencl/reduce2.cl b/modules/core/src/opencl/reduce2.cl index 7800e7a743..457378cc13 100644 --- a/modules/core/src/opencl/reduce2.cl +++ b/modules/core/src/opencl/reduce2.cl @@ -81,29 +81,34 @@ #define PROCESS_ELEM(acc, value) acc += value #elif defined OCL_CV_REDUCE_MAX #define INIT_VALUE MIN_VAL -#define PROCESS_ELEM(acc, value) acc = value > acc ? value : acc +#define PROCESS_ELEM(acc, value) acc = max(value, acc) #elif defined OCL_CV_REDUCE_MIN #define INIT_VALUE MAX_VAL -#define PROCESS_ELEM(acc, value) acc = value < acc ? value : acc +#define PROCESS_ELEM(acc, value) acc = min(value, acc) #else #error "No operation is specified" #endif #ifdef OP_REDUCE_PRE -__kernel void reduce_horz_pre(__global const uchar * srcptr, int src_step, int src_offset, int rows, int cols, - __global uchar * bufptr, int buf_step, int buf_offset) +__kernel void reduce_horz_opt(__global const uchar * srcptr, int src_step, int src_offset, int rows, int cols, + __global uchar * dstptr, int dst_step, int dst_offset +#ifdef OCL_CV_REDUCE_AVG + , float fscale +#endif + ) { + __local bufT lsmem[TILE_HEIGHT][BUF_COLS][cn]; + int x = get_global_id(0); int y = get_global_id(1); - if (x < BUF_COLS) + int liy = get_local_id(1); + if ((x < BUF_COLS) && (y < rows)) { int src_index = mad24(y, src_step, mad24(x, (int)sizeof(srcT) * cn, src_offset)); - int buf_index = mad24(y, buf_step, mad24(x, (int)sizeof(dstT) * cn, buf_offset)); __global const srcT * src = (__global const srcT *)(srcptr + src_index); - __global dstT * buf = (__global dstT *)(bufptr + buf_index); - dstT tmp[cn] = { INIT_VALUE }; + bufT tmp[cn] = { INIT_VALUE }; int src_step_mul = BUF_COLS * cn; for (int idx = x; idx < cols; idx += BUF_COLS, src += src_step_mul) @@ -111,14 +116,49 @@ __kernel void reduce_horz_pre(__global const uchar * srcptr, int src_step, int s #pragma unroll for (int c = 0; c < cn; ++c) { - dstT value = convertToDT(src[c]); + bufT value = convertToBufT(src[c]); PROCESS_ELEM(tmp[c], value); } } #pragma unroll for (int c = 0; c < cn; ++c) - buf[c] = tmp[c]; + lsmem[liy][x][c] = tmp[c]; + } + barrier(CLK_LOCAL_MEM_FENCE); + if ((x < BUF_COLS / 2) && (y < rows)) + { + #pragma unroll + for (int c = 0; c < cn; ++c) + { + PROCESS_ELEM(lsmem[liy][x][c], lsmem[liy][x + BUF_COLS / 2][c]); + } + } + barrier(CLK_LOCAL_MEM_FENCE); + if ((x == 0) && (y < rows)) + { + int dst_index = mad24(y, dst_step, dst_offset); + + __global dstT * dst = (__global dstT *)(dstptr + dst_index); + bufT tmp[cn] = { INIT_VALUE }; + + #pragma unroll + for (int xin = 0; xin < BUF_COLS / 2; xin ++) + { + #pragma unroll + for (int c = 0; c < cn; ++c) + { + PROCESS_ELEM(tmp[c], lsmem[liy][xin][c]); + } + } + + #pragma unroll + for (int c = 0; c < cn; ++c) +#ifdef OCL_CV_REDUCE_AVG + dst[c] = convertToDT(convertToWT(tmp[c]) * fscale); +#else + dst[c] = convertToDT(tmp[c]); +#endif } } From 10c772fa7f899b9139a32f3cf887b83e536f3793 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 2 Jul 2014 17:06:34 +0400 Subject: [PATCH 031/136] minor optimization of cv::LUT --- modules/core/src/convert.cpp | 14 ++-- modules/core/src/opencl/lut.cl | 136 +++++++++++++++++---------------- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 7b2684c85e..21d5bdaca7 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -1729,22 +1729,18 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst) UMat src = _src.getUMat(), lut = _lut.getUMat(); _dst.create(src.size(), CV_MAKETYPE(ddepth, dcn)); UMat dst = _dst.getUMat(); - bool bAligned = (1 == lcn) && (0 == (src.offset % 4)) && (0 == ((dcn * src.cols) % 4)); - // dst.cols == src.cols by params of dst.create + int kercn = lcn == 1 ? std::min(4, ocl::predictOptimalVectorWidth(_dst)) : dcn; ocl::Kernel k("LUT", ocl::core::lut_oclsrc, - format("-D dcn=%d -D lcn=%d -D srcT=%s -D dstT=%s", bAligned ? 4 : dcn, lcn, - ocl::typeToStr(src.depth()), ocl::memopTypeToStr(ddepth) - )); + format("-D dcn=%d -D lcn=%d -D srcT=%s -D dstT=%s", kercn, lcn, + ocl::typeToStr(src.depth()), ocl::memopTypeToStr(ddepth))); if (k.empty()) return false; - int cols = bAligned ? dcn * dst.cols / 4 : dst.cols; - k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::ReadOnlyNoSize(lut), - ocl::KernelArg::WriteOnlyNoSize(dst), dst.rows, cols); + ocl::KernelArg::WriteOnly(dst, dcn, kercn)); - size_t globalSize[2] = { cols, (dst.rows + 3) / 4 }; + size_t globalSize[2] = { dst.cols * dcn / kercn, (dst.rows + 3) / 4 }; return k.run(2, globalSize, NULL, false); } diff --git a/modules/core/src/opencl/lut.cl b/modules/core/src/opencl/lut.cl index 9bcd1b66f2..81ca4349a3 100644 --- a/modules/core/src/opencl/lut.cl +++ b/modules/core/src/opencl/lut.cl @@ -36,114 +36,118 @@ #if lcn == 1 #if dcn == 4 - #define LUT_OP(num)\ - int idx = *(__global const int *)(srcptr + mad24(num, src_step, src_index));\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ - dst[0] = lut_l[idx & 0xff];\ - dst[1] = lut_l[(idx >> 8) & 0xff];\ - dst[2] = lut_l[(idx >> 16) & 0xff];\ + #define LUT_OP \ + int idx = *(__global const int *)(srcptr + src_index); \ + dst = (__global dstT *)(dstptr + dst_index); \ + dst[0] = lut_l[idx & 0xff]; \ + dst[1] = lut_l[(idx >> 8) & 0xff]; \ + dst[2] = lut_l[(idx >> 16) & 0xff]; \ dst[3] = lut_l[(idx >> 24) & 0xff]; #elif dcn == 3 - #define LUT_OP(num)\ - uchar3 idx = vload3(0, srcptr + mad24(num, src_step, src_index));\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ - dst[0] = lut_l[idx.x];\ - dst[1] = lut_l[idx.y];\ + #define LUT_OP \ + uchar3 idx = vload3(0, srcptr + src_index); \ + dst = (__global dstT *)(dstptr + dst_index); \ + dst[0] = lut_l[idx.x]; \ + dst[1] = lut_l[idx.y]; \ dst[2] = lut_l[idx.z]; #elif dcn == 2 - #define LUT_OP(num)\ - short idx = *(__global const short *)(srcptr + mad24(num, src_step, src_index));\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ - dst[0] = lut_l[idx & 0xff];\ + #define LUT_OP \ + short idx = *(__global const short *)(srcptr + src_index); \ + dst = (__global dstT *)(dstptr + dst_index); \ + dst[0] = lut_l[idx & 0xff]; \ dst[1] = lut_l[(idx >> 8) & 0xff]; #elif dcn == 1 - #define LUT_OP(num)\ - uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ + #define LUT_OP \ + uchar idx = (srcptr + src_index)[0]; \ + dst = (__global dstT *)(dstptr + dst_index); \ dst[0] = lut_l[idx]; #else - #define LUT_OP(num)\ - __global const srcT * src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ - for (int cn = 0; cn < dcn; ++cn)\ + #define LUT_OP \ + __global const srcT * src = (__global const srcT *)(srcptr + src_index); \ + dst = (__global dstT *)(dstptr + dst_index); \ + for (int cn = 0; cn < dcn; ++cn) \ dst[cn] = lut_l[src[cn]]; #endif #else #if dcn == 4 - #define LUT_OP(num)\ - __global const uchar4 *src_pixel = (__global const uchar4 *)(srcptr + mad24(num, src_step, src_index));\ - int4 idx = convert_int4(src_pixel[0]) * lcn + (int4)(0, 1, 2, 3);\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ - dst[0] = lut_l[idx.x];\ - dst[1] = lut_l[idx.y];\ - dst[2] = lut_l[idx.z];\ + #define LUT_OP \ + __global const uchar4 * src_pixel = (__global const uchar4 *)(srcptr + src_index); \ + int4 idx = mad24(convert_int4(src_pixel[0]), (int4)(lcn), (int4)(0, 1, 2, 3)); \ + dst = (__global dstT *)(dstptr + dst_index); \ + dst[0] = lut_l[idx.x]; \ + dst[1] = lut_l[idx.y]; \ + dst[2] = lut_l[idx.z]; \ dst[3] = lut_l[idx.w]; #elif dcn == 3 - #define LUT_OP(num)\ - uchar3 src_pixel = vload3(0, srcptr + mad24(num, src_step, src_index));\ - int3 idx = convert_int3(src_pixel) * lcn + (int3)(0, 1, 2);\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ - dst[0] = lut_l[idx.x];\ - dst[1] = lut_l[idx.y];\ + #define LUT_OP \ + uchar3 src_pixel = vload3(0, srcptr + src_index); \ + int3 idx = mad24(convert_int3(src_pixel), (int3)(lcn), (int3)(0, 1, 2)); \ + dst = (__global dstT *)(dstptr + dst_index); \ + dst[0] = lut_l[idx.x]; \ + dst[1] = lut_l[idx.y]; \ dst[2] = lut_l[idx.z]; #elif dcn == 2 - #define LUT_OP(num)\ - __global const uchar2 *src_pixel = (__global const uchar2 *)(srcptr + mad24(num, src_step, src_index));\ - int2 idx = convert_int2(src_pixel[0]) * lcn + (int2)(0, 1);\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ - dst[0] = lut_l[idx.x];\ + #define LUT_OP \ + __global const uchar2 * src_pixel = (__global const uchar2 *)(srcptr + src_index); \ + int2 idx = mad24(convert_int2(src_pixel[0]), lcn, (int2)(0, 1)); \ + dst = (__global dstT *)(dstptr + dst_index); \ + dst[0] = lut_l[idx.x]; \ dst[1] = lut_l[idx.y]; #elif dcn == 1 //error case (1 < lcn) ==> lcn == scn == dcn - #define LUT_OP(num)\ - uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ + #define LUT_OP \ + uchar idx = (srcptr + src_index)[0]; \ + dst = (__global dstT *)(dstptr + dst_index); \ dst[0] = lut_l[idx]; #else - #define LUT_OP(num)\ - __global const srcT *src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\ - dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\ - for (int cn = 0; cn < dcn; ++cn)\ + #define LUT_OP \ + __global const srcT * src = (__global const srcT *)(srcptr + src_index); \ + dst = (__global dstT *)(dstptr + dst_index); \ + for (int cn = 0; cn < dcn; ++cn) \ dst[cn] = lut_l[mad24(src[cn], lcn, cn)]; #endif #endif -#define LOCAL_LUT_INIT\ - {\ - __global const dstT * lut = (__global const dstT *)(lutptr + lut_offset);\ - int init = mad24((int)get_local_id(1), (int)get_local_size(0), (int)get_local_id(0));\ - int step = get_local_size(0) * get_local_size(1);\ - for (int i = init; i < 256 * lcn; i += step)\ - {\ - lut_l[i] = lut[i];\ - }\ - barrier(CLK_LOCAL_MEM_FENCE);\ - } - __kernel void LUT(__global const uchar * srcptr, int src_step, int src_offset, __global const uchar * lutptr, int lut_step, int lut_offset, __global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols) { + int x = get_global_id(0); + int y = get_global_id(1) << 2; + __local dstT lut_l[256 * lcn]; - LOCAL_LUT_INIT; + __global const dstT * lut = (__global const dstT *)(lutptr + lut_offset); - int x = get_global_id(0); - int y = 4 * get_global_id(1); + for (int i = mad24((int)get_local_id(1), (int)get_local_size(0), (int)get_local_id(0)), + step = get_local_size(0) * get_local_size(1); i < 256 * lcn; i += step) + lut_l[i] = lut[i]; + barrier(CLK_LOCAL_MEM_FENCE); if (x < cols && y < rows) { int src_index = mad24(y, src_step, mad24(x, (int)sizeof(srcT) * dcn, src_offset)); int dst_index = mad24(y, dst_step, mad24(x, (int)sizeof(dstT) * dcn, dst_offset)); + __global dstT * dst; - LUT_OP(0); + + LUT_OP; + if (y < rows - 1) { - LUT_OP(1); + src_index += src_step; + dst_index += dst_step; + LUT_OP; + if (y < rows - 2) { - LUT_OP(2); + src_index += src_step; + dst_index += dst_step; + LUT_OP; + if (y < rows - 3) { - LUT_OP(3); + src_index += src_step; + dst_index += dst_step; + LUT_OP; } } } From 46e2216165ada8ed3f038470c2b1bec687ad4845 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 2 Jul 2014 19:32:10 +0400 Subject: [PATCH 032/136] fixed cv::warpPerspective --- modules/imgproc/src/imgwarp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index b69d75d6d4..e07641f6a1 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -4188,7 +4188,7 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0, const char * const kernelName = op_type == OCL_OP_AFFINE ? "warpAffine" : "warpPerspective"; int scalarcn = cn == 3 ? 4 : cn; - bool is32f = !dev.isAMD() && (interpolation == INTER_CUBIC || interpolation == INTER_LINEAR); + bool is32f = !dev.isAMD() && (interpolation == INTER_CUBIC || interpolation == INTER_LINEAR) && op_type == OCL_OP_AFFINE; int wdepth = interpolation == INTER_NEAREST ? depth : std::max(is32f ? CV_32F : CV_32S, depth); int sctype = CV_MAKETYPE(wdepth, scalarcn); From e5b63d43f2422037c7660d8712d76b62ced0a2df Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 3 Jul 2014 01:28:31 +0400 Subject: [PATCH 033/136] sse2 optimization of inv_sqrt_64f --- modules/core/src/mathfuncs.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 7a02bd6d72..46a80cd414 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -348,7 +348,18 @@ static void InvSqrt_32f(const float* src, float* dst, int len) static void InvSqrt_64f(const double* src, double* dst, int len) { - for( int i = 0; i < len; i++ ) + int i = 0; + +#if CV_SSE2 + if (USE_SSE2) + { + __m128d v_1 = _mm_set1_pd(1.0); + for ( ; i <= len - 2; i += 2) + _mm_storeu_pd(dst + i, _mm_div_pd(v_1, _mm_sqrt_pd(_mm_loadu_pd(src + i)))); + } +#endif + + for( ; i < len; i++ ) dst[i] = 1/std::sqrt(src[i]); } From 93f8581b6954233284dc9983a27ff808afac70d4 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 1 Jul 2014 14:31:25 +0400 Subject: [PATCH 034/136] fixed warnings --- modules/highgui/src/cap_qtkit.mm | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/modules/highgui/src/cap_qtkit.mm b/modules/highgui/src/cap_qtkit.mm index b0800a1302..461bc1f33c 100644 --- a/modules/highgui/src/cap_qtkit.mm +++ b/modules/highgui/src/cap_qtkit.mm @@ -448,13 +448,12 @@ double CvCaptureCAM::getProperty(int property_id){ QTFormatDescription* format = [[connections objectAtIndex:0] formatDescription]; NSSize s1 = [[format attributeForKey:QTFormatDescriptionVideoCleanApertureDisplaySizeAttribute] sizeValue]; - int width=s1.width, height=s1.height; switch (property_id) { case CV_CAP_PROP_FRAME_WIDTH: - retval = width; + retval = s1.width; break; case CV_CAP_PROP_FRAME_HEIGHT: - retval = height; + retval = s1.height; break; default: retval = 0; @@ -1011,22 +1010,22 @@ bool CvVideoWriter_QT::writeFrame(const IplImage* image) { cvCvtColor(image, argbimage, CV_BGR2BGRA); - unsigned char* imagedata = (unsigned char*)argbimage->imageData; + unsigned char* imagedata_ = (unsigned char*)argbimage->imageData; //BGRA --> ARGB for (int j = 0; j < argbimage->height; j++) { int rowstart = argbimage->widthStep * j; for (int i = rowstart; i < rowstart+argbimage->widthStep; i+=4) { - unsigned char temp = imagedata[i]; - imagedata[i] = 255; - imagedata[i+3] = temp; - temp = imagedata[i+2]; - imagedata[i+2] = imagedata[i+1]; - imagedata[i+1] = temp; + unsigned char temp = imagedata_[i]; + imagedata_[i] = 255; + imagedata_[i+3] = temp; + temp = imagedata_[i+2]; + imagedata_[i+2] = imagedata_[i+1]; + imagedata_[i+1] = temp; } } - NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&imagedata + NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&imagedata_ pixelsWide:movieSize.width pixelsHigh:movieSize.height bitsPerSample:8 From c5d3c08256e06fab298e153f3bde89793eceb221 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 3 Jul 2014 12:18:19 +0400 Subject: [PATCH 035/136] ocl: add try-catch for OpenCL device getter --- modules/core/src/ocl.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 0b196d9c52..8ffd1d200a 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1416,7 +1416,16 @@ bool useOpenCL() { CoreTLSData* data = coreTlsData.get(); if( data->useOpenCL < 0 ) - data->useOpenCL = (int)haveOpenCL() && Device::getDefault().ptr() != NULL; + { + try + { + data->useOpenCL = (int)haveOpenCL() && Device::getDefault().ptr() != NULL; + } + catch (...) + { + data->useOpenCL = 0; + } + } return data->useOpenCL > 0; } From 8fdbdb131d3b2bb6de6d0bda1808a06a5f5114b8 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 2 Jul 2014 01:32:45 +0400 Subject: [PATCH 036/136] SSE4.1 optimiation of cv::Moments CV_16U --- modules/imgproc/src/moments.cpp | 161 ++++++++++++++++++++------------ 1 file changed, 103 insertions(+), 58 deletions(-) diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index 61fff29852..a61002a792 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -203,69 +203,27 @@ static Moments contourMoments( const Mat& contour ) \****************************************************************************************/ template -#if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 9 -// Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60196 -__attribute__((optimize("no-tree-vectorize"))) -#endif -static void momentsInTile( const Mat& img, double* moments ) +struct MomentsInTile_SSE { - Size size = img.size(); - int x, y; - MT mom[10] = {0,0,0,0,0,0,0,0,0,0}; - - for( y = 0; y < size.height; y++ ) + int operator() (const T *, int, WT &, WT &, WT &, MT &) { - const T* ptr = (const T*)(img.data + y*img.step); - WT x0 = 0, x1 = 0, x2 = 0; - MT x3 = 0; - - for( x = 0; x < size.width; x++ ) - { - WT p = ptr[x]; - WT xp = x * p, xxp; - - x0 += p; - x1 += xp; - xxp = xp * x; - x2 += xxp; - x3 += xxp * x; - } - - WT py = y * x0, sy = y*y; - - mom[9] += ((MT)py) * sy; // m03 - mom[8] += ((MT)x1) * sy; // m12 - mom[7] += ((MT)x2) * y; // m21 - mom[6] += x3; // m30 - mom[5] += x0 * sy; // m02 - mom[4] += x1 * y; // m11 - mom[3] += x2; // m20 - mom[2] += py; // m01 - mom[1] += x1; // m10 - mom[0] += x0; // m00 + return 0; } - - for( x = 0; x < 10; x++ ) - moments[x] = (double)mom[x]; -} - +}; #if CV_SSE2 -template<> void momentsInTile( const cv::Mat& img, double* moments ) +template <> +struct MomentsInTile_SSE { - typedef uchar T; - typedef int WT; - typedef int MT; - Size size = img.size(); - int y; - MT mom[10] = {0,0,0,0,0,0,0,0,0,0}; - bool useSIMD = checkHardwareSupport(CV_CPU_SSE2); + MomentsInTile_SSE() + { + useSIMD = checkHardwareSupport(CV_CPU_SSE2); + } - for( y = 0; y < size.height; y++ ) + int operator() (const uchar * ptr, int len, int & x0, int & x1, int & x2, int & x3) { - const T* ptr = img.ptr(y); - int x0 = 0, x1 = 0, x2 = 0, x3 = 0, x = 0; + int x = 0; if( useSIMD ) { @@ -273,7 +231,7 @@ template<> void momentsInTile( const cv::Mat& img, double* mome __m128i dx = _mm_set1_epi16(8); __m128i z = _mm_setzero_si128(), qx0 = z, qx1 = z, qx2 = z, qx3 = z, qx = qx_init; - for( ; x <= size.width - 8; x += 8 ) + for( ; x <= len - 8; x += 8 ) { __m128i p = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(ptr + x)), z); qx0 = _mm_add_epi32(qx0, _mm_sad_epu8(p, z)); @@ -285,6 +243,7 @@ template<> void momentsInTile( const cv::Mat& img, double* mome qx = _mm_add_epi16(qx, dx); } + int CV_DECL_ALIGNED(16) buf[4]; _mm_store_si128((__m128i*)buf, qx0); x0 = buf[0] + buf[1] + buf[2] + buf[3]; @@ -296,6 +255,94 @@ template<> void momentsInTile( const cv::Mat& img, double* mome x3 = buf[0] + buf[1] + buf[2] + buf[3]; } + return x; + } + + bool useSIMD; +}; + +#endif + +#if CV_SSE4_1 + +template <> +struct MomentsInTile_SSE +{ + MomentsInTile_SSE() + { + useSIMD = checkHardwareSupport(CV_CPU_SSE4_1); + } + + int operator() (const ushort * ptr, int len, int & x0, int & x1, int & x2, int64 & x3) + { + int x = 0; + + if (useSIMD) + { + __m128i vx_init0 = _mm_setr_epi32(0, 1, 2, 3), vx_init1 = _mm_setr_epi32(4, 5, 6, 7), + v_delta = _mm_set1_epi32(8), v_zero = _mm_setzero_si128(), v_x0 = v_zero, + v_x1 = v_zero, v_x2 = v_zero, v_x3 = v_zero, v_ix0 = vx_init0, v_ix1 = vx_init1; + + for( ; x <= len - 8; x += 8 ) + { + __m128i v_src = _mm_loadu_si128((const __m128i *)(ptr + x)); + __m128i v_src0 = _mm_unpacklo_epi16(v_src, v_zero), v_src1 = _mm_unpackhi_epi16(v_src, v_zero); + + v_x0 = _mm_add_epi32(v_x0, _mm_add_epi32(v_src0, v_src1)); + __m128i v_x1_0 = _mm_mullo_epi32(v_src0, v_ix0), v_x1_1 = _mm_mullo_epi32(v_src1, v_ix1); + v_x1 = _mm_add_epi32(v_x1, _mm_add_epi32(v_x1_0, v_x1_1)); + + __m128i v_2ix0 = _mm_mullo_epi32(v_ix0, v_ix0), v_2ix1 = _mm_mullo_epi32(v_ix1, v_ix1); + v_x2 = _mm_add_epi32(v_x2, _mm_add_epi32(_mm_mullo_epi32(v_2ix0, v_src0), _mm_mullo_epi32(v_2ix1, v_src1))); + + __m128i t = _mm_add_epi32(_mm_mullo_epi32(v_2ix0, v_x1_0), _mm_mullo_epi32(v_2ix1, v_x1_1)); + v_x3 = _mm_add_epi64(v_x3, _mm_add_epi64(_mm_unpacklo_epi32(t, v_zero), _mm_unpackhi_epi32(t, v_zero))); + + v_ix0 = _mm_add_epi32(v_ix0, v_delta); + v_ix1 = _mm_add_epi32(v_ix1, v_delta); + } + + int CV_DECL_ALIGNED(16) buf[4]; + int64 CV_DECL_ALIGNED(16) buf64[2]; + + _mm_store_si128((__m128i*)buf, v_x0); + x0 = buf[0] + buf[1] + buf[2] + buf[3]; + _mm_store_si128((__m128i*)buf, v_x1); + x1 = buf[0] + buf[1] + buf[2] + buf[3]; + _mm_store_si128((__m128i*)buf, v_x2); + x2 = buf[0] + buf[1] + buf[2] + buf[3]; + + _mm_store_si128((__m128i*)buf64, v_x3); + x3 = buf64[0] + buf64[1]; + } + + return x; + } + + bool useSIMD; +}; + +#endif + +template +#if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 9 +// Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60196 +__attribute__((optimize("no-tree-vectorize"))) +#endif +static void momentsInTile( const Mat& img, double* moments ) +{ + Size size = img.size(); + int x, y; + MT mom[10] = {0,0,0,0,0,0,0,0,0,0}; + MomentsInTile_SSE vop; + + for( y = 0; y < size.height; y++ ) + { + const T* ptr = (const T*)(img.data + y*img.step); + WT x0 = 0, x1 = 0, x2 = 0; + MT x3 = 0; + x = vop(ptr, size.width, x0, x1, x2, x3); + for( ; x < size.width; x++ ) { WT p = ptr[x]; @@ -322,12 +369,10 @@ template<> void momentsInTile( const cv::Mat& img, double* mome mom[0] += x0; // m00 } - for(int x = 0; x < 10; x++ ) + for( x = 0; x < 10; x++ ) moments[x] = (double)mom[x]; } -#endif - typedef void (*MomentsInTileFunc)(const Mat& img, double* moments); Moments::Moments() From 2fe07abf83360467a318406dbecb6b32d3b2522f Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 3 Jul 2014 13:45:55 +0400 Subject: [PATCH 037/136] use vectors for devices of all vendors --- modules/core/src/ocl.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 0b196d9c52..43e1ab2c95 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -4428,11 +4428,13 @@ int predictOptimalVectorWidth(InputArray src1, InputArray src2, InputArray src3, d.preferredVectorWidthShort(), d.preferredVectorWidthShort(), d.preferredVectorWidthInt(), d.preferredVectorWidthFloat(), d.preferredVectorWidthDouble(), -1 }, kercn = vectorWidths[depth]; - if (d.isIntel()) + + // if the device says don't use vectors + if (vectorWidths[0] == 1) { // it's heuristic - int vectorWidthsIntel[] = { 16, 16, 8, 8, 1, 1, 1, -1 }; - kercn = vectorWidthsIntel[depth]; + int vectorWidthsOthers[] = { 16, 16, 8, 8, 1, 1, 1, -1 }; + kercn = vectorWidthsOthers[depth]; } if (ssize.width * cn < kercn || kercn <= 0) From 690c932d7f536b971879f8d901543843b2d13ac8 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 3 Jul 2014 15:50:56 +0400 Subject: [PATCH 038/136] Change groups count for Intel --- modules/core/src/stat.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 3dd042860d..48d85900d9 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -918,8 +918,14 @@ static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0, isContinuous = _src.isContinuous(); - int groups = ocl::Device::getDefault().maxComputeUnits(); - size_t wgs = ocl::Device::getDefault().maxWorkGroupSize(); + const ocl::Device &defDev = ocl::Device::getDefault(); + int groups = defDev.maxComputeUnits(); + if (defDev.isIntel()) + { + static const int subSliceEUCount = 10; + groups = (groups / subSliceEUCount) * 2; + } + size_t wgs = defDev.maxWorkGroupSize(); int ddepth = std::max(CV_32S, depth), sqddepth = std::max(CV_32F, depth), dtype = CV_MAKE_TYPE(ddepth, cn), From 55d84cf8155c27554b37fafdf268a08f4b41f3fb Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 3 Jul 2014 16:16:23 +0400 Subject: [PATCH 039/136] optimization of cv::minMaxLoc - used min/max --- modules/core/src/opencl/minmaxloc.cl | 86 ++++++++++++++++------------ 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/modules/core/src/opencl/minmaxloc.cl b/modules/core/src/opencl/minmaxloc.cl index a51c5d93a3..664673e5a2 100644 --- a/modules/core/src/opencl/minmaxloc.cl +++ b/modules/core/src/opencl/minmaxloc.cl @@ -42,9 +42,13 @@ #if wdepth <= 4 #define MIN_ABS(a) convertFromU(abs(a)) #define MIN_ABS2(a, b) convertFromU(abs_diff(a, b)) +#define MIN(a, b) min(a, b) +#define MAX(a, b) max(a, b) #else #define MIN_ABS(a) fabs(a) #define MIN_ABS2(a, b) fabs(a - b) +#define MIN(a, b) fmin(a, b) +#define MAX(a, b) fmax(a, b) #endif #if kercn != 3 @@ -60,44 +64,41 @@ #define srcTSIZE (int)sizeof(srcT1) #endif -#ifdef NEED_MINLOC -#define CALC_MINLOC(inc) minloc = id + inc -#else -#define CALC_MINLOC(inc) -#endif - -#ifdef NEED_MAXLOC -#define CALC_MAXLOC(inc) maxloc = id + inc -#else -#define CALC_MAXLOC(inc) -#endif - #ifdef NEED_MINVAL +#ifdef NEED_MINLOC #define CALC_MIN(p, inc) \ if (minval > temp.p) \ { \ minval = temp.p; \ - CALC_MINLOC(inc); \ + minloc = id + inc; \ } #else +#define CALC_MIN(p, inc) \ + minval = MIN(minval, temp.p); +#endif +#else #define CALC_MIN(p, inc) #endif #ifdef NEED_MAXVAL +#ifdef NEED_MAXLOC #define CALC_MAX(p, inc) \ if (maxval < temp.p) \ { \ maxval = temp.p; \ - CALC_MAXLOC(inc); \ + maxloc = id + inc; \ } #else +#define CALC_MAX(p, inc) \ + maxval = MAX(maxval, temp.p); +#endif +#else #define CALC_MAX(p, inc) #endif #ifdef OP_CALC2 #define CALC_MAX2(p) \ - if (maxval2 < temp.p) \ - maxval2 = temp.p; + maxval2 = MAX(maxval2, temp.p); #else #define CALC_MAX2(p) #endif @@ -208,25 +209,28 @@ __kernel void minmaxloc(__global const uchar * srcptr, int src_step, int src_off #if kercn == 1 #ifdef NEED_MINVAL +#if NEED_MINLOC if (minval > temp) { minval = temp; -#ifdef NEED_MINLOC minloc = id; -#endif } +#else + minval = MIN(minval, temp); +#endif #endif #ifdef NEED_MAXVAL +#ifdef NEED_MAXLOC if (maxval < temp) { maxval = temp; -#ifdef NEED_MAXLOC maxloc = id; -#endif } +#else + maxval = MAX(maxval, temp); +#endif #ifdef OP_CALC2 - if (maxval2 < temp2) - maxval2 = temp2; + maxval2 = MAX(maxval2, temp2); #endif #endif #elif kercn >= 2 @@ -282,32 +286,35 @@ __kernel void minmaxloc(__global const uchar * srcptr, int src_step, int src_off { int lid3 = lid - WGS2_ALIGNED; #ifdef NEED_MINVAL +#ifdef NEED_MINLOC if (localmem_min[lid3] >= minval) { -#ifdef NEED_MINLOC if (localmem_min[lid3] == minval) localmem_minloc[lid3] = min(localmem_minloc[lid3], minloc); else localmem_minloc[lid3] = minloc, -#endif - localmem_min[lid3] = minval; + localmem_min[lid3] = minval; } +#else + localmem_min[lid3] = MIN(localmem_min[lid3], minval); +#endif #endif #ifdef NEED_MAXVAL +#ifdef NEED_MAXLOC if (localmem_max[lid3] <= maxval) { -#ifdef NEED_MAXLOC if (localmem_max[lid3] == maxval) localmem_maxloc[lid3] = min(localmem_maxloc[lid3], maxloc); else localmem_maxloc[lid3] = maxloc, -#endif - localmem_max[lid3] = maxval; + localmem_max[lid3] = maxval; } +#else + localmem_max[lid3] = MAX(localmem_max[lid3], maxval); +#endif #endif #ifdef OP_CALC2 - if (localmem_max2[lid3] < maxval2) - localmem_max2[lid3] = maxval2; + localmem_max2[lid3] = MAX(localmem_max2[lid3], maxval2); #endif } barrier(CLK_LOCAL_MEM_FENCE); @@ -319,32 +326,35 @@ __kernel void minmaxloc(__global const uchar * srcptr, int src_step, int src_off int lid2 = lsize + lid; #ifdef NEED_MINVAL +#ifdef NEED_MAXLOC if (localmem_min[lid] >= localmem_min[lid2]) { -#ifdef NEED_MINLOC if (localmem_min[lid] == localmem_min[lid2]) localmem_minloc[lid] = min(localmem_minloc[lid2], localmem_minloc[lid]); else localmem_minloc[lid] = localmem_minloc[lid2], -#endif - localmem_min[lid] = localmem_min[lid2]; + localmem_min[lid] = localmem_min[lid2]; } +#else + localmem_min[lid] = MIN(localmem_min[lid], localmem_min[lid2]); +#endif #endif #ifdef NEED_MAXVAL +#ifdef NEED_MAXLOC if (localmem_max[lid] <= localmem_max[lid2]) { -#ifdef NEED_MAXLOC if (localmem_max[lid] == localmem_max[lid2]) localmem_maxloc[lid] = min(localmem_maxloc[lid2], localmem_maxloc[lid]); else localmem_maxloc[lid] = localmem_maxloc[lid2], -#endif - localmem_max[lid] = localmem_max[lid2]; + localmem_max[lid] = localmem_max[lid2]; } +#else + localmem_max[lid] = MAX(localmem_max[lid], localmem_max[lid2]); +#endif #endif #ifdef OP_CALC2 - if (localmem_max2[lid] < localmem_max2[lid2]) - localmem_max2[lid] = localmem_max2[lid2]; + localmem_max2[lid] = MAX(localmem_max2[lid], localmem_max2[lid2]); #endif } barrier(CLK_LOCAL_MEM_FENCE); From 7674f3ddbff1231021f1026df5c9259fba06fa4c Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Thu, 3 Jul 2014 22:14:58 +0300 Subject: [PATCH 040/136] Added call to clone() to avoid unexpected change to external data. - Fix both stitching_detailed.cpp sample and cv::Stitcher. --- modules/stitching/src/stitcher.cpp | 2 +- samples/cpp/stitching_detailed.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/stitching/src/stitcher.cpp b/modules/stitching/src/stitcher.cpp index ddfdb50843..0d4623af8f 100644 --- a/modules/stitching/src/stitcher.cpp +++ b/modules/stitching/src/stitcher.cpp @@ -522,7 +522,7 @@ Stitcher::Status Stitcher::estimateCameraParams() { std::vector rmats; for (size_t i = 0; i < cameras_.size(); ++i) - rmats.push_back(cameras_[i].R); + rmats.push_back(cameras_[i].R.clone()); detail::waveCorrect(rmats, wave_correct_kind_); for (size_t i = 0; i < cameras_.size(); ++i) cameras_[i].R = rmats[i]; diff --git a/samples/cpp/stitching_detailed.cpp b/samples/cpp/stitching_detailed.cpp index df0a9abc84..740047f528 100644 --- a/samples/cpp/stitching_detailed.cpp +++ b/samples/cpp/stitching_detailed.cpp @@ -527,7 +527,7 @@ int main(int argc, char* argv[]) { vector rmats; for (size_t i = 0; i < cameras.size(); ++i) - rmats.push_back(cameras[i].R); + rmats.push_back(cameras[i].R.clone()); waveCorrect(rmats, wave_correct); for (size_t i = 0; i < cameras.size(); ++i) cameras[i].R = rmats[i]; From b71744082b9d601bde333c2d3743a4694fb1d498 Mon Sep 17 00:00:00 2001 From: David Bradley Date: Thu, 3 Jul 2014 15:15:23 -0400 Subject: [PATCH 041/136] cudabgsegm module was not compiling. Changing all references of opencv2/legacy.hpp to opencv2/cudalegacy.hpp seemed to work. I'm new at this so it would be good to have someone familiar with the build system confirm the change. --- modules/cudabgsegm/perf/perf_bgsegm.cpp | 8 ++++---- modules/cudabgsegm/test/test_bgsegm.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/cudabgsegm/perf/perf_bgsegm.cpp b/modules/cudabgsegm/perf/perf_bgsegm.cpp index 9d3da2927f..02fc9a8ee9 100644 --- a/modules/cudabgsegm/perf/perf_bgsegm.cpp +++ b/modules/cudabgsegm/perf/perf_bgsegm.cpp @@ -42,8 +42,8 @@ #include "perf_precomp.hpp" -#ifdef HAVE_OPENCV_LEGACY -# include "opencv2/legacy.hpp" +#ifdef HAVE_OPENCV_CUDALEGACY +# include "opencv2/cudalegacy.hpp" #endif #ifdef HAVE_OPENCV_CUDAIMGPROC @@ -72,7 +72,7 @@ using namespace perf; #if BUILD_WITH_VIDEO_INPUT_SUPPORT -#ifdef HAVE_OPENCV_LEGACY +#ifdef HAVE_OPENCV_CUDALEGACY namespace cv { @@ -150,7 +150,7 @@ PERF_TEST_P(Video, FGDStatModel, } else { -#ifdef HAVE_OPENCV_LEGACY +#ifdef HAVE_OPENCV_CUDALEGACY IplImage ipl_frame = frame; cv::Ptr model(cvCreateFGDStatModel(&ipl_frame)); diff --git a/modules/cudabgsegm/test/test_bgsegm.cpp b/modules/cudabgsegm/test/test_bgsegm.cpp index 75d6d73a3f..34f3dcc9ab 100644 --- a/modules/cudabgsegm/test/test_bgsegm.cpp +++ b/modules/cudabgsegm/test/test_bgsegm.cpp @@ -42,8 +42,8 @@ #include "test_precomp.hpp" -#ifdef HAVE_OPENCV_LEGACY -# include "opencv2/legacy.hpp" +#ifdef HAVE_OPENCV_CUDALEGACY +# include "opencv2/cudalegacy.hpp" #endif #ifdef HAVE_CUDA @@ -66,7 +66,7 @@ using namespace cvtest; ////////////////////////////////////////////////////// // FGDStatModel -#if BUILD_WITH_VIDEO_INPUT_SUPPORT && defined(HAVE_OPENCV_LEGACY) +#if BUILD_WITH_VIDEO_INPUT_SUPPORT && defined(HAVE_OPENCV_CUDALEGACY) namespace cv { From 68827072c903e4cee6c9bd683f71294521051c09 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Mon, 20 Jan 2014 21:44:27 +0200 Subject: [PATCH 042/136] [HighGUI] On Windows: Support Ctrl+C to copy image to clipboard. --- modules/highgui/src/window_w32.cpp | 84 ++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 8b317dff71..a7aca0ec47 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1286,6 +1286,10 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) switch(uMsg) { + case WM_COPY: + ::WindowProc(hwnd, uMsg, wParam, lParam); // call highgui proc. There may be a better way to do this. + break; + case WM_DESTROY: icvRemoveWindow(window); @@ -1448,6 +1452,81 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM // Process the message switch(uMsg) { + case WM_COPY: + { + if (!::OpenClipboard(hwnd) ) + break; + + HDC hDC = 0; + HDC memDC = 0; + HBITMAP memBM = 0; + + // We'll use a do-while(0){} scope as a single-run breakable scope + // Upon any error we can jump out of the single-time while scope to clean up the resources. + do + { + if (!::EmptyClipboard()) + break; + + if(!window->image) + break; + + // Get window device context + if (0 == (hDC = ::GetDC(hwnd))) + break; + + // Create another DC compatible with hDC + if (0 == (memDC = ::CreateCompatibleDC( hDC ))) + break; + + // Determine the bitmap's dimensions + int nchannels = 3; + SIZE size = {0,0}; + icvGetBitmapData( window, &size, &nchannels, 0 ); + + // Create bitmap to draw on and it in the new DC + if (0 == (memBM = ::CreateCompatibleBitmap ( hDC, size.cx, size.cy))) + break; + + if (!::SelectObject( memDC, memBM )) + break; + + // Begin drawing to DC + if (!::SetStretchBltMode(memDC, COLORONCOLOR)) + break; + + RGBQUAD table[256]; + if( 1 == nchannels ) + { + for(int i = 0; i < 256; ++i) + { + table[i].rgbBlue = (unsigned char)i; + table[i].rgbGreen = (unsigned char)i; + table[i].rgbRed = (unsigned char)i; + } + if (!::SetDIBColorTable(window->dc, 0, 255, table)) + break; + } + + // The image copied to the clipboard will be in its original size, regardless if the window itself was resized. + + // Render the image to the dc/bitmap (at original size). + if (!::BitBlt( memDC, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY )) + break; + + // Finally, set bitmap to clipboard + ::SetClipboardData(CF_BITMAP, memBM); + } while (0,0); // (0,0) instead of (0) to avoid MSVC compiler warning C4127: "conditional expression is constant" + + ////////////////////////////////////////////////////////////////////////// + // if handle is allocated (i.e. != 0) then clean-up. + memBM && ::DeleteObject(memBM); + memDC && ::DeleteDC(memDC); + hDC && ::ReleaseDC(hwnd, hDC); + ::CloseClipboard(); + break; + } + case WM_WINDOWPOSCHANGING: { LPWINDOWPOS pos = (LPWINDOWPOS)lParam; @@ -1798,6 +1877,11 @@ cvWaitKey( int delay ) is_processed = 1; return (int)(message.wParam << 16); } + + // Intercept Ctrl+C for copy to clipboard + if ('C' == message.wParam && (::GetKeyState(VK_CONTROL)>>15)) + ::PostMessage(message.hwnd, WM_COPY, 0, 0); + default: DispatchMessage(&message); is_processed = 1; From d44e3c369d58579013d42c4ea573215385fe51d9 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Mon, 20 Jan 2014 22:09:52 +0200 Subject: [PATCH 043/136] Added documentation. --- modules/highgui/doc/user_interface.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/highgui/doc/user_interface.rst b/modules/highgui/doc/user_interface.rst index 0d0ccde946..565ea6d449 100644 --- a/modules/highgui/doc/user_interface.rst +++ b/modules/highgui/doc/user_interface.rst @@ -83,6 +83,9 @@ If window was created with OpenGL support, ``imshow`` also support :ocv:class:`o .. note:: This function should be followed by ``waitKey`` function which displays the image for specified milliseconds. Otherwise, it won't display the image. For example, ``waitKey(0)`` will display the window infinitely until any keypress (it is suitable for image display). ``waitKey(25)`` will display a frame for 25 ms, after which display will be automatically closed. (If you put it in a loop to read videos, it will display the video frame-by-frame) +.. note:: + + [Windows Backend Only] Pressing Ctrl+C will copy the image to the clipboard. namedWindow --------------- From e25dca21d18c1a6af4cf87e697b5612dd34d0175 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Mon, 27 Jan 2014 10:14:49 +0200 Subject: [PATCH 044/136] Fixed indentation. --- modules/highgui/src/window_w32.cpp | 106 ++++++++++++++--------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index a7aca0ec47..658bb4f481 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1287,8 +1287,8 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) switch(uMsg) { case WM_COPY: - ::WindowProc(hwnd, uMsg, wParam, lParam); // call highgui proc. There may be a better way to do this. - break; + ::WindowProc(hwnd, uMsg, wParam, lParam); // call highgui proc. There may be a better way to do this. + break; case WM_DESTROY: @@ -1465,57 +1465,57 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM // Upon any error we can jump out of the single-time while scope to clean up the resources. do { - if (!::EmptyClipboard()) - break; - - if(!window->image) - break; - - // Get window device context - if (0 == (hDC = ::GetDC(hwnd))) - break; - - // Create another DC compatible with hDC - if (0 == (memDC = ::CreateCompatibleDC( hDC ))) - break; - - // Determine the bitmap's dimensions - int nchannels = 3; - SIZE size = {0,0}; - icvGetBitmapData( window, &size, &nchannels, 0 ); - - // Create bitmap to draw on and it in the new DC - if (0 == (memBM = ::CreateCompatibleBitmap ( hDC, size.cx, size.cy))) - break; - - if (!::SelectObject( memDC, memBM )) - break; - - // Begin drawing to DC - if (!::SetStretchBltMode(memDC, COLORONCOLOR)) - break; - - RGBQUAD table[256]; - if( 1 == nchannels ) - { - for(int i = 0; i < 256; ++i) - { - table[i].rgbBlue = (unsigned char)i; - table[i].rgbGreen = (unsigned char)i; - table[i].rgbRed = (unsigned char)i; - } - if (!::SetDIBColorTable(window->dc, 0, 255, table)) - break; - } - - // The image copied to the clipboard will be in its original size, regardless if the window itself was resized. - - // Render the image to the dc/bitmap (at original size). - if (!::BitBlt( memDC, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY )) - break; - - // Finally, set bitmap to clipboard - ::SetClipboardData(CF_BITMAP, memBM); + if (!::EmptyClipboard()) + break; + + if(!window->image) + break; + + // Get window device context + if (0 == (hDC = ::GetDC(hwnd))) + break; + + // Create another DC compatible with hDC + if (0 == (memDC = ::CreateCompatibleDC( hDC ))) + break; + + // Determine the bitmap's dimensions + int nchannels = 3; + SIZE size = {0,0}; + icvGetBitmapData( window, &size, &nchannels, 0 ); + + // Create bitmap to draw on and it in the new DC + if (0 == (memBM = ::CreateCompatibleBitmap ( hDC, size.cx, size.cy))) + break; + + if (!::SelectObject( memDC, memBM )) + break; + + // Begin drawing to DC + if (!::SetStretchBltMode(memDC, COLORONCOLOR)) + break; + + RGBQUAD table[256]; + if( 1 == nchannels ) + { + for(int i = 0; i < 256; ++i) + { + table[i].rgbBlue = (unsigned char)i; + table[i].rgbGreen = (unsigned char)i; + table[i].rgbRed = (unsigned char)i; + } + if (!::SetDIBColorTable(window->dc, 0, 255, table)) + break; + } + + // The image copied to the clipboard will be in its original size, regardless if the window itself was resized. + + // Render the image to the dc/bitmap (at original size). + if (!::BitBlt( memDC, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY )) + break; + + // Finally, set bitmap to clipboard + ::SetClipboardData(CF_BITMAP, memBM); } while (0,0); // (0,0) instead of (0) to avoid MSVC compiler warning C4127: "conditional expression is constant" ////////////////////////////////////////////////////////////////////////// From b449bd5150076535e984805860fbe23484bec840 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Thu, 3 Jul 2014 22:45:11 +0300 Subject: [PATCH 045/136] Clarified code. --- modules/highgui/src/window_w32.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 658bb4f481..bcf1bae8be 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1520,9 +1520,9 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM ////////////////////////////////////////////////////////////////////////// // if handle is allocated (i.e. != 0) then clean-up. - memBM && ::DeleteObject(memBM); - memDC && ::DeleteDC(memDC); - hDC && ::ReleaseDC(hwnd, hDC); + if (memBM) ::DeleteObject(memBM); + if (memDC) ::DeleteDC(memDC); + if (hDC) ::ReleaseDC(hwnd, hDC); ::CloseClipboard(); break; } From e04c39b089cc5048f7cbbe8f01ddedae612e23c5 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 4 Jul 2014 00:36:32 +0400 Subject: [PATCH 046/136] SSE2 optimization of cv::inRange --- modules/core/src/arithm.cpp | 187 +++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 3 deletions(-) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 751659684c..b98bf830e4 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -2980,8 +2980,187 @@ void cv::compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op) namespace cv { -template static void -inRange_(const T* src1, size_t step1, const T* src2, size_t step2, +template +struct InRange_SSE +{ + int operator () (const T *, const T *, const T *, uchar *, int) const + { + return 0; + } +}; + +#if CV_SSE2 + +template <> +struct InRange_SSE +{ + int operator () (const uchar * src1, const uchar * src2, const uchar * src3, + uchar * dst, int len) const + { + int x = 0; + + if (USE_SSE2) + { + __m128i v_full = _mm_set1_epi8(-1), v_128 = _mm_set1_epi8(-128); + + for ( ; x <= len - 16; x += 16 ) + { + __m128i v_src = _mm_add_epi8(_mm_loadu_si128((const __m128i *)(src1 + x)), v_128); + __m128i v_mask1 = _mm_cmpgt_epi8(_mm_add_epi8(_mm_loadu_si128((const __m128i *)(src2 + x)), v_128), v_src); + __m128i v_mask2 = _mm_cmpgt_epi8(v_src, _mm_add_epi8(_mm_loadu_si128((const __m128i *)(src3 + x)), v_128)); + _mm_storeu_si128((__m128i *)(dst + x), _mm_andnot_si128(_mm_or_si128(v_mask1, v_mask2), v_full)); + } + } + + return x; + } +}; + +template <> +struct InRange_SSE +{ + int operator () (const schar * src1, const schar * src2, const schar * src3, + uchar * dst, int len) const + { + int x = 0; + + if (USE_SSE2) + { + __m128i v_full = _mm_set1_epi8(-1); + + for ( ; x <= len - 16; x += 16 ) + { + __m128i v_src = _mm_loadu_si128((const __m128i *)(src1 + x)); + __m128i v_mask1 = _mm_cmpgt_epi8(_mm_loadu_si128((const __m128i *)(src2 + x)), v_src); + __m128i v_mask2 = _mm_cmpgt_epi8(v_src, _mm_loadu_si128((const __m128i *)(src3 + x))); + _mm_storeu_si128((__m128i *)(dst + x), _mm_andnot_si128(_mm_or_si128(v_mask1, v_mask2), v_full)); + } + } + + return x; + } +}; + +template <> +struct InRange_SSE +{ + int operator () (const ushort * src1, const ushort * src2, const ushort * src3, + uchar * dst, int len) const + { + int x = 0; + + if (USE_SSE2) + { + __m128i v_zero = _mm_setzero_si128(), v_full = _mm_set1_epi16(-1), v_32768 = _mm_set1_epi16(-32768); + + for ( ; x <= len - 8; x += 8 ) + { + __m128i v_src = _mm_add_epi16(_mm_loadu_si128((const __m128i *)(src1 + x)), v_32768); + __m128i v_mask1 = _mm_cmpgt_epi16(_mm_add_epi16(_mm_loadu_si128((const __m128i *)(src2 + x)), v_32768), v_src); + __m128i v_mask2 = _mm_cmpgt_epi16(v_src, _mm_add_epi16(_mm_loadu_si128((const __m128i *)(src3 + x)), v_32768)); + __m128i v_res = _mm_andnot_si128(_mm_or_si128(v_mask1, v_mask2), v_full); + _mm_storel_epi64((__m128i *)(dst + x), _mm_packus_epi16(_mm_srli_epi16(v_res, 8), v_zero)); + } + } + + return x; + } +}; + +template <> +struct InRange_SSE +{ + int operator () (const short * src1, const short * src2, const short * src3, + uchar * dst, int len) const + { + int x = 0; + + if (USE_SSE2) + { + __m128i v_zero = _mm_setzero_si128(), v_full = _mm_set1_epi16(-1); + + for ( ; x <= len - 8; x += 8 ) + { + __m128i v_src = _mm_loadu_si128((const __m128i *)(src1 + x)); + __m128i v_mask1 = _mm_cmpgt_epi16(_mm_loadu_si128((const __m128i *)(src2 + x)), v_src); + __m128i v_mask2 = _mm_cmpgt_epi16(v_src, _mm_loadu_si128((const __m128i *)(src3 + x))); + __m128i v_res = _mm_andnot_si128(_mm_or_si128(v_mask1, v_mask2), v_full); + _mm_storel_epi64((__m128i *)(dst + x), _mm_packus_epi16(_mm_srli_epi16(v_res, 8), v_zero)); + } + } + + return x; + } +}; + +template <> +struct InRange_SSE +{ + int operator () (const int * src1, const int * src2, const int * src3, + uchar * dst, int len) const + { + int x = 0; + + if (USE_SSE2) + { + __m128i v_zero = _mm_setzero_si128(), v_full = _mm_set1_epi32(-1); + + for ( ; x <= len - 8; x += 8 ) + { + __m128i v_src = _mm_loadu_si128((const __m128i *)(src1 + x)); + __m128i v_res1 = _mm_or_si128(_mm_cmpgt_epi32(_mm_loadu_si128((const __m128i *)(src2 + x)), v_src), + _mm_cmpgt_epi32(v_src, _mm_loadu_si128((const __m128i *)(src3 + x)))); + + v_src = _mm_loadu_si128((const __m128i *)(src1 + x + 4)); + __m128i v_res2 = _mm_or_si128(_mm_cmpgt_epi32(_mm_loadu_si128((const __m128i *)(src2 + x + 4)), v_src), + _mm_cmpgt_epi32(v_src, _mm_loadu_si128((const __m128i *)(src3 + x + 4)))); + + __m128i v_res = _mm_packs_epi32(_mm_srli_epi32(_mm_andnot_si128(v_res1, v_full), 16), + _mm_srli_epi32(_mm_andnot_si128(v_res2, v_full), 16)); + _mm_storel_epi64((__m128i *)(dst + x), _mm_packus_epi16(v_res, v_zero)); + } + } + + return x; + } +}; + +template <> +struct InRange_SSE +{ + int operator () (const float * src1, const float * src2, const float * src3, + uchar * dst, int len) const + { + int x = 0; + + if (USE_SSE2) + { + __m128i v_zero = _mm_setzero_si128(); + + for ( ; x <= len - 8; x += 8 ) + { + __m128 v_src = _mm_loadu_ps(src1 + x); + __m128 v_res1 = _mm_and_ps(_mm_cmple_ps(_mm_loadu_ps(src2 + x), v_src), + _mm_cmple_ps(v_src, _mm_loadu_ps(src3 + x))); + + v_src = _mm_loadu_ps(src1 + x + 4); + __m128 v_res2 = _mm_and_ps(_mm_cmple_ps(_mm_loadu_ps(src2 + x + 4), v_src), + _mm_cmple_ps(v_src, _mm_loadu_ps(src3 + x + 4))); + + __m128i v_res1i = _mm_cvtps_epi32(v_res1), v_res2i = _mm_cvtps_epi32(v_res2); + __m128i v_res = _mm_packs_epi32(_mm_srli_epi32(v_res1i, 16), _mm_srli_epi32(v_res2i, 16)); + _mm_storel_epi64((__m128i *)(dst + x), _mm_packus_epi16(v_res, v_zero)); + } + } + + return x; + } +}; + +#endif + +template +static void inRange_(const T* src1, size_t step1, const T* src2, size_t step2, const T* src3, size_t step3, uchar* dst, size_t step, Size size) { @@ -2989,9 +3168,11 @@ inRange_(const T* src1, size_t step1, const T* src2, size_t step2, step2 /= sizeof(src2[0]); step3 /= sizeof(src3[0]); + InRange_SSE vop; + for( ; size.height--; src1 += step1, src2 += step2, src3 += step3, dst += step ) { - int x = 0; + int x = vop(src1, src2, src3, dst, size.width); #if CV_ENABLE_UNROLLED for( ; x <= size.width - 4; x += 4 ) { From e2b86974ae1d45ef3a6c9d32494f18cc0081ed1e Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 3 Jul 2014 21:28:54 +0400 Subject: [PATCH 047/136] SSE2 optimization of cv::patchNaNs --- modules/core/src/mathfuncs.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 7a02bd6d72..f6dd5b6588 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -2543,12 +2543,33 @@ void patchNaNs( InputOutputArray _a, double _val ) NAryMatIterator it(arrays, (uchar**)ptrs); size_t len = it.size*a.channels(); Cv32suf val; - val.f = (float)_val; + float fval = (float)_val; + val.f = fval; + +#if CV_SSE2 + __m128i v_mask1 = _mm_set1_epi32(0x7fffffff), v_mask2 = _mm_set1_epi32(0x7f800000); + __m128i v_val = _mm_set1_epi32(val.i); +#endif for( size_t i = 0; i < it.nplanes; i++, ++it ) { int* tptr = ptrs[0]; - for( size_t j = 0; j < len; j++ ) + size_t j = 0; + +#if CV_SSE2 + if (USE_SSE2) + { + for ( ; j < len; j += 4) + { + __m128i v_src = _mm_loadu_si128((__m128i const *)(tptr + j)); + __m128i v_cmp_mask = _mm_cmplt_epi32(v_mask2, _mm_and_si128(v_src, v_mask1)); + __m128i v_res = _mm_or_si128(_mm_andnot_si128(v_cmp_mask, v_src), _mm_and_si128(v_cmp_mask, v_val)); + _mm_storeu_si128((__m128i *)(tptr + j), v_res); + } + } +#endif + + for( ; j < len; j++ ) if( (tptr[j] & 0x7fffffff) > 0x7f800000 ) tptr[j] = val.i; } From 90dce8431419e144665e0193c4ca36c9f45c1e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beat=20K=C3=BCng?= Date: Sat, 5 Jul 2014 09:27:11 +0200 Subject: [PATCH 048/136] imgproc: fix compiler error for gcc 4.8 this bug was introduced in a73809e6. --- modules/imgproc/src/morph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index a621a6e403..4f696b4209 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1257,7 +1257,7 @@ static bool IPPMorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kerne } #undef IPP_MORPH_CASE -#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 8 +#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 8 return false; /// It disables false positive warning in GCC 4.8 and further #endif } From 4286f6038716fd4cee6b4cacd3ef6ac42d84a906 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Fri, 4 Jul 2014 18:48:15 +0400 Subject: [PATCH 049/136] Extract imgcodecs module from highgui --- 3rdparty/readme.txt | 10 +- apps/traincascade/CMakeLists.txt | 2 +- apps/traincascade/imagestorage.cpp | 3 +- apps/traincascade/imagestorage.h | 3 - cmake/OpenCVModule.cmake | 10 +- doc/CMakeLists.txt | 2 +- doc/check_docs.py | 2 + doc/conf.py | 12 +- doc/opencv_cheatsheet.tex | 6 +- .../py_video_display/py_video_display.rst | 2 +- .../discrete_fourier_transform.rst | 2 +- .../how_to_scan_images/how_to_scan_images.rst | 12 +- .../interoperability_with_OpenCV_1.rst | 10 +- .../mat_the_basic_image_container.rst | 2 +- .../table_of_content_core.rst | 3 - .../display_image/display_image.rst | 16 +- .../how_to_write_a_tutorial.rst | 8 +- .../load_save_image/load_save_image.rst | 12 +- .../ml/non_linear_svms/non_linear_svms.rst | 2 +- include/opencv2/opencv.hpp | 1 + modules/calib3d/perf/perf_precomp.hpp | 2 +- modules/calib3d/test/test_precomp.hpp | 2 +- modules/features2d/perf/perf_precomp.hpp | 2 +- .../test/test_descriptors_regression.cpp | 1 - modules/features2d/test/test_precomp.hpp | 2 +- modules/highgui/CMakeLists.txt | 56 +----- modules/highgui/doc/highgui.rst | 3 +- ...ideo.rst => reading_and_writing_video.rst} | 187 +----------------- modules/highgui/include/opencv2/highgui.hpp | 47 ----- .../include/opencv2/highgui/highgui_c.h | 61 ------ modules/highgui/perf/perf_precomp.hpp | 1 + modules/highgui/src/precomp.hpp | 1 + modules/highgui/test/test_precomp.hpp | 1 + modules/imgcodecs/CMakeLists.txt | 131 ++++++++++++ modules/imgcodecs/doc/imgcodecs.rst | 10 + .../doc/reading_and_writing_images.rst | 187 ++++++++++++++++++ .../imgcodecs/include/opencv2/imgcodecs.hpp | 91 +++++++++ .../include/opencv2/imgcodecs/imgcodecs.hpp | 48 +++++ .../include/opencv2/imgcodecs/imgcodecs_c.h | 117 +++++++++++ .../imgcodecs/include/opencv2/imgcodecs/ios.h | 48 +++++ modules/imgcodecs/perf/perf_main.cpp | 3 + modules/imgcodecs/perf/perf_precomp.hpp | 19 ++ .../{highgui => imgcodecs}/src/bitstrm.cpp | 0 .../{highgui => imgcodecs}/src/bitstrm.hpp | 0 .../{highgui => imgcodecs}/src/grfmt_base.cpp | 0 .../{highgui => imgcodecs}/src/grfmt_base.hpp | 0 .../{highgui => imgcodecs}/src/grfmt_bmp.cpp | 0 .../{highgui => imgcodecs}/src/grfmt_bmp.hpp | 0 .../{highgui => imgcodecs}/src/grfmt_exr.cpp | 0 .../{highgui => imgcodecs}/src/grfmt_exr.hpp | 0 .../{highgui => imgcodecs}/src/grfmt_hdr.cpp | 0 .../{highgui => imgcodecs}/src/grfmt_hdr.hpp | 0 .../{highgui => imgcodecs}/src/grfmt_jpeg.cpp | 0 .../{highgui => imgcodecs}/src/grfmt_jpeg.hpp | 0 .../src/grfmt_jpeg2000.cpp | 0 .../src/grfmt_jpeg2000.hpp | 0 .../{highgui => imgcodecs}/src/grfmt_png.cpp | 0 .../{highgui => imgcodecs}/src/grfmt_png.hpp | 0 .../{highgui => imgcodecs}/src/grfmt_pxm.cpp | 0 .../{highgui => imgcodecs}/src/grfmt_pxm.hpp | 0 .../src/grfmt_sunras.cpp | 0 .../src/grfmt_sunras.hpp | 0 .../{highgui => imgcodecs}/src/grfmt_tiff.cpp | 0 .../{highgui => imgcodecs}/src/grfmt_tiff.hpp | 0 .../{highgui => imgcodecs}/src/grfmt_webp.cpp | 0 .../{highgui => imgcodecs}/src/grfmt_webp.hpp | 0 modules/{highgui => imgcodecs}/src/grfmts.hpp | 0 .../src/ios_conversions.mm | 0 .../{highgui => imgcodecs}/src/loadsave.cpp | 0 modules/imgcodecs/src/precomp.hpp | 87 ++++++++ modules/{highgui => imgcodecs}/src/rgbe.cpp | 0 modules/{highgui => imgcodecs}/src/rgbe.hpp | 0 modules/{highgui => imgcodecs}/src/utils.cpp | 0 modules/{highgui => imgcodecs}/src/utils.hpp | 0 .../test/test_drawing.cpp | 1 - .../test/test_grfmt.cpp | 1 - modules/imgcodecs/test/test_main.cpp | 3 + modules/imgcodecs/test/test_precomp.hpp | 20 ++ modules/imgproc/perf/perf_precomp.hpp | 2 +- modules/imgproc/test/test_precomp.hpp | 2 +- modules/java/CMakeLists.txt | 2 +- modules/java/generator/rst_parser.py | 2 +- .../generator/src/java/android+Utils.java | 4 +- modules/nonfree/perf/perf_precomp.hpp | 2 +- modules/objdetect/test/test_precomp.hpp | 2 +- modules/optim/test/test_denoise_tvl1.cpp | 1 - modules/optim/test/test_precomp.hpp | 1 + modules/photo/perf/perf_precomp.hpp | 2 +- modules/photo/test/test_precomp.hpp | 2 +- modules/python/CMakeLists.txt | 3 +- modules/python/src2/hdr_parser.py | 1 + modules/shape/test/test_precomp.hpp | 2 +- modules/stitching/perf/perf_stich.cpp | 2 +- modules/stitching/test/test_precomp.hpp | 2 +- modules/ts/CMakeLists.txt | 2 +- modules/ts/include/opencv2/ts/cuda_perf.hpp | 2 +- modules/ts/include/opencv2/ts/cuda_test.hpp | 1 + modules/ts/include/opencv2/ts/ocl_test.hpp | 1 + modules/video/perf/perf_precomp.hpp | 2 +- modules/video/test/test_precomp.hpp | 2 +- samples/android/CMakeLists.txt | 4 +- samples/android/hello-android/main.cpp | 1 + samples/cpp/3calibration.cpp | 1 + samples/cpp/CMakeLists.txt | 2 +- samples/cpp/bagofwords_classification.cpp | 1 + samples/cpp/calibration.cpp | 1 + samples/cpp/cloning_demo.cpp | 1 + samples/cpp/cloning_gui.cpp | 1 + samples/cpp/connected_components.cpp | 1 + samples/cpp/create_mask.cpp | 1 + samples/cpp/demhist.cpp | 1 + samples/cpp/descriptor_extractor_matcher.cpp | 1 + samples/cpp/dft.cpp | 1 + samples/cpp/distrans.cpp | 1 + samples/cpp/edge.cpp | 1 + samples/cpp/facedetect.cpp | 1 + samples/cpp/ffilldemo.cpp | 1 + samples/cpp/fitellipse.cpp | 1 + samples/cpp/grabcut.cpp | 1 + samples/cpp/houghcircles.cpp | 1 + samples/cpp/houghlines.cpp | 1 + samples/cpp/image.cpp | 1 + samples/cpp/image_alignment.cpp | 1 + samples/cpp/imagelist_creator.cpp | 1 + samples/cpp/inpaint.cpp | 1 + samples/cpp/lsd_lines.cpp | 1 + samples/cpp/morphology2.cpp | 1 + samples/cpp/npr_demo.cpp | 1 + samples/cpp/pca.cpp | 1 + samples/cpp/select3dobj.cpp | 1 + samples/cpp/shape_example.cpp | 1 + samples/cpp/shape_transformation.cpp | 1 + samples/cpp/simpleflow_demo.cpp | 1 + samples/cpp/squares.cpp | 1 + samples/cpp/starter_imagelist.cpp | 1 + samples/cpp/starter_video.cpp | 1 + samples/cpp/stereo_calib.cpp | 1 + samples/cpp/stereo_match.cpp | 1 + samples/cpp/stitching.cpp | 1 + samples/cpp/stitching_detailed.cpp | 1 + samples/cpp/textdetection.cpp | 1 + .../HighGUI/AddingImagesTrackbar.cpp | 1 + .../HighGUI/BasicLinearTransformsTrackbar.cpp | 1 + .../Histograms_Matching/EqualizeHist_Demo.cpp | 1 + .../MatchTemplate_Demo.cpp | 1 + .../calcBackProject_Demo1.cpp | 1 + .../calcBackProject_Demo2.cpp | 1 + .../Histograms_Matching/calcHist_Demo.cpp | 1 + .../Histograms_Matching/compareHist_Demo.cpp | 1 + .../tutorial_code/ImgProc/AddingImages.cpp | 1 + .../ImgProc/BasicLinearTransforms.cpp | 1 + .../tutorial_code/ImgProc/Morphology_1.cpp | 1 + .../tutorial_code/ImgProc/Morphology_2.cpp | 1 + .../cpp/tutorial_code/ImgProc/Pyramids.cpp | 1 + .../cpp/tutorial_code/ImgProc/Smoothing.cpp | 1 + .../cpp/tutorial_code/ImgProc/Threshold.cpp | 1 + .../ImgTrans/CannyDetector_Demo.cpp | 1 + .../ImgTrans/Geometric_Transforms_Demo.cpp | 1 + .../ImgTrans/HoughCircle_Demo.cpp | 1 + .../ImgTrans/HoughLines_Demo.cpp | 1 + .../tutorial_code/ImgTrans/Laplace_Demo.cpp | 1 + .../cpp/tutorial_code/ImgTrans/Remap_Demo.cpp | 1 + .../cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp | 1 + .../ImgTrans/copyMakeBorder_demo.cpp | 1 + .../tutorial_code/ImgTrans/filter2D_demo.cpp | 1 + .../ShapeDescriptors/findContours_demo.cpp | 1 + .../generalContours_demo1.cpp | 1 + .../generalContours_demo2.cpp | 1 + .../ShapeDescriptors/hull_demo.cpp | 1 + .../ShapeDescriptors/moments_demo.cpp | 1 + .../TrackingMotion/cornerDetector_Demo.cpp | 1 + .../TrackingMotion/cornerHarris_Demo.cpp | 1 + .../TrackingMotion/cornerSubPix_Demo.cpp | 1 + .../goodFeaturesToTrack_Demo.cpp | 1 + .../camera_calibration/camera_calibration.cpp | 1 + .../calib3d/stereoBM/SBM_Sample.cpp | 1 + .../discrete_fourier_transform.cpp | 1 + .../how_to_scan_images/how_to_scan_images.cpp | 1 + .../interoperability_with_OpenCV_1.cpp | 2 + .../mat_mask_operations.cpp | 1 + .../features2D/SURF_FlannMatcher.cpp | 1 + .../features2D/SURF_Homography.cpp | 1 + .../features2D/SURF_descriptor.cpp | 1 + .../features2D/SURF_detector.cpp | 1 + .../gpu-basics-similarity.cpp | 2 +- .../display_image/display_image.cpp | 1 + .../introduction_windows_vs.cpp | 1 + .../introduction_to_svm.cpp | 1 + .../ml/non_linear_svms/non_linear_svms.cpp | 1 + .../photo/hdr_imaging/hdr_imaging.cpp | 1 + samples/cpp/tutorial_code/video/bg_sub.cpp | 1 + samples/cpp/tvl1_optical_flow.cpp | 1 + samples/cpp/ufacedetect.cpp | 1 + samples/cpp/watershed.cpp | 1 + samples/directx/CMakeLists.txt | 2 +- samples/directx/d3d_base.inl.hpp | 1 + samples/gpu/CMakeLists.txt | 2 +- samples/tapi/CMakeLists.txt | 2 +- samples/tapi/clahe.cpp | 1 + samples/tapi/hog.cpp | 1 + samples/tapi/pyrlk_optical_flow.cpp | 1 + samples/tapi/squares.cpp | 1 + samples/tapi/surf_matcher.cpp | 1 + samples/tapi/tvl1_optical_flow.cpp | 1 + 204 files changed, 968 insertions(+), 439 deletions(-) rename modules/highgui/doc/{reading_and_writing_images_and_video.rst => reading_and_writing_video.rst} (63%) create mode 100644 modules/imgcodecs/CMakeLists.txt create mode 100644 modules/imgcodecs/doc/imgcodecs.rst create mode 100644 modules/imgcodecs/doc/reading_and_writing_images.rst create mode 100644 modules/imgcodecs/include/opencv2/imgcodecs.hpp create mode 100644 modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs.hpp create mode 100644 modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h create mode 100644 modules/imgcodecs/include/opencv2/imgcodecs/ios.h create mode 100644 modules/imgcodecs/perf/perf_main.cpp create mode 100644 modules/imgcodecs/perf/perf_precomp.hpp rename modules/{highgui => imgcodecs}/src/bitstrm.cpp (100%) rename modules/{highgui => imgcodecs}/src/bitstrm.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_base.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_base.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_bmp.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_bmp.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_exr.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_exr.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_hdr.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_hdr.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_jpeg.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_jpeg.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_jpeg2000.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_jpeg2000.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_png.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_png.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_pxm.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_pxm.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_sunras.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_sunras.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_tiff.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_tiff.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_webp.cpp (100%) rename modules/{highgui => imgcodecs}/src/grfmt_webp.hpp (100%) rename modules/{highgui => imgcodecs}/src/grfmts.hpp (100%) rename modules/{highgui => imgcodecs}/src/ios_conversions.mm (100%) rename modules/{highgui => imgcodecs}/src/loadsave.cpp (100%) create mode 100644 modules/imgcodecs/src/precomp.hpp rename modules/{highgui => imgcodecs}/src/rgbe.cpp (100%) rename modules/{highgui => imgcodecs}/src/rgbe.hpp (100%) rename modules/{highgui => imgcodecs}/src/utils.cpp (100%) rename modules/{highgui => imgcodecs}/src/utils.hpp (100%) rename modules/{highgui => imgcodecs}/test/test_drawing.cpp (99%) rename modules/{highgui => imgcodecs}/test/test_grfmt.cpp (99%) create mode 100644 modules/imgcodecs/test/test_main.cpp create mode 100644 modules/imgcodecs/test/test_precomp.hpp diff --git a/3rdparty/readme.txt b/3rdparty/readme.txt index ca46fbd576..64e2563a85 100644 --- a/3rdparty/readme.txt +++ b/3rdparty/readme.txt @@ -1,5 +1,5 @@ This folder contains libraries and headers of a few very popular still image codecs -used by highgui module. +used by imgcodecs module. The libraries and headers are preferably to build Win32 and Win64 versions of OpenCV. On UNIX systems all the libraries are automatically detected by configure script. In order to use these versions of libraries instead of system ones on UNIX systems you @@ -11,7 +11,7 @@ libjpeg 8d (8.4) - The Independent JPEG Group's JPEG software. See IGJ home page http://www.ijg.org for details and links to the source code - HAVE_JPEG preprocessor flag must be set to make highgui use libjpeg. + HAVE_JPEG preprocessor flag must be set to make imgcodecs use libjpeg. On UNIX systems configure script takes care of it. ------------------------------------------------------------------------------------ libpng 1.5.12 - Portable Network Graphics library. @@ -19,7 +19,7 @@ libpng 1.5.12 - Portable Network Graphics library. See libpng home page http://www.libpng.org for details and links to the source code - HAVE_PNG preprocessor flag must be set to make highgui use libpng. + HAVE_PNG preprocessor flag must be set to make imgcodecs use libpng. On UNIX systems configure script takes care of it. ------------------------------------------------------------------------------------ libtiff 4.0.2 - Tag Image File Format (TIFF) Software @@ -28,7 +28,7 @@ libtiff 4.0.2 - Tag Image File Format (TIFF) Software See libtiff home page http://www.remotesensing.org/libtiff/ for details and links to the source code - HAVE_TIFF preprocessor flag must be set to make highgui use libtiff. + HAVE_TIFF preprocessor flag must be set to make imgcodecs use libtiff. On UNIX systems configure script takes care of it. In this build support for ZIP (LZ77 compression) is turned on. ------------------------------------------------------------------------------------ @@ -37,7 +37,7 @@ zlib 1.2.7 - General purpose LZ77 compression library See zlib home page http://www.zlib.net for details and links to the source code - No preprocessor definition is needed to make highgui use this library - + No preprocessor definition is needed to make imgcodecs use this library - it is included automatically if either libpng or libtiff are used. ------------------------------------------------------------------------------------ jasper-1.900.1 - JasPer is a collection of software diff --git a/apps/traincascade/CMakeLists.txt b/apps/traincascade/CMakeLists.txt index e560ed815c..c815303d49 100644 --- a/apps/traincascade/CMakeLists.txt +++ b/apps/traincascade/CMakeLists.txt @@ -1,4 +1,4 @@ -set(OPENCV_TRAINCASCADE_DEPS opencv_core opencv_ml opencv_imgproc opencv_photo opencv_objdetect opencv_highgui opencv_calib3d opencv_video opencv_features2d) +set(OPENCV_TRAINCASCADE_DEPS opencv_core opencv_ml opencv_imgproc opencv_photo opencv_objdetect opencv_imgcodecs opencv_highgui opencv_calib3d opencv_video opencv_features2d) ocv_check_dependencies(${OPENCV_TRAINCASCADE_DEPS}) if(NOT OCV_DEPENDENCIES_FOUND) diff --git a/apps/traincascade/imagestorage.cpp b/apps/traincascade/imagestorage.cpp index e69a7df1ad..2f791240e4 100644 --- a/apps/traincascade/imagestorage.cpp +++ b/apps/traincascade/imagestorage.cpp @@ -1,6 +1,7 @@ #include "opencv2/core.hpp" +#include "opencv2/core/core_c.h" #include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include "imagestorage.h" #include diff --git a/apps/traincascade/imagestorage.h b/apps/traincascade/imagestorage.h index fb68e25cb2..38ca52a8b5 100644 --- a/apps/traincascade/imagestorage.h +++ b/apps/traincascade/imagestorage.h @@ -1,9 +1,6 @@ #ifndef _OPENCV_IMAGESTORAGE_H_ #define _OPENCV_IMAGESTORAGE_H_ -#include "highgui.h" - - class CvCascadeImageReader { diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index e6fa199119..6618ca8834 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -704,8 +704,8 @@ function(ocv_add_perf_tests) if(BUILD_PERF_TESTS AND EXISTS "${perf_path}") __ocv_parse_test_sources(PERF ${ARGN}) - # opencv_highgui is required for imread/imwrite - set(perf_deps ${the_module} opencv_ts opencv_highgui ${OPENCV_PERF_${the_module}_DEPS} ${OPENCV_MODULE_opencv_ts_DEPS}) + # opencv_imgcodecs is required for imread/imwrite + set(perf_deps ${the_module} opencv_ts opencv_imgcodecs ${OPENCV_PERF_${the_module}_DEPS} ${OPENCV_MODULE_opencv_ts_DEPS}) ocv_check_dependencies(${perf_deps}) if(OCV_DEPENDENCIES_FOUND) @@ -757,8 +757,8 @@ function(ocv_add_accuracy_tests) if(BUILD_TESTS AND EXISTS "${test_path}") __ocv_parse_test_sources(TEST ${ARGN}) - # opencv_highgui is required for imread/imwrite - set(test_deps ${the_module} opencv_ts opencv_highgui ${OPENCV_TEST_${the_module}_DEPS} ${OPENCV_MODULE_opencv_ts_DEPS}) + # opencv_imgcodecs is required for imread/imwrite + set(test_deps ${the_module} opencv_ts opencv_imgcodecs opencv_highgui ${OPENCV_TEST_${the_module}_DEPS} ${OPENCV_MODULE_opencv_ts_DEPS}) ocv_check_dependencies(${test_deps}) if(OCV_DEPENDENCIES_FOUND) @@ -811,7 +811,7 @@ function(ocv_add_samples) string(REGEX REPLACE "^opencv_" "" module_id ${the_module}) if(BUILD_EXAMPLES AND EXISTS "${samples_path}") - set(samples_deps ${the_module} ${OPENCV_MODULE_${the_module}_DEPS} opencv_highgui ${ARGN}) + set(samples_deps ${the_module} ${OPENCV_MODULE_${the_module}_DEPS} opencv_imgcodecs opencv_highgui ${ARGN}) ocv_check_dependencies(${samples_deps}) if(OCV_DEPENDENCIES_FOUND) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 1c284539ee..33fd9957d3 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -33,7 +33,7 @@ if(BUILD_DOCS AND HAVE_SPHINX) endif() endforeach() - set(FIXED_ORDER_MODULES core imgproc highgui video calib3d features2d objdetect ml flann photo stitching nonfree contrib legacy) + set(FIXED_ORDER_MODULES core imgproc imgcodecs highgui video calib3d features2d objdetect ml flann photo stitching nonfree contrib legacy) list(REMOVE_ITEM BASE_MODULES ${FIXED_ORDER_MODULES}) diff --git a/doc/check_docs.py b/doc/check_docs.py index 0290fc70f4..c0e519b29c 100755 --- a/doc/check_docs.py +++ b/doc/check_docs.py @@ -14,6 +14,7 @@ opencv_hdr_list = [ "../modules/video/include/opencv2/video/tracking.hpp", "../modules/video/include/opencv2/video/background_segm.hpp", "../modules/objdetect/include/opencv2/objdetect.hpp", +"../modules/imgcodecs/include/opencv2/imgcodecs.hpp", "../modules/highgui/include/opencv2/highgui.hpp", ] @@ -24,6 +25,7 @@ opencv_module_list = [ "features2d", "video", "objdetect", +"imgcodecs", "highgui", "ml" ] diff --git a/doc/conf.py b/doc/conf.py index a0c231c3b5..c17dfb618f 100755 --- a/doc/conf.py +++ b/doc/conf.py @@ -302,14 +302,16 @@ man_pages = [ extlinks = { 'basicstructures' : ('http://docs.opencv.org/modules/core/doc/basic_structures.html#%s', None), 'oldbasicstructures' : ('http://docs.opencv.org/modules/core/doc/old_basic_structures.html#%s', None), - 'readwriteimagevideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None), + 'readwriteimage' : ('http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html#%s', None), + 'readwritevideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_video.html#%s', None), 'operationsonarrays' : ('http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#%s', None), 'utilitysystemfunctions' : ('http://docs.opencv.org/modules/core/doc/utility_and_system_functions_and_macros.html#%s', None), 'imgprocfilter' : ('http://docs.opencv.org/modules/imgproc/doc/filtering.html#%s', None), 'svms' : ('http://docs.opencv.org/modules/ml/doc/support_vector_machines.html#%s', None), 'drawingfunc' : ('http://docs.opencv.org/modules/core/doc/drawing_functions.html#%s', None), 'xmlymlpers' : ('http://docs.opencv.org/modules/core/doc/xml_yaml_persistence.html#%s', None), - 'hgvideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None), + 'rwimg' : ('http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html#%s', None), + 'hgvideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_video.html#%s', None), 'gpuinit' : ('http://docs.opencv.org/modules/gpu/doc/initalization_and_information.html#%s', None), 'gpudatastructure' : ('http://docs.opencv.org/modules/gpu/doc/data_structures.html#%s', None), 'gpuopmatrices' : ('http://docs.opencv.org/modules/gpu/doc/operations_on_matrices.html#%s', None), @@ -329,8 +331,8 @@ extlinks = { 'how_to_contribute' : ('http://code.opencv.org/projects/opencv/wiki/How_to_contribute/%s', None), 'cvt_color' : ('http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html?highlight=cvtcolor#cvtcolor%s', None), - 'imread' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imread#imread%s', None), - 'imwrite' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imwrite#imwrite%s', None), + 'imread' : ('http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html?highlight=imread#imread%s', None), + 'imwrite' : ('http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html?highlight=imwrite#imwrite%s', None), 'imshow' : ('http://docs.opencv.org/modules/highgui/doc/user_interface.html?highlight=imshow#imshow%s', None), 'named_window' : ('http://docs.opencv.org/modules/highgui/doc/user_interface.html?highlight=namedwindow#namedwindow%s', None), 'wait_key' : ('http://docs.opencv.org/modules/highgui/doc/user_interface.html?highlight=waitkey#waitkey%s', None), @@ -418,7 +420,7 @@ extlinks = { 'background_subtractor' : ('http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=backgroundsubtractor#backgroundsubtractor%s', None), 'background_subtractor_mog' : ('http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=backgroundsubtractorMOG#backgroundsubtractormog%s', None), 'background_subtractor_mog_two' : ('http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=backgroundsubtractorMOG2#backgroundsubtractormog2%s', None), - 'video_capture' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=videocapture#videocapture%s', None), + 'video_capture' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_video.html?highlight=videocapture#videocapture%s', None), 'ippa_convert': ('http://docs.opencv.org/modules/core/doc/ipp_async_converters.html#%s', None), 'ptr':('http://docs.opencv.org/modules/core/doc/basic_structures.html?highlight=Ptr#Ptr%s', None) } diff --git a/doc/opencv_cheatsheet.tex b/doc/opencv_cheatsheet.tex index d6c339916d..01d5c275d9 100644 --- a/doc/opencv_cheatsheet.tex +++ b/doc/opencv_cheatsheet.tex @@ -522,9 +522,9 @@ samples on what are the contours and how to use them. \begin{tabbing} \textbf{Wr}\=\textbf{iting and reading raster images}\\ -\texttt{\href{http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html\#imwrite}{imwrite}("myimage.jpg", image);}\\ -\texttt{Mat image\_color\_copy = \href{http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html\#imread}{imread}("myimage.jpg", 1);}\\ -\texttt{Mat image\_grayscale\_copy = \href{http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html\#imread}{imread}("myimage.jpg", 0);}\\ +\texttt{\href{http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html\#imwrite}{imwrite}("myimage.jpg", image);}\\ +\texttt{Mat image\_color\_copy = \href{http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html\#imread}{imread}("myimage.jpg", 1);}\\ +\texttt{Mat image\_grayscale\_copy = \href{http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html\#imread}{imread}("myimage.jpg", 0);}\\ \end{tabbing} \emph{The functions can read/write images in the following formats: \textbf{BMP (.bmp), JPEG (.jpg, .jpeg), TIFF (.tif, .tiff), PNG (.png), PBM/PGM/PPM (.p?m), Sun Raster (.sr), JPEG 2000 (.jp2)}. Every format supports 8-bit, 1- or 3-channel images. Some formats (PNG, JPEG 2000) support 16 bits per channel.} diff --git a/doc/py_tutorials/py_gui/py_video_display/py_video_display.rst b/doc/py_tutorials/py_gui/py_video_display/py_video_display.rst index 56946bc5db..5bdf4fcb87 100644 --- a/doc/py_tutorials/py_gui/py_video_display/py_video_display.rst +++ b/doc/py_tutorials/py_gui/py_video_display/py_video_display.rst @@ -46,7 +46,7 @@ To capture a video, you need to create a **VideoCapture** object. Its argument c Sometimes, ``cap`` may not have initialized the capture. In that case, this code shows error. You can check whether it is initialized or not by the method **cap.isOpened()**. If it is True, OK. Otherwise open it using **cap.open()**. -You can also access some of the features of this video using **cap.get(propId)** method where propId is a number from 0 to 18. Each number denotes a property of the video (if it is applicable to that video) and full details can be seen here: `Property Identifier `_. Some of these values can be modified using **cap.set(propId, value)**. Value is the new value you want. +You can also access some of the features of this video using **cap.get(propId)** method where propId is a number from 0 to 18. Each number denotes a property of the video (if it is applicable to that video) and full details can be seen here: `Property Identifier `_. Some of these values can be modified using **cap.set(propId, value)**. Value is the new value you want. For example, I can check the frame width and height by ``cap.get(3)`` and ``cap.get(4)``. It gives me 640x480 by default. But I want to modify it to 320x240. Just use ``ret = cap.set(3,320)`` and ``ret = cap.set(4,240)``. diff --git a/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.rst b/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.rst index b7cf446687..ca3d75dca3 100644 --- a/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.rst +++ b/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.rst @@ -25,7 +25,7 @@ Here's a sample usage of :operationsonarrays:`dft() ` : :language: cpp :linenos: :tab-width: 4 - :lines: 1-3, 5, 19-20, 23-78 + :lines: 1-4, 6, 20-21, 24-79 Explanation =========== diff --git a/doc/tutorials/core/how_to_scan_images/how_to_scan_images.rst b/doc/tutorials/core/how_to_scan_images/how_to_scan_images.rst index b6a18fee88..6162985ddb 100644 --- a/doc/tutorials/core/how_to_scan_images/how_to_scan_images.rst +++ b/doc/tutorials/core/how_to_scan_images/how_to_scan_images.rst @@ -45,7 +45,7 @@ The final argument is optional. If given the image will be loaded in gray scale .. literalinclude:: ../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp :language: cpp :tab-width: 4 - :lines: 48-60 + :lines: 49-61 Here we first use the C++ *stringstream* class to convert the third command line argument from text to an integer format. Then we use a simple look and the upper formula to calculate the lookup table. No OpenCV specific stuff here. @@ -99,7 +99,7 @@ When it comes to performance you cannot beat the classic C style operator[] (poi .. literalinclude:: ../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp :language: cpp :tab-width: 4 - :lines: 125-152 + :lines: 126-153 Here we basically just acquire a pointer to the start of each row and go through it until it ends. In the special case that the matrix is stored in a continues manner we only need to request the pointer a single time and go all the way to the end. We need to look out for color images: we have three channels so we need to pass through three times more items in each row. @@ -122,7 +122,7 @@ In case of the efficient way making sure that you pass through the right amount .. literalinclude:: ../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp :language: cpp :tab-width: 4 - :lines: 154-182 + :lines: 155-183 In case of color images we have three uchar items per column. This may be considered a short vector of uchar items, that has been baptized in OpenCV with the *Vec3b* name. To access the n-th sub column we use simple operator[] access. It's important to remember that OpenCV iterators go through the columns and automatically skip to the next row. Therefore in case of color images if you use a simple *uchar* iterator you'll be able to access only the blue channel values. @@ -134,7 +134,7 @@ The final method isn't recommended for scanning. It was made to acquire or modif .. literalinclude:: ../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp :language: cpp :tab-width: 4 - :lines: 184-216 + :lines: 185-217 The functions takes your input type and coordinates and calculates on the fly the address of the queried item. Then returns a reference to that. This may be a constant when you *get* the value and non-constant when you *set* the value. As a safety step in **debug mode only*** there is performed a check that your input coordinates are valid and does exist. If this isn't the case you'll get a nice output message of this on the standard error output stream. Compared to the efficient way in release mode the only difference in using this is that for every element of the image you'll get a new row pointer for what we use the C operator[] to acquire the column element. @@ -148,14 +148,14 @@ This is a bonus method of achieving lookup table modification in an image. Becau .. literalinclude:: ../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp :language: cpp :tab-width: 4 - :lines: 107-110 + :lines: 108-111 Finally call the function (I is our input image and J the output one): .. literalinclude:: ../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp :language: cpp :tab-width: 4 - :lines: 115 + :lines: 116 Performance Difference ====================== diff --git a/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.rst b/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.rst index 9285509b07..9d4189363f 100644 --- a/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.rst +++ b/doc/tutorials/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.rst @@ -77,7 +77,7 @@ Now that you have the basics done :download:`here's <../../../../samples/cpp/tut :language: cpp :linenos: :tab-width: 4 - :lines: 1-9, 22-25, 27-44 + :lines: 1-10, 23-26, 29-46 Here you can observe that with the new structure we have no pointer problems, although it is possible to use the old functions and in the end just transform the result to a *Mat* object. @@ -85,7 +85,7 @@ Here you can observe that with the new structure we have no pointer problems, al :language: cpp :linenos: :tab-width: 4 - :lines: 46-51 + :lines: 48-53 Because, we want to mess around with the images luma component we first convert from the default RGB to the YUV color space and then split the result up into separate planes. Here the program splits: in the first example it processes each plane using one of the three major image scanning algorithms in OpenCV (C [] operator, iterator, individual element access). In a second variant we add to the image some Gaussian noise and then mix together the channels according to some formula. @@ -95,7 +95,7 @@ The scanning version looks like: :language: cpp :linenos: :tab-width: 4 - :lines: 55-75 + :lines: 57-77 Here you can observe that we may go through all the pixels of an image in three fashions: an iterator, a C pointer and an individual element access style. You can read a more in-depth description of these in the :ref:`howToScanImagesOpenCV` tutorial. Converting from the old function names is easy. Just remove the cv prefix and use the new *Mat* data structure. Here's an example of this by using the weighted addition function: @@ -103,7 +103,7 @@ Here you can observe that we may go through all the pixels of an image in three :language: cpp :linenos: :tab-width: 4 - :lines: 79-112 + :lines: 81-113 As you may observe the *planes* variable is of type *Mat*. However, converting from *Mat* to *IplImage* is easy and made automatically with a simple assignment operator. @@ -111,7 +111,7 @@ As you may observe the *planes* variable is of type *Mat*. However, converting f :language: cpp :linenos: :tab-width: 4 - :lines: 115-127 + :lines: 117-129 The new *imshow* highgui function accepts both the *Mat* and *IplImage* data structures. Compile and run the program and if the first image below is your input you may get either the first or second as output: diff --git a/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.rst b/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.rst index 736aceb02d..67517d32f1 100644 --- a/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.rst +++ b/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.rst @@ -86,7 +86,7 @@ Each of the building components has their own valid domains. This leads to the d Creating a *Mat* object explicitly ================================== -In the :ref:`Load_Save_Image` tutorial you have already learned how to write a matrix to an image file by using the :readwriteimagevideo:`imwrite() ` function. However, for debugging purposes it's much more convenient to see the actual values. You can do this using the << operator of *Mat*. Be aware that this only works for two dimensional matrices. +In the :ref:`Load_Save_Image` tutorial you have already learned how to write a matrix to an image file by using the :readwriteimage:`imwrite() ` function. However, for debugging purposes it's much more convenient to see the actual values. You can do this using the << operator of *Mat*. Be aware that this only works for two dimensional matrices. Although *Mat* works really well as an image container, it is also a general matrix class. Therefore, it is possible to create and manipulate multidimensional matrices. You can create a Mat object in multiple ways: diff --git a/doc/tutorials/core/table_of_content_core/table_of_content_core.rst b/doc/tutorials/core/table_of_content_core/table_of_content_core.rst index 1fcf4ee2b1..ea5756da23 100644 --- a/doc/tutorials/core/table_of_content_core/table_of_content_core.rst +++ b/doc/tutorials/core/table_of_content_core/table_of_content_core.rst @@ -200,7 +200,6 @@ Here you will learn the about the basic building blocks of the library. A must r :height: 90pt :width: 90pt - =============== ====================================================== + .. tabularcolumns:: m{100pt} m{300pt} .. cssclass:: toctableopencv @@ -221,8 +220,6 @@ Here you will learn the about the basic building blocks of the library. A must r :width: 90pt .. |Author_ElenaG| unicode:: Elena U+0020 Gvozdeva - =============== ====================================================== - .. raw:: latex \pagebreak diff --git a/doc/tutorials/introduction/display_image/display_image.rst b/doc/tutorials/introduction/display_image/display_image.rst index 6b30b7c295..fc6e6ca5cc 100644 --- a/doc/tutorials/introduction/display_image/display_image.rst +++ b/doc/tutorials/introduction/display_image/display_image.rst @@ -39,28 +39,28 @@ You'll almost always end up using the: .. literalinclude:: ../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp :language: cpp :tab-width: 4 - :lines: 1-3 + :lines: 1-4 We also include the *iostream* to facilitate console line output and input. To avoid data structure and function name conflicts with other libraries, OpenCV has its own namespace: *cv*. To avoid the need appending prior each of these the *cv::* keyword you can import the namespace in the whole file by using the lines: .. literalinclude:: ../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp :language: cpp :tab-width: 4 - :lines: 5-6 + :lines: 6-7 This is true for the STL library too (used for console I/O). Now, let's analyze the *main* function. We start up assuring that we acquire a valid image name argument from the command line. .. literalinclude:: ../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp :language: cpp :tab-width: 4 - :lines: 10-14 + :lines: 11-15 Then create a *Mat* object that will store the data of the loaded image. .. literalinclude:: ../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp :language: cpp :tab-width: 4 - :lines: 16 + :lines: 17 Now we call the :imread:`imread <>` function which loads the image name specified by the first argument (*argv[1]*). The second argument specifies the format in what we want the image. This may be: @@ -73,7 +73,7 @@ Now we call the :imread:`imread <>` function which loads the image name specifie .. literalinclude:: ../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp :language: cpp :tab-width: 4 - :lines: 17 + :lines: 18 .. note:: @@ -88,21 +88,21 @@ After checking that the image data was loaded correctly, we want to display our .. literalinclude:: ../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp :language: cpp - :lines: 25 + :lines: 26 :tab-width: 4 Finally, to update the content of the OpenCV window with a new image use the :imshow:`imshow <>` function. Specify the OpenCV window name to update and the image to use during this operation: .. literalinclude:: ../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp :language: cpp - :lines: 26 + :lines: 27 :tab-width: 4 Because we want our window to be displayed until the user presses a key (otherwise the program would end far too quickly), we use the :wait_key:`waitKey <>` function whose only parameter is just how long should it wait for a user input (measured in milliseconds). Zero means to wait forever. .. literalinclude:: ../../../../samples/cpp/tutorial_code/introduction/display_image/display_image.cpp :language: cpp - :lines: 28 + :lines: 29 :tab-width: 4 Result diff --git a/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst b/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst index 5ae5062492..d68116c818 100644 --- a/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst +++ b/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst @@ -361,16 +361,16 @@ Now here's our recommendation for the structure of the tutorial (although, remem # ---- External links for tutorials ----------------- extlinks = { - 'hgvideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#%s', None) + 'rwimg' : ('http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html#%s', None) } - In short here we defined a new **hgvideo** directive that refers to an external webpage link. Its usage is: + In short here we defined a new **rwimg** directive that refers to an external webpage link. Its usage is: .. code-block:: rst - A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function `. + A sample function of the highgui modules image write and read page is the :rwimg:`imread() function `. - Which turns to: A sample function of the highgui modules image write and read page is the :hgvideo:`imread() function `. The argument you give between the <> will be put in place of the ``%s`` in the upper definition, and as the link will anchor to the correct function. To find out the anchor of a given function just open up a web page, search for the function and click on it. In the address bar it should appear like: ``http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imread`` . Look here for the name of the directives for each page of the OpenCV reference manual. If none present for one of them feel free to add one for it. + Which turns to: A sample function of the highgui modules image write and read page is the :rwimg:`imread() function `. The argument you give between the <> will be put in place of the ``%s`` in the upper definition, and as the link will anchor to the correct function. To find out the anchor of a given function just open up a web page, search for the function and click on it. In the address bar it should appear like: ``http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images.html#imread`` . Look here for the name of the directives for each page of the OpenCV reference manual. If none present for one of them feel free to add one for it. For formulas you can add LATEX code that will translate in the web pages into images. You do this by using the *math* directive. A usage tip: diff --git a/doc/tutorials/introduction/load_save_image/load_save_image.rst b/doc/tutorials/introduction/load_save_image/load_save_image.rst index dec75c1958..cde81e12b5 100644 --- a/doc/tutorials/introduction/load_save_image/load_save_image.rst +++ b/doc/tutorials/introduction/load_save_image/load_save_image.rst @@ -5,7 +5,7 @@ Load, Modify, and Save an Image .. note:: - We assume that by now you know how to load an image using :readwriteimagevideo:`imread ` and to display it in a window (using :user_interface:`imshow `). Read the :ref:`Display_Image` tutorial otherwise. + We assume that by now you know how to load an image using :readwriteimage:`imread ` and to display it in a window (using :user_interface:`imshow `). Read the :ref:`Display_Image` tutorial otherwise. Goals ====== @@ -14,9 +14,9 @@ In this tutorial you will learn how to: .. container:: enumeratevisibleitemswithsquare - * Load an image using :readwriteimagevideo:`imread ` + * Load an image using :readwriteimage:`imread ` * Transform an image from BGR to Grayscale format by using :miscellaneous_transformations:`cvtColor ` - * Save your transformed image in a file on disk (using :readwriteimagevideo:`imwrite `) + * Save your transformed image in a file on disk (using :readwriteimage:`imwrite `) Code ====== @@ -62,7 +62,7 @@ Here it is: Explanation ============ -#. We begin by loading an image using :readwriteimagevideo:`imread `, located in the path given by *imageName*. For this example, assume you are loading a RGB image. +#. We begin by loading an image using :readwriteimage:`imread `, located in the path given by *imageName*. For this example, assume you are loading a RGB image. #. Now we are going to convert our image from BGR to Grayscale format. OpenCV has a really nice function to do this kind of transformations: @@ -76,9 +76,9 @@ Explanation * a source image (*image*) * a destination image (*gray_image*), in which we will save the converted image. - * an additional parameter that indicates what kind of transformation will be performed. In this case we use **CV_BGR2GRAY** (because of :readwriteimagevideo:`imread ` has BGR default channel order in case of color images). + * an additional parameter that indicates what kind of transformation will be performed. In this case we use **CV_BGR2GRAY** (because of :readwriteimage:`imread ` has BGR default channel order in case of color images). -#. So now we have our new *gray_image* and want to save it on disk (otherwise it will get lost after the program ends). To save it, we will use a function analagous to :readwriteimagevideo:`imread `: :readwriteimagevideo:`imwrite ` +#. So now we have our new *gray_image* and want to save it on disk (otherwise it will get lost after the program ends). To save it, we will use a function analagous to :readwriteimage:`imread `: :readwriteimage:`imwrite ` .. code-block:: cpp diff --git a/doc/tutorials/ml/non_linear_svms/non_linear_svms.rst b/doc/tutorials/ml/non_linear_svms/non_linear_svms.rst index 57e0b1b6ea..bd7fde8775 100644 --- a/doc/tutorials/ml/non_linear_svms/non_linear_svms.rst +++ b/doc/tutorials/ml/non_linear_svms/non_linear_svms.rst @@ -73,7 +73,7 @@ You may also find the source code and these video file in the :file:`samples/cpp :language: cpp :linenos: :tab-width: 4 - :lines: 1-11, 22-23, 26- + :lines: 1-12, 23-24, 27- Explanation =========== diff --git a/include/opencv2/opencv.hpp b/include/opencv2/opencv.hpp index b7c290a49c..fc24981eb6 100644 --- a/include/opencv2/opencv.hpp +++ b/include/opencv2/opencv.hpp @@ -50,6 +50,7 @@ #include "opencv2/features2d.hpp" #include "opencv2/objdetect.hpp" #include "opencv2/calib3d.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/ml.hpp" diff --git a/modules/calib3d/perf/perf_precomp.hpp b/modules/calib3d/perf/perf_precomp.hpp index 86312de1b8..9c5ab997d1 100644 --- a/modules/calib3d/perf/perf_precomp.hpp +++ b/modules/calib3d/perf/perf_precomp.hpp @@ -11,7 +11,7 @@ #include "opencv2/ts.hpp" #include "opencv2/calib3d.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/imgproc.hpp" #ifdef GTEST_CREATE_SHARED_LIBRARY diff --git a/modules/calib3d/test/test_precomp.hpp b/modules/calib3d/test/test_precomp.hpp index d670a4c220..ac3371cef3 100644 --- a/modules/calib3d/test/test_precomp.hpp +++ b/modules/calib3d/test/test_precomp.hpp @@ -13,7 +13,7 @@ #include "opencv2/ts.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/calib3d.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" namespace cvtest { diff --git a/modules/features2d/perf/perf_precomp.hpp b/modules/features2d/perf/perf_precomp.hpp index 30607daaf6..f5280a84e8 100644 --- a/modules/features2d/perf/perf_precomp.hpp +++ b/modules/features2d/perf/perf_precomp.hpp @@ -10,7 +10,7 @@ #define __OPENCV_PERF_PRECOMP_HPP__ #include "opencv2/ts.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/features2d.hpp" #ifdef GTEST_CREATE_SHARED_LIBRARY diff --git a/modules/features2d/test/test_descriptors_regression.cpp b/modules/features2d/test/test_descriptors_regression.cpp index 7119d590ef..281df244a1 100644 --- a/modules/features2d/test/test_descriptors_regression.cpp +++ b/modules/features2d/test/test_descriptors_regression.cpp @@ -40,7 +40,6 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui.hpp" using namespace std; using namespace cv; diff --git a/modules/features2d/test/test_precomp.hpp b/modules/features2d/test/test_precomp.hpp index 49bc1dfd18..bce72f7296 100644 --- a/modules/features2d/test/test_precomp.hpp +++ b/modules/features2d/test/test_precomp.hpp @@ -12,7 +12,7 @@ #include "opencv2/ts.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/features2d.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include #endif diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index f4a19cffe6..efe31a1cac 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -1,5 +1,5 @@ set(the_description "High-level GUI and Media I/O") -ocv_add_module(highgui opencv_imgproc OPTIONAL opencv_androidcamera) +ocv_add_module(highgui opencv_imgproc opencv_imgcodecs OPTIONAL opencv_androidcamera) # ---------------------------------------------------------------------------- # CMake file for highgui. See root CMakeLists.txt @@ -7,61 +7,17 @@ ocv_add_module(highgui opencv_imgproc OPTIONAL opencv_androidcamera) # Jose Luis Blanco, 2008 # ---------------------------------------------------------------------------- -ocv_clear_vars(GRFMT_LIBS) - if(HAVE_WINRT_CX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /ZW") endif() -if(HAVE_PNG OR HAVE_TIFF OR HAVE_OPENEXR) +if(APPLE) ocv_include_directories(${ZLIB_INCLUDE_DIRS}) - list(APPEND GRFMT_LIBS ${ZLIB_LIBRARIES}) -endif() - -if(HAVE_JPEG) - ocv_include_directories(${JPEG_INCLUDE_DIR}) - list(APPEND GRFMT_LIBS ${JPEG_LIBRARIES}) -endif() - -if(WITH_WEBP) - add_definitions(-DHAVE_WEBP) - ocv_include_directories(${WEBP_INCLUDE_DIR}) - list(APPEND GRFMT_LIBS ${WEBP_LIBRARIES}) -endif() - -if(HAVE_PNG) - add_definitions(${PNG_DEFINITIONS}) - ocv_include_directories(${PNG_INCLUDE_DIR}) - list(APPEND GRFMT_LIBS ${PNG_LIBRARIES}) + list(APPEND HIGHGUI_LIBRARIES ${ZLIB_LIBRARIES}) endif() -if(HAVE_TIFF) - ocv_include_directories(${TIFF_INCLUDE_DIR}) - list(APPEND GRFMT_LIBS ${TIFF_LIBRARIES}) -endif() - -if(HAVE_JASPER) - ocv_include_directories(${JASPER_INCLUDE_DIR}) - list(APPEND GRFMT_LIBS ${JASPER_LIBRARIES}) -endif() - -if(HAVE_OPENEXR) - include_directories(SYSTEM ${OPENEXR_INCLUDE_PATHS}) - list(APPEND GRFMT_LIBS ${OPENEXR_LIBRARIES}) -endif() - -file(GLOB grfmt_hdrs src/grfmt*.hpp) -file(GLOB grfmt_srcs src/grfmt*.cpp) -list(APPEND grfmt_hdrs src/bitstrm.hpp) -list(APPEND grfmt_srcs src/bitstrm.cpp) -list(APPEND grfmt_hdrs src/rgbe.hpp) -list(APPEND grfmt_srcs src/rgbe.cpp) - -source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs}) - set(highgui_hdrs src/precomp.hpp - src/utils.hpp src/cap_ffmpeg_impl.hpp ) @@ -69,8 +25,6 @@ set(highgui_srcs src/cap.cpp src/cap_images.cpp src/cap_ffmpeg.cpp - src/loadsave.cpp - src/utils.cpp src/window.cpp ) @@ -257,10 +211,10 @@ endif() source_group("Src" FILES ${highgui_srcs} ${highgui_hdrs}) source_group("Include" FILES ${highgui_ext_hdrs}) -ocv_set_module_sources(HEADERS ${highgui_ext_hdrs} SOURCES ${highgui_srcs} ${highgui_hdrs} ${grfmt_srcs} ${grfmt_hdrs}) +ocv_set_module_sources(HEADERS ${highgui_ext_hdrs} SOURCES ${highgui_srcs} ${highgui_hdrs}) ocv_module_include_directories() -ocv_create_module(${GRFMT_LIBS} ${HIGHGUI_LIBRARIES}) +ocv_create_module(${HIGHGUI_LIBRARIES}) if(APPLE) ocv_check_flag_support(OBJCXX "-fobjc-exceptions" HAVE_OBJC_EXCEPTIONS) diff --git a/modules/highgui/doc/highgui.rst b/modules/highgui/doc/highgui.rst index 02beddbafb..0450018785 100644 --- a/modules/highgui/doc/highgui.rst +++ b/modules/highgui/doc/highgui.rst @@ -9,12 +9,11 @@ It provides easy interface to: * Create and manipulate windows that can display images and "remember" their content (no need to handle repaint events from OS). * Add trackbars to the windows, handle simple mouse events as well as keyboard commands. -* Read and write images to/from disk or memory. * Read video from camera or file and write video to a file. .. toctree:: :maxdepth: 2 user_interface - reading_and_writing_images_and_video + reading_and_writing_video qt_new_functions diff --git a/modules/highgui/doc/reading_and_writing_images_and_video.rst b/modules/highgui/doc/reading_and_writing_video.rst similarity index 63% rename from modules/highgui/doc/reading_and_writing_images_and_video.rst rename to modules/highgui/doc/reading_and_writing_video.rst index c094ef7e23..4c7355129a 100644 --- a/modules/highgui/doc/reading_and_writing_images_and_video.rst +++ b/modules/highgui/doc/reading_and_writing_video.rst @@ -1,191 +1,8 @@ -Reading and Writing Images and Video -==================================== +Reading and Writing Video +========================= .. highlight:: cpp -imdecode --------- -Reads an image from a buffer in memory. - -.. ocv:function:: Mat imdecode( InputArray buf, int flags ) - -.. ocv:function:: Mat imdecode( InputArray buf, int flags, Mat* dst ) - -.. ocv:cfunction:: IplImage* cvDecodeImage( const CvMat* buf, int iscolor=CV_LOAD_IMAGE_COLOR) - -.. ocv:cfunction:: CvMat* cvDecodeImageM( const CvMat* buf, int iscolor=CV_LOAD_IMAGE_COLOR) - -.. ocv:pyfunction:: cv2.imdecode(buf, flags) -> retval - - :param buf: Input array or vector of bytes. - - :param flags: The same flags as in :ocv:func:`imread` . - - :param dst: The optional output placeholder for the decoded matrix. It can save the image reallocations when the function is called repeatedly for images of the same size. - -The function reads an image from the specified buffer in the memory. -If the buffer is too short or contains invalid data, the empty matrix/image is returned. - -See -:ocv:func:`imread` for the list of supported formats and flags description. - -.. note:: In the case of color images, the decoded images will have the channels stored in ``B G R`` order. - -imencode --------- -Encodes an image into a memory buffer. - -.. ocv:function:: bool imencode( const String& ext, InputArray img, vector& buf, const vector& params=vector()) - -.. ocv:cfunction:: CvMat* cvEncodeImage( const char* ext, const CvArr* image, const int* params=0 ) - -.. ocv:pyfunction:: cv2.imencode(ext, img[, params]) -> retval, buf - - :param ext: File extension that defines the output format. - - :param img: Image to be written. - - :param buf: Output buffer resized to fit the compressed image. - - :param params: Format-specific parameters. See :ocv:func:`imwrite` . - -The function compresses the image and stores it in the memory buffer that is resized to fit the result. -See -:ocv:func:`imwrite` for the list of supported formats and flags description. - -.. note:: ``cvEncodeImage`` returns single-row matrix of type ``CV_8UC1`` that contains encoded image as array of bytes. - -imread ------- -Loads an image from a file. - -.. ocv:function:: Mat imread( const String& filename, int flags=IMREAD_COLOR ) - -.. ocv:pyfunction:: cv2.imread(filename[, flags]) -> retval - -.. ocv:cfunction:: IplImage* cvLoadImage( const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR ) - -.. ocv:cfunction:: CvMat* cvLoadImageM( const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR ) - - :param filename: Name of file to be loaded. - - :param flags: Flags specifying the color type of a loaded image: - - * CV_LOAD_IMAGE_ANYDEPTH - If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. - - * CV_LOAD_IMAGE_COLOR - If set, always convert image to the color one - - * CV_LOAD_IMAGE_GRAYSCALE - If set, always convert image to the grayscale one - - * **>0** Return a 3-channel color image. - .. note:: In the current implementation the alpha channel, if any, is stripped from the output image. Use negative value if you need the alpha channel. - - * **=0** Return a grayscale image. - - * **<0** Return the loaded image as is (with alpha channel). - -The function ``imread`` loads an image from the specified file and returns it. If the image cannot be read (because of missing file, improper permissions, unsupported or invalid format), the function returns an empty matrix ( ``Mat::data==NULL`` ). Currently, the following file formats are supported: - - * Windows bitmaps - ``*.bmp, *.dib`` (always supported) - - * JPEG files - ``*.jpeg, *.jpg, *.jpe`` (see the *Notes* section) - - * JPEG 2000 files - ``*.jp2`` (see the *Notes* section) - - * Portable Network Graphics - ``*.png`` (see the *Notes* section) - - * WebP - ``*.webp`` (see the *Notes* section) - - * Portable image format - ``*.pbm, *.pgm, *.ppm`` (always supported) - - * Sun rasters - ``*.sr, *.ras`` (always supported) - - * TIFF files - ``*.tiff, *.tif`` (see the *Notes* section) - -.. note:: - - * The function determines the type of an image by the content, not by the file extension. - - * On Microsoft Windows* OS and MacOSX*, the codecs shipped with an OpenCV image (libjpeg, libpng, libtiff, and libjasper) are used by default. So, OpenCV can always read JPEGs, PNGs, and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers. But beware that currently these native image loaders give images with different pixel values because of the color management embedded into MacOSX. - - * On Linux*, BSD flavors and other Unix-like open-source operating systems, OpenCV looks for codecs supplied with an OS image. Install the relevant packages (do not forget the development files, for example, "libjpeg-dev", in Debian* and Ubuntu*) to get the codec support or turn on the ``OPENCV_BUILD_3RDPARTY_LIBS`` flag in CMake. - -.. note:: In the case of color images, the decoded images will have the channels stored in ``B G R`` order. - -imwrite ------------ -Saves an image to a specified file. - -.. ocv:function:: bool imwrite( const String& filename, InputArray img, const vector& params=vector() ) - -.. ocv:pyfunction:: cv2.imwrite(filename, img[, params]) -> retval - -.. ocv:cfunction:: int cvSaveImage( const char* filename, const CvArr* image, const int* params=0 ) - - :param filename: Name of the file. - - :param image: Image to be saved. - - :param params: Format-specific save parameters encoded as pairs ``paramId_1, paramValue_1, paramId_2, paramValue_2, ...`` . The following parameters are currently supported: - - * For JPEG, it can be a quality ( ``CV_IMWRITE_JPEG_QUALITY`` ) from 0 to 100 (the higher is the better). Default value is 95. - - * For WEBP, it can be a quality ( CV_IMWRITE_WEBP_QUALITY ) from 1 to 100 (the higher is the better). - By default (without any parameter) and for quality above 100 the lossless compression is used. - - * For PNG, it can be the compression level ( ``CV_IMWRITE_PNG_COMPRESSION`` ) from 0 to 9. A higher value means a smaller size and longer compression time. Default value is 3. - - * For PPM, PGM, or PBM, it can be a binary format flag ( ``CV_IMWRITE_PXM_BINARY`` ), 0 or 1. Default value is 1. - -The function ``imwrite`` saves the image to the specified file. The image format is chosen based on the ``filename`` extension (see -:ocv:func:`imread` for the list of extensions). Only 8-bit (or 16-bit unsigned (``CV_16U``) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function. If the format, depth or channel order is different, use -:ocv:func:`Mat::convertTo` , and -:ocv:func:`cvtColor` to convert it before saving. Or, use the universal :ocv:class:`FileStorage` I/O functions to save the image to XML or YAML format. - -It is possible to store PNG images with an alpha channel using this function. To do this, create 8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535. The sample below shows how to create such a BGRA image and store to PNG file. It also demonstrates how to set custom compression parameters :: - - #include - #include - #include - - using namespace cv; - using namespace std; - - void createAlphaMat(Mat &mat) - { - for (int i = 0; i < mat.rows; ++i) { - for (int j = 0; j < mat.cols; ++j) { - Vec4b& rgba = mat.at(i, j); - rgba[0] = UCHAR_MAX; - rgba[1] = saturate_cast((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX); - rgba[2] = saturate_cast((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX); - rgba[3] = saturate_cast(0.5 * (rgba[1] + rgba[2])); - } - } - } - - int main(int argv, char **argc) - { - // Create mat with alpha channel - Mat mat(480, 640, CV_8UC4); - createAlphaMat(mat); - - vector compression_params; - compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); - compression_params.push_back(9); - - try { - imwrite("alpha.png", mat, compression_params); - } - catch (runtime_error& ex) { - fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); - return 1; - } - - fprintf(stdout, "Saved PNG file with alpha data.\n"); - return 0; - } - VideoCapture ------------ diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index f05825f784..e0f40b9292 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -202,53 +202,6 @@ CV_EXPORTS int createButton( const String& bar_name, ButtonCallback on_change, } // cv - - -//////////////////////////////// image codec //////////////////////////////// -namespace cv -{ - -enum { IMREAD_UNCHANGED = -1, // 8bit, color or not - IMREAD_GRAYSCALE = 0, // 8bit, gray - IMREAD_COLOR = 1, // ?, color - IMREAD_ANYDEPTH = 2, // any depth, ? - IMREAD_ANYCOLOR = 4 // ?, any color - }; - -enum { IMWRITE_JPEG_QUALITY = 1, - IMWRITE_JPEG_PROGRESSIVE = 2, - IMWRITE_JPEG_OPTIMIZE = 3, - IMWRITE_PNG_COMPRESSION = 16, - IMWRITE_PNG_STRATEGY = 17, - IMWRITE_PNG_BILEVEL = 18, - IMWRITE_PXM_BINARY = 32, - IMWRITE_WEBP_QUALITY = 64 - }; - -enum { IMWRITE_PNG_STRATEGY_DEFAULT = 0, - IMWRITE_PNG_STRATEGY_FILTERED = 1, - IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, - IMWRITE_PNG_STRATEGY_RLE = 3, - IMWRITE_PNG_STRATEGY_FIXED = 4 - }; - -CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR ); - -CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, - const std::vector& params = std::vector()); - -CV_EXPORTS_W Mat imdecode( InputArray buf, int flags ); - -CV_EXPORTS Mat imdecode( InputArray buf, int flags, Mat* dst); - -CV_EXPORTS_W bool imencode( const String& ext, InputArray img, - CV_OUT std::vector& buf, - const std::vector& params = std::vector()); - -} // cv - - - ////////////////////////////////// video io ///////////////////////////////// typedef struct CvCapture CvCapture; diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 130302150f..a94e69601b 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -194,67 +194,6 @@ typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, vo CVAPI(void) cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param CV_DEFAULT(NULL)); -enum -{ -/* 8bit, color or not */ - CV_LOAD_IMAGE_UNCHANGED =-1, -/* 8bit, gray */ - CV_LOAD_IMAGE_GRAYSCALE =0, -/* ?, color */ - CV_LOAD_IMAGE_COLOR =1, -/* any depth, ? */ - CV_LOAD_IMAGE_ANYDEPTH =2, -/* ?, any color */ - CV_LOAD_IMAGE_ANYCOLOR =4 -}; - -/* load image from file - iscolor can be a combination of above flags where CV_LOAD_IMAGE_UNCHANGED - overrides the other flags - using CV_LOAD_IMAGE_ANYCOLOR alone is equivalent to CV_LOAD_IMAGE_UNCHANGED - unless CV_LOAD_IMAGE_ANYDEPTH is specified images are converted to 8bit -*/ -CVAPI(IplImage*) cvLoadImage( const char* filename, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); -CVAPI(CvMat*) cvLoadImageM( const char* filename, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); - -enum -{ - CV_IMWRITE_JPEG_QUALITY =1, - CV_IMWRITE_JPEG_PROGRESSIVE =2, - CV_IMWRITE_JPEG_OPTIMIZE =3, - CV_IMWRITE_PNG_COMPRESSION =16, - CV_IMWRITE_PNG_STRATEGY =17, - CV_IMWRITE_PNG_BILEVEL =18, - CV_IMWRITE_PNG_STRATEGY_DEFAULT =0, - CV_IMWRITE_PNG_STRATEGY_FILTERED =1, - CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY =2, - CV_IMWRITE_PNG_STRATEGY_RLE =3, - CV_IMWRITE_PNG_STRATEGY_FIXED =4, - CV_IMWRITE_PXM_BINARY =32, - CV_IMWRITE_WEBP_QUALITY =64 -}; - -/* save image to file */ -CVAPI(int) cvSaveImage( const char* filename, const CvArr* image, - const int* params CV_DEFAULT(0) ); - -/* decode image stored in the buffer */ -CVAPI(IplImage*) cvDecodeImage( const CvMat* buf, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); -CVAPI(CvMat*) cvDecodeImageM( const CvMat* buf, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); - -/* encode image and store the result as a byte vector (single-row 8uC1 matrix) */ -CVAPI(CvMat*) cvEncodeImage( const char* ext, const CvArr* image, - const int* params CV_DEFAULT(0) ); - -enum -{ - CV_CVTIMG_FLIP =1, - CV_CVTIMG_SWAP_RB =2 -}; - -/* utility function: convert one image to another with optional vertical flip */ -CVAPI(void) cvConvertImage( const CvArr* src, CvArr* dst, int flags CV_DEFAULT(0)); - /* wait for key event infinitely (delay<=0) or for "delay" milliseconds */ CVAPI(int) cvWaitKey(int delay CV_DEFAULT(0)); diff --git a/modules/highgui/perf/perf_precomp.hpp b/modules/highgui/perf/perf_precomp.hpp index faf34617e3..a5286691f6 100644 --- a/modules/highgui/perf/perf_precomp.hpp +++ b/modules/highgui/perf/perf_precomp.hpp @@ -10,6 +10,7 @@ #define __OPENCV_PERF_PRECOMP_HPP__ #include "opencv2/ts.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #ifdef GTEST_CREATE_SHARED_LIBRARY diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index bb4ed8ede5..7f78c7d05b 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -48,6 +48,7 @@ #include "opencv2/core/private.hpp" #include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/imgcodecs/imgcodecs_c.h" #include "opencv2/highgui/highgui_c.h" #include diff --git a/modules/highgui/test/test_precomp.hpp b/modules/highgui/test/test_precomp.hpp index 826d165749..9e14123d32 100644 --- a/modules/highgui/test/test_precomp.hpp +++ b/modules/highgui/test/test_precomp.hpp @@ -12,6 +12,7 @@ #include #include "opencv2/ts.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc/imgproc_c.h" diff --git a/modules/imgcodecs/CMakeLists.txt b/modules/imgcodecs/CMakeLists.txt new file mode 100644 index 0000000000..8cf60e5469 --- /dev/null +++ b/modules/imgcodecs/CMakeLists.txt @@ -0,0 +1,131 @@ +set(the_description "Image codecs") +ocv_add_module(imgcodecs opencv_imgproc) + +# ---------------------------------------------------------------------------- +# CMake file for imgcodecs. See root CMakeLists.txt +# Some parts taken from version of Hartmut Seichter, HIT Lab NZ. +# Jose Luis Blanco, 2008 +# ---------------------------------------------------------------------------- + +ocv_clear_vars(GRFMT_LIBS) + +if(HAVE_WINRT_CX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /ZW") +endif() + +if(HAVE_PNG OR HAVE_TIFF OR HAVE_OPENEXR) + ocv_include_directories(${ZLIB_INCLUDE_DIRS}) + list(APPEND GRFMT_LIBS ${ZLIB_LIBRARIES}) +endif() + +if(HAVE_JPEG) + ocv_include_directories(${JPEG_INCLUDE_DIR}) + list(APPEND GRFMT_LIBS ${JPEG_LIBRARIES}) +endif() + +if(WITH_WEBP) + add_definitions(-DHAVE_WEBP) + ocv_include_directories(${WEBP_INCLUDE_DIR}) + list(APPEND GRFMT_LIBS ${WEBP_LIBRARIES}) +endif() + +if(HAVE_PNG) + add_definitions(${PNG_DEFINITIONS}) + ocv_include_directories(${PNG_INCLUDE_DIR}) + list(APPEND GRFMT_LIBS ${PNG_LIBRARIES}) +endif() + +if(HAVE_TIFF) + ocv_include_directories(${TIFF_INCLUDE_DIR}) + list(APPEND GRFMT_LIBS ${TIFF_LIBRARIES}) +endif() + +if(HAVE_JASPER) + ocv_include_directories(${JASPER_INCLUDE_DIR}) + list(APPEND GRFMT_LIBS ${JASPER_LIBRARIES}) +endif() + +if(HAVE_OPENEXR) + include_directories(SYSTEM ${OPENEXR_INCLUDE_PATHS}) + list(APPEND GRFMT_LIBS ${OPENEXR_LIBRARIES}) +endif() + +file(GLOB grfmt_hdrs src/grfmt*.hpp) +file(GLOB grfmt_srcs src/grfmt*.cpp) +list(APPEND grfmt_hdrs src/bitstrm.hpp) +list(APPEND grfmt_srcs src/bitstrm.cpp) +list(APPEND grfmt_hdrs src/rgbe.hpp) +list(APPEND grfmt_srcs src/rgbe.cpp) + +source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs}) + +set(imgcodecs_hdrs + src/precomp.hpp + src/utils.hpp + ) + +set(imgcodecs_srcs + src/loadsave.cpp + src/utils.cpp + ) + +file(GLOB imgcodecs_ext_hdrs "include/opencv2/*.hpp" "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h") + +if(IOS) + add_definitions(-DHAVE_IOS=1) + list(APPEND imgcodecs_srcs src/ios_conversions.mm) + list(APPEND IMGCODECS_LIBRARIES "-framework Accelerate" "-framework CoreGraphics" "-framework CoreImage" "-framework QuartzCore" "-framework AssetsLibrary") +endif() + +if(UNIX) + #these variables are set by CHECK_MODULE macro + foreach(P ${IMGCODECS_INCLUDE_DIRS}) + ocv_include_directories(${P}) + endforeach() + + foreach(P ${IMGCODECS_LIBRARY_DIRS}) + link_directories(${P}) + endforeach() +endif() + +source_group("Src" FILES ${imgcodecs_srcs} ${imgcodecs_hdrs}) +source_group("Include" FILES ${imgcodecs_ext_hdrs}) +ocv_set_module_sources(HEADERS ${imgcodecs_ext_hdrs} SOURCES ${imgcodecs_srcs} ${imgcodecs_hdrs} ${grfmt_srcs} ${grfmt_hdrs}) +ocv_module_include_directories() + +ocv_create_module(${GRFMT_LIBS} ${IMGCODECS_LIBRARIES}) + +if(APPLE) + ocv_check_flag_support(OBJCXX "-fobjc-exceptions" HAVE_OBJC_EXCEPTIONS) + if(HAVE_OBJC_EXCEPTIONS) + foreach(source ${OPENCV_MODULE_${the_module}_SOURCES}) + if("${source}" MATCHES "\\.mm$") + get_source_file_property(flags "${source}" COMPILE_FLAGS) + if(flags) + set(flags "${_flags} -fobjc-exceptions") + else() + set(flags "-fobjc-exceptions") + endif() + + set_source_files_properties("${source}" PROPERTIES COMPILE_FLAGS "${flags}") + endif() + endforeach() + endif() +endif() + +if(BUILD_SHARED_LIBS) + add_definitions(-DIMGCODECS_EXPORTS) +endif() + +if(MSVC) + set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /NODEFAULTLIB:libcmt.lib /DEBUG") +endif() + +#stop automatic dependencies propagation for this module +set_target_properties(${the_module} PROPERTIES LINK_INTERFACE_LIBRARIES "") + +ocv_add_precompiled_headers(${the_module}) +ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated-declarations) + +ocv_add_accuracy_tests() +ocv_add_perf_tests() diff --git a/modules/imgcodecs/doc/imgcodecs.rst b/modules/imgcodecs/doc/imgcodecs.rst new file mode 100644 index 0000000000..bcb3131f56 --- /dev/null +++ b/modules/imgcodecs/doc/imgcodecs.rst @@ -0,0 +1,10 @@ +***************************************** +imgcodecs. Image file reading and writing +***************************************** + +This module of the OpenCV help you read and write images to/from disk or memory. + +.. toctree:: + :maxdepth: 2 + + reading_and_writing_images diff --git a/modules/imgcodecs/doc/reading_and_writing_images.rst b/modules/imgcodecs/doc/reading_and_writing_images.rst new file mode 100644 index 0000000000..9f8dcaafef --- /dev/null +++ b/modules/imgcodecs/doc/reading_and_writing_images.rst @@ -0,0 +1,187 @@ +Reading and Writing Images +========================== + +.. highlight:: cpp + +imdecode +-------- +Reads an image from a buffer in memory. + +.. ocv:function:: Mat imdecode( InputArray buf, int flags ) + +.. ocv:function:: Mat imdecode( InputArray buf, int flags, Mat* dst ) + +.. ocv:cfunction:: IplImage* cvDecodeImage( const CvMat* buf, int iscolor=CV_LOAD_IMAGE_COLOR) + +.. ocv:cfunction:: CvMat* cvDecodeImageM( const CvMat* buf, int iscolor=CV_LOAD_IMAGE_COLOR) + +.. ocv:pyfunction:: cv2.imdecode(buf, flags) -> retval + + :param buf: Input array or vector of bytes. + + :param flags: The same flags as in :ocv:func:`imread` . + + :param dst: The optional output placeholder for the decoded matrix. It can save the image reallocations when the function is called repeatedly for images of the same size. + +The function reads an image from the specified buffer in the memory. +If the buffer is too short or contains invalid data, the empty matrix/image is returned. + +See +:ocv:func:`imread` for the list of supported formats and flags description. + +.. note:: In the case of color images, the decoded images will have the channels stored in ``B G R`` order. + +imencode +-------- +Encodes an image into a memory buffer. + +.. ocv:function:: bool imencode( const String& ext, InputArray img, vector& buf, const vector& params=vector()) + +.. ocv:cfunction:: CvMat* cvEncodeImage( const char* ext, const CvArr* image, const int* params=0 ) + +.. ocv:pyfunction:: cv2.imencode(ext, img[, params]) -> retval, buf + + :param ext: File extension that defines the output format. + + :param img: Image to be written. + + :param buf: Output buffer resized to fit the compressed image. + + :param params: Format-specific parameters. See :ocv:func:`imwrite` . + +The function compresses the image and stores it in the memory buffer that is resized to fit the result. +See +:ocv:func:`imwrite` for the list of supported formats and flags description. + +.. note:: ``cvEncodeImage`` returns single-row matrix of type ``CV_8UC1`` that contains encoded image as array of bytes. + +imread +------ +Loads an image from a file. + +.. ocv:function:: Mat imread( const String& filename, int flags=IMREAD_COLOR ) + +.. ocv:pyfunction:: cv2.imread(filename[, flags]) -> retval + +.. ocv:cfunction:: IplImage* cvLoadImage( const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR ) + +.. ocv:cfunction:: CvMat* cvLoadImageM( const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR ) + + :param filename: Name of file to be loaded. + + :param flags: Flags specifying the color type of a loaded image: + + * CV_LOAD_IMAGE_ANYDEPTH - If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. + + * CV_LOAD_IMAGE_COLOR - If set, always convert image to the color one + + * CV_LOAD_IMAGE_GRAYSCALE - If set, always convert image to the grayscale one + + * **>0** Return a 3-channel color image. + .. note:: In the current implementation the alpha channel, if any, is stripped from the output image. Use negative value if you need the alpha channel. + + * **=0** Return a grayscale image. + + * **<0** Return the loaded image as is (with alpha channel). + +The function ``imread`` loads an image from the specified file and returns it. If the image cannot be read (because of missing file, improper permissions, unsupported or invalid format), the function returns an empty matrix ( ``Mat::data==NULL`` ). Currently, the following file formats are supported: + + * Windows bitmaps - ``*.bmp, *.dib`` (always supported) + + * JPEG files - ``*.jpeg, *.jpg, *.jpe`` (see the *Notes* section) + + * JPEG 2000 files - ``*.jp2`` (see the *Notes* section) + + * Portable Network Graphics - ``*.png`` (see the *Notes* section) + + * WebP - ``*.webp`` (see the *Notes* section) + + * Portable image format - ``*.pbm, *.pgm, *.ppm`` (always supported) + + * Sun rasters - ``*.sr, *.ras`` (always supported) + + * TIFF files - ``*.tiff, *.tif`` (see the *Notes* section) + +.. note:: + + * The function determines the type of an image by the content, not by the file extension. + + * On Microsoft Windows* OS and MacOSX*, the codecs shipped with an OpenCV image (libjpeg, libpng, libtiff, and libjasper) are used by default. So, OpenCV can always read JPEGs, PNGs, and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers. But beware that currently these native image loaders give images with different pixel values because of the color management embedded into MacOSX. + + * On Linux*, BSD flavors and other Unix-like open-source operating systems, OpenCV looks for codecs supplied with an OS image. Install the relevant packages (do not forget the development files, for example, "libjpeg-dev", in Debian* and Ubuntu*) to get the codec support or turn on the ``OPENCV_BUILD_3RDPARTY_LIBS`` flag in CMake. + +.. note:: In the case of color images, the decoded images will have the channels stored in ``B G R`` order. + +imwrite +----------- +Saves an image to a specified file. + +.. ocv:function:: bool imwrite( const String& filename, InputArray img, const vector& params=vector() ) + +.. ocv:pyfunction:: cv2.imwrite(filename, img[, params]) -> retval + +.. ocv:cfunction:: int cvSaveImage( const char* filename, const CvArr* image, const int* params=0 ) + + :param filename: Name of the file. + + :param image: Image to be saved. + + :param params: Format-specific save parameters encoded as pairs ``paramId_1, paramValue_1, paramId_2, paramValue_2, ...`` . The following parameters are currently supported: + + * For JPEG, it can be a quality ( ``CV_IMWRITE_JPEG_QUALITY`` ) from 0 to 100 (the higher is the better). Default value is 95. + + * For WEBP, it can be a quality ( CV_IMWRITE_WEBP_QUALITY ) from 1 to 100 (the higher is the better). + By default (without any parameter) and for quality above 100 the lossless compression is used. + + * For PNG, it can be the compression level ( ``CV_IMWRITE_PNG_COMPRESSION`` ) from 0 to 9. A higher value means a smaller size and longer compression time. Default value is 3. + + * For PPM, PGM, or PBM, it can be a binary format flag ( ``CV_IMWRITE_PXM_BINARY`` ), 0 or 1. Default value is 1. + +The function ``imwrite`` saves the image to the specified file. The image format is chosen based on the ``filename`` extension (see +:ocv:func:`imread` for the list of extensions). Only 8-bit (or 16-bit unsigned (``CV_16U``) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function. If the format, depth or channel order is different, use +:ocv:func:`Mat::convertTo` , and +:ocv:func:`cvtColor` to convert it before saving. Or, use the universal :ocv:class:`FileStorage` I/O functions to save the image to XML or YAML format. + +It is possible to store PNG images with an alpha channel using this function. To do this, create 8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535. The sample below shows how to create such a BGRA image and store to PNG file. It also demonstrates how to set custom compression parameters :: + + #include + #include + #include + + using namespace cv; + using namespace std; + + void createAlphaMat(Mat &mat) + { + for (int i = 0; i < mat.rows; ++i) { + for (int j = 0; j < mat.cols; ++j) { + Vec4b& rgba = mat.at(i, j); + rgba[0] = UCHAR_MAX; + rgba[1] = saturate_cast((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX); + rgba[2] = saturate_cast((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX); + rgba[3] = saturate_cast(0.5 * (rgba[1] + rgba[2])); + } + } + } + + int main(int argv, char **argc) + { + // Create mat with alpha channel + Mat mat(480, 640, CV_8UC4); + createAlphaMat(mat); + + vector compression_params; + compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); + compression_params.push_back(9); + + try { + imwrite("alpha.png", mat, compression_params); + } + catch (runtime_error& ex) { + fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); + return 1; + } + + fprintf(stdout, "Saved PNG file with alpha data.\n"); + return 0; + } diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp new file mode 100644 index 0000000000..81f8a45f65 --- /dev/null +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -0,0 +1,91 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_IMGCODECS_HPP__ +#define __OPENCV_IMGCODECS_HPP__ + +#include "opencv2/core.hpp" + +//////////////////////////////// image codec //////////////////////////////// +namespace cv +{ + +enum { IMREAD_UNCHANGED = -1, // 8bit, color or not + IMREAD_GRAYSCALE = 0, // 8bit, gray + IMREAD_COLOR = 1, // ?, color + IMREAD_ANYDEPTH = 2, // any depth, ? + IMREAD_ANYCOLOR = 4 // ?, any color + }; + +enum { IMWRITE_JPEG_QUALITY = 1, + IMWRITE_JPEG_PROGRESSIVE = 2, + IMWRITE_JPEG_OPTIMIZE = 3, + IMWRITE_PNG_COMPRESSION = 16, + IMWRITE_PNG_STRATEGY = 17, + IMWRITE_PNG_BILEVEL = 18, + IMWRITE_PXM_BINARY = 32, + IMWRITE_WEBP_QUALITY = 64 + }; + +enum { IMWRITE_PNG_STRATEGY_DEFAULT = 0, + IMWRITE_PNG_STRATEGY_FILTERED = 1, + IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, + IMWRITE_PNG_STRATEGY_RLE = 3, + IMWRITE_PNG_STRATEGY_FIXED = 4 + }; + +CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR ); + +CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, + const std::vector& params = std::vector()); + +CV_EXPORTS_W Mat imdecode( InputArray buf, int flags ); + +CV_EXPORTS Mat imdecode( InputArray buf, int flags, Mat* dst); + +CV_EXPORTS_W bool imencode( const String& ext, InputArray img, + CV_OUT std::vector& buf, + const std::vector& params = std::vector()); + +} // cv + +#endif //__OPENCV_IMGCODECS_HPP__ diff --git a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs.hpp new file mode 100644 index 0000000000..a3cd232645 --- /dev/null +++ b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/imgcodecs.hpp" diff --git a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h new file mode 100644 index 0000000000..81566eb659 --- /dev/null +++ b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h @@ -0,0 +1,117 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_IMGCODECS_H__ +#define __OPENCV_IMGCODECS_H__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +enum +{ +/* 8bit, color or not */ + CV_LOAD_IMAGE_UNCHANGED =-1, +/* 8bit, gray */ + CV_LOAD_IMAGE_GRAYSCALE =0, +/* ?, color */ + CV_LOAD_IMAGE_COLOR =1, +/* any depth, ? */ + CV_LOAD_IMAGE_ANYDEPTH =2, +/* ?, any color */ + CV_LOAD_IMAGE_ANYCOLOR =4 +}; + +/* load image from file + iscolor can be a combination of above flags where CV_LOAD_IMAGE_UNCHANGED + overrides the other flags + using CV_LOAD_IMAGE_ANYCOLOR alone is equivalent to CV_LOAD_IMAGE_UNCHANGED + unless CV_LOAD_IMAGE_ANYDEPTH is specified images are converted to 8bit +*/ +CVAPI(IplImage*) cvLoadImage( const char* filename, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); +CVAPI(CvMat*) cvLoadImageM( const char* filename, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); + +enum +{ + CV_IMWRITE_JPEG_QUALITY =1, + CV_IMWRITE_JPEG_PROGRESSIVE =2, + CV_IMWRITE_JPEG_OPTIMIZE =3, + CV_IMWRITE_PNG_COMPRESSION =16, + CV_IMWRITE_PNG_STRATEGY =17, + CV_IMWRITE_PNG_BILEVEL =18, + CV_IMWRITE_PNG_STRATEGY_DEFAULT =0, + CV_IMWRITE_PNG_STRATEGY_FILTERED =1, + CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY =2, + CV_IMWRITE_PNG_STRATEGY_RLE =3, + CV_IMWRITE_PNG_STRATEGY_FIXED =4, + CV_IMWRITE_PXM_BINARY =32, + CV_IMWRITE_WEBP_QUALITY =64 +}; + +/* save image to file */ +CVAPI(int) cvSaveImage( const char* filename, const CvArr* image, + const int* params CV_DEFAULT(0) ); + +/* decode image stored in the buffer */ +CVAPI(IplImage*) cvDecodeImage( const CvMat* buf, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); +CVAPI(CvMat*) cvDecodeImageM( const CvMat* buf, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); + +/* encode image and store the result as a byte vector (single-row 8uC1 matrix) */ +CVAPI(CvMat*) cvEncodeImage( const char* ext, const CvArr* image, + const int* params CV_DEFAULT(0) ); + +enum +{ + CV_CVTIMG_FLIP =1, + CV_CVTIMG_SWAP_RB =2 +}; + +/* utility function: convert one image to another with optional vertical flip */ +CVAPI(void) cvConvertImage( const CvArr* src, CvArr* dst, int flags CV_DEFAULT(0)); + + +#ifdef __cplusplus +} +#endif + +#endif // __OPENCV_IMGCODECS_H__ diff --git a/modules/imgcodecs/include/opencv2/imgcodecs/ios.h b/modules/imgcodecs/include/opencv2/imgcodecs/ios.h new file mode 100644 index 0000000000..d7ba6e67c2 --- /dev/null +++ b/modules/imgcodecs/include/opencv2/imgcodecs/ios.h @@ -0,0 +1,48 @@ + +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "opencv2/core/core.hpp" + +UIImage* MatToUIImage(const cv::Mat& image); +void UIImageToMat(const UIImage* image, + cv::Mat& m, bool alphaExist = false); diff --git a/modules/imgcodecs/perf/perf_main.cpp b/modules/imgcodecs/perf/perf_main.cpp new file mode 100644 index 0000000000..ebe94ab7cc --- /dev/null +++ b/modules/imgcodecs/perf/perf_main.cpp @@ -0,0 +1,3 @@ +#include "perf_precomp.hpp" + +CV_PERF_TEST_MAIN(highgui) diff --git a/modules/imgcodecs/perf/perf_precomp.hpp b/modules/imgcodecs/perf/perf_precomp.hpp new file mode 100644 index 0000000000..e6e34b40c6 --- /dev/null +++ b/modules/imgcodecs/perf/perf_precomp.hpp @@ -0,0 +1,19 @@ +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-declarations" +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic ignored "-Wmissing-prototypes" +# pragma GCC diagnostic ignored "-Wextra" +# endif +#endif + +#ifndef __OPENCV_PERF_PRECOMP_HPP__ +#define __OPENCV_PERF_PRECOMP_HPP__ + +#include "opencv2/ts.hpp" +#include "opencv2/imgcodecs.hpp" + +#ifdef GTEST_CREATE_SHARED_LIBRARY +#error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined +#endif + +#endif diff --git a/modules/highgui/src/bitstrm.cpp b/modules/imgcodecs/src/bitstrm.cpp similarity index 100% rename from modules/highgui/src/bitstrm.cpp rename to modules/imgcodecs/src/bitstrm.cpp diff --git a/modules/highgui/src/bitstrm.hpp b/modules/imgcodecs/src/bitstrm.hpp similarity index 100% rename from modules/highgui/src/bitstrm.hpp rename to modules/imgcodecs/src/bitstrm.hpp diff --git a/modules/highgui/src/grfmt_base.cpp b/modules/imgcodecs/src/grfmt_base.cpp similarity index 100% rename from modules/highgui/src/grfmt_base.cpp rename to modules/imgcodecs/src/grfmt_base.cpp diff --git a/modules/highgui/src/grfmt_base.hpp b/modules/imgcodecs/src/grfmt_base.hpp similarity index 100% rename from modules/highgui/src/grfmt_base.hpp rename to modules/imgcodecs/src/grfmt_base.hpp diff --git a/modules/highgui/src/grfmt_bmp.cpp b/modules/imgcodecs/src/grfmt_bmp.cpp similarity index 100% rename from modules/highgui/src/grfmt_bmp.cpp rename to modules/imgcodecs/src/grfmt_bmp.cpp diff --git a/modules/highgui/src/grfmt_bmp.hpp b/modules/imgcodecs/src/grfmt_bmp.hpp similarity index 100% rename from modules/highgui/src/grfmt_bmp.hpp rename to modules/imgcodecs/src/grfmt_bmp.hpp diff --git a/modules/highgui/src/grfmt_exr.cpp b/modules/imgcodecs/src/grfmt_exr.cpp similarity index 100% rename from modules/highgui/src/grfmt_exr.cpp rename to modules/imgcodecs/src/grfmt_exr.cpp diff --git a/modules/highgui/src/grfmt_exr.hpp b/modules/imgcodecs/src/grfmt_exr.hpp similarity index 100% rename from modules/highgui/src/grfmt_exr.hpp rename to modules/imgcodecs/src/grfmt_exr.hpp diff --git a/modules/highgui/src/grfmt_hdr.cpp b/modules/imgcodecs/src/grfmt_hdr.cpp similarity index 100% rename from modules/highgui/src/grfmt_hdr.cpp rename to modules/imgcodecs/src/grfmt_hdr.cpp diff --git a/modules/highgui/src/grfmt_hdr.hpp b/modules/imgcodecs/src/grfmt_hdr.hpp similarity index 100% rename from modules/highgui/src/grfmt_hdr.hpp rename to modules/imgcodecs/src/grfmt_hdr.hpp diff --git a/modules/highgui/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp similarity index 100% rename from modules/highgui/src/grfmt_jpeg.cpp rename to modules/imgcodecs/src/grfmt_jpeg.cpp diff --git a/modules/highgui/src/grfmt_jpeg.hpp b/modules/imgcodecs/src/grfmt_jpeg.hpp similarity index 100% rename from modules/highgui/src/grfmt_jpeg.hpp rename to modules/imgcodecs/src/grfmt_jpeg.hpp diff --git a/modules/highgui/src/grfmt_jpeg2000.cpp b/modules/imgcodecs/src/grfmt_jpeg2000.cpp similarity index 100% rename from modules/highgui/src/grfmt_jpeg2000.cpp rename to modules/imgcodecs/src/grfmt_jpeg2000.cpp diff --git a/modules/highgui/src/grfmt_jpeg2000.hpp b/modules/imgcodecs/src/grfmt_jpeg2000.hpp similarity index 100% rename from modules/highgui/src/grfmt_jpeg2000.hpp rename to modules/imgcodecs/src/grfmt_jpeg2000.hpp diff --git a/modules/highgui/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp similarity index 100% rename from modules/highgui/src/grfmt_png.cpp rename to modules/imgcodecs/src/grfmt_png.cpp diff --git a/modules/highgui/src/grfmt_png.hpp b/modules/imgcodecs/src/grfmt_png.hpp similarity index 100% rename from modules/highgui/src/grfmt_png.hpp rename to modules/imgcodecs/src/grfmt_png.hpp diff --git a/modules/highgui/src/grfmt_pxm.cpp b/modules/imgcodecs/src/grfmt_pxm.cpp similarity index 100% rename from modules/highgui/src/grfmt_pxm.cpp rename to modules/imgcodecs/src/grfmt_pxm.cpp diff --git a/modules/highgui/src/grfmt_pxm.hpp b/modules/imgcodecs/src/grfmt_pxm.hpp similarity index 100% rename from modules/highgui/src/grfmt_pxm.hpp rename to modules/imgcodecs/src/grfmt_pxm.hpp diff --git a/modules/highgui/src/grfmt_sunras.cpp b/modules/imgcodecs/src/grfmt_sunras.cpp similarity index 100% rename from modules/highgui/src/grfmt_sunras.cpp rename to modules/imgcodecs/src/grfmt_sunras.cpp diff --git a/modules/highgui/src/grfmt_sunras.hpp b/modules/imgcodecs/src/grfmt_sunras.hpp similarity index 100% rename from modules/highgui/src/grfmt_sunras.hpp rename to modules/imgcodecs/src/grfmt_sunras.hpp diff --git a/modules/highgui/src/grfmt_tiff.cpp b/modules/imgcodecs/src/grfmt_tiff.cpp similarity index 100% rename from modules/highgui/src/grfmt_tiff.cpp rename to modules/imgcodecs/src/grfmt_tiff.cpp diff --git a/modules/highgui/src/grfmt_tiff.hpp b/modules/imgcodecs/src/grfmt_tiff.hpp similarity index 100% rename from modules/highgui/src/grfmt_tiff.hpp rename to modules/imgcodecs/src/grfmt_tiff.hpp diff --git a/modules/highgui/src/grfmt_webp.cpp b/modules/imgcodecs/src/grfmt_webp.cpp similarity index 100% rename from modules/highgui/src/grfmt_webp.cpp rename to modules/imgcodecs/src/grfmt_webp.cpp diff --git a/modules/highgui/src/grfmt_webp.hpp b/modules/imgcodecs/src/grfmt_webp.hpp similarity index 100% rename from modules/highgui/src/grfmt_webp.hpp rename to modules/imgcodecs/src/grfmt_webp.hpp diff --git a/modules/highgui/src/grfmts.hpp b/modules/imgcodecs/src/grfmts.hpp similarity index 100% rename from modules/highgui/src/grfmts.hpp rename to modules/imgcodecs/src/grfmts.hpp diff --git a/modules/highgui/src/ios_conversions.mm b/modules/imgcodecs/src/ios_conversions.mm similarity index 100% rename from modules/highgui/src/ios_conversions.mm rename to modules/imgcodecs/src/ios_conversions.mm diff --git a/modules/highgui/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp similarity index 100% rename from modules/highgui/src/loadsave.cpp rename to modules/imgcodecs/src/loadsave.cpp diff --git a/modules/imgcodecs/src/precomp.hpp b/modules/imgcodecs/src/precomp.hpp new file mode 100644 index 0000000000..88959a036f --- /dev/null +++ b/modules/imgcodecs/src/precomp.hpp @@ -0,0 +1,87 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __IMGCODECS_H_ +#define __IMGCODECS_H_ + +#include "opencv2/imgcodecs.hpp" + +#include "opencv2/core/utility.hpp" +#include "opencv2/core/private.hpp" + +#include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/imgcodecs/imgcodecs_c.h" + +#include +#include +#include +#include +#include +#include + +#if defined WIN32 || defined WINCE + #if !defined _WIN32_WINNT + #ifdef HAVE_MSMF + #define _WIN32_WINNT 0x0600 // Windows Vista + #else + #define _WIN32_WINNT 0x0500 // Windows 2000 + #endif + #endif + + #include + #undef small + #undef min + #undef max + #undef abs +#endif + +#ifdef HAVE_TEGRA_OPTIMIZATION +#include "opencv2/imgcodecs/imgcodecs_tegra.hpp" +#endif + +#define __BEGIN__ __CV_BEGIN__ +#define __END__ __CV_END__ +#define EXIT __CV_EXIT__ + +CVAPI(int) cvHaveImageReader(const char* filename); +CVAPI(int) cvHaveImageWriter(const char* filename); + +#endif /* __HIGHGUI_H_ */ diff --git a/modules/highgui/src/rgbe.cpp b/modules/imgcodecs/src/rgbe.cpp similarity index 100% rename from modules/highgui/src/rgbe.cpp rename to modules/imgcodecs/src/rgbe.cpp diff --git a/modules/highgui/src/rgbe.hpp b/modules/imgcodecs/src/rgbe.hpp similarity index 100% rename from modules/highgui/src/rgbe.hpp rename to modules/imgcodecs/src/rgbe.hpp diff --git a/modules/highgui/src/utils.cpp b/modules/imgcodecs/src/utils.cpp similarity index 100% rename from modules/highgui/src/utils.cpp rename to modules/imgcodecs/src/utils.cpp diff --git a/modules/highgui/src/utils.hpp b/modules/imgcodecs/src/utils.hpp similarity index 100% rename from modules/highgui/src/utils.hpp rename to modules/imgcodecs/src/utils.hpp diff --git a/modules/highgui/test/test_drawing.cpp b/modules/imgcodecs/test/test_drawing.cpp similarity index 99% rename from modules/highgui/test/test_drawing.cpp rename to modules/imgcodecs/test/test_drawing.cpp index 9d9e17dde2..7621ccf983 100644 --- a/modules/highgui/test/test_drawing.cpp +++ b/modules/imgcodecs/test/test_drawing.cpp @@ -41,7 +41,6 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui.hpp" using namespace std; using namespace cv; diff --git a/modules/highgui/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp similarity index 99% rename from modules/highgui/test/test_grfmt.cpp rename to modules/imgcodecs/test/test_grfmt.cpp index e4d3e70461..02851a0da6 100644 --- a/modules/highgui/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -41,7 +41,6 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui.hpp" using namespace cv; using namespace std; diff --git a/modules/imgcodecs/test/test_main.cpp b/modules/imgcodecs/test/test_main.cpp new file mode 100644 index 0000000000..461e7fac7f --- /dev/null +++ b/modules/imgcodecs/test/test_main.cpp @@ -0,0 +1,3 @@ +#include "test_precomp.hpp" + +CV_TEST_MAIN("imgcodecs") diff --git a/modules/imgcodecs/test/test_precomp.hpp b/modules/imgcodecs/test/test_precomp.hpp new file mode 100644 index 0000000000..2aed614337 --- /dev/null +++ b/modules/imgcodecs/test/test_precomp.hpp @@ -0,0 +1,20 @@ +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-declarations" +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic ignored "-Wmissing-prototypes" +# pragma GCC diagnostic ignored "-Wextra" +# endif +#endif + +#ifndef __OPENCV_TEST_PRECOMP_HPP__ +#define __OPENCV_TEST_PRECOMP_HPP__ + +#include +#include "opencv2/ts.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" +#include "opencv2/imgproc/imgproc_c.h" + +#include "opencv2/core/private.hpp" + +#endif diff --git a/modules/imgproc/perf/perf_precomp.hpp b/modules/imgproc/perf/perf_precomp.hpp index 19f62712c1..5bede78db8 100644 --- a/modules/imgproc/perf/perf_precomp.hpp +++ b/modules/imgproc/perf/perf_precomp.hpp @@ -11,7 +11,7 @@ #include "opencv2/ts.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #ifdef GTEST_CREATE_SHARED_LIBRARY #error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined diff --git a/modules/imgproc/test/test_precomp.hpp b/modules/imgproc/test/test_precomp.hpp index 53f315ee4f..249ec8d629 100644 --- a/modules/imgproc/test/test_precomp.hpp +++ b/modules/imgproc/test/test_precomp.hpp @@ -13,7 +13,7 @@ #include "opencv2/ts.hpp" #include "opencv2/core/private.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/imgproc/imgproc_c.h" diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 1948e21141..25c9352f4e 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -6,7 +6,7 @@ if(IOS OR NOT PYTHON_EXECUTABLE OR NOT ANT_EXECUTABLE OR NOT (JNI_FOUND OR (ANDR endif() set(the_description "The java bindings") -ocv_add_module(java BINDINGS opencv_core opencv_imgproc OPTIONAL opencv_objdetect opencv_features2d opencv_video opencv_highgui opencv_ml opencv_calib3d opencv_photo opencv_nonfree opencv_contrib) +ocv_add_module(java BINDINGS opencv_core opencv_imgproc OPTIONAL opencv_objdetect opencv_features2d opencv_video opencv_imgcodecs opencv_highgui opencv_ml opencv_calib3d opencv_photo opencv_nonfree opencv_contrib) ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/generator/src/cpp") if(NOT ANDROID) diff --git a/modules/java/generator/rst_parser.py b/modules/java/generator/rst_parser.py index 750d6f0be8..0fe3e5a3bd 100755 --- a/modules/java/generator/rst_parser.py +++ b/modules/java/generator/rst_parser.py @@ -2,7 +2,7 @@ from __future__ import print_function import os, sys, re, string, fnmatch -allmodules = ["core", "flann", "imgproc", "ml", "highgui", "video", "features2d", "calib3d", "objdetect", "legacy", "contrib", "cuda", "androidcamera", "java", "python", "stitching", "ts", "photo", "nonfree", "videostab", "softcascade", "superres"] +allmodules = ["core", "flann", "imgproc", "ml", "imgcodecs", "highgui", "video", "features2d", "calib3d", "objdetect", "legacy", "contrib", "cuda", "androidcamera", "java", "python", "stitching", "ts", "photo", "nonfree", "videostab", "softcascade", "superres"] verbose = False show_warnings = True show_errors = True diff --git a/modules/java/generator/src/java/android+Utils.java b/modules/java/generator/src/java/android+Utils.java index 9c461087c4..404c986da8 100644 --- a/modules/java/generator/src/java/android+Utils.java +++ b/modules/java/generator/src/java/android+Utils.java @@ -6,7 +6,7 @@ import android.graphics.Bitmap; import org.opencv.core.CvException; import org.opencv.core.CvType; import org.opencv.core.Mat; -import org.opencv.highgui.Highgui; +import org.opencv.imgcodecs.Imgcodecs; import java.io.ByteArrayOutputStream; import java.io.File; @@ -67,7 +67,7 @@ public class Utils { encoded.put(0, 0, os.toByteArray()); os.close(); - Mat decoded = Highgui.imdecode(encoded, flags); + Mat decoded = Imgcodecs.imdecode(encoded, flags); encoded.release(); return decoded; diff --git a/modules/nonfree/perf/perf_precomp.hpp b/modules/nonfree/perf/perf_precomp.hpp index 45478eb8a3..ed84be8e37 100644 --- a/modules/nonfree/perf/perf_precomp.hpp +++ b/modules/nonfree/perf/perf_precomp.hpp @@ -13,7 +13,7 @@ #include "opencv2/ts.hpp" #include "opencv2/nonfree.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/opencv_modules.hpp" diff --git a/modules/objdetect/test/test_precomp.hpp b/modules/objdetect/test/test_precomp.hpp index cd0fbe4987..a68dd79911 100644 --- a/modules/objdetect/test/test_precomp.hpp +++ b/modules/objdetect/test/test_precomp.hpp @@ -12,6 +12,6 @@ #include "opencv2/ts.hpp" #include "opencv2/objdetect.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #endif diff --git a/modules/optim/test/test_denoise_tvl1.cpp b/modules/optim/test/test_denoise_tvl1.cpp index 76ec2cda3e..f757a1438d 100644 --- a/modules/optim/test/test_denoise_tvl1.cpp +++ b/modules/optim/test/test_denoise_tvl1.cpp @@ -39,7 +39,6 @@ // //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui.hpp" void make_noisy(const cv::Mat& img, cv::Mat& noisy, double sigma, double pepper_salt_ratio,cv::RNG& rng) { diff --git a/modules/optim/test/test_precomp.hpp b/modules/optim/test/test_precomp.hpp index 9a86cab4b5..4f633e517a 100644 --- a/modules/optim/test/test_precomp.hpp +++ b/modules/optim/test/test_precomp.hpp @@ -11,5 +11,6 @@ #include "opencv2/ts.hpp" #include "opencv2/optim.hpp" +#include "opencv2/imgcodecs.hpp" #endif diff --git a/modules/photo/perf/perf_precomp.hpp b/modules/photo/perf/perf_precomp.hpp index 1fd0c81093..8e0acf7a24 100644 --- a/modules/photo/perf/perf_precomp.hpp +++ b/modules/photo/perf/perf_precomp.hpp @@ -11,7 +11,7 @@ #include "opencv2/ts.hpp" #include "opencv2/photo.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #ifdef GTEST_CREATE_SHARED_LIBRARY #error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined diff --git a/modules/photo/test/test_precomp.hpp b/modules/photo/test/test_precomp.hpp index 336e5f8424..0b18859525 100644 --- a/modules/photo/test/test_precomp.hpp +++ b/modules/photo/test/test_precomp.hpp @@ -12,7 +12,7 @@ #include #include "opencv2/ts.hpp" #include "opencv2/photo.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include #include #include diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index a50e372cc9..44f3fe5008 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -11,7 +11,7 @@ if(ANDROID OR IOS OR NOT PYTHONLIBS_FOUND OR NOT PYTHON_NUMPY_INCLUDE_DIRS) endif() set(the_description "The python bindings") -ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_highgui opencv_calib3d opencv_photo opencv_objdetect OPTIONAL opencv_nonfree) +ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_imgcodecs opencv_highgui opencv_calib3d opencv_photo opencv_objdetect OPTIONAL opencv_nonfree) ocv_module_include_directories( "${PYTHON_INCLUDE_PATH}" @@ -31,6 +31,7 @@ set(opencv_hdrs "${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/background_segm.hpp" "${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/tracking.hpp" "${OPENCV_MODULE_opencv_photo_LOCATION}/include/opencv2/photo.hpp" + "${OPENCV_MODULE_opencv_imgcodecs_LOCATION}/include/opencv2/imgcodecs.hpp" "${OPENCV_MODULE_opencv_highgui_LOCATION}/include/opencv2/highgui.hpp" "${OPENCV_MODULE_opencv_ml_LOCATION}/include/opencv2/ml.hpp" "${OPENCV_MODULE_opencv_features2d_LOCATION}/include/opencv2/features2d.hpp" diff --git a/modules/python/src2/hdr_parser.py b/modules/python/src2/hdr_parser.py index e2bab9e7d3..93b137b897 100755 --- a/modules/python/src2/hdr_parser.py +++ b/modules/python/src2/hdr_parser.py @@ -15,6 +15,7 @@ opencv_hdr_list = [ "../../video/include/opencv2/video/tracking.hpp", "../../video/include/opencv2/video/background_segm.hpp", "../../objdetect/include/opencv2/objdetect.hpp", +"../../imgcodecs/include/opencv2/imgcodecs.hpp", "../../highgui/include/opencv2/highgui.hpp" ] diff --git a/modules/shape/test/test_precomp.hpp b/modules/shape/test/test_precomp.hpp index e73248422b..819d711e85 100644 --- a/modules/shape/test/test_precomp.hpp +++ b/modules/shape/test/test_precomp.hpp @@ -13,7 +13,7 @@ #include "opencv2/ts.hpp" #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/shape.hpp" #include "opencv2/opencv_modules.hpp" diff --git a/modules/stitching/perf/perf_stich.cpp b/modules/stitching/perf/perf_stich.cpp index 1a37472e98..b64fa18984 100644 --- a/modules/stitching/perf/perf_stich.cpp +++ b/modules/stitching/perf/perf_stich.cpp @@ -1,5 +1,5 @@ #include "perf_precomp.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/flann.hpp" #include "opencv2/opencv_modules.hpp" diff --git a/modules/stitching/test/test_precomp.hpp b/modules/stitching/test/test_precomp.hpp index 60d6b3f057..0a3a709d18 100644 --- a/modules/stitching/test/test_precomp.hpp +++ b/modules/stitching/test/test_precomp.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/modules/ts/CMakeLists.txt b/modules/ts/CMakeLists.txt index 3e1b5a05ac..9bab70accc 100644 --- a/modules/ts/CMakeLists.txt +++ b/modules/ts/CMakeLists.txt @@ -9,7 +9,7 @@ set(OPENCV_MODULE_IS_PART_OF_WORLD FALSE) ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef) -ocv_add_module(ts opencv_core opencv_imgproc opencv_highgui) +ocv_add_module(ts opencv_core opencv_imgproc opencv_imgcodecs opencv_highgui) ocv_glob_module_sources() ocv_module_include_directories() diff --git a/modules/ts/include/opencv2/ts/cuda_perf.hpp b/modules/ts/include/opencv2/ts/cuda_perf.hpp index 8a23857f99..e503618ca0 100644 --- a/modules/ts/include/opencv2/ts/cuda_perf.hpp +++ b/modules/ts/include/opencv2/ts/cuda_perf.hpp @@ -44,7 +44,7 @@ #define __OPENCV_CUDA_PERF_UTILITY_HPP__ #include "opencv2/core.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/ts/ts_perf.hpp" #include "cvconfig.h" diff --git a/modules/ts/include/opencv2/ts/cuda_test.hpp b/modules/ts/include/opencv2/ts/cuda_test.hpp index c433dfec7a..049021b544 100644 --- a/modules/ts/include/opencv2/ts/cuda_test.hpp +++ b/modules/ts/include/opencv2/ts/cuda_test.hpp @@ -47,6 +47,7 @@ #include "cvconfig.h" #include "opencv2/core.hpp" #include "opencv2/core/cuda.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/ts.hpp" diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp index 43c01b2dab..227fdfc049 100644 --- a/modules/ts/include/opencv2/ts/ocl_test.hpp +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -46,6 +46,7 @@ #include "opencv2/ts.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/imgproc/types_c.h" diff --git a/modules/video/perf/perf_precomp.hpp b/modules/video/perf/perf_precomp.hpp index 0ea88f0da5..7d1e9d922e 100644 --- a/modules/video/perf/perf_precomp.hpp +++ b/modules/video/perf/perf_precomp.hpp @@ -12,7 +12,7 @@ #include "opencv2/ts.hpp" #include #include -#include +#include #ifdef GTEST_CREATE_SHARED_LIBRARY #error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined diff --git a/modules/video/test/test_precomp.hpp b/modules/video/test/test_precomp.hpp index 0aae1031f8..96a96f88fb 100644 --- a/modules/video/test/test_precomp.hpp +++ b/modules/video/test/test_precomp.hpp @@ -13,6 +13,6 @@ #include "opencv2/ts.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/video.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #endif diff --git a/samples/android/CMakeLists.txt b/samples/android/CMakeLists.txt index 0dc4a3cd69..b82c297a67 100644 --- a/samples/android/CMakeLists.txt +++ b/samples/android/CMakeLists.txt @@ -19,9 +19,9 @@ add_subdirectory(native-activity) # hello-android sample if(HAVE_opencv_highgui) - ocv_include_modules_recurse(opencv_highgui opencv_core) + ocv_include_modules_recurse(opencv_imgcodecs opencv_highgui opencv_core) add_executable(hello-android hello-android/main.cpp) - target_link_libraries(hello-android ${OPENCV_LINKER_LIBS} opencv_highgui opencv_core) + target_link_libraries(hello-android ${OPENCV_LINKER_LIBS} opencv_imgcodecs opencv_highgui opencv_core) set_target_properties(hello-android PROPERTIES OUTPUT_NAME hello-android RUNTIME_OUTPUT_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") add_dependencies(opencv_android_examples hello-android) endif() diff --git a/samples/android/hello-android/main.cpp b/samples/android/hello-android/main.cpp index cd02e1742a..3e9f762455 100644 --- a/samples/android/hello-android/main.cpp +++ b/samples/android/hello-android/main.cpp @@ -1,4 +1,5 @@ #include +#include #include using namespace cv; diff --git a/samples/cpp/3calibration.cpp b/samples/cpp/3calibration.cpp index 55644e9db4..53254050c0 100644 --- a/samples/cpp/3calibration.cpp +++ b/samples/cpp/3calibration.cpp @@ -4,6 +4,7 @@ #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/CMakeLists.txt b/samples/cpp/CMakeLists.txt index e597c0c387..732df786b5 100644 --- a/samples/cpp/CMakeLists.txt +++ b/samples/cpp/CMakeLists.txt @@ -4,7 +4,7 @@ # ---------------------------------------------------------------------------- SET(OPENCV_CPP_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_flann - opencv_highgui opencv_ml opencv_video opencv_objdetect opencv_photo opencv_nonfree + opencv_imgcodecs opencv_highgui opencv_ml opencv_video opencv_objdetect opencv_photo opencv_nonfree opencv_features2d opencv_calib3d opencv_stitching opencv_videostab opencv_shape) ocv_check_dependencies(${OPENCV_CPP_SAMPLES_REQUIRED_DEPS}) diff --git a/samples/cpp/bagofwords_classification.cpp b/samples/cpp/bagofwords_classification.cpp index 5601aa53ac..ef4f3c73c6 100644 --- a/samples/cpp/bagofwords_classification.cpp +++ b/samples/cpp/bagofwords_classification.cpp @@ -1,4 +1,5 @@ #include "opencv2/opencv_modules.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/features2d/features2d.hpp" diff --git a/samples/cpp/calibration.cpp b/samples/cpp/calibration.cpp index bb7c396b43..ffd665fa8c 100644 --- a/samples/cpp/calibration.cpp +++ b/samples/cpp/calibration.cpp @@ -2,6 +2,7 @@ #include #include "opencv2/imgproc.hpp" #include "opencv2/calib3d.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp index 24d9b7facf..be5da04bea 100644 --- a/samples/cpp/cloning_demo.cpp +++ b/samples/cpp/cloning_demo.cpp @@ -23,6 +23,7 @@ #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/core.hpp" #include diff --git a/samples/cpp/cloning_gui.cpp b/samples/cpp/cloning_gui.cpp index 2457b12154..db6cfcfde9 100644 --- a/samples/cpp/cloning_gui.cpp +++ b/samples/cpp/cloning_gui.cpp @@ -33,6 +33,7 @@ #include #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/core.hpp" #include diff --git a/samples/cpp/connected_components.cpp b/samples/cpp/connected_components.cpp index 50c677d372..32bd0dc053 100644 --- a/samples/cpp/connected_components.cpp +++ b/samples/cpp/connected_components.cpp @@ -1,5 +1,6 @@ #include #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/create_mask.cpp b/samples/cpp/create_mask.cpp index 6da64d738f..42225ebc6c 100644 --- a/samples/cpp/create_mask.cpp +++ b/samples/cpp/create_mask.cpp @@ -10,6 +10,7 @@ */ #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/core.hpp" #include diff --git a/samples/cpp/demhist.cpp b/samples/cpp/demhist.cpp index ba60115df0..033b63d82c 100644 --- a/samples/cpp/demhist.cpp +++ b/samples/cpp/demhist.cpp @@ -1,5 +1,6 @@ #include "opencv2/core/utility.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/descriptor_extractor_matcher.cpp b/samples/cpp/descriptor_extractor_matcher.cpp index fe3d4d212e..6f25ac48d7 100644 --- a/samples/cpp/descriptor_extractor_matcher.cpp +++ b/samples/cpp/descriptor_extractor_matcher.cpp @@ -1,3 +1,4 @@ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/imgproc/imgproc.hpp" diff --git a/samples/cpp/dft.cpp b/samples/cpp/dft.cpp index 4708defabb..c4034e896c 100644 --- a/samples/cpp/dft.cpp +++ b/samples/cpp/dft.cpp @@ -1,6 +1,7 @@ #include "opencv2/core.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/distrans.cpp b/samples/cpp/distrans.cpp index 706f506637..8f0ae57b55 100644 --- a/samples/cpp/distrans.cpp +++ b/samples/cpp/distrans.cpp @@ -1,5 +1,6 @@ #include #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/edge.cpp b/samples/cpp/edge.cpp index 262833c672..a4c0f5d0bb 100644 --- a/samples/cpp/edge.cpp +++ b/samples/cpp/edge.cpp @@ -1,5 +1,6 @@ #include "opencv2/core/utility.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/facedetect.cpp b/samples/cpp/facedetect.cpp index 4c5250664d..80b57b2c87 100644 --- a/samples/cpp/facedetect.cpp +++ b/samples/cpp/facedetect.cpp @@ -1,4 +1,5 @@ #include "opencv2/objdetect.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/core/utility.hpp" diff --git a/samples/cpp/ffilldemo.cpp b/samples/cpp/ffilldemo.cpp index 1cdce9bb5c..251f2a06a1 100644 --- a/samples/cpp/ffilldemo.cpp +++ b/samples/cpp/ffilldemo.cpp @@ -1,4 +1,5 @@ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/fitellipse.cpp b/samples/cpp/fitellipse.cpp index c42f8f3c3e..1e9a85857a 100644 --- a/samples/cpp/fitellipse.cpp +++ b/samples/cpp/fitellipse.cpp @@ -15,6 +15,7 @@ * ********************************************************************************/ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include using namespace cv; diff --git a/samples/cpp/grabcut.cpp b/samples/cpp/grabcut.cpp index d6cf201f4b..110e0ff770 100644 --- a/samples/cpp/grabcut.cpp +++ b/samples/cpp/grabcut.cpp @@ -1,3 +1,4 @@ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" diff --git a/samples/cpp/houghcircles.cpp b/samples/cpp/houghcircles.cpp index 12f1c57677..2a20b62a76 100644 --- a/samples/cpp/houghcircles.cpp +++ b/samples/cpp/houghcircles.cpp @@ -1,3 +1,4 @@ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" diff --git a/samples/cpp/houghlines.cpp b/samples/cpp/houghlines.cpp index 2fdabe8397..ad472a47cc 100644 --- a/samples/cpp/houghlines.cpp +++ b/samples/cpp/houghlines.cpp @@ -1,3 +1,4 @@ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" diff --git a/samples/cpp/image.cpp b/samples/cpp/image.cpp index 4d7a5715a3..f63d3b77ec 100644 --- a/samples/cpp/image.cpp +++ b/samples/cpp/image.cpp @@ -22,6 +22,7 @@ static void help() #ifdef DEMO_MIXED_API_USE # include +# include #endif int main( int argc, char** argv ) diff --git a/samples/cpp/image_alignment.cpp b/samples/cpp/image_alignment.cpp index 56e8209dd9..85fcc919de 100644 --- a/samples/cpp/image_alignment.cpp +++ b/samples/cpp/image_alignment.cpp @@ -13,6 +13,7 @@ * Authors: G. Evangelidis, INRIA, Grenoble, France * M. Asbach, Fraunhofer IAIS, St. Augustin, Germany */ +#include #include #include #include diff --git a/samples/cpp/imagelist_creator.cpp b/samples/cpp/imagelist_creator.cpp index 96114a9c4c..f2abb11c9a 100644 --- a/samples/cpp/imagelist_creator.cpp +++ b/samples/cpp/imagelist_creator.cpp @@ -2,6 +2,7 @@ */ #include "opencv2/core/core.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/inpaint.cpp b/samples/cpp/inpaint.cpp index 7690595cc2..7d17d0bf9f 100644 --- a/samples/cpp/inpaint.cpp +++ b/samples/cpp/inpaint.cpp @@ -1,3 +1,4 @@ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/photo/photo.hpp" diff --git a/samples/cpp/lsd_lines.cpp b/samples/cpp/lsd_lines.cpp index 92452a99c8..82842b2548 100644 --- a/samples/cpp/lsd_lines.cpp +++ b/samples/cpp/lsd_lines.cpp @@ -4,6 +4,7 @@ #include "opencv2/core/core.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" using namespace std; diff --git a/samples/cpp/morphology2.cpp b/samples/cpp/morphology2.cpp index e4ec8162c2..1bb4ec55e3 100644 --- a/samples/cpp/morphology2.cpp +++ b/samples/cpp/morphology2.cpp @@ -1,4 +1,5 @@ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/npr_demo.cpp b/samples/cpp/npr_demo.cpp index 5579ca269f..ff6a3fce60 100644 --- a/samples/cpp/npr_demo.cpp +++ b/samples/cpp/npr_demo.cpp @@ -17,6 +17,7 @@ #include #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/core.hpp" #include diff --git a/samples/cpp/pca.cpp b/samples/cpp/pca.cpp index d4272736c2..db5fb3802f 100644 --- a/samples/cpp/pca.cpp +++ b/samples/cpp/pca.cpp @@ -43,6 +43,7 @@ #include #include +#include "opencv2/imgcodecs.hpp" #include using namespace cv; diff --git a/samples/cpp/select3dobj.cpp b/samples/cpp/select3dobj.cpp index 32d30552f5..c0c526e178 100644 --- a/samples/cpp/select3dobj.cpp +++ b/samples/cpp/select3dobj.cpp @@ -12,6 +12,7 @@ #include #include "opencv2/imgproc.hpp" #include "opencv2/calib3d.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/shape_example.cpp b/samples/cpp/shape_example.cpp index 42630033eb..42bcffdb96 100644 --- a/samples/cpp/shape_example.cpp +++ b/samples/cpp/shape_example.cpp @@ -3,6 +3,7 @@ */ #include "opencv2/shape.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include diff --git a/samples/cpp/shape_transformation.cpp b/samples/cpp/shape_transformation.cpp index 5dac0a5116..62e5554101 100644 --- a/samples/cpp/shape_transformation.cpp +++ b/samples/cpp/shape_transformation.cpp @@ -3,6 +3,7 @@ */ #include "opencv2/shape.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/features2d/features2d.hpp" diff --git a/samples/cpp/simpleflow_demo.cpp b/samples/cpp/simpleflow_demo.cpp index c9cde783da..cc84249ec6 100644 --- a/samples/cpp/simpleflow_demo.cpp +++ b/samples/cpp/simpleflow_demo.cpp @@ -1,6 +1,7 @@ #include #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/squares.cpp b/samples/cpp/squares.cpp index 392075d79f..23d2ad0f13 100644 --- a/samples/cpp/squares.cpp +++ b/samples/cpp/squares.cpp @@ -4,6 +4,7 @@ #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/starter_imagelist.cpp b/samples/cpp/starter_imagelist.cpp index fe89579301..a576030b95 100644 --- a/samples/cpp/starter_imagelist.cpp +++ b/samples/cpp/starter_imagelist.cpp @@ -8,6 +8,7 @@ * that was generated with imagelist_creator.cpp * easy as CV_PI right? */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/starter_video.cpp b/samples/cpp/starter_video.cpp index 1a3d5b0c9a..3cc4467a81 100644 --- a/samples/cpp/starter_video.cpp +++ b/samples/cpp/starter_video.cpp @@ -11,6 +11,7 @@ * easy as CV_PI right? */ +#include #include #include diff --git a/samples/cpp/stereo_calib.cpp b/samples/cpp/stereo_calib.cpp index a989e2a011..f042d638e5 100644 --- a/samples/cpp/stereo_calib.cpp +++ b/samples/cpp/stereo_calib.cpp @@ -23,6 +23,7 @@ ************************************************** */ #include "opencv2/calib3d/calib3d.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" diff --git a/samples/cpp/stereo_match.cpp b/samples/cpp/stereo_match.cpp index 92ebc485ad..aaeea6d810 100644 --- a/samples/cpp/stereo_match.cpp +++ b/samples/cpp/stereo_match.cpp @@ -9,6 +9,7 @@ #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/core/utility.hpp" diff --git a/samples/cpp/stitching.cpp b/samples/cpp/stitching.cpp index 602edfe86e..5b4437ac9e 100644 --- a/samples/cpp/stitching.cpp +++ b/samples/cpp/stitching.cpp @@ -42,6 +42,7 @@ #include #include +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/stitching.hpp" diff --git a/samples/cpp/stitching_detailed.cpp b/samples/cpp/stitching_detailed.cpp index df0a9abc84..f33f8e19bd 100644 --- a/samples/cpp/stitching_detailed.cpp +++ b/samples/cpp/stitching_detailed.cpp @@ -46,6 +46,7 @@ #include #include "opencv2/opencv_modules.hpp" #include +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/stitching/detail/autocalib.hpp" #include "opencv2/stitching/detail/blenders.hpp" diff --git a/samples/cpp/textdetection.cpp b/samples/cpp/textdetection.cpp index f1b4ce2650..8f853250fe 100644 --- a/samples/cpp/textdetection.cpp +++ b/samples/cpp/textdetection.cpp @@ -10,6 +10,7 @@ #include "opencv2/opencv.hpp" #include "opencv2/objdetect.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" diff --git a/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp b/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp index eb858a4728..475675b417 100644 --- a/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp +++ b/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/tutorial_code/HighGUI/BasicLinearTransformsTrackbar.cpp b/samples/cpp/tutorial_code/HighGUI/BasicLinearTransformsTrackbar.cpp index 88c1dd4968..213850f995 100644 --- a/samples/cpp/tutorial_code/HighGUI/BasicLinearTransformsTrackbar.cpp +++ b/samples/cpp/tutorial_code/HighGUI/BasicLinearTransformsTrackbar.cpp @@ -5,6 +5,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" using namespace cv; diff --git a/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp index 38a5839bb2..3edfa8c3df 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp index c9e29a4aeb..e106cb461e 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp b/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp index 86d2f2e154..ce0e911237 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo1.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp b/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp index 28181c2d31..ff7b369e2c 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/calcBackProject_Demo2.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp index 577c8a8b9c..766ca3bf42 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/calcHist_Demo.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/highgui/highgui.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/imgproc/imgproc.hpp" #include #include diff --git a/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp index 424a38e93a..122e19bebc 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ImgProc/AddingImages.cpp b/samples/cpp/tutorial_code/ImgProc/AddingImages.cpp index 4e974275c6..c32a6a6fd6 100644 --- a/samples/cpp/tutorial_code/ImgProc/AddingImages.cpp +++ b/samples/cpp/tutorial_code/ImgProc/AddingImages.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/tutorial_code/ImgProc/BasicLinearTransforms.cpp b/samples/cpp/tutorial_code/ImgProc/BasicLinearTransforms.cpp index fee56bf0c2..9ffe1563de 100644 --- a/samples/cpp/tutorial_code/ImgProc/BasicLinearTransforms.cpp +++ b/samples/cpp/tutorial_code/ImgProc/BasicLinearTransforms.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp b/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp index 13a96a1f51..6d4e6eba55 100644 --- a/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp b/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp index a963bf83e6..96eb26ee0a 100644 --- a/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp b/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp index fc98d1c21a..4751a5b53f 100644 --- a/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Pyramids.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp b/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp index 8513bcf76a..238f921e92 100644 --- a/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp @@ -7,6 +7,7 @@ #include #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/features2d/features2d.hpp" diff --git a/samples/cpp/tutorial_code/ImgProc/Threshold.cpp b/samples/cpp/tutorial_code/ImgProc/Threshold.cpp index 96d5686a8d..0944f6cd3b 100644 --- a/samples/cpp/tutorial_code/ImgProc/Threshold.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Threshold.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp index 7851c9f58b..f5611b01f6 100644 --- a/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/CannyDetector_Demo.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp index 0a2a2f5fa4..00184a3f87 100644 --- a/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp index 29648ceca5..5fc36a2f7f 100644 --- a/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp index 6400c43794..2d9b7b6454 100644 --- a/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp index f6dff102d8..b6ccdf5a4c 100644 --- a/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/Laplace_Demo.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp index 86b6a2cb60..49727e9cf0 100644 --- a/samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp @@ -4,6 +4,7 @@ * @author Ana Huaman */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp b/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp index f8c97c4117..2647a4d049 100644 --- a/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/Sobel_Demo.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp b/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp index 0a441ccdfc..17cffc0c05 100644 --- a/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/copyMakeBorder_demo.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp b/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp index 86db4d8ed4..cf1577f917 100644 --- a/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp +++ b/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp index 5eb2d92a7e..cd29b1c2e7 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/findContours_demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp index d481d03898..a9c22e60fc 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp index e1f44712b7..c6fd379328 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp index 499eb452e2..0b354291a9 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/moments_demo.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/moments_demo.cpp index 9ca230f875..c3a5cbf60a 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/moments_demo.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/moments_demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp b/samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp index 31c7004787..c5dceab48b 100644 --- a/samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp +++ b/samples/cpp/tutorial_code/TrackingMotion/cornerDetector_Demo.cpp @@ -3,6 +3,7 @@ * @brief Demo code for detecting corners using OpenCV built-in functions * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp b/samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp index e048f057b2..4314a97e26 100644 --- a/samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp +++ b/samples/cpp/tutorial_code/TrackingMotion/cornerHarris_Demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp b/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp index 5957a95d6d..775e566ce7 100644 --- a/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp +++ b/samples/cpp/tutorial_code/TrackingMotion/cornerSubPix_Demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp b/samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp index b45d60a083..cff59f5390 100644 --- a/samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp +++ b/samples/cpp/tutorial_code/TrackingMotion/goodFeaturesToTrack_Demo.cpp @@ -4,6 +4,7 @@ * @author OpenCV team */ +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp index 13fde6f857..4cd9a85d84 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "opencv2/imgcodecs.hpp" #include #ifndef _CRT_SECURE_NO_WARNINGS diff --git a/samples/cpp/tutorial_code/calib3d/stereoBM/SBM_Sample.cpp b/samples/cpp/tutorial_code/calib3d/stereoBM/SBM_Sample.cpp index 64c650bb82..f4493bb56c 100644 --- a/samples/cpp/tutorial_code/calib3d/stereoBM/SBM_Sample.cpp +++ b/samples/cpp/tutorial_code/calib3d/stereoBM/SBM_Sample.cpp @@ -8,6 +8,7 @@ #include #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/core/core.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" using namespace cv; diff --git a/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp b/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp index de7a32ca6b..581a968246 100644 --- a/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp +++ b/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp @@ -1,5 +1,6 @@ #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp b/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp index f257d6ed6e..ca40fc76d9 100644 --- a/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp +++ b/samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp @@ -1,5 +1,6 @@ #include #include +#include "opencv2/imgcodecs.hpp" #include #include #include diff --git a/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp b/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp index e13f2b6960..1b1c1bc6b3 100644 --- a/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp +++ b/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp @@ -3,6 +3,7 @@ #include #include +#include "opencv2/imgcodecs.hpp" #include #include @@ -24,6 +25,7 @@ static void help( char* progName) #ifdef DEMO_MIXED_API_USE # include +# include #endif int main( int argc, char** argv ) diff --git a/samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp b/samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp index dea929960c..93e22ceb65 100644 --- a/samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp +++ b/samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/samples/cpp/tutorial_code/features2D/SURF_FlannMatcher.cpp b/samples/cpp/tutorial_code/features2D/SURF_FlannMatcher.cpp index 7ccebcdd5f..e861a5f108 100644 --- a/samples/cpp/tutorial_code/features2D/SURF_FlannMatcher.cpp +++ b/samples/cpp/tutorial_code/features2D/SURF_FlannMatcher.cpp @@ -8,6 +8,7 @@ #include #include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/nonfree/features2d.hpp" diff --git a/samples/cpp/tutorial_code/features2D/SURF_Homography.cpp b/samples/cpp/tutorial_code/features2D/SURF_Homography.cpp index 47bc3ecfe3..f3d4df88fb 100644 --- a/samples/cpp/tutorial_code/features2D/SURF_Homography.cpp +++ b/samples/cpp/tutorial_code/features2D/SURF_Homography.cpp @@ -8,6 +8,7 @@ #include #include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/nonfree/features2d.hpp" diff --git a/samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp b/samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp index 89b60d4baa..140136d3a6 100644 --- a/samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp +++ b/samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp @@ -8,6 +8,7 @@ #include #include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/nonfree/features2d.hpp" diff --git a/samples/cpp/tutorial_code/features2D/SURF_detector.cpp b/samples/cpp/tutorial_code/features2D/SURF_detector.cpp index a1288a8c85..2a14bdc079 100644 --- a/samples/cpp/tutorial_code/features2D/SURF_detector.cpp +++ b/samples/cpp/tutorial_code/features2D/SURF_detector.cpp @@ -8,6 +8,7 @@ #include #include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/nonfree/features2d.hpp" diff --git a/samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp b/samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp index 501f87c484..515f7a38b1 100644 --- a/samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp +++ b/samples/cpp/tutorial_code/gpu/gpu-basics-similarity/gpu-basics-similarity.cpp @@ -4,7 +4,7 @@ #include // Basic OpenCV structures #include #include // Image processing methods for the CPU -#include // Read images +#include // Read images // CUDA structures and methods #include diff --git a/samples/cpp/tutorial_code/introduction/display_image/display_image.cpp b/samples/cpp/tutorial_code/introduction/display_image/display_image.cpp index 847cd8f6dc..67403708a1 100644 --- a/samples/cpp/tutorial_code/introduction/display_image/display_image.cpp +++ b/samples/cpp/tutorial_code/introduction/display_image/display_image.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/samples/cpp/tutorial_code/introduction/windows_visual_studio_Opencv/introduction_windows_vs.cpp b/samples/cpp/tutorial_code/introduction/windows_visual_studio_Opencv/introduction_windows_vs.cpp index 8db86d8de8..c3343fb86b 100644 --- a/samples/cpp/tutorial_code/introduction/windows_visual_studio_Opencv/introduction_windows_vs.cpp +++ b/samples/cpp/tutorial_code/introduction/windows_visual_studio_Opencv/introduction_windows_vs.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/samples/cpp/tutorial_code/ml/introduction_to_svm/introduction_to_svm.cpp b/samples/cpp/tutorial_code/ml/introduction_to_svm/introduction_to_svm.cpp index 1c8dbd24a6..2b4a97d54d 100644 --- a/samples/cpp/tutorial_code/ml/introduction_to_svm/introduction_to_svm.cpp +++ b/samples/cpp/tutorial_code/ml/introduction_to_svm/introduction_to_svm.cpp @@ -1,4 +1,5 @@ #include +#include "opencv2/imgcodecs.hpp" #include #include diff --git a/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp b/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp index 4f6daecaa9..bfab746cdf 100644 --- a/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp +++ b/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp @@ -1,5 +1,6 @@ #include #include +#include "opencv2/imgcodecs.hpp" #include #include diff --git a/samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp b/samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp index aa84b15d4e..6ff6687678 100644 --- a/samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp +++ b/samples/cpp/tutorial_code/photo/hdr_imaging/hdr_imaging.cpp @@ -1,4 +1,5 @@ #include +#include "opencv2/imgcodecs.hpp" #include #include #include diff --git a/samples/cpp/tutorial_code/video/bg_sub.cpp b/samples/cpp/tutorial_code/video/bg_sub.cpp index 24805a1edc..6faa020b80 100644 --- a/samples/cpp/tutorial_code/video/bg_sub.cpp +++ b/samples/cpp/tutorial_code/video/bg_sub.cpp @@ -5,6 +5,7 @@ */ //opencv +#include "opencv2/imgcodecs.hpp" #include #include //C diff --git a/samples/cpp/tvl1_optical_flow.cpp b/samples/cpp/tvl1_optical_flow.cpp index f5e71863c2..dee9cf6e33 100644 --- a/samples/cpp/tvl1_optical_flow.cpp +++ b/samples/cpp/tvl1_optical_flow.cpp @@ -3,6 +3,7 @@ #include #include "opencv2/video.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" using namespace cv; diff --git a/samples/cpp/ufacedetect.cpp b/samples/cpp/ufacedetect.cpp index 5e13a8211e..e7e85d5633 100644 --- a/samples/cpp/ufacedetect.cpp +++ b/samples/cpp/ufacedetect.cpp @@ -1,4 +1,5 @@ #include "opencv2/objdetect.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/core/utility.hpp" diff --git a/samples/cpp/watershed.cpp b/samples/cpp/watershed.cpp index cd47505045..e57c5aa1cf 100644 --- a/samples/cpp/watershed.cpp +++ b/samples/cpp/watershed.cpp @@ -1,5 +1,6 @@ #include #include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/directx/CMakeLists.txt b/samples/directx/CMakeLists.txt index 0bd7de941e..97d7fc305c 100644 --- a/samples/directx/CMakeLists.txt +++ b/samples/directx/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_highgui) +SET(OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_highgui) ocv_check_dependencies(${OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS}) diff --git a/samples/directx/d3d_base.inl.hpp b/samples/directx/d3d_base.inl.hpp index 0ef5c00a00..0ba44eca15 100644 --- a/samples/directx/d3d_base.inl.hpp +++ b/samples/directx/d3d_base.inl.hpp @@ -8,6 +8,7 @@ #include "opencv2/imgproc/types_c.h" // cvtColor #include "opencv2/highgui.hpp" // imread #include "opencv2/core/directx.hpp" +#include "opencv2/imgcodecs.hpp" #include #include diff --git a/samples/gpu/CMakeLists.txt b/samples/gpu/CMakeLists.txt index ca5243aa0b..87beb1bea1 100644 --- a/samples/gpu/CMakeLists.txt +++ b/samples/gpu/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(OPENCV_CUDA_SAMPLES_REQUIRED_DEPS opencv_core opencv_flann opencv_imgproc opencv_highgui +SET(OPENCV_CUDA_SAMPLES_REQUIRED_DEPS opencv_core opencv_flann opencv_imgproc opencv_imgcodecs opencv_highgui opencv_ml opencv_video opencv_objdetect opencv_features2d opencv_calib3d opencv_legacy opencv_contrib opencv_cuda opencv_nonfree opencv_softcascade opencv_superres diff --git a/samples/tapi/CMakeLists.txt b/samples/tapi/CMakeLists.txt index e1fc8552c6..25436bb710 100644 --- a/samples/tapi/CMakeLists.txt +++ b/samples/tapi/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(OPENCV_TAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_video opencv_highgui opencv_objdetect opencv_features2d opencv_calib3d opencv_nonfree opencv_flann) +SET(OPENCV_TAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_video opencv_imgcodecs opencv_highgui opencv_objdetect opencv_features2d opencv_calib3d opencv_nonfree opencv_flann) ocv_check_dependencies(${OPENCV_TAPI_SAMPLES_REQUIRED_DEPS}) diff --git a/samples/tapi/clahe.cpp b/samples/tapi/clahe.cpp index a28f2ab05d..9f9404d35d 100644 --- a/samples/tapi/clahe.cpp +++ b/samples/tapi/clahe.cpp @@ -3,6 +3,7 @@ #include "opencv2/core/ocl.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" using namespace cv; diff --git a/samples/tapi/hog.cpp b/samples/tapi/hog.cpp index ee537b310e..ac227fc0c9 100644 --- a/samples/tapi/hog.cpp +++ b/samples/tapi/hog.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "opencv2/imgcodecs.hpp" #include #include #include diff --git a/samples/tapi/pyrlk_optical_flow.cpp b/samples/tapi/pyrlk_optical_flow.cpp index d4b77294be..cc48374a6e 100644 --- a/samples/tapi/pyrlk_optical_flow.cpp +++ b/samples/tapi/pyrlk_optical_flow.cpp @@ -3,6 +3,7 @@ #include #include "opencv2/core/utility.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/core/ocl.hpp" #include "opencv2/video/video.hpp" diff --git a/samples/tapi/squares.cpp b/samples/tapi/squares.cpp index 402702e497..87a3894b93 100644 --- a/samples/tapi/squares.cpp +++ b/samples/tapi/squares.cpp @@ -6,6 +6,7 @@ #include "opencv2/core/ocl.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include #include diff --git a/samples/tapi/surf_matcher.cpp b/samples/tapi/surf_matcher.cpp index 9066bfd3fb..2aca96f1bc 100644 --- a/samples/tapi/surf_matcher.cpp +++ b/samples/tapi/surf_matcher.cpp @@ -3,6 +3,7 @@ #include "opencv2/core/core.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/core/ocl.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/features2d.hpp" #include "opencv2/calib3d.hpp" diff --git a/samples/tapi/tvl1_optical_flow.cpp b/samples/tapi/tvl1_optical_flow.cpp index 436ba715c8..b37c5bb764 100644 --- a/samples/tapi/tvl1_optical_flow.cpp +++ b/samples/tapi/tvl1_optical_flow.cpp @@ -4,6 +4,7 @@ #include "opencv2/core/ocl.hpp" #include "opencv2/core/utility.hpp" +#include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/video/video.hpp" From eb8366bb0a75819f286c7f4d3452999c10dc9cf1 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Tue, 8 Jul 2014 12:21:54 +0400 Subject: [PATCH 050/136] DShow camera as IVideoCapture object --- modules/highgui/src/cap.cpp | 30 ++-- modules/highgui/src/cap_dshow.cpp | 256 ++++++++++++------------------ modules/highgui/src/cap_dshow.hpp | 49 ++++++ 3 files changed, 163 insertions(+), 172 deletions(-) create mode 100644 modules/highgui/src/cap_dshow.hpp diff --git a/modules/highgui/src/cap.cpp b/modules/highgui/src/cap.cpp index 9311694d0a..17cbf6191c 100644 --- a/modules/highgui/src/cap.cpp +++ b/modules/highgui/src/cap.cpp @@ -41,6 +41,7 @@ #include "precomp.hpp" #include "cap_intelperc.hpp" +#include "cap_dshow.hpp" #if defined _M_X64 && defined _MSC_VER && !defined CV_ICC #pragma optimize("",off) @@ -115,9 +116,6 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) { int domains[] = { -#ifdef HAVE_DSHOW - CV_CAP_DSHOW, -#endif #ifdef HAVE_MSMF CV_CAP_MSMF, #endif @@ -175,8 +173,7 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) // try every possibly installed camera API for (int i = 0; domains[i] >= 0; i++) { -#if defined(HAVE_DSHOW) || \ - defined(HAVE_MSMF) || \ +#if defined(HAVE_MSMF) || \ defined(HAVE_TYZX) || \ defined(HAVE_VFW) || \ defined(HAVE_LIBV4L) || \ @@ -205,13 +202,6 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) switch (domains[i]) { -#ifdef HAVE_DSHOW - case CV_CAP_DSHOW: - capture = cvCreateCameraCapture_DShow (index); - if (capture) - return capture; - break; -#endif #ifdef HAVE_MSMF case CV_CAP_MSMF: capture = cvCreateCameraCapture_MSMF (index); @@ -589,6 +579,9 @@ Ptr VideoCapture::createCameraCapture(int index) { int domains[] = { +#ifdef HAVE_DSHOW + CV_CAP_DSHOW, +#endif #ifdef HAVE_INTELPERC CV_CAP_INTELPERC, #endif @@ -607,18 +600,26 @@ Ptr VideoCapture::createCameraCapture(int index) // try every possibly installed camera API for (int i = 0; domains[i] >= 0; i++) { -#if defined(HAVE_INTELPERC) || \ +#if defined(HAVE_DSHOW) || \ + defined(HAVE_INTELPERC) || \ (0) Ptr capture; switch (domains[i]) { +#ifdef HAVE_DSHOW + case CV_CAP_DSHOW: + capture = Ptr(new cv::VideoCapture_DShow(index)); + if (capture) + return capture; + break; // CV_CAP_DSHOW +#endif #ifdef HAVE_INTELPERC case CV_CAP_INTELPERC: capture = Ptr(new cv::VideoCapture_IntelPerC()); if (capture) return capture; - break; // CV_CAP_INTEL_PERC + break; // CV_CAP_INTEL_PERC #endif } #endif @@ -628,7 +629,6 @@ Ptr VideoCapture::createCameraCapture(int index) return Ptr(); } - VideoWriter::VideoWriter() {} diff --git a/modules/highgui/src/cap_dshow.cpp b/modules/highgui/src/cap_dshow.cpp index 90ffa00034..337ed6d3f6 100644 --- a/modules/highgui/src/cap_dshow.cpp +++ b/modules/highgui/src/cap_dshow.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #if (defined WIN32 || defined _WIN32) && defined HAVE_DSHOW +#include "cap_dshow.hpp" /* DirectShow-based Video Capturing module is based on @@ -455,13 +456,7 @@ class videoDevice{ }; - - - ////////////////////////////////////// VIDEO INPUT ///////////////////////////////////// - - - class videoInput{ public: @@ -3098,131 +3093,53 @@ HRESULT videoInput::routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter * return hr; } - -/********************* Capturing video from camera via DirectShow *********************/ - -class CvCaptureCAM_DShow : public CvCapture -{ -public: - CvCaptureCAM_DShow(); - virtual ~CvCaptureCAM_DShow(); - - virtual bool open( int index ); - virtual void close(); - virtual double getProperty(int); - virtual bool setProperty(int, double); - virtual bool grabFrame(); - virtual IplImage* retrieveFrame(int); - virtual int getCaptureDomain() { return CV_CAP_DSHOW; } // Return the type of the capture object: CV_CAP_VFW, etc... - -protected: - void init(); - - int index, width, height,fourcc; - int widthSet, heightSet; - IplImage* frame; - static videoInput VI; -}; - - struct SuppressVideoInputMessages { SuppressVideoInputMessages() { videoInput::setVerbose(false); } }; static SuppressVideoInputMessages do_it; -videoInput CvCaptureCAM_DShow::VI; -CvCaptureCAM_DShow::CvCaptureCAM_DShow() +namespace cv +{ +videoInput VideoCapture_DShow::g_VI; + +VideoCapture_DShow::VideoCapture_DShow(int index) + : m_index(-1) + , m_frame(0) + , m_width(-1) + , m_height(-1) + , m_fourcc(-1) + , m_widthSet(-1) + , m_heightSet(-1) { - index = -1; - frame = 0; - width = height = fourcc = -1; - widthSet = heightSet = -1; CoInitialize(0); + open(index); } - -CvCaptureCAM_DShow::~CvCaptureCAM_DShow() +VideoCapture_DShow::~VideoCapture_DShow() { close(); CoUninitialize(); } -void CvCaptureCAM_DShow::close() -{ - if( index >= 0 ) - { - VI.stopDevice(index); - index = -1; - cvReleaseImage(&frame); - } - widthSet = heightSet = width = height = -1; -} - -// Initialize camera input -bool CvCaptureCAM_DShow::open( int _index ) -{ - int devices = 0; - - close(); - devices = VI.listDevices(true); - if (devices == 0) - return false; - if (_index < 0 || _index > devices-1) - return false; - VI.setupDevice(_index); - if( !VI.isDeviceSetup(_index) ) - return false; - index = _index; - return true; -} - -bool CvCaptureCAM_DShow::grabFrame() -{ - return true; -} - - -IplImage* CvCaptureCAM_DShow::retrieveFrame(int) -{ - if( !frame || VI.getWidth(index) != frame->width || VI.getHeight(index) != frame->height ) - { - if (frame) - cvReleaseImage( &frame ); - int w = VI.getWidth(index), h = VI.getHeight(index); - frame = cvCreateImage( cvSize(w,h), 8, 3 ); - } - - if (VI.getPixels( index, (uchar*)frame->imageData, false, true )) - return frame; - else - return NULL; -} - -double CvCaptureCAM_DShow::getProperty( int property_id ) +double VideoCapture_DShow::getProperty(int propIdx) { - long min_value,max_value,stepping_delta,current_value,flags,defaultValue; + long min_value, max_value, stepping_delta, current_value, flags, defaultValue; - // image format proprrties - switch( property_id ) + switch (propIdx) { + // image format properties case CV_CAP_PROP_FRAME_WIDTH: - return VI.getWidth(index); - + return g_VI.getWidth(m_index); case CV_CAP_PROP_FRAME_HEIGHT: - return VI.getHeight(index); - + return g_VI.getHeight(m_index); case CV_CAP_PROP_FOURCC: - return VI.getFourcc(index); - + return g_VI.getFourcc(m_index); case CV_CAP_PROP_FPS: - return VI.getFPS(index); - } + return g_VI.getFPS(m_index); // video filter properties - switch( property_id ) - { case CV_CAP_PROP_BRIGHTNESS: case CV_CAP_PROP_CONTRAST: case CV_CAP_PROP_HUE: @@ -3233,12 +3150,10 @@ double CvCaptureCAM_DShow::getProperty( int property_id ) case CV_CAP_PROP_WHITE_BALANCE_BLUE_U: case CV_CAP_PROP_BACKLIGHT: case CV_CAP_PROP_GAIN: - if (VI.getVideoSettingFilter(index,VI.getVideoPropertyFromCV(property_id),min_value,max_value,stepping_delta,current_value,flags,defaultValue) ) return (double)current_value; - } + if (g_VI.getVideoSettingFilter(m_index, g_VI.getVideoPropertyFromCV(propIdx), min_value, max_value, stepping_delta, current_value, flags, defaultValue)) + return (double)current_value; // camera properties - switch( property_id ) - { case CV_CAP_PROP_PAN: case CV_CAP_PROP_TILT: case CV_CAP_PROP_ROLL: @@ -3246,33 +3161,33 @@ double CvCaptureCAM_DShow::getProperty( int property_id ) case CV_CAP_PROP_EXPOSURE: case CV_CAP_PROP_IRIS: case CV_CAP_PROP_FOCUS: - if (VI.getVideoSettingCamera(index,VI.getCameraPropertyFromCV(property_id),min_value,max_value,stepping_delta,current_value,flags,defaultValue) ) return (double)current_value; - + if (g_VI.getVideoSettingCamera(m_index, g_VI.getCameraPropertyFromCV(propIdx), min_value, max_value, stepping_delta, current_value, flags, defaultValue)) + return (double)current_value; } // unknown parameter or value not available return -1; } - -bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) +bool VideoCapture_DShow::setProperty(int propIdx, double propVal) { // image capture properties bool handled = false; - switch( property_id ) + switch (propIdx) { case CV_CAP_PROP_FRAME_WIDTH: - width = cvRound(value); + m_width = cvRound(propVal); handled = true; break; case CV_CAP_PROP_FRAME_HEIGHT: - height = cvRound(value); + m_height = cvRound(propVal); handled = true; break; case CV_CAP_PROP_FOURCC: - fourcc = (int)(unsigned long)(value); - if ( fourcc == -1 ) { + m_fourcc = (int)(unsigned long)(propVal); + if (-1 == m_fourcc) + { // following cvCreateVideo usage will pop up caprturepindialog here if fourcc=-1 // TODO - how to create a capture pin dialog } @@ -3280,38 +3195,38 @@ bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) break; case CV_CAP_PROP_FPS: - int fps = cvRound(value); - if (fps != VI.getFPS(index)) + int fps = cvRound(propVal); + if (fps != g_VI.getFPS(m_index)) { - VI.stopDevice(index); - VI.setIdealFramerate(index,fps); - if (widthSet > 0 && heightSet > 0) - VI.setupDevice(index, widthSet, heightSet); + g_VI.stopDevice(m_index); + g_VI.setIdealFramerate(m_index, fps); + if (m_widthSet > 0 && m_heightSet > 0) + g_VI.setupDevice(m_index, m_widthSet, m_heightSet); else - VI.setupDevice(index); + g_VI.setupDevice(m_index); } - return VI.isDeviceSetup(index); - + return g_VI.isDeviceSetup(m_index); } - if ( handled ) { + if (handled) + { // a stream setting - if( width > 0 && height > 0 ) + if (m_width > 0 && m_height > 0) { - if( width != VI.getWidth(index) || height != VI.getHeight(index) )//|| fourcc != VI.getFourcc(index) ) + if (m_width != g_VI.getWidth(m_index) || m_height != g_VI.getHeight(m_index) )//|| fourcc != VI.getFourcc(index) ) { - int fps = static_cast(VI.getFPS(index)); - VI.stopDevice(index); - VI.setIdealFramerate(index, fps); - VI.setupDeviceFourcc(index, width, height, fourcc); + int fps = static_cast(g_VI.getFPS(m_index)); + g_VI.stopDevice(m_index); + g_VI.setIdealFramerate(m_index, fps); + g_VI.setupDeviceFourcc(m_index, m_width, m_height, m_fourcc); } - bool success = VI.isDeviceSetup(index); + bool success = g_VI.isDeviceSetup(m_index); if (success) { - widthSet = width; - heightSet = height; - width = height = fourcc = -1; + m_widthSet = m_width; + m_heightSet = m_height; + m_width = m_height = m_fourcc = -1; } return success; } @@ -3319,13 +3234,14 @@ bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) } // show video/camera filter dialog - if ( property_id == CV_CAP_PROP_SETTINGS ) { - VI.showSettingsWindow(index); + if (propIdx == CV_CAP_PROP_SETTINGS ) + { + g_VI.showSettingsWindow(m_index); return true; } //video Filter properties - switch( property_id ) + switch (propIdx) { case CV_CAP_PROP_BRIGHTNESS: case CV_CAP_PROP_CONTRAST: @@ -3337,11 +3253,11 @@ bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) case CV_CAP_PROP_WHITE_BALANCE_BLUE_U: case CV_CAP_PROP_BACKLIGHT: case CV_CAP_PROP_GAIN: - return VI.setVideoSettingFilter(index,VI.getVideoPropertyFromCV(property_id),(long)value); + return g_VI.setVideoSettingFilter(m_index, g_VI.getVideoPropertyFromCV(propIdx), (long)propVal); } //camera properties - switch( property_id ) + switch (propIdx) { case CV_CAP_PROP_PAN: case CV_CAP_PROP_TILT: @@ -3350,30 +3266,56 @@ bool CvCaptureCAM_DShow::setProperty( int property_id, double value ) case CV_CAP_PROP_EXPOSURE: case CV_CAP_PROP_IRIS: case CV_CAP_PROP_FOCUS: - return VI.setVideoSettingCamera(index,VI.getCameraPropertyFromCV(property_id),(long)value); + return g_VI.setVideoSettingCamera(m_index, g_VI.getCameraPropertyFromCV(propIdx), (long)propVal); } return false; } +bool VideoCapture_DShow::grabFrame() +{ + return true; +} +bool VideoCapture_DShow::retrieveFrame(int, OutputArray frame) +{ + frame.create(Size(g_VI.getWidth(m_index), g_VI.getHeight(m_index)), CV_8UC3); + cv::Mat mat = frame.getMat(); + return g_VI.getPixels(m_index, mat.ptr(), false, true ); +} +int VideoCapture_DShow::getCaptureDomain() +{ + return CV_CAP_DSHOW; +} +bool VideoCapture_DShow::isOpened() const +{ + return (-1 != m_index); +} -CvCapture* cvCreateCameraCapture_DShow( int index ) +void VideoCapture_DShow::open(int index) { - CvCaptureCAM_DShow* capture = new CvCaptureCAM_DShow; + close(); + int devices = g_VI.listDevices(true); + if (0 == devices) + return; + if (index < 0 || index > devices-1) + return; + g_VI.setupDevice(index); + if (!g_VI.isDeviceSetup(index)) + return; + m_index = index; +} - try - { - if( capture->open( index )) - return capture; - } - catch(...) +void VideoCapture_DShow::close() +{ + if (m_index >= 0) { - delete capture; - throw; + g_VI.stopDevice(m_index); + m_index = -1; + cvReleaseImage(&m_frame); } + m_widthSet = m_heightSet = m_width = m_height = -1; +} - delete capture; - return 0; } #endif diff --git a/modules/highgui/src/cap_dshow.hpp b/modules/highgui/src/cap_dshow.hpp new file mode 100644 index 0000000000..c4ab57161f --- /dev/null +++ b/modules/highgui/src/cap_dshow.hpp @@ -0,0 +1,49 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2014, Itseez, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +//M*/ + +#ifndef _CAP_DSHOW_HPP_ +#define _CAP_DSHOW_HPP_ + +#include "precomp.hpp" + +#ifdef HAVE_DSHOW + +class videoInput; +namespace cv +{ + +class VideoCapture_DShow : public IVideoCapture +{ +public: + VideoCapture_DShow(int index); + virtual ~VideoCapture_DShow(); + + virtual double getProperty(int propIdx); + virtual bool setProperty(int propIdx, double propVal); + + virtual bool grabFrame(); + virtual bool retrieveFrame(int outputType, OutputArray frame); + virtual int getCaptureDomain(); + bool isOpened() const; +protected: + void open(int index); + void close(); + + int m_index, m_width, m_height, m_fourcc; + int m_widthSet, m_heightSet; + IplImage* m_frame; + static videoInput g_VI; +}; + +} + +#endif //HAVE_DSHOW +#endif //_CAP_DSHOW_HPP_ \ No newline at end of file From 7fe7facfee4407b2b95a9a13e4041c7ebcf340ba Mon Sep 17 00:00:00 2001 From: vbystricky Date: Tue, 8 Jul 2014 13:29:28 +0400 Subject: [PATCH 051/136] Remove unused variable --- modules/highgui/src/cap_dshow.cpp | 2 -- modules/highgui/src/cap_dshow.hpp | 1 - 2 files changed, 3 deletions(-) diff --git a/modules/highgui/src/cap_dshow.cpp b/modules/highgui/src/cap_dshow.cpp index 337ed6d3f6..bc9f05eb8f 100644 --- a/modules/highgui/src/cap_dshow.cpp +++ b/modules/highgui/src/cap_dshow.cpp @@ -3106,7 +3106,6 @@ videoInput VideoCapture_DShow::g_VI; VideoCapture_DShow::VideoCapture_DShow(int index) : m_index(-1) - , m_frame(0) , m_width(-1) , m_height(-1) , m_fourcc(-1) @@ -3311,7 +3310,6 @@ void VideoCapture_DShow::close() { g_VI.stopDevice(m_index); m_index = -1; - cvReleaseImage(&m_frame); } m_widthSet = m_heightSet = m_width = m_height = -1; } diff --git a/modules/highgui/src/cap_dshow.hpp b/modules/highgui/src/cap_dshow.hpp index c4ab57161f..2225145faa 100644 --- a/modules/highgui/src/cap_dshow.hpp +++ b/modules/highgui/src/cap_dshow.hpp @@ -39,7 +39,6 @@ protected: int m_index, m_width, m_height, m_fourcc; int m_widthSet, m_heightSet; - IplImage* m_frame; static videoInput g_VI; }; From e8f5c2fcf63de2fd620e1c941f8740aba276d4c6 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 8 Jul 2014 18:51:27 +0400 Subject: [PATCH 052/136] OpenCL before IPP --- modules/imgproc/src/deriv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 5e920ec0b8..1a29c38abf 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -702,7 +702,7 @@ void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, #ifdef HAVE_IPP if ((ksize == 3 || ksize == 5) && ((borderType & BORDER_ISOLATED) != 0 || !_src.isSubmatrix()) && - ((stype == CV_8UC1 && ddepth == CV_16S) || (ddepth == CV_32F && stype == CV_32FC1))) + ((stype == CV_8UC1 && ddepth == CV_16S) || (ddepth == CV_32F && stype == CV_32FC1)) && !ocl::useOpenCL()) { int iscale = saturate_cast(scale), idelta = saturate_cast(delta); bool floatScale = std::fabs(scale - iscale) > DBL_EPSILON, needScale = iscale != 1; From f8b23cff18abbc5c3f7f9117a242b7298dbaa7f2 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 9 Jul 2014 13:39:40 +0800 Subject: [PATCH 053/136] Fixed test errors, added support for C data types. --- modules/imgproc/src/histogram.cpp | 34 +++++++++++++++++++----- modules/imgproc/test/test_histograms.cpp | 18 +++++++------ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 1be7315acb..c16386e1a7 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -2325,13 +2325,16 @@ double cv::compareHist( InputArray _H1, InputArray _H2, int method ) } else if( method == CV_COMP_KL_DIV ) { - for( j = 0; j < len; j++ ){ + for( j = 0; j < len; j++ ) + { double p = h1[j]; double q = h2[j]; - if( p == 0.0 ) + if( fabs(p) <= DBL_EPSILON ) { continue; - if( q == 0.0 ) - q += 1e-10; + } + if( fabs(q) <= DBL_EPSILON ) { + q = 1e-10; + } result += p * cv::log( p / q ); } } @@ -2370,7 +2373,7 @@ double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method ) CV_Assert( H1.size(i) == H2.size(i) ); const SparseMat *PH1 = &H1, *PH2 = &H2; - if( PH1->nzcount() > PH2->nzcount() && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT) + if( PH1->nzcount() > PH2->nzcount() && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT && method != CV_COMP_KL_DIV ) std::swap(PH1, PH2); SparseMatConstIterator it = PH1->begin(); @@ -2450,6 +2453,18 @@ double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method ) s1 = fabs(s1) > FLT_EPSILON ? 1./std::sqrt(s1) : 1.; result = std::sqrt(std::max(1. - result*s1, 0.)); } + else if( method == CV_COMP_KL_DIV ) + { + for( i = 0; i < N1; i++, ++it ) + { + float v1 = it.value(); + const SparseMat::Node* node = it.node(); + float v2 = PH2->value(node->idx, (size_t*)&node->hashval); + if( !v2 ) + v2 = 1e-10; + result += v1 * cv::log( v1 / v2 ); + } + } else CV_Error( CV_StsBadArg, "Unknown comparison method" ); @@ -2795,7 +2810,7 @@ cvCompareHist( const CvHistogram* hist1, CvSparseMatIterator iterator; CvSparseNode *node1, *node2; - if( mat1->heap->active_count > mat2->heap->active_count && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT) + if( mat1->heap->active_count > mat2->heap->active_count && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT && method != CV_COMP_KL_DIV ) { CvSparseMat* t; CV_SWAP( mat1, mat2, t ); @@ -2897,6 +2912,13 @@ cvCompareHist( const CvHistogram* hist1, result = 1. - result*s1; result = sqrt(MAX(result,0.)); } + else if( method == CV_COMP_KL_DIV ) + { + cv::SparseMat sH1, sH2; + ((const CvSparseMat*)hist1->bins)->copyToSparseMat(sH1); + ((const CvSparseMat*)hist2->bins)->copyToSparseMat(sH2); + result = cv::compareHist( sH1, sH2, CV_COMP_KL_DIV ); + } else CV_Error( CV_StsBadArg, "Unknown comparison method" ); diff --git a/modules/imgproc/test/test_histograms.cpp b/modules/imgproc/test/test_histograms.cpp index 55f4df03c1..51c3aab985 100644 --- a/modules/imgproc/test/test_histograms.cpp +++ b/modules/imgproc/test/test_histograms.cpp @@ -1021,11 +1021,12 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ ) sq0 += v0*v0; sq1 += v1*v1; result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1); - if( fabs(v0) > DBL_EPSILON ) { - if( fabs(v1) < DBL_EPSILON ) - v1 += 1e-10; - result0[CV_COMP_KL_DIV] += v0 * cv::log( v0 / v1 ); + if( fabs(v0) <= DBL_EPSILON ) + continue; + if( fabs(v1) <= DBL_EPSILON ) + v1 = 1e-10; + result0[CV_COMP_KL_DIV] += v0 * std::log( v0 / v1 ); } } } @@ -1052,11 +1053,12 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ ) s0 += v0; sq0 += v0*v0; result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1); - if( fabs(v0) > DBL_EPSILON ) { - if( fabs(v1) < DBL_EPSILON ) - v1 += 1e-10; - result0[CV_COMP_KL_DIV] += v0 * cv::log( v0 / v1 ); + if (v0 <= DBL_EPSILON) + continue; + if (!v1) + v1 = 1e-10; + result0[CV_COMP_KL_DIV] += v0 * cv::log( v0 / v1 ); } } From 0d49f97128b852040d44048bc4cf9a8764fc38a9 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 9 Jul 2014 15:29:47 +0800 Subject: [PATCH 054/136] Fixed truncation warning --- modules/imgproc/src/histogram.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index c16386e1a7..97ca3deda5 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -2457,9 +2457,9 @@ double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method ) { for( i = 0; i < N1; i++, ++it ) { - float v1 = it.value(); + double v1 = it.value(); const SparseMat::Node* node = it.node(); - float v2 = PH2->value(node->idx, (size_t*)&node->hashval); + double v2 = PH2->value(node->idx, (size_t*)&node->hashval); if( !v2 ) v2 = 1e-10; result += v1 * cv::log( v1 / v2 ); From 2e49ca4903175f507e828047a58acabc1010e827 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 9 Jul 2014 16:04:22 +0800 Subject: [PATCH 055/136] Avoid unmap an umat(ocl) which hasn't been mapped at all. According to opencl 1.2 spec 5.4.2: enqueues a command to unmap a previously mapped region of a memory object. ... CL_INVALID_VALUE if mapped_ptr is not a valid pointer returned by clEnqueueMapBuffer, or clEnqueueMapImage for memobj. So if the u->data is not from a clEnqueueMapBuffer call, we should not call clEnqueueUnmapMemObject() unmap it. With this patch, the cases ./opencv_test_video --gtest_filter=OCL_Video/FarnebackOpticalFlow.Mat/* could work well with beignet 0.9.1, Otherwise, it will get a CL_INVALID_VALUE at the clEnqueueUnmapMemObject(). Signed-off-by: Zhigang Gong --- modules/core/include/opencv2/core/mat.hpp | 4 +++- modules/core/include/opencv2/core/mat.inl.hpp | 9 +++++++++ modules/core/src/ocl.cpp | 7 ++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index d399265b0b..945b450303 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -360,7 +360,7 @@ struct CV_EXPORTS UMatData { enum { COPY_ON_MAP=1, HOST_COPY_OBSOLETE=2, DEVICE_COPY_OBSOLETE=4, TEMP_UMAT=8, TEMP_COPIED_UMAT=24, - USER_ALLOCATED=32 }; + USER_ALLOCATED=32, DEVICE_MEM_MAPPED=64}; UMatData(const MatAllocator* allocator); ~UMatData(); @@ -370,11 +370,13 @@ struct CV_EXPORTS UMatData bool hostCopyObsolete() const; bool deviceCopyObsolete() const; + bool deviceMemMapped() const; bool copyOnMap() const; bool tempUMat() const; bool tempCopiedUMat() const; void markHostCopyObsolete(bool flag); void markDeviceCopyObsolete(bool flag); + void markDeviceMemMapped(bool flag); const MatAllocator* prevAllocator; const MatAllocator* currAllocator; diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index d463eec671..dae0e137a8 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -3350,10 +3350,19 @@ size_t UMat::total() const inline bool UMatData::hostCopyObsolete() const { return (flags & HOST_COPY_OBSOLETE) != 0; } inline bool UMatData::deviceCopyObsolete() const { return (flags & DEVICE_COPY_OBSOLETE) != 0; } +inline bool UMatData::deviceMemMapped() const { return (flags & DEVICE_MEM_MAPPED) != 0; } inline bool UMatData::copyOnMap() const { return (flags & COPY_ON_MAP) != 0; } inline bool UMatData::tempUMat() const { return (flags & TEMP_UMAT) != 0; } inline bool UMatData::tempCopiedUMat() const { return (flags & TEMP_COPIED_UMAT) == TEMP_COPIED_UMAT; } +inline void UMatData::markDeviceMemMapped(bool flag) +{ + if(flag) + flags |= DEVICE_MEM_MAPPED; + else + flags &= ~DEVICE_MEM_MAPPED; +} + inline void UMatData::markHostCopyObsolete(bool flag) { if(flag) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index ed72ffc7f1..11b5f0c442 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3739,6 +3739,7 @@ public: u->handle = clCreateBuffer(ctx_handle, CL_MEM_COPY_HOST_PTR|CL_MEM_READ_WRITE|createFlags, u->size, u->origdata, &retval); tempUMatFlags = UMatData::TEMP_COPIED_UMAT; + } if(!u->handle || retval != CL_SUCCESS) return false; @@ -3880,6 +3881,7 @@ public: if(u->data && retval == CL_SUCCESS) { u->markHostCopyObsolete(false); + u->markDeviceMemMapped(true); return; } @@ -3908,6 +3910,7 @@ public: if(!u) return; + CV_Assert(u->handle != 0); UMatDataAutoLock autolock(u); @@ -3918,8 +3921,10 @@ public: cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); cl_int retval = 0; - if( !u->copyOnMap() && u->data ) + if( !u->copyOnMap() && u->deviceMemMapped() ) { + CV_Assert(u->data != NULL); + u->markDeviceMemMapped(false); CV_Assert( (retval = clEnqueueUnmapMemObject(q, (cl_mem)u->handle, u->data, 0, 0, 0)) == CL_SUCCESS ); CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); From c949845a6be4874db8588f338406e0a3bca72ef5 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 10 Jul 2014 15:54:43 +0400 Subject: [PATCH 056/136] fixed perf test --- modules/core/perf/opencl/perf_matop.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/core/perf/opencl/perf_matop.cpp b/modules/core/perf/opencl/perf_matop.cpp index 9bb375587f..67d382239c 100644 --- a/modules/core/perf/opencl/perf_matop.cpp +++ b/modules/core/perf/opencl/perf_matop.cpp @@ -139,6 +139,7 @@ OCL_PERF_TEST_P(CopyToFixture, CopyToWithMaskUninit, dst.release(); startTimer(); src.copyTo(dst, mask); + cv::ocl::finish(); stopTimer(); } From fee3d6931b8a633cb2e060058ae10c7e8c251214 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 10 Jul 2014 17:04:24 +0400 Subject: [PATCH 057/136] corners --- modules/imgproc/src/opencl/corner.cl | 30 +++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/modules/imgproc/src/opencl/corner.cl b/modules/imgproc/src/opencl/corner.cl index 563cb98081..e1c2e407dc 100644 --- a/modules/imgproc/src/opencl/corner.cl +++ b/modules/imgproc/src/opencl/corner.cl @@ -114,25 +114,23 @@ __kernel void corner(__global const float * Dx, int dx_step, int dx_offset, int int dst_startX = gX * (THREADS-ksX+1) + dst_x_off; int dst_startY = (gY << 1) + dst_y_off; - float dx_data[ksY+1],dy_data[ksY+1], data[3][ksY+1]; + float data[3][ksY+1]; __local float temp[6][THREADS]; #ifdef BORDER_CONSTANT for (int i=0; i < ksY+1; i++) { bool dx_con = dx_startX+col >= 0 && dx_startX+col < dx_whole_cols && dx_startY+i >= 0 && dx_startY+i < dx_whole_rows; - int indexDx = (dx_startY+i)*(dx_step>>2)+(dx_startX+col); + int indexDx = mad24(dx_startY+i, dx_step>>2, dx_startX+col); float dx_s = dx_con ? Dx[indexDx] : 0.0f; - dx_data[i] = dx_s; bool dy_con = dy_startX+col >= 0 && dy_startX+col < dy_whole_cols && dy_startY+i >= 0 && dy_startY+i < dy_whole_rows; - int indexDy = (dy_startY+i)*(dy_step>>2)+(dy_startX+col); + int indexDy = mad24(dy_startY+i, dy_step>>2, dy_startX+col); float dy_s = dy_con ? Dy[indexDy] : 0.0f; - dy_data[i] = dy_s; - data[0][i] = dx_data[i] * dx_data[i]; - data[1][i] = dx_data[i] * dy_data[i]; - data[2][i] = dy_data[i] * dy_data[i]; + data[0][i] = dx_s * dx_s; + data[1][i] = dx_s * dy_s; + data[2][i] = dy_s * dy_s; } #else int clamped_col = min(2*dst_cols, col); @@ -141,16 +139,16 @@ __kernel void corner(__global const float * Dx, int dx_step, int dx_offset, int int dx_selected_row = dx_startY+i, dx_selected_col = dx_startX+clamped_col; EXTRAPOLATE(dx_selected_row, dx_whole_rows) EXTRAPOLATE(dx_selected_col, dx_whole_cols) - dx_data[i] = Dx[dx_selected_row * (dx_step>>2) + dx_selected_col]; + float dx_s = Dx[mad24(dx_selected_row, dx_step>>2, dx_selected_col)]; int dy_selected_row = dy_startY+i, dy_selected_col = dy_startX+clamped_col; EXTRAPOLATE(dy_selected_row, dy_whole_rows) EXTRAPOLATE(dy_selected_col, dy_whole_cols) - dy_data[i] = Dy[dy_selected_row * (dy_step>>2) + dy_selected_col]; + float dy_s = Dy[mad24(dy_selected_row, dy_step>>2, dy_selected_col)]; - data[0][i] = dx_data[i] * dx_data[i]; - data[1][i] = dx_data[i] * dy_data[i]; - data[2][i] = dy_data[i] * dy_data[i]; + data[0][i] = dx_s * dx_s; + data[1][i] = dx_s * dy_s; + data[2][i] = dy_s * dy_s; } #endif float sum0 = 0.0f, sum1 = 0.0f, sum2 = 0.0f; @@ -180,7 +178,7 @@ __kernel void corner(__global const float * Dx, int dx_step, int dx_offset, int col += anX; int posX = dst_startX - dst_x_off + col - anX; int posY = (gly << 1); - int till = (ksX + 1)%2; + int till = (ksX + 1) & 1; float tmp_sum[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; for (int k=0; k<6; k++) { @@ -210,7 +208,7 @@ __kernel void corner(__global const float * Dx, int dx_step, int dx_offset, int float a = tmp_sum[0] * 0.5f; float b = tmp_sum[2]; float c = tmp_sum[4] * 0.5f; - *(__global float *)(dst + dst_index) = (float)((a+c) - sqrt((a-c)*(a-c) + b*b)); + *(__global float *)(dst + dst_index) = (float)((a+c) - native_sqrt((a-c)*(a-c) + b*b)); } if (posX < dst_cols && (posY + 1) < dst_rows) { @@ -218,7 +216,7 @@ __kernel void corner(__global const float * Dx, int dx_step, int dx_offset, int float a = tmp_sum[1] * 0.5f; float b = tmp_sum[3]; float c = tmp_sum[5] * 0.5f; - *(__global float *)(dst + dst_index) = (float)((a+c) - sqrt((a-c)*(a-c) + b*b)); + *(__global float *)(dst + dst_index) = (float)((a+c) - native_sqrt((a-c)*(a-c) + b*b)); } #else #error "No such corners type" From 6dd32440198001877f261e632a3bc4f407f43106 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 10 Jul 2014 17:59:37 +0400 Subject: [PATCH 058/136] fix build --- modules/highgui/src/precomp.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index 7f78c7d05b..86fc91264d 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -47,6 +47,8 @@ #include "opencv2/core/utility.hpp" #include "opencv2/core/private.hpp" +#include "opencv2/imgcodecs.hpp" + #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/imgcodecs/imgcodecs_c.h" #include "opencv2/highgui/highgui_c.h" From f2a2467de36f081bc88228bb38e581b76283b7a2 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 10 Jul 2014 18:13:01 +0400 Subject: [PATCH 059/136] enabled BufferPool --- modules/core/src/ocl.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index ed72ffc7f1..3c148741a3 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3494,9 +3494,8 @@ public: OpenCLBufferPoolImpl() : currentReservedSize(0), maxReservedSize(0) { - // Note: Buffer pool is disabled by default, - // because we didn't receive significant performance improvement - maxReservedSize = getConfigurationParameterForSize("OPENCV_OPENCL_BUFFERPOOL_LIMIT", 0); + int poolSize = ocl::Device::getDefault().isIntel() ? 1 << 27 : 0; + maxReservedSize = getConfigurationParameterForSize("OPENCV_OPENCL_BUFFERPOOL_LIMIT", poolSize); } virtual ~OpenCLBufferPoolImpl() { From d58f736935d368a7c2884efbe424d5caefe2796c Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 10 Jul 2014 18:27:32 +0400 Subject: [PATCH 060/136] Split highgui module to videoio and highgui --- CMakeLists.txt | 4 +- cmake/OpenCVConfig.cmake | 2 +- cmake/OpenCVFindLibsVideo.cmake | 15 +- cmake/OpenCVModule.cmake | 4 +- cmake/OpenCVUtils.cmake | 3 + cmake/templates/OpenCVConfig.cmake.in | 2 +- doc/CMakeLists.txt | 2 +- doc/check_docs.py | 2 + doc/conf.py | 6 +- .../video-input-psnr-ssim.rst | 2 +- .../clojure_dev_intro/clojure_dev_intro.rst | 2 +- .../desktop_java/java_dev_intro.rst | 6 +- .../how_to_write_a_tutorial.rst | 2 +- .../windows_visual_studio_image_watch.rst | 2 +- .../ios/video_processing/video_processing.rst | 2 +- include/opencv2/opencv.hpp | 1 + modules/core/doc/basic_structures.rst | 2 +- modules/core/doc/intro.rst | 3 +- modules/cudacodec/CMakeLists.txt | 2 +- modules/highgui/CMakeLists.txt | 154 ------- modules/highgui/doc/highgui.rst | 2 - modules/highgui/include/opencv2/highgui.hpp | 340 -------------- .../include/opencv2/highgui/highgui_c.h | 357 --------------- modules/highgui/src/precomp.hpp | 98 ----- modules/highgui/test/test_precomp.hpp | 80 +--- .../include/opencv2/imgcodecs/imgcodecs_c.h | 12 + .../imgcodecs/include/opencv2/imgcodecs/ios.h | 4 + modules/imgcodecs/perf/perf_main.cpp | 2 +- modules/imgcodecs/src/ios_conversions.mm | 6 +- modules/imgcodecs/src/loadsave.cpp | 2 +- modules/imgcodecs/src/precomp.hpp | 5 +- modules/imgcodecs/test/test_drawing.cpp | 6 +- modules/imgcodecs/test/test_grfmt.cpp | 34 +- modules/java/CMakeLists.txt | 2 +- .../src/org/opencv/test/OpenCVTestCase.java | 6 +- .../org/opencv/test/android/UtilsTest.java | 4 +- .../test/features2d/Features2dTest.java | 6 +- .../org/opencv/test/highgui/HighguiTest.java | 18 +- .../opencv/test/highgui/VideoCaptureTest.java | 36 +- modules/java/generator/gen_java.py | 8 +- modules/java/generator/rst_parser.py | 2 +- .../java/android+CameraBridgeViewBase.java | 10 +- .../src/java/android+NativeCameraView.java | 16 +- .../src/org/opencv/test/OpenCVTestCase.java | 6 +- modules/matlab/CMakeLists.txt | 3 +- modules/python/CMakeLists.txt | 3 +- modules/python/src2/hdr_parser.py | 1 + modules/superres/CMakeLists.txt | 2 +- modules/superres/src/frame_source.cpp | 6 +- modules/superres/src/precomp.hpp | 4 +- modules/ts/CMakeLists.txt | 2 +- modules/ts/include/opencv2/ts/cuda_perf.hpp | 1 + modules/ts/include/opencv2/ts/ocl_test.hpp | 1 + modules/videoio/CMakeLists.txt | 233 ++++++++++ .../doc/reading_and_writing_video.rst | 0 modules/videoio/doc/videoio.rst | 12 + modules/videoio/include/opencv2/videoio.hpp | 389 ++++++++++++++++ .../include/opencv2/videoio}/cap_ios.h | 0 .../include/opencv2/videoio/videoio.hpp} | 11 +- .../include/opencv2/videoio/videoio_c.h | 416 ++++++++++++++++++ .../{highgui => videoio}/perf/perf_input.cpp | 0 .../{highgui => videoio}/perf/perf_main.cpp | 2 +- .../{highgui => videoio}/perf/perf_output.cpp | 0 .../perf/perf_precomp.hpp | 2 +- modules/{highgui => videoio}/src/cap.cpp | 0 .../{highgui => videoio}/src/cap_android.cpp | 16 +- .../src/cap_avfoundation.mm | 2 +- modules/{highgui => videoio}/src/cap_cmu.cpp | 0 .../{highgui => videoio}/src/cap_dc1394.cpp | 12 +- .../src/cap_dc1394_v2.cpp | 0 .../{highgui => videoio}/src/cap_dshow.cpp | 0 .../{highgui => videoio}/src/cap_ffmpeg.cpp | 0 .../src/cap_ffmpeg_api.hpp | 0 .../src/cap_ffmpeg_impl.hpp | 0 .../src/cap_giganetix.cpp | 0 .../src/cap_gstreamer.cpp | 0 .../{highgui => videoio}/src/cap_images.cpp | 0 .../src/cap_intelperc.cpp | 0 .../src/cap_intelperc.hpp | 0 .../src/cap_ios_abstract_camera.mm | 2 +- .../src/cap_ios_photo_camera.mm | 2 +- .../src/cap_ios_video_camera.mm | 2 +- .../{highgui => videoio}/src/cap_libv4l.cpp | 76 ++-- modules/{highgui => videoio}/src/cap_msmf.cpp | 0 modules/{highgui => videoio}/src/cap_msmf.hpp | 2 +- .../{highgui => videoio}/src/cap_openni.cpp | 0 .../{highgui => videoio}/src/cap_pvapi.cpp | 0 modules/{highgui => videoio}/src/cap_qt.cpp | 0 modules/{highgui => videoio}/src/cap_qtkit.mm | 0 .../{highgui => videoio}/src/cap_unicap.cpp | 0 modules/{highgui => videoio}/src/cap_v4l.cpp | 70 +-- modules/{highgui => videoio}/src/cap_vfw.cpp | 0 .../{highgui => videoio}/src/cap_ximea.cpp | 0 modules/{highgui => videoio}/src/cap_xine.cpp | 0 .../src/ffmpeg_codecs.hpp | 0 modules/videoio/src/precomp.hpp | 178 ++++++++ .../{highgui => videoio}/test/test_ffmpeg.cpp | 8 +- .../{highgui => videoio}/test/test_fourcc.cpp | 4 +- .../test/test_framecount.cpp | 4 +- modules/videoio/test/test_main.cpp | 3 + .../test/test_positioning.cpp | 6 +- modules/videoio/test/test_precomp.hpp | 91 ++++ .../test/test_video_io.cpp | 32 +- .../test/test_video_pos.cpp | 10 +- modules/videostab/CMakeLists.txt | 2 +- modules/videostab/src/frame_source.cpp | 12 +- samples/android/CMakeLists.txt | 4 +- samples/cpp/CMakeLists.txt | 5 +- samples/cpp/bgfg_gmg.cpp | 1 + samples/cpp/bgfg_segm.cpp | 1 + samples/cpp/calibration.cpp | 1 + samples/cpp/camshiftdemo.cpp | 1 + samples/cpp/dbt_face_detection.cpp | 1 + samples/cpp/facedetect.cpp | 2 + samples/cpp/fback.cpp | 1 + samples/cpp/ffilldemo.cpp | 1 + samples/cpp/image_sequence.cpp | 1 + samples/cpp/intelperc_capture.cpp | 1 + samples/cpp/laplace.cpp | 1 + samples/cpp/linemod.cpp | 1 + samples/cpp/lkdemo.cpp | 1 + samples/cpp/motempl.cpp | 1 + samples/cpp/openni_capture.cpp | 1 + samples/cpp/phase_corr.cpp | 1 + samples/cpp/polar_transforms.cpp | 1 + samples/cpp/segment_objects.cpp | 1 + samples/cpp/select3dobj.cpp | 1 + samples/cpp/smiledetect.cpp | 1 + samples/cpp/starter_video.cpp | 1 + .../video-input-psnr-ssim.cpp | 1 + .../HighGUI/video-write/video-write.cpp | 2 +- .../camera_calibration/camera_calibration.cpp | 3 +- .../objectDetection/objectDetection.cpp | 1 + .../objectDetection/objectDetection2.cpp | 1 + samples/cpp/tutorial_code/video/bg_sub.cpp | 1 + samples/cpp/ufacedetect.cpp | 1 + samples/cpp/video_homography.cpp | 1 + samples/cpp/videostab.cpp | 1 + .../simple-sample/src/simple_sample/core.clj | 6 +- .../sbt/src/main/java/DetectFaceDemo.java | 6 +- .../ScalaCorrespondenceMatchingDemo.scala | 8 +- .../src/main/scala/ScalaDetectFaceDemo.scala | 6 +- samples/tapi/CMakeLists.txt | 2 +- samples/tapi/bgfg_segm.cpp | 1 + samples/tapi/camshift.cpp | 1 + samples/tapi/clahe.cpp | 1 + samples/tapi/hog.cpp | 2 + samples/tapi/pyrlk_optical_flow.cpp | 3 +- samples/tapi/tvl1_optical_flow.cpp | 1 + 149 files changed, 1673 insertions(+), 1309 deletions(-) create mode 100644 modules/videoio/CMakeLists.txt rename modules/{highgui => videoio}/doc/reading_and_writing_video.rst (100%) create mode 100644 modules/videoio/doc/videoio.rst create mode 100644 modules/videoio/include/opencv2/videoio.hpp rename modules/{highgui/include/opencv2/highgui => videoio/include/opencv2/videoio}/cap_ios.h (100%) rename modules/{highgui/include/opencv2/highgui/ios.h => videoio/include/opencv2/videoio/videoio.hpp} (90%) create mode 100644 modules/videoio/include/opencv2/videoio/videoio_c.h rename modules/{highgui => videoio}/perf/perf_input.cpp (100%) rename modules/{highgui => videoio}/perf/perf_main.cpp (51%) rename modules/{highgui => videoio}/perf/perf_output.cpp (100%) rename modules/{highgui => videoio}/perf/perf_precomp.hpp (97%) rename modules/{highgui => videoio}/src/cap.cpp (100%) rename modules/{highgui => videoio}/src/cap_android.cpp (97%) rename modules/{highgui => videoio}/src/cap_avfoundation.mm (99%) rename modules/{highgui => videoio}/src/cap_cmu.cpp (100%) rename modules/{highgui => videoio}/src/cap_dc1394.cpp (99%) rename modules/{highgui => videoio}/src/cap_dc1394_v2.cpp (100%) rename modules/{highgui => videoio}/src/cap_dshow.cpp (100%) rename modules/{highgui => videoio}/src/cap_ffmpeg.cpp (100%) rename modules/{highgui => videoio}/src/cap_ffmpeg_api.hpp (100%) rename modules/{highgui => videoio}/src/cap_ffmpeg_impl.hpp (100%) rename modules/{highgui => videoio}/src/cap_giganetix.cpp (100%) rename modules/{highgui => videoio}/src/cap_gstreamer.cpp (100%) rename modules/{highgui => videoio}/src/cap_images.cpp (100%) rename modules/{highgui => videoio}/src/cap_intelperc.cpp (100%) rename modules/{highgui => videoio}/src/cap_intelperc.hpp (100%) rename modules/{highgui => videoio}/src/cap_ios_abstract_camera.mm (99%) rename modules/{highgui => videoio}/src/cap_ios_photo_camera.mm (99%) rename modules/{highgui => videoio}/src/cap_ios_video_camera.mm (99%) rename modules/{highgui => videoio}/src/cap_libv4l.cpp (96%) rename modules/{highgui => videoio}/src/cap_msmf.cpp (100%) rename modules/{highgui => videoio}/src/cap_msmf.hpp (99%) rename modules/{highgui => videoio}/src/cap_openni.cpp (100%) rename modules/{highgui => videoio}/src/cap_pvapi.cpp (100%) rename modules/{highgui => videoio}/src/cap_qt.cpp (100%) rename modules/{highgui => videoio}/src/cap_qtkit.mm (100%) rename modules/{highgui => videoio}/src/cap_unicap.cpp (100%) rename modules/{highgui => videoio}/src/cap_v4l.cpp (97%) rename modules/{highgui => videoio}/src/cap_vfw.cpp (100%) rename modules/{highgui => videoio}/src/cap_ximea.cpp (100%) rename modules/{highgui => videoio}/src/cap_xine.cpp (100%) rename modules/{highgui => videoio}/src/ffmpeg_codecs.hpp (100%) create mode 100644 modules/videoio/src/precomp.hpp rename modules/{highgui => videoio}/test/test_ffmpeg.cpp (98%) rename modules/{highgui => videoio}/test/test_fourcc.cpp (99%) rename modules/{highgui => videoio}/test/test_framecount.cpp (97%) create mode 100644 modules/videoio/test/test_main.cpp rename modules/{highgui => videoio}/test/test_positioning.cpp (97%) create mode 100644 modules/videoio/test/test_precomp.hpp rename modules/{highgui => videoio}/test/test_video_io.cpp (95%) rename modules/{highgui => videoio}/test/test_video_pos.cpp (93%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5abf449804..d314cf6483 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,8 +148,8 @@ OCV_OPTION(WITH_TIFF "Include TIFF support" ON OCV_OPTION(WITH_UNICAP "Include Unicap support (GPL)" OFF IF (UNIX AND NOT APPLE AND NOT ANDROID) ) OCV_OPTION(WITH_V4L "Include Video 4 Linux support" ON IF (UNIX AND NOT ANDROID) ) OCV_OPTION(WITH_LIBV4L "Use libv4l for Video 4 Linux support" ON IF (UNIX AND NOT ANDROID) ) -OCV_OPTION(WITH_DSHOW "Build HighGUI with DirectShow support" ON IF (WIN32 AND NOT ARM) ) -OCV_OPTION(WITH_MSMF "Build HighGUI with Media Foundation support" OFF IF WIN32 ) +OCV_OPTION(WITH_DSHOW "Build VideoIO with DirectShow support" ON IF (WIN32 AND NOT ARM) ) +OCV_OPTION(WITH_MSMF "Build VideoIO with Media Foundation support" OFF IF WIN32 ) OCV_OPTION(WITH_XIMEA "Include XIMEA cameras support" OFF IF (NOT ANDROID AND NOT APPLE) ) OCV_OPTION(WITH_XINE "Include Xine support (GPL)" OFF IF (UNIX AND NOT APPLE AND NOT ANDROID) ) OCV_OPTION(WITH_CLP "Include Clp support (EPL)" OFF) diff --git a/cmake/OpenCVConfig.cmake b/cmake/OpenCVConfig.cmake index 2d80f765b5..896a1901c1 100644 --- a/cmake/OpenCVConfig.cmake +++ b/cmake/OpenCVConfig.cmake @@ -11,7 +11,7 @@ # # Or you can search for specific OpenCV modules: # -# FIND_PACKAGE(OpenCV REQUIRED core highgui) +# FIND_PACKAGE(OpenCV REQUIRED core imgcodecs) # # If the module is found then OPENCV__FOUND is set to TRUE. # diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 5520d05521..5054072f1e 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -131,7 +131,7 @@ if(WITH_1394) if(HAVE_DC1394_2) ocv_parse_pkg("libdc1394-2" "${DC1394_2_LIB_DIR}/pkgconfig" "") ocv_include_directories(${DC1394_2_INCLUDE_PATH}) - set(HIGHGUI_LIBRARIES ${HIGHGUI_LIBRARIES} + set(VIDEOIO_LIBRARIES ${VIDEOIO_LIBRARIES} "${DC1394_2_LIB_DIR}/libdc1394.a" "${CMU1394_LIB_DIR}/lib1394camera.a") endif(HAVE_DC1394_2) @@ -234,7 +234,7 @@ if(WITH_FFMPEG) endif() endif(FFMPEG_INCLUDE_DIR) if(HAVE_FFMPEG) - set(HIGHGUI_LIBRARIES ${HIGHGUI_LIBRARIES} "${FFMPEG_LIB_DIR}/libavcodec.a" + set(VIDEOIO_LIBRARIES ${VIDEOIO_LIBRARIES} "${FFMPEG_LIB_DIR}/libavcodec.a" "${FFMPEG_LIB_DIR}/libavformat.a" "${FFMPEG_LIB_DIR}/libavutil.a" "${FFMPEG_LIB_DIR}/libswscale.a") ocv_include_directories(${FFMPEG_INCLUDE_DIR}) @@ -253,14 +253,15 @@ if(WITH_MSMF) check_include_file(Mfapi.h HAVE_MSMF) endif(WITH_MSMF) -# --- Extra HighGUI libs on Windows --- +# --- Extra HighGUI and VideoIO libs on Windows --- if(WIN32) - list(APPEND HIGHGUI_LIBRARIES comctl32 gdi32 ole32 setupapi ws2_32 vfw32) + list(APPEND HIGHGUI_LIBRARIES comctl32 gdi32 ole32 setupapi ws2_32) + list(APPEND VIDEOIO_LIBRARIES vfw32) if(MINGW64) - list(APPEND HIGHGUI_LIBRARIES avifil32 avicap32 winmm msvfw32) - list(REMOVE_ITEM HIGHGUI_LIBRARIES vfw32) + list(APPEND VIDEOIO_LIBRARIES avifil32 avicap32 winmm msvfw32) + list(REMOVE_ITEM VIDEOIO_LIBRARIES vfw32) elseif(MINGW) - list(APPEND HIGHGUI_LIBRARIES winmm) + list(APPEND VIDEOIO_LIBRARIES winmm) endif() endif(WIN32) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 6618ca8834..3f4da5f106 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -758,7 +758,7 @@ function(ocv_add_accuracy_tests) __ocv_parse_test_sources(TEST ${ARGN}) # opencv_imgcodecs is required for imread/imwrite - set(test_deps ${the_module} opencv_ts opencv_imgcodecs opencv_highgui ${OPENCV_TEST_${the_module}_DEPS} ${OPENCV_MODULE_opencv_ts_DEPS}) + set(test_deps ${the_module} opencv_ts opencv_imgcodecs opencv_videoio ${OPENCV_TEST_${the_module}_DEPS} ${OPENCV_MODULE_opencv_ts_DEPS}) ocv_check_dependencies(${test_deps}) if(OCV_DEPENDENCIES_FOUND) @@ -811,7 +811,7 @@ function(ocv_add_samples) string(REGEX REPLACE "^opencv_" "" module_id ${the_module}) if(BUILD_EXAMPLES AND EXISTS "${samples_path}") - set(samples_deps ${the_module} ${OPENCV_MODULE_${the_module}_DEPS} opencv_imgcodecs opencv_highgui ${ARGN}) + set(samples_deps ${the_module} ${OPENCV_MODULE_${the_module}_DEPS} opencv_imgcodecs opencv_videoio opencv_highgui ${ARGN}) ocv_check_dependencies(${samples_deps}) if(OCV_DEPENDENCIES_FOUND) diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index f2a0197f82..d8171770de 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -265,16 +265,19 @@ macro(CHECK_MODULE module_name define) set(${define} 1) foreach(P "${ALIAS_INCLUDE_DIRS}") if(${P}) + list(APPEND VIDEOIO_INCLUDE_DIRS ${${P}}) list(APPEND HIGHGUI_INCLUDE_DIRS ${${P}}) endif() endforeach() foreach(P "${ALIAS_LIBRARY_DIRS}") if(${P}) + list(APPEND VIDEOIO_LIBRARY_DIRS ${${P}}) list(APPEND HIGHGUI_LIBRARY_DIRS ${${P}}) endif() endforeach() + list(APPEND VIDEOIO_LIBRARIES ${${ALIAS_LIBRARIES}}) list(APPEND HIGHGUI_LIBRARIES ${${ALIAS_LIBRARIES}}) endif() endif() diff --git a/cmake/templates/OpenCVConfig.cmake.in b/cmake/templates/OpenCVConfig.cmake.in index 24a9374ef8..e3bde4bbe3 100644 --- a/cmake/templates/OpenCVConfig.cmake.in +++ b/cmake/templates/OpenCVConfig.cmake.in @@ -12,7 +12,7 @@ # # Or you can search for specific OpenCV modules: # -# find_package(OpenCV REQUIRED core highgui) +# find_package(OpenCV REQUIRED core videoio) # # If the module is found then OPENCV__FOUND is set to TRUE. # diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 33fd9957d3..f796d474ca 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -33,7 +33,7 @@ if(BUILD_DOCS AND HAVE_SPHINX) endif() endforeach() - set(FIXED_ORDER_MODULES core imgproc imgcodecs highgui video calib3d features2d objdetect ml flann photo stitching nonfree contrib legacy) + set(FIXED_ORDER_MODULES core imgproc imgcodecs videoio highgui video calib3d features2d objdetect ml flann photo stitching nonfree contrib legacy) list(REMOVE_ITEM BASE_MODULES ${FIXED_ORDER_MODULES}) diff --git a/doc/check_docs.py b/doc/check_docs.py index c0e519b29c..96f62f068d 100755 --- a/doc/check_docs.py +++ b/doc/check_docs.py @@ -15,6 +15,7 @@ opencv_hdr_list = [ "../modules/video/include/opencv2/video/background_segm.hpp", "../modules/objdetect/include/opencv2/objdetect.hpp", "../modules/imgcodecs/include/opencv2/imgcodecs.hpp", +"../modules/videoio/include/opencv2/videoio.hpp", "../modules/highgui/include/opencv2/highgui.hpp", ] @@ -26,6 +27,7 @@ opencv_module_list = [ "video", "objdetect", "imgcodecs", +"videoio", "highgui", "ml" ] diff --git a/doc/conf.py b/doc/conf.py index c17dfb618f..a30ee8aea4 100755 --- a/doc/conf.py +++ b/doc/conf.py @@ -303,7 +303,7 @@ extlinks = { 'basicstructures' : ('http://docs.opencv.org/modules/core/doc/basic_structures.html#%s', None), 'oldbasicstructures' : ('http://docs.opencv.org/modules/core/doc/old_basic_structures.html#%s', None), 'readwriteimage' : ('http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html#%s', None), - 'readwritevideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_video.html#%s', None), + 'readwritevideo' : ('http://docs.opencv.org/modules/videoio/doc/reading_and_writing_video.html#%s', None), 'operationsonarrays' : ('http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#%s', None), 'utilitysystemfunctions' : ('http://docs.opencv.org/modules/core/doc/utility_and_system_functions_and_macros.html#%s', None), 'imgprocfilter' : ('http://docs.opencv.org/modules/imgproc/doc/filtering.html#%s', None), @@ -311,7 +311,7 @@ extlinks = { 'drawingfunc' : ('http://docs.opencv.org/modules/core/doc/drawing_functions.html#%s', None), 'xmlymlpers' : ('http://docs.opencv.org/modules/core/doc/xml_yaml_persistence.html#%s', None), 'rwimg' : ('http://docs.opencv.org/modules/imgcodecs/doc/reading_and_writing_images.html#%s', None), - 'hgvideo' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_video.html#%s', None), + 'hgvideo' : ('http://docs.opencv.org/modules/videoio/doc/reading_and_writing_video.html#%s', None), 'gpuinit' : ('http://docs.opencv.org/modules/gpu/doc/initalization_and_information.html#%s', None), 'gpudatastructure' : ('http://docs.opencv.org/modules/gpu/doc/data_structures.html#%s', None), 'gpuopmatrices' : ('http://docs.opencv.org/modules/gpu/doc/operations_on_matrices.html#%s', None), @@ -420,7 +420,7 @@ extlinks = { 'background_subtractor' : ('http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=backgroundsubtractor#backgroundsubtractor%s', None), 'background_subtractor_mog' : ('http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=backgroundsubtractorMOG#backgroundsubtractormog%s', None), 'background_subtractor_mog_two' : ('http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=backgroundsubtractorMOG2#backgroundsubtractormog2%s', None), - 'video_capture' : ('http://docs.opencv.org/modules/highgui/doc/reading_and_writing_video.html?highlight=videocapture#videocapture%s', None), + 'video_capture' : ('http://docs.opencv.org/modules/videoio/doc/reading_and_writing_video.html?highlight=videocapture#videocapture%s', None), 'ippa_convert': ('http://docs.opencv.org/modules/core/doc/ipp_async_converters.html#%s', None), 'ptr':('http://docs.opencv.org/modules/core/doc/basic_structures.html?highlight=Ptr#Ptr%s', None) } diff --git a/doc/tutorials/highgui/video-input-psnr-ssim/video-input-psnr-ssim.rst b/doc/tutorials/highgui/video-input-psnr-ssim/video-input-psnr-ssim.rst index 6f5476cf05..8f63bf1a2e 100644 --- a/doc/tutorials/highgui/video-input-psnr-ssim/video-input-psnr-ssim.rst +++ b/doc/tutorials/highgui/video-input-psnr-ssim/video-input-psnr-ssim.rst @@ -22,7 +22,7 @@ As a test case where to show off these using OpenCV I've created a small program :language: cpp :linenos: :tab-width: 4 - :lines: 1-14, 28-29, 31-205 + :lines: 1-15, 29-31, 33-208 How to read a video stream (online-camera or offline-file)? =========================================================== diff --git a/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.rst b/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.rst index 248abdf6d2..0ad47863eb 100644 --- a/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.rst +++ b/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.rst @@ -656,7 +656,7 @@ classes we're going to use: Results: Stored in vars *1, *2, *3, an exception in *e user=> (import '[org.opencv.core Mat Size CvType] - '[org.opencv.highgui Highgui] + '[org.opencv.imgcodecs Imgcodecs] '[org.opencv.imgproc Imgproc]) org.opencv.imgproc.Imgproc diff --git a/doc/tutorials/introduction/desktop_java/java_dev_intro.rst b/doc/tutorials/introduction/desktop_java/java_dev_intro.rst index d5cb31f894..513f39d106 100644 --- a/doc/tutorials/introduction/desktop_java/java_dev_intro.rst +++ b/doc/tutorials/introduction/desktop_java/java_dev_intro.rst @@ -373,7 +373,7 @@ Now modify src/main/java/HelloOpenCV.java so it contains the following Java code import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Scalar; - import org.opencv.highgui.Highgui; + import org.opencv.imgcodecs.Imgcodecs; import org.opencv.objdetect.CascadeClassifier; // @@ -387,7 +387,7 @@ Now modify src/main/java/HelloOpenCV.java so it contains the following Java code // Create a face detector from the cascade file in the resources // directory. CascadeClassifier faceDetector = new CascadeClassifier(getClass().getResource("/lbpcascade_frontalface.xml").getPath()); - Mat image = Highgui.imread(getClass().getResource("/lena.png").getPath()); + Mat image = Imgcodecs.imread(getClass().getResource("/lena.png").getPath()); // Detect faces in the image. // MatOfRect is a special container class for Rect. @@ -404,7 +404,7 @@ Now modify src/main/java/HelloOpenCV.java so it contains the following Java code // Save the visualized detection. String filename = "faceDetection.png"; System.out.println(String.format("Writing %s", filename)); - Highgui.imwrite(filename, image); + Imgcodecs.imwrite(filename, image); } } diff --git a/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst b/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst index d68116c818..7696be4a13 100644 --- a/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst +++ b/doc/tutorials/introduction/how_to_write_a_tutorial/how_to_write_a_tutorial.rst @@ -349,7 +349,7 @@ Now here's our recommendation for the structure of the tutorial (although, remem :language: cpp :linenos: :tab-width: 4 - :lines: 1-8, 21-22, 24- + :lines: 1-8, 21-23, 25- After the directive you specify a relative path to the file from what to import. It has four options: the language to use, if you add the ``:linenos:`` the line numbers will be shown, you can specify the tab size with the ``:tab-width:`` and you do not need to load the whole file, you can show just the important lines. Use the *lines* option to do not show redundant information (such as the *help* function). Here basically you specify ranges, if the second range line number is missing than that means that until the end of the file. The ranges specified here do no need to be in an ascending order, you may even reorganize the structure of how you want to show your sample inside the tutorial. diff --git a/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.rst b/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.rst index 5a68dad5c9..21f679c971 100644 --- a/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.rst +++ b/doc/tutorials/introduction/windows_visual_studio_image_watch/windows_visual_studio_image_watch.rst @@ -32,7 +32,7 @@ Image Watch works with any existing project that uses OpenCV image objects (for #include // std::cout #include // cv::Mat - #include // cv::imread() + #include // cv::imread() #include // cv::Canny() using namespace std; diff --git a/doc/tutorials/ios/video_processing/video_processing.rst b/doc/tutorials/ios/video_processing/video_processing.rst index 84ccfcf971..eb5da5b111 100644 --- a/doc/tutorials/ios/video_processing/video_processing.rst +++ b/doc/tutorials/ios/video_processing/video_processing.rst @@ -80,7 +80,7 @@ We add a camera controller to the view controller and initialize it when the vie .. code-block:: objc :linenos: - #import + #import using namespace cv; diff --git a/include/opencv2/opencv.hpp b/include/opencv2/opencv.hpp index fc24981eb6..fd9ca5898e 100644 --- a/include/opencv2/opencv.hpp +++ b/include/opencv2/opencv.hpp @@ -51,6 +51,7 @@ #include "opencv2/objdetect.hpp" #include "opencv2/calib3d.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/ml.hpp" diff --git a/modules/core/doc/basic_structures.rst b/modules/core/doc/basic_structures.rst index 459a6a9c98..a94fa1731e 100644 --- a/modules/core/doc/basic_structures.rst +++ b/modules/core/doc/basic_structures.rst @@ -2981,7 +2981,7 @@ The class provides the following features for all derived classes: * so called "virtual constructor". That is, each Algorithm derivative is registered at program start and you can get the list of registered algorithms and create instance of a particular algorithm by its name (see ``Algorithm::create``). If you plan to add your own algorithms, it is good practice to add a unique prefix to your algorithms to distinguish them from other algorithms. - * setting/retrieving algorithm parameters by name. If you used video capturing functionality from OpenCV highgui module, you are probably familar with ``cvSetCaptureProperty()``, ``cvGetCaptureProperty()``, ``VideoCapture::set()`` and ``VideoCapture::get()``. ``Algorithm`` provides similar method where instead of integer id's you specify the parameter names as text strings. See ``Algorithm::set`` and ``Algorithm::get`` for details. + * setting/retrieving algorithm parameters by name. If you used video capturing functionality from OpenCV videoio module, you are probably familar with ``cvSetCaptureProperty()``, ``cvGetCaptureProperty()``, ``VideoCapture::set()`` and ``VideoCapture::get()``. ``Algorithm`` provides similar method where instead of integer id's you specify the parameter names as text strings. See ``Algorithm::set`` and ``Algorithm::get`` for details. * reading and writing parameters from/to XML or YAML files. Every Algorithm derivative can store all its parameters and then read them back. There is no need to re-implement it each time. diff --git a/modules/core/doc/intro.rst b/modules/core/doc/intro.rst index 6d9fdfca5e..032e7453a5 100644 --- a/modules/core/doc/intro.rst +++ b/modules/core/doc/intro.rst @@ -14,7 +14,8 @@ OpenCV has a modular structure, which means that the package includes several sh * **calib3d** - basic multiple-view geometry algorithms, single and stereo camera calibration, object pose estimation, stereo correspondence algorithms, and elements of 3D reconstruction. * **features2d** - salient feature detectors, descriptors, and descriptor matchers. * **objdetect** - detection of objects and instances of the predefined classes (for example, faces, eyes, mugs, people, cars, and so on). - * **highgui** - an easy-to-use interface to video capturing, image and video codecs, as well as simple UI capabilities. + * **highgui** - an easy-to-use interface to simple UI capabilities. + * **videoio** - an easy-to-use interface to video capturing and video codecs. * **gpu** - GPU-accelerated algorithms from different OpenCV modules. * ... some other helper modules, such as FLANN and Google test wrappers, Python bindings, and others. diff --git a/modules/cudacodec/CMakeLists.txt b/modules/cudacodec/CMakeLists.txt index ace7cb3763..ca62995505 100644 --- a/modules/cudacodec/CMakeLists.txt +++ b/modules/cudacodec/CMakeLists.txt @@ -6,7 +6,7 @@ set(the_description "CUDA-accelerated Video Encoding/Decoding") ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127 /wd4324 /wd4512 -Wundef) -ocv_add_module(cudacodec opencv_highgui OPTIONAL opencv_cudev) +ocv_add_module(cudacodec OPTIONAL opencv_cudev) ocv_module_include_directories() ocv_glob_module_sources() diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index efe31a1cac..b0c93a8eba 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -18,13 +18,9 @@ endif() set(highgui_hdrs src/precomp.hpp - src/cap_ffmpeg_impl.hpp ) set(highgui_srcs - src/cap.cpp - src/cap_images.cpp - src/cap_ffmpeg.cpp src/window.cpp ) @@ -76,128 +72,6 @@ elseif(HAVE_COCOA) list(APPEND HIGHGUI_LIBRARIES "-framework Cocoa") endif() -if(WIN32 AND NOT ARM) - list(APPEND highgui_srcs src/cap_cmu.cpp) -endif() - -if (WIN32 AND HAVE_DSHOW) - list(APPEND highgui_srcs src/cap_dshow.cpp) -endif() - -if (WIN32 AND HAVE_MSMF) - list(APPEND highgui_srcs src/cap_msmf.cpp) -endif() - -if (WIN32 AND HAVE_VFW) - list(APPEND highgui_srcs src/cap_vfw.cpp) -endif() - -if(HAVE_XINE) - list(APPEND highgui_srcs src/cap_xine.cpp) -endif(HAVE_XINE) - -if(HAVE_DC1394_2) - list(APPEND highgui_srcs src/cap_dc1394_v2.cpp) -endif(HAVE_DC1394_2) - -if(HAVE_DC1394) - list(APPEND highgui_srcs src/cap_dc1394.cpp) -endif(HAVE_DC1394) - -if(HAVE_GSTREAMER) - list(APPEND highgui_srcs src/cap_gstreamer.cpp) -endif(HAVE_GSTREAMER) - -if(HAVE_UNICAP) - list(APPEND highgui_srcs src/cap_unicap.cpp) -endif(HAVE_UNICAP) - -if(HAVE_LIBV4L) - list(APPEND highgui_srcs src/cap_libv4l.cpp) -elseif(HAVE_CAMV4L OR HAVE_CAMV4L2 OR HAVE_VIDEOIO) - list(APPEND highgui_srcs src/cap_v4l.cpp) -endif() - -if(HAVE_OPENNI) - list(APPEND highgui_srcs src/cap_openni.cpp) - ocv_include_directories(${OPENNI_INCLUDE_DIR}) - list(APPEND HIGHGUI_LIBRARIES ${OPENNI_LIBRARY}) -endif(HAVE_OPENNI) - -if(HAVE_opencv_androidcamera) - list(APPEND highgui_srcs src/cap_android.cpp) - add_definitions(-DHAVE_ANDROID_NATIVE_CAMERA)#TODO: remove this line -endif(HAVE_opencv_androidcamera) - -if(HAVE_XIMEA) - list(APPEND highgui_srcs src/cap_ximea.cpp) - ocv_include_directories(${XIMEA_PATH}) - if(XIMEA_LIBRARY_DIR) - link_directories("${XIMEA_LIBRARY_DIR}") - endif() - if(X86_64) - list(APPEND HIGHGUI_LIBRARIES m3apiX64) - else() - list(APPEND HIGHGUI_LIBRARIES m3api) - endif() -endif(HAVE_XIMEA) - -if(HAVE_FFMPEG) - if(UNIX AND BZIP2_LIBRARIES) - list(APPEND HIGHGUI_LIBRARIES ${BZIP2_LIBRARIES}) - endif() - if(APPLE) - list(APPEND HIGHGUI_LIBRARIES "-framework VideoDecodeAcceleration" bz2) - endif() -endif(HAVE_FFMPEG) - -if(HAVE_PVAPI) - add_definitions(-DHAVE_PVAPI) - add_definitions(${PVAPI_DEFINITIONS}) - ocv_include_directories(${PVAPI_INCLUDE_PATH}) - set(highgui_srcs src/cap_pvapi.cpp ${highgui_srcs}) - list(APPEND HIGHGUI_LIBRARIES ${PVAPI_LIBRARY}) -endif() - -if(HAVE_GIGE_API) - add_definitions(-DHAVE_GIGE_API) - ocv_include_directories(${GIGEAPI_INCLUDE_PATH}) - set(highgui_srcs src/cap_giganetix.cpp ${highgui_srcs}) - list(APPEND HIGHGUI_LIBRARIES ${GIGEAPI_LIBRARIES}) - list(APPEND highgui_srcs src/cap_giganetix.cpp) -endif(HAVE_GIGE_API) - -if(HAVE_AVFOUNDATION) - list(APPEND highgui_srcs src/cap_avfoundation.mm) - list(APPEND HIGHGUI_LIBRARIES "-framework AVFoundation" "-framework QuartzCore") -endif() - -if(HAVE_QUICKTIME) - list(APPEND highgui_srcs src/cap_qt.cpp) - list(APPEND HIGHGUI_LIBRARIES "-framework Carbon" "-framework QuickTime" "-framework CoreFoundation" "-framework QuartzCore") -elseif(HAVE_QTKIT) - list(APPEND highgui_srcs src/cap_qtkit.mm) - list(APPEND HIGHGUI_LIBRARIES "-framework QTKit" "-framework QuartzCore" "-framework AppKit") -endif() - -if(HAVE_INTELPERC) - list(APPEND highgui_srcs src/cap_intelperc.cpp) - ocv_include_directories(${INTELPERC_INCLUDE_DIR}) - list(APPEND HIGHGUI_LIBRARIES ${INTELPERC_LIBRARIES}) -endif(HAVE_INTELPERC) - -if(IOS) - add_definitions(-DHAVE_IOS=1) - list(APPEND highgui_srcs src/ios_conversions.mm src/cap_ios_abstract_camera.mm src/cap_ios_photo_camera.mm src/cap_ios_video_camera.mm) - list(APPEND HIGHGUI_LIBRARIES "-framework Accelerate" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreImage" "-framework CoreMedia" "-framework CoreVideo" "-framework QuartzCore" "-framework AssetsLibrary") -endif() - -if(WIN32) - link_directories("${OpenCV_SOURCE_DIR}/3rdparty/lib") # for ffmpeg wrapper only - include_directories(AFTER SYSTEM "${OpenCV_SOURCE_DIR}/3rdparty/include") # for directshow in VS2005 and multi-monitor support on MinGW - include_directories(AFTER SYSTEM "${OpenCV_SOURCE_DIR}/3rdparty/include/ffmpeg_") # for tests -endif() - if(UNIX) #these variables are set by CHECK_MODULE macro foreach(P ${HIGHGUI_INCLUDE_DIRS}) @@ -248,33 +122,5 @@ set_target_properties(${the_module} PROPERTIES LINK_INTERFACE_LIBRARIES "") ocv_add_precompiled_headers(${the_module}) ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated-declarations) -if(WIN32 AND WITH_FFMPEG) - #copy ffmpeg dll to the output folder - if(MSVC64 OR MINGW64) - set(FFMPEG_SUFFIX _64) - endif() - - set(ffmpeg_bare_name "opencv_ffmpeg${FFMPEG_SUFFIX}.dll") - set(ffmpeg_bare_name_ver "opencv_ffmpeg${OPENCV_DLLVERSION}${FFMPEG_SUFFIX}.dll") - set(ffmpeg_path "${OpenCV_SOURCE_DIR}/3rdparty/ffmpeg/${ffmpeg_bare_name}") - - if(MSVC_IDE) - add_custom_command(TARGET ${the_module} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Release/${ffmpeg_bare_name_ver}" - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Debug/${ffmpeg_bare_name_ver}" - COMMENT "Copying ${ffmpeg_path} to the output directory") - elseif(MSVC AND (CMAKE_GENERATOR MATCHES "Visual")) - add_custom_command(TARGET ${the_module} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/${ffmpeg_bare_name_ver}" - COMMENT "Copying ${ffmpeg_path} to the output directory") - else() - add_custom_command(TARGET ${the_module} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${ffmpeg_bare_name_ver}" - COMMENT "Copying ${ffmpeg_path} to the output directory") - endif() - - install(FILES "${ffmpeg_path}" DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT libs RENAME "${ffmpeg_bare_name_ver}") -endif() - ocv_add_accuracy_tests() ocv_add_perf_tests() diff --git a/modules/highgui/doc/highgui.rst b/modules/highgui/doc/highgui.rst index 0450018785..b42ac7a8ef 100644 --- a/modules/highgui/doc/highgui.rst +++ b/modules/highgui/doc/highgui.rst @@ -9,11 +9,9 @@ It provides easy interface to: * Create and manipulate windows that can display images and "remember" their content (no need to handle repaint events from OS). * Add trackbars to the windows, handle simple mouse events as well as keyboard commands. -* Read video from camera or file and write video to a file. .. toctree:: :maxdepth: 2 user_interface - reading_and_writing_video qt_new_functions diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index e0f40b9292..3dfc7d7561 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -202,344 +202,4 @@ CV_EXPORTS int createButton( const String& bar_name, ButtonCallback on_change, } // cv -////////////////////////////////// video io ///////////////////////////////// - -typedef struct CvCapture CvCapture; -typedef struct CvVideoWriter CvVideoWriter; - -namespace cv -{ - -// Camera API -enum { CAP_ANY = 0, // autodetect - CAP_VFW = 200, // platform native - CAP_V4L = 200, - CAP_V4L2 = CAP_V4L, - CAP_FIREWARE = 300, // IEEE 1394 drivers - CAP_FIREWIRE = CAP_FIREWARE, - CAP_IEEE1394 = CAP_FIREWARE, - CAP_DC1394 = CAP_FIREWARE, - CAP_CMU1394 = CAP_FIREWARE, - CAP_QT = 500, // QuickTime - CAP_UNICAP = 600, // Unicap drivers - CAP_DSHOW = 700, // DirectShow (via videoInput) - CAP_PVAPI = 800, // PvAPI, Prosilica GigE SDK - CAP_OPENNI = 900, // OpenNI (for Kinect) - CAP_OPENNI_ASUS = 910, // OpenNI (for Asus Xtion) - CAP_ANDROID = 1000, // Android - CAP_XIAPI = 1100, // XIMEA Camera API - CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) - CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK - CAP_MSMF = 1400, // Microsoft Media Foundation (via videoInput) - CAP_INTELPERC = 1500 // Intel Perceptual Computing SDK - }; - -// generic properties (based on DC1394 properties) -enum { CAP_PROP_POS_MSEC =0, - CAP_PROP_POS_FRAMES =1, - CAP_PROP_POS_AVI_RATIO =2, - CAP_PROP_FRAME_WIDTH =3, - CAP_PROP_FRAME_HEIGHT =4, - CAP_PROP_FPS =5, - CAP_PROP_FOURCC =6, - CAP_PROP_FRAME_COUNT =7, - CAP_PROP_FORMAT =8, - CAP_PROP_MODE =9, - CAP_PROP_BRIGHTNESS =10, - CAP_PROP_CONTRAST =11, - CAP_PROP_SATURATION =12, - CAP_PROP_HUE =13, - CAP_PROP_GAIN =14, - CAP_PROP_EXPOSURE =15, - CAP_PROP_CONVERT_RGB =16, - CAP_PROP_WHITE_BALANCE_BLUE_U =17, - CAP_PROP_RECTIFICATION =18, - CAP_PROP_MONOCROME =19, - CAP_PROP_SHARPNESS =20, - CAP_PROP_AUTO_EXPOSURE =21, // DC1394: exposure control done by camera, user can adjust refernce level using this feature - CAP_PROP_GAMMA =22, - CAP_PROP_TEMPERATURE =23, - CAP_PROP_TRIGGER =24, - CAP_PROP_TRIGGER_DELAY =25, - CAP_PROP_WHITE_BALANCE_RED_V =26, - CAP_PROP_ZOOM =27, - CAP_PROP_FOCUS =28, - CAP_PROP_GUID =29, - CAP_PROP_ISO_SPEED =30, - CAP_PROP_BACKLIGHT =32, - CAP_PROP_PAN =33, - CAP_PROP_TILT =34, - CAP_PROP_ROLL =35, - CAP_PROP_IRIS =36, - CAP_PROP_SETTINGS =37 - }; - - -// DC1394 only -// modes of the controlling registers (can be: auto, manual, auto single push, absolute Latter allowed with any other mode) -// every feature can have only one mode turned on at a time -enum { CAP_PROP_DC1394_OFF = -4, //turn the feature off (not controlled manually nor automatically) - CAP_PROP_DC1394_MODE_MANUAL = -3, //set automatically when a value of the feature is set by the user - CAP_PROP_DC1394_MODE_AUTO = -2, - CAP_PROP_DC1394_MODE_ONE_PUSH_AUTO = -1, - CAP_PROP_DC1394_MAX = 31 - }; - - -// OpenNI map generators -enum { CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, - CAP_OPENNI_IMAGE_GENERATOR = 1 << 30, - CAP_OPENNI_GENERATORS_MASK = CAP_OPENNI_DEPTH_GENERATOR + CAP_OPENNI_IMAGE_GENERATOR - }; - -// Properties of cameras available through OpenNI interfaces -enum { CAP_PROP_OPENNI_OUTPUT_MODE = 100, - CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, // in mm - CAP_PROP_OPENNI_BASELINE = 102, // in mm - CAP_PROP_OPENNI_FOCAL_LENGTH = 103, // in pixels - CAP_PROP_OPENNI_REGISTRATION = 104, // flag that synchronizes the remapping depth map to image map - // by changing depth generator's view point (if the flag is "on") or - // sets this view point to its normal one (if the flag is "off"). - CAP_PROP_OPENNI_REGISTRATION_ON = CAP_PROP_OPENNI_REGISTRATION, - CAP_PROP_OPENNI_APPROX_FRAME_SYNC = 105, - CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, - CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, - CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, - CAP_PROP_OPENNI_GENERATOR_PRESENT = 109 - }; - -// OpenNI shortcats -enum { CAP_OPENNI_IMAGE_GENERATOR_PRESENT = CAP_OPENNI_IMAGE_GENERATOR + CAP_PROP_OPENNI_GENERATOR_PRESENT, - CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CAP_OPENNI_IMAGE_GENERATOR + CAP_PROP_OPENNI_OUTPUT_MODE, - CAP_OPENNI_DEPTH_GENERATOR_BASELINE = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_BASELINE, - CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_FOCAL_LENGTH, - CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_REGISTRATION, - CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION_ON = CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION - }; - -// OpenNI data given from depth generator -enum { CAP_OPENNI_DEPTH_MAP = 0, // Depth values in mm (CV_16UC1) - CAP_OPENNI_POINT_CLOUD_MAP = 1, // XYZ in meters (CV_32FC3) - CAP_OPENNI_DISPARITY_MAP = 2, // Disparity in pixels (CV_8UC1) - CAP_OPENNI_DISPARITY_MAP_32F = 3, // Disparity in pixels (CV_32FC1) - CAP_OPENNI_VALID_DEPTH_MASK = 4, // CV_8UC1 - - // Data given from RGB image generator - CAP_OPENNI_BGR_IMAGE = 5, - CAP_OPENNI_GRAY_IMAGE = 6 - }; - -// Supported output modes of OpenNI image generator -enum { CAP_OPENNI_VGA_30HZ = 0, - CAP_OPENNI_SXGA_15HZ = 1, - CAP_OPENNI_SXGA_30HZ = 2, - CAP_OPENNI_QVGA_30HZ = 3, - CAP_OPENNI_QVGA_60HZ = 4 - }; - - -// GStreamer -enum { CAP_PROP_GSTREAMER_QUEUE_LENGTH = 200 // default is 1 - }; - - -// PVAPI -enum { CAP_PROP_PVAPI_MULTICASTIP = 300, // ip for anable multicast master mode. 0 for disable multicast - CAP_PROP_PVAPI_FRAMESTARTTRIGGERMODE = 301 // FrameStartTriggerMode: Determines how a frame is initiated - }; - -// PVAPI: FrameStartTriggerMode -enum { CAP_PVAPI_FSTRIGMODE_FREERUN = 0, // Freerun - CAP_PVAPI_FSTRIGMODE_SYNCIN1 = 1, // SyncIn1 - CAP_PVAPI_FSTRIGMODE_SYNCIN2 = 2, // SyncIn2 - CAP_PVAPI_FSTRIGMODE_FIXEDRATE = 3, // FixedRate - CAP_PVAPI_FSTRIGMODE_SOFTWARE = 4 // Software - }; - -// Properties of cameras available through XIMEA SDK interface -enum { CAP_PROP_XI_DOWNSAMPLING = 400, // Change image resolution by binning or skipping. - CAP_PROP_XI_DATA_FORMAT = 401, // Output data format. - CAP_PROP_XI_OFFSET_X = 402, // Horizontal offset from the origin to the area of interest (in pixels). - CAP_PROP_XI_OFFSET_Y = 403, // Vertical offset from the origin to the area of interest (in pixels). - CAP_PROP_XI_TRG_SOURCE = 404, // Defines source of trigger. - CAP_PROP_XI_TRG_SOFTWARE = 405, // Generates an internal trigger. PRM_TRG_SOURCE must be set to TRG_SOFTWARE. - CAP_PROP_XI_GPI_SELECTOR = 406, // Selects general purpose input - CAP_PROP_XI_GPI_MODE = 407, // Set general purpose input mode - CAP_PROP_XI_GPI_LEVEL = 408, // Get general purpose level - CAP_PROP_XI_GPO_SELECTOR = 409, // Selects general purpose output - CAP_PROP_XI_GPO_MODE = 410, // Set general purpose output mode - CAP_PROP_XI_LED_SELECTOR = 411, // Selects camera signalling LED - CAP_PROP_XI_LED_MODE = 412, // Define camera signalling LED functionality - CAP_PROP_XI_MANUAL_WB = 413, // Calculates White Balance(must be called during acquisition) - CAP_PROP_XI_AUTO_WB = 414, // Automatic white balance - CAP_PROP_XI_AEAG = 415, // Automatic exposure/gain - CAP_PROP_XI_EXP_PRIORITY = 416, // Exposure priority (0.5 - exposure 50%, gain 50%). - CAP_PROP_XI_AE_MAX_LIMIT = 417, // Maximum limit of exposure in AEAG procedure - CAP_PROP_XI_AG_MAX_LIMIT = 418, // Maximum limit of gain in AEAG procedure - CAP_PROP_XI_AEAG_LEVEL = 419, // Average intensity of output signal AEAG should achieve(in %) - CAP_PROP_XI_TIMEOUT = 420 // Image capture timeout in milliseconds - }; - - -// Properties for Android cameras -enum { CAP_PROP_ANDROID_AUTOGRAB = 1024, - CAP_PROP_ANDROID_PREVIEW_SIZES_STRING = 1025, // readonly, tricky property, returns const char* indeed - CAP_PROP_ANDROID_PREVIEW_FORMAT = 1026, // readonly, tricky property, returns const char* indeed - CAP_PROP_ANDROID_FLASH_MODE = 8001, - CAP_PROP_ANDROID_FOCUS_MODE = 8002, - CAP_PROP_ANDROID_WHITE_BALANCE = 8003, - CAP_PROP_ANDROID_ANTIBANDING = 8004, - CAP_PROP_ANDROID_FOCAL_LENGTH = 8005, - CAP_PROP_ANDROID_FOCUS_DISTANCE_NEAR = 8006, - CAP_PROP_ANDROID_FOCUS_DISTANCE_OPTIMAL = 8007, - CAP_PROP_ANDROID_FOCUS_DISTANCE_FAR = 8008 - }; - - -// Android camera output formats -enum { CAP_ANDROID_COLOR_FRAME_BGR = 0, //BGR - CAP_ANDROID_COLOR_FRAME = CAP_ANDROID_COLOR_FRAME_BGR, - CAP_ANDROID_GREY_FRAME = 1, //Y - CAP_ANDROID_COLOR_FRAME_RGB = 2, - CAP_ANDROID_COLOR_FRAME_BGRA = 3, - CAP_ANDROID_COLOR_FRAME_RGBA = 4 - }; - - -// Android camera flash modes -enum { CAP_ANDROID_FLASH_MODE_AUTO = 0, - CAP_ANDROID_FLASH_MODE_OFF = 1, - CAP_ANDROID_FLASH_MODE_ON = 2, - CAP_ANDROID_FLASH_MODE_RED_EYE = 3, - CAP_ANDROID_FLASH_MODE_TORCH = 4 - }; - - -// Android camera focus modes -enum { CAP_ANDROID_FOCUS_MODE_AUTO = 0, - CAP_ANDROID_FOCUS_MODE_CONTINUOUS_VIDEO = 1, - CAP_ANDROID_FOCUS_MODE_EDOF = 2, - CAP_ANDROID_FOCUS_MODE_FIXED = 3, - CAP_ANDROID_FOCUS_MODE_INFINITY = 4, - CAP_ANDROID_FOCUS_MODE_MACRO = 5 - }; - - -// Android camera white balance modes -enum { CAP_ANDROID_WHITE_BALANCE_AUTO = 0, - CAP_ANDROID_WHITE_BALANCE_CLOUDY_DAYLIGHT = 1, - CAP_ANDROID_WHITE_BALANCE_DAYLIGHT = 2, - CAP_ANDROID_WHITE_BALANCE_FLUORESCENT = 3, - CAP_ANDROID_WHITE_BALANCE_INCANDESCENT = 4, - CAP_ANDROID_WHITE_BALANCE_SHADE = 5, - CAP_ANDROID_WHITE_BALANCE_TWILIGHT = 6, - CAP_ANDROID_WHITE_BALANCE_WARM_FLUORESCENT = 7 - }; - - -// Android camera antibanding modes -enum { CAP_ANDROID_ANTIBANDING_50HZ = 0, - CAP_ANDROID_ANTIBANDING_60HZ = 1, - CAP_ANDROID_ANTIBANDING_AUTO = 2, - CAP_ANDROID_ANTIBANDING_OFF = 3 - }; - - -// Properties of cameras available through AVFOUNDATION interface -enum { CAP_PROP_IOS_DEVICE_FOCUS = 9001, - CAP_PROP_IOS_DEVICE_EXPOSURE = 9002, - CAP_PROP_IOS_DEVICE_FLASH = 9003, - CAP_PROP_IOS_DEVICE_WHITEBALANCE = 9004, - CAP_PROP_IOS_DEVICE_TORCH = 9005 - }; - - -// Properties of cameras available through Smartek Giganetix Ethernet Vision interface -/* --- Vladimir Litvinenko (litvinenko.vladimir@gmail.com) --- */ -enum { CAP_PROP_GIGA_FRAME_OFFSET_X = 10001, - CAP_PROP_GIGA_FRAME_OFFSET_Y = 10002, - CAP_PROP_GIGA_FRAME_WIDTH_MAX = 10003, - CAP_PROP_GIGA_FRAME_HEIGH_MAX = 10004, - CAP_PROP_GIGA_FRAME_SENS_WIDTH = 10005, - CAP_PROP_GIGA_FRAME_SENS_HEIGH = 10006 - }; - -enum { CAP_PROP_INTELPERC_PROFILE_COUNT = 11001, - CAP_PROP_INTELPERC_PROFILE_IDX = 11002, - CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE = 11003, - CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE = 11004, - CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD = 11005, - CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_HORZ = 11006, - CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT = 11007 - }; - -// Intel PerC streams -enum { CAP_INTELPERC_DEPTH_GENERATOR = 1 << 29, - CAP_INTELPERC_IMAGE_GENERATOR = 1 << 28, - CAP_INTELPERC_GENERATORS_MASK = CAP_INTELPERC_DEPTH_GENERATOR + CAP_INTELPERC_IMAGE_GENERATOR - }; - -enum { CAP_INTELPERC_DEPTH_MAP = 0, // Each pixel is a 16-bit integer. The value indicates the distance from an object to the camera's XY plane or the Cartesian depth. - CAP_INTELPERC_UVDEPTH_MAP = 1, // Each pixel contains two 32-bit floating point values in the range of 0-1, representing the mapping of depth coordinates to the color coordinates. - CAP_INTELPERC_IR_MAP = 2, // Each pixel is a 16-bit integer. The value indicates the intensity of the reflected laser beam. - CAP_INTELPERC_IMAGE = 3 - }; - - -class IVideoCapture; -class CV_EXPORTS_W VideoCapture -{ -public: - CV_WRAP VideoCapture(); - CV_WRAP VideoCapture(const String& filename); - CV_WRAP VideoCapture(int device); - - virtual ~VideoCapture(); - CV_WRAP virtual bool open(const String& filename); - CV_WRAP virtual bool open(int device); - CV_WRAP virtual bool isOpened() const; - CV_WRAP virtual void release(); - - CV_WRAP virtual bool grab(); - CV_WRAP virtual bool retrieve(OutputArray image, int flag = 0); - virtual VideoCapture& operator >> (CV_OUT Mat& image); - virtual VideoCapture& operator >> (CV_OUT UMat& image); - CV_WRAP virtual bool read(OutputArray image); - - CV_WRAP virtual bool set(int propId, double value); - CV_WRAP virtual double get(int propId); - -protected: - Ptr cap; - Ptr icap; -private: - static Ptr createCameraCapture(int index); -}; - -class CV_EXPORTS_W VideoWriter -{ -public: - CV_WRAP VideoWriter(); - CV_WRAP VideoWriter(const String& filename, int fourcc, double fps, - Size frameSize, bool isColor = true); - - virtual ~VideoWriter(); - CV_WRAP virtual bool open(const String& filename, int fourcc, double fps, - Size frameSize, bool isColor = true); - CV_WRAP virtual bool isOpened() const; - CV_WRAP virtual void release(); - virtual VideoWriter& operator << (const Mat& image); - CV_WRAP virtual void write(const Mat& image); - - CV_WRAP static int fourcc(char c1, char c2, char c3, char c4); - -protected: - Ptr writer; -}; - -template<> CV_EXPORTS void DefaultDeleter::operator ()(CvCapture* obj) const; -template<> CV_EXPORTS void DefaultDeleter::operator ()(CvVideoWriter* obj) const; - -} // cv - #endif diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index a94e69601b..2d3e6bc108 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -206,364 +206,10 @@ CVAPI(void) cvSetOpenGlContext(const char* window_name); CVAPI(void) cvUpdateWindow(const char* window_name); -/****************************************************************************************\ -* Working with Video Files and Cameras * -\****************************************************************************************/ - -/* "black box" capture structure */ -typedef struct CvCapture CvCapture; - -/* start capturing frames from video file */ -CVAPI(CvCapture*) cvCreateFileCapture( const char* filename ); - -enum -{ - CV_CAP_ANY =0, // autodetect - - CV_CAP_MIL =100, // MIL proprietary drivers - - CV_CAP_VFW =200, // platform native - CV_CAP_V4L =200, - CV_CAP_V4L2 =200, - - CV_CAP_FIREWARE =300, // IEEE 1394 drivers - CV_CAP_FIREWIRE =300, - CV_CAP_IEEE1394 =300, - CV_CAP_DC1394 =300, - CV_CAP_CMU1394 =300, - - CV_CAP_STEREO =400, // TYZX proprietary drivers - CV_CAP_TYZX =400, - CV_TYZX_LEFT =400, - CV_TYZX_RIGHT =401, - CV_TYZX_COLOR =402, - CV_TYZX_Z =403, - - CV_CAP_QT =500, // QuickTime - - CV_CAP_UNICAP =600, // Unicap drivers - - CV_CAP_DSHOW =700, // DirectShow (via videoInput) - CV_CAP_MSMF =1400, // Microsoft Media Foundation (via videoInput) - - CV_CAP_PVAPI =800, // PvAPI, Prosilica GigE SDK - - CV_CAP_OPENNI =900, // OpenNI (for Kinect) - CV_CAP_OPENNI_ASUS =910, // OpenNI (for Asus Xtion) - - CV_CAP_ANDROID =1000, // Android - CV_CAP_ANDROID_BACK =CV_CAP_ANDROID+99, // Android back camera - CV_CAP_ANDROID_FRONT =CV_CAP_ANDROID+98, // Android front camera - - CV_CAP_XIAPI =1100, // XIMEA Camera API - - CV_CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) - - CV_CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK - - CV_CAP_INTELPERC = 1500 // Intel Perceptual Computing SDK -}; - -/* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */ -CVAPI(CvCapture*) cvCreateCameraCapture( int index ); - -/* grab a frame, return 1 on success, 0 on fail. - this function is thought to be fast */ -CVAPI(int) cvGrabFrame( CvCapture* capture ); - -/* get the frame grabbed with cvGrabFrame(..) - This function may apply some frame processing like - frame decompression, flipping etc. - !!!DO NOT RELEASE or MODIFY the retrieved frame!!! */ -CVAPI(IplImage*) cvRetrieveFrame( CvCapture* capture, int streamIdx CV_DEFAULT(0) ); - -/* Just a combination of cvGrabFrame and cvRetrieveFrame - !!!DO NOT RELEASE or MODIFY the retrieved frame!!! */ -CVAPI(IplImage*) cvQueryFrame( CvCapture* capture ); - -/* stop capturing/reading and free resources */ -CVAPI(void) cvReleaseCapture( CvCapture** capture ); - -enum -{ - // modes of the controlling registers (can be: auto, manual, auto single push, absolute Latter allowed with any other mode) - // every feature can have only one mode turned on at a time - CV_CAP_PROP_DC1394_OFF = -4, //turn the feature off (not controlled manually nor automatically) - CV_CAP_PROP_DC1394_MODE_MANUAL = -3, //set automatically when a value of the feature is set by the user - CV_CAP_PROP_DC1394_MODE_AUTO = -2, - CV_CAP_PROP_DC1394_MODE_ONE_PUSH_AUTO = -1, - CV_CAP_PROP_POS_MSEC =0, - CV_CAP_PROP_POS_FRAMES =1, - CV_CAP_PROP_POS_AVI_RATIO =2, - CV_CAP_PROP_FRAME_WIDTH =3, - CV_CAP_PROP_FRAME_HEIGHT =4, - CV_CAP_PROP_FPS =5, - CV_CAP_PROP_FOURCC =6, - CV_CAP_PROP_FRAME_COUNT =7, - CV_CAP_PROP_FORMAT =8, - CV_CAP_PROP_MODE =9, - CV_CAP_PROP_BRIGHTNESS =10, - CV_CAP_PROP_CONTRAST =11, - CV_CAP_PROP_SATURATION =12, - CV_CAP_PROP_HUE =13, - CV_CAP_PROP_GAIN =14, - CV_CAP_PROP_EXPOSURE =15, - CV_CAP_PROP_CONVERT_RGB =16, - CV_CAP_PROP_WHITE_BALANCE_BLUE_U =17, - CV_CAP_PROP_RECTIFICATION =18, - CV_CAP_PROP_MONOCROME =19, - CV_CAP_PROP_SHARPNESS =20, - CV_CAP_PROP_AUTO_EXPOSURE =21, // exposure control done by camera, - // user can adjust refernce level - // using this feature - CV_CAP_PROP_GAMMA =22, - CV_CAP_PROP_TEMPERATURE =23, - CV_CAP_PROP_TRIGGER =24, - CV_CAP_PROP_TRIGGER_DELAY =25, - CV_CAP_PROP_WHITE_BALANCE_RED_V =26, - CV_CAP_PROP_ZOOM =27, - CV_CAP_PROP_FOCUS =28, - CV_CAP_PROP_GUID =29, - CV_CAP_PROP_ISO_SPEED =30, - CV_CAP_PROP_MAX_DC1394 =31, - CV_CAP_PROP_BACKLIGHT =32, - CV_CAP_PROP_PAN =33, - CV_CAP_PROP_TILT =34, - CV_CAP_PROP_ROLL =35, - CV_CAP_PROP_IRIS =36, - CV_CAP_PROP_SETTINGS =37, - - CV_CAP_PROP_AUTOGRAB =1024, // property for highgui class CvCapture_Android only - CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING=1025, // readonly, tricky property, returns cpnst char* indeed - CV_CAP_PROP_PREVIEW_FORMAT=1026, // readonly, tricky property, returns cpnst char* indeed - - // OpenNI map generators - CV_CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, - CV_CAP_OPENNI_IMAGE_GENERATOR = 1 << 30, - CV_CAP_OPENNI_GENERATORS_MASK = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_OPENNI_IMAGE_GENERATOR, - - // Properties of cameras available through OpenNI interfaces - CV_CAP_PROP_OPENNI_OUTPUT_MODE = 100, - CV_CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, // in mm - CV_CAP_PROP_OPENNI_BASELINE = 102, // in mm - CV_CAP_PROP_OPENNI_FOCAL_LENGTH = 103, // in pixels - CV_CAP_PROP_OPENNI_REGISTRATION = 104, // flag - CV_CAP_PROP_OPENNI_REGISTRATION_ON = CV_CAP_PROP_OPENNI_REGISTRATION, // flag that synchronizes the remapping depth map to image map - // by changing depth generator's view point (if the flag is "on") or - // sets this view point to its normal one (if the flag is "off"). - CV_CAP_PROP_OPENNI_APPROX_FRAME_SYNC = 105, - CV_CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, - CV_CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, - CV_CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, - - CV_CAP_PROP_OPENNI_GENERATOR_PRESENT = 109, - - CV_CAP_OPENNI_IMAGE_GENERATOR_PRESENT = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_GENERATOR_PRESENT, - CV_CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_OUTPUT_MODE, - CV_CAP_OPENNI_DEPTH_GENERATOR_BASELINE = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_BASELINE, - CV_CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_FOCAL_LENGTH, - CV_CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_REGISTRATION, - CV_CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION_ON = CV_CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION, - - // Properties of cameras available through GStreamer interface - CV_CAP_GSTREAMER_QUEUE_LENGTH = 200, // default is 1 - - // PVAPI - CV_CAP_PROP_PVAPI_MULTICASTIP = 300, // ip for anable multicast master mode. 0 for disable multicast - CV_CAP_PROP_PVAPI_FRAMESTARTTRIGGERMODE = 301, // FrameStartTriggerMode: Determines how a frame is initiated - - // Properties of cameras available through XIMEA SDK interface - CV_CAP_PROP_XI_DOWNSAMPLING = 400, // Change image resolution by binning or skipping. - CV_CAP_PROP_XI_DATA_FORMAT = 401, // Output data format. - CV_CAP_PROP_XI_OFFSET_X = 402, // Horizontal offset from the origin to the area of interest (in pixels). - CV_CAP_PROP_XI_OFFSET_Y = 403, // Vertical offset from the origin to the area of interest (in pixels). - CV_CAP_PROP_XI_TRG_SOURCE = 404, // Defines source of trigger. - CV_CAP_PROP_XI_TRG_SOFTWARE = 405, // Generates an internal trigger. PRM_TRG_SOURCE must be set to TRG_SOFTWARE. - CV_CAP_PROP_XI_GPI_SELECTOR = 406, // Selects general purpose input - CV_CAP_PROP_XI_GPI_MODE = 407, // Set general purpose input mode - CV_CAP_PROP_XI_GPI_LEVEL = 408, // Get general purpose level - CV_CAP_PROP_XI_GPO_SELECTOR = 409, // Selects general purpose output - CV_CAP_PROP_XI_GPO_MODE = 410, // Set general purpose output mode - CV_CAP_PROP_XI_LED_SELECTOR = 411, // Selects camera signalling LED - CV_CAP_PROP_XI_LED_MODE = 412, // Define camera signalling LED functionality - CV_CAP_PROP_XI_MANUAL_WB = 413, // Calculates White Balance(must be called during acquisition) - CV_CAP_PROP_XI_AUTO_WB = 414, // Automatic white balance - CV_CAP_PROP_XI_AEAG = 415, // Automatic exposure/gain - CV_CAP_PROP_XI_EXP_PRIORITY = 416, // Exposure priority (0.5 - exposure 50%, gain 50%). - CV_CAP_PROP_XI_AE_MAX_LIMIT = 417, // Maximum limit of exposure in AEAG procedure - CV_CAP_PROP_XI_AG_MAX_LIMIT = 418, // Maximum limit of gain in AEAG procedure - CV_CAP_PROP_XI_AEAG_LEVEL = 419, // Average intensity of output signal AEAG should achieve(in %) - CV_CAP_PROP_XI_TIMEOUT = 420, // Image capture timeout in milliseconds - - // Properties for Android cameras - CV_CAP_PROP_ANDROID_FLASH_MODE = 8001, - CV_CAP_PROP_ANDROID_FOCUS_MODE = 8002, - CV_CAP_PROP_ANDROID_WHITE_BALANCE = 8003, - CV_CAP_PROP_ANDROID_ANTIBANDING = 8004, - CV_CAP_PROP_ANDROID_FOCAL_LENGTH = 8005, - CV_CAP_PROP_ANDROID_FOCUS_DISTANCE_NEAR = 8006, - CV_CAP_PROP_ANDROID_FOCUS_DISTANCE_OPTIMAL = 8007, - CV_CAP_PROP_ANDROID_FOCUS_DISTANCE_FAR = 8008, - CV_CAP_PROP_ANDROID_EXPOSE_LOCK = 8009, - CV_CAP_PROP_ANDROID_WHITEBALANCE_LOCK = 8010, - - // Properties of cameras available through AVFOUNDATION interface - CV_CAP_PROP_IOS_DEVICE_FOCUS = 9001, - CV_CAP_PROP_IOS_DEVICE_EXPOSURE = 9002, - CV_CAP_PROP_IOS_DEVICE_FLASH = 9003, - CV_CAP_PROP_IOS_DEVICE_WHITEBALANCE = 9004, - CV_CAP_PROP_IOS_DEVICE_TORCH = 9005, - - // Properties of cameras available through Smartek Giganetix Ethernet Vision interface - /* --- Vladimir Litvinenko (litvinenko.vladimir@gmail.com) --- */ - CV_CAP_PROP_GIGA_FRAME_OFFSET_X = 10001, - CV_CAP_PROP_GIGA_FRAME_OFFSET_Y = 10002, - CV_CAP_PROP_GIGA_FRAME_WIDTH_MAX = 10003, - CV_CAP_PROP_GIGA_FRAME_HEIGH_MAX = 10004, - CV_CAP_PROP_GIGA_FRAME_SENS_WIDTH = 10005, - CV_CAP_PROP_GIGA_FRAME_SENS_HEIGH = 10006, - - CV_CAP_PROP_INTELPERC_PROFILE_COUNT = 11001, - CV_CAP_PROP_INTELPERC_PROFILE_IDX = 11002, - CV_CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE = 11003, - CV_CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE = 11004, - CV_CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD = 11005, - CV_CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_HORZ = 11006, - CV_CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT = 11007, - - // Intel PerC streams - CV_CAP_INTELPERC_DEPTH_GENERATOR = 1 << 29, - CV_CAP_INTELPERC_IMAGE_GENERATOR = 1 << 28, - CV_CAP_INTELPERC_GENERATORS_MASK = CV_CAP_INTELPERC_DEPTH_GENERATOR + CV_CAP_INTELPERC_IMAGE_GENERATOR -}; - -enum -{ - // Data given from depth generator. - CV_CAP_OPENNI_DEPTH_MAP = 0, // Depth values in mm (CV_16UC1) - CV_CAP_OPENNI_POINT_CLOUD_MAP = 1, // XYZ in meters (CV_32FC3) - CV_CAP_OPENNI_DISPARITY_MAP = 2, // Disparity in pixels (CV_8UC1) - CV_CAP_OPENNI_DISPARITY_MAP_32F = 3, // Disparity in pixels (CV_32FC1) - CV_CAP_OPENNI_VALID_DEPTH_MASK = 4, // CV_8UC1 - - // Data given from RGB image generator. - CV_CAP_OPENNI_BGR_IMAGE = 5, - CV_CAP_OPENNI_GRAY_IMAGE = 6 -}; - -// Supported output modes of OpenNI image generator -enum -{ - CV_CAP_OPENNI_VGA_30HZ = 0, - CV_CAP_OPENNI_SXGA_15HZ = 1, - CV_CAP_OPENNI_SXGA_30HZ = 2, - CV_CAP_OPENNI_QVGA_30HZ = 3, - CV_CAP_OPENNI_QVGA_60HZ = 4 -}; - -//supported by Android camera output formats -enum -{ - CV_CAP_ANDROID_COLOR_FRAME_BGR = 0, //BGR - CV_CAP_ANDROID_COLOR_FRAME = CV_CAP_ANDROID_COLOR_FRAME_BGR, - CV_CAP_ANDROID_GREY_FRAME = 1, //Y - CV_CAP_ANDROID_COLOR_FRAME_RGB = 2, - CV_CAP_ANDROID_COLOR_FRAME_BGRA = 3, - CV_CAP_ANDROID_COLOR_FRAME_RGBA = 4 -}; - -// supported Android camera flash modes -enum -{ - CV_CAP_ANDROID_FLASH_MODE_AUTO = 0, - CV_CAP_ANDROID_FLASH_MODE_OFF, - CV_CAP_ANDROID_FLASH_MODE_ON, - CV_CAP_ANDROID_FLASH_MODE_RED_EYE, - CV_CAP_ANDROID_FLASH_MODE_TORCH -}; - -// supported Android camera focus modes -enum -{ - CV_CAP_ANDROID_FOCUS_MODE_AUTO = 0, - CV_CAP_ANDROID_FOCUS_MODE_CONTINUOUS_PICTURE, - CV_CAP_ANDROID_FOCUS_MODE_CONTINUOUS_VIDEO, - CV_CAP_ANDROID_FOCUS_MODE_EDOF, - CV_CAP_ANDROID_FOCUS_MODE_FIXED, - CV_CAP_ANDROID_FOCUS_MODE_INFINITY, - CV_CAP_ANDROID_FOCUS_MODE_MACRO -}; - -// supported Android camera white balance modes -enum -{ - CV_CAP_ANDROID_WHITE_BALANCE_AUTO = 0, - CV_CAP_ANDROID_WHITE_BALANCE_CLOUDY_DAYLIGHT, - CV_CAP_ANDROID_WHITE_BALANCE_DAYLIGHT, - CV_CAP_ANDROID_WHITE_BALANCE_FLUORESCENT, - CV_CAP_ANDROID_WHITE_BALANCE_INCANDESCENT, - CV_CAP_ANDROID_WHITE_BALANCE_SHADE, - CV_CAP_ANDROID_WHITE_BALANCE_TWILIGHT, - CV_CAP_ANDROID_WHITE_BALANCE_WARM_FLUORESCENT -}; - -// supported Android camera antibanding modes -enum -{ - CV_CAP_ANDROID_ANTIBANDING_50HZ = 0, - CV_CAP_ANDROID_ANTIBANDING_60HZ, - CV_CAP_ANDROID_ANTIBANDING_AUTO, - CV_CAP_ANDROID_ANTIBANDING_OFF -}; - -enum -{ - CV_CAP_INTELPERC_DEPTH_MAP = 0, // Each pixel is a 16-bit integer. The value indicates the distance from an object to the camera's XY plane or the Cartesian depth. - CV_CAP_INTELPERC_UVDEPTH_MAP = 1, // Each pixel contains two 32-bit floating point values in the range of 0-1, representing the mapping of depth coordinates to the color coordinates. - CV_CAP_INTELPERC_IR_MAP = 2, // Each pixel is a 16-bit integer. The value indicates the intensity of the reflected laser beam. - CV_CAP_INTELPERC_IMAGE = 3 -}; - -/* retrieve or set capture properties */ -CVAPI(double) cvGetCaptureProperty( CvCapture* capture, int property_id ); -CVAPI(int) cvSetCaptureProperty( CvCapture* capture, int property_id, double value ); - -// Return the type of the capturer (eg, CV_CAP_V4W, CV_CAP_UNICAP), which is unknown if created with CV_CAP_ANY -CVAPI(int) cvGetCaptureDomain( CvCapture* capture); - -/* "black box" video file writer structure */ -typedef struct CvVideoWriter CvVideoWriter; - -#define CV_FOURCC_MACRO(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24)) - -CV_INLINE int CV_FOURCC(char c1, char c2, char c3, char c4) -{ - return CV_FOURCC_MACRO(c1, c2, c3, c4); -} - -#define CV_FOURCC_PROMPT -1 /* Open Codec Selection Dialog (Windows only) */ -#define CV_FOURCC_DEFAULT CV_FOURCC('I', 'Y', 'U', 'V') /* Use default codec for specified filename (Linux only) */ - -/* initialize video file writer */ -CVAPI(CvVideoWriter*) cvCreateVideoWriter( const char* filename, int fourcc, - double fps, CvSize frame_size, - int is_color CV_DEFAULT(1)); - -/* write frame to video file */ -CVAPI(int) cvWriteFrame( CvVideoWriter* writer, const IplImage* image ); - -/* close video file writer */ -CVAPI(void) cvReleaseVideoWriter( CvVideoWriter** writer ); - /****************************************************************************************\ * Obsolete functions/synonyms * \****************************************************************************************/ -#define cvCaptureFromFile cvCreateFileCapture -#define cvCaptureFromCAM cvCreateCameraCapture -#define cvCaptureFromAVI cvCaptureFromFile -#define cvCreateAVIWriter cvCreateVideoWriter -#define cvWriteToAVI cvWriteFrame #define cvAddSearchPath(path) #define cvvInitSystem cvInitSystem #define cvvNamedWindow cvNamedWindow @@ -571,12 +217,9 @@ CVAPI(void) cvReleaseVideoWriter( CvVideoWriter** writer ); #define cvvResizeWindow cvResizeWindow #define cvvDestroyWindow cvDestroyWindow #define cvvCreateTrackbar cvCreateTrackbar -#define cvvLoadImage(name) cvLoadImage((name),1) -#define cvvSaveImage cvSaveImage #define cvvAddSearchPath cvAddSearchPath #define cvvWaitKey(name) cvWaitKey(0) #define cvvWaitKeyEx(name,delay) cvWaitKey(delay) -#define cvvConvertImage cvConvertImage #define HG_AUTOSIZE CV_WINDOW_AUTOSIZE #define set_preprocess_func cvSetPreprocessFuncWin32 #define set_postprocess_func cvSetPostprocessFuncWin32 diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index 86fc91264d..c9517783f9 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -95,90 +95,6 @@ #define CV_WINDOW_MAGIC_VAL 0x00420042 #define CV_TRACKBAR_MAGIC_VAL 0x00420043 -/***************************** CvCapture structure ******************************/ - -struct CvCapture -{ - virtual ~CvCapture() {} - virtual double getProperty(int) { return 0; } - virtual bool setProperty(int, double) { return 0; } - virtual bool grabFrame() { return true; } - virtual IplImage* retrieveFrame(int) { return 0; } - virtual int getCaptureDomain() { return CV_CAP_ANY; } // Return the type of the capture object: CV_CAP_VFW, etc... -}; - -/*************************** CvVideoWriter structure ****************************/ - -struct CvVideoWriter -{ - virtual ~CvVideoWriter() {} - virtual bool writeFrame(const IplImage*) { return false; } -}; - -CvCapture * cvCreateCameraCapture_V4L( int index ); -CvCapture * cvCreateCameraCapture_DC1394( int index ); -CvCapture * cvCreateCameraCapture_DC1394_2( int index ); -CvCapture* cvCreateCameraCapture_MIL( int index ); -CvCapture* cvCreateCameraCapture_Giganetix( int index ); -CvCapture * cvCreateCameraCapture_CMU( int index ); -CV_IMPL CvCapture * cvCreateCameraCapture_TYZX( int index ); -CvCapture* cvCreateFileCapture_Win32( const char* filename ); -CvCapture* cvCreateCameraCapture_VFW( int index ); -CvCapture* cvCreateFileCapture_VFW( const char* filename ); -CvVideoWriter* cvCreateVideoWriter_Win32( const char* filename, int fourcc, - double fps, CvSize frameSize, int is_color ); -CvVideoWriter* cvCreateVideoWriter_VFW( const char* filename, int fourcc, - double fps, CvSize frameSize, int is_color ); -CvCapture* cvCreateCameraCapture_DShow( int index ); -CvCapture* cvCreateCameraCapture_MSMF( int index ); -CvCapture* cvCreateFileCapture_MSMF (const char* filename); -CvVideoWriter* cvCreateVideoWriter_MSMF( const char* filename, int fourcc, - double fps, CvSize frameSize, int is_color ); -CvCapture* cvCreateCameraCapture_OpenNI( int index ); -CvCapture* cvCreateFileCapture_OpenNI( const char* filename ); -CvCapture* cvCreateCameraCapture_Android( int index ); -CvCapture* cvCreateCameraCapture_XIMEA( int index ); -CvCapture* cvCreateCameraCapture_AVFoundation(int index); - -CVAPI(int) cvHaveImageReader(const char* filename); -CVAPI(int) cvHaveImageWriter(const char* filename); - -CvCapture* cvCreateFileCapture_Images(const char* filename); -CvVideoWriter* cvCreateVideoWriter_Images(const char* filename); - -CvCapture* cvCreateFileCapture_XINE (const char* filename); - - - - -#define CV_CAP_GSTREAMER_1394 0 -#define CV_CAP_GSTREAMER_V4L 1 -#define CV_CAP_GSTREAMER_V4L2 2 -#define CV_CAP_GSTREAMER_FILE 3 - -CvCapture* cvCreateCapture_GStreamer(int type, const char *filename); -CvCapture* cvCreateFileCapture_FFMPEG_proxy(const char* filename); - - -CvVideoWriter* cvCreateVideoWriter_FFMPEG_proxy( const char* filename, int fourcc, - double fps, CvSize frameSize, int is_color ); - -CvCapture * cvCreateFileCapture_QT (const char * filename); -CvCapture * cvCreateCameraCapture_QT (const int index); - -CvVideoWriter* cvCreateVideoWriter_QT ( const char* filename, int fourcc, - double fps, CvSize frameSize, int is_color ); - -CvCapture* cvCreateFileCapture_AVFoundation (const char * filename); -CvVideoWriter* cvCreateVideoWriter_AVFoundation( const char* filename, int fourcc, - double fps, CvSize frameSize, int is_color ); - - -CvCapture * cvCreateCameraCapture_Unicap (const int index); -CvCapture * cvCreateCameraCapture_PvAPI (const int index); -CvVideoWriter* cvCreateVideoWriter_GStreamer( const char* filename, int fourcc, - double fps, CvSize frameSize, int is_color ); - //Yannick Verdie 2010 void cvSetModeWindow_W32(const char* name, double prop_value); void cvSetModeWindow_GTK(const char* name, double prop_value); @@ -199,20 +115,6 @@ double cvGetRatioWindow_GTK(const char* name); double cvGetOpenGlProp_W32(const char* name); double cvGetOpenGlProp_GTK(const char* name); -namespace cv -{ - class IVideoCapture - { - public: - virtual ~IVideoCapture() {} - virtual double getProperty(int) { return 0; } - virtual bool setProperty(int, double) { return 0; } - virtual bool grabFrame() = 0; - virtual bool retrieveFrame(int, cv::OutputArray) = 0; - virtual int getCaptureDomain() { return CAP_ANY; } // Return the type of the capture object: CAP_VFW, etc... - }; -}; - //for QT #if defined (HAVE_QT) double cvGetModeWindow_QT(const char* name); diff --git a/modules/highgui/test/test_precomp.hpp b/modules/highgui/test/test_precomp.hpp index 9e14123d32..e4d7797158 100644 --- a/modules/highgui/test/test_precomp.hpp +++ b/modules/highgui/test/test_precomp.hpp @@ -11,81 +11,11 @@ #include #include "opencv2/ts.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/imgcodecs.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/imgproc/imgproc_c.h" +//#include "opencv2/imgproc.hpp" +//#include "opencv2/imgcodecs.hpp" +//#include "opencv2/highgui.hpp" +//#include "opencv2/imgproc/imgproc_c.h" -#include "opencv2/core/private.hpp" - -#if defined(HAVE_DSHOW) || \ - defined(HAVE_TYZX) || \ - defined(HAVE_VFW) || \ - defined(HAVE_LIBV4L) || \ - (defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)) || \ - defined(HAVE_GSTREAMER) || \ - defined(HAVE_DC1394_2) || \ - defined(HAVE_DC1394) || \ - defined(HAVE_CMU1394) || \ - defined(HAVE_MIL) || \ - defined(HAVE_QUICKTIME) || \ - defined(HAVE_QTKIT) || \ - defined(HAVE_UNICAP) || \ - defined(HAVE_PVAPI) || \ - defined(HAVE_OPENNI) || \ - defined(HAVE_XIMEA) || \ - defined(HAVE_AVFOUNDATION) || \ - defined(HAVE_GIGE_API) || \ - defined(HAVE_INTELPERC) || \ - (0) - //defined(HAVE_ANDROID_NATIVE_CAMERA) || - enable after #1193 -# define BUILD_WITH_CAMERA_SUPPORT 1 -#else -# define BUILD_WITH_CAMERA_SUPPORT 0 -#endif - -#if defined(HAVE_XINE) || \ - defined(HAVE_GSTREAMER) || \ - defined(HAVE_QUICKTIME) || \ - defined(HAVE_QTKIT) || \ - defined(HAVE_AVFOUNDATION) || \ - /*defined(HAVE_OPENNI) || too specialized */ \ - defined(HAVE_FFMPEG) || \ - defined(HAVE_MSMF) -# define BUILD_WITH_VIDEO_INPUT_SUPPORT 1 -#else -# define BUILD_WITH_VIDEO_INPUT_SUPPORT 0 -#endif - -#if /*defined(HAVE_XINE) || */\ - defined(HAVE_GSTREAMER) || \ - defined(HAVE_QUICKTIME) || \ - defined(HAVE_QTKIT) || \ - defined(HAVE_AVFOUNDATION) || \ - defined(HAVE_FFMPEG) || \ - defined(HAVE_MSMF) -# define BUILD_WITH_VIDEO_OUTPUT_SUPPORT 1 -#else -# define BUILD_WITH_VIDEO_OUTPUT_SUPPORT 0 -#endif - -namespace cvtest -{ - -string fourccToString(int fourcc); - -struct VideoFormat -{ - VideoFormat() { fourcc = -1; } - VideoFormat(const string& _ext, int _fourcc) : ext(_ext), fourcc(_fourcc) {} - bool empty() const { return ext.empty(); } - - string ext; - int fourcc; -}; - -extern const VideoFormat g_specific_fmt_list[]; - -} +//#include "opencv2/core/private.hpp" #endif diff --git a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h index 81566eb659..f0c2ae13fe 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h +++ b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h @@ -109,6 +109,18 @@ enum /* utility function: convert one image to another with optional vertical flip */ CVAPI(void) cvConvertImage( const CvArr* src, CvArr* dst, int flags CV_DEFAULT(0)); +CVAPI(int) cvHaveImageReader(const char* filename); +CVAPI(int) cvHaveImageWriter(const char* filename); + + +/****************************************************************************************\ +* Obsolete functions/synonyms * +\****************************************************************************************/ + +#define cvvLoadImage(name) cvLoadImage((name),1) +#define cvvSaveImage cvSaveImage +#define cvvConvertImage cvConvertImage + #ifdef __cplusplus } diff --git a/modules/imgcodecs/include/opencv2/imgcodecs/ios.h b/modules/imgcodecs/include/opencv2/imgcodecs/ios.h index d7ba6e67c2..8ec1356053 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs/ios.h +++ b/modules/imgcodecs/include/opencv2/imgcodecs/ios.h @@ -41,6 +41,10 @@ // //M*/ +#import +#import +#import +#import #include "opencv2/core/core.hpp" UIImage* MatToUIImage(const cv::Mat& image); diff --git a/modules/imgcodecs/perf/perf_main.cpp b/modules/imgcodecs/perf/perf_main.cpp index ebe94ab7cc..403402112d 100644 --- a/modules/imgcodecs/perf/perf_main.cpp +++ b/modules/imgcodecs/perf/perf_main.cpp @@ -1,3 +1,3 @@ #include "perf_precomp.hpp" -CV_PERF_TEST_MAIN(highgui) +CV_PERF_TEST_MAIN(imgcodecs) diff --git a/modules/imgcodecs/src/ios_conversions.mm b/modules/imgcodecs/src/ios_conversions.mm index fa6208a17f..af522900c8 100644 --- a/modules/imgcodecs/src/ios_conversions.mm +++ b/modules/imgcodecs/src/ios_conversions.mm @@ -40,7 +40,11 @@ // //M*/ -#import "opencv2/highgui/cap_ios.h" +#import +#import +#import +#import +#include "opencv2/core.hpp" #include "precomp.hpp" UIImage* MatToUIImage(const cv::Mat& image) { diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index cdcaa23e5d..a3fcaba630 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -454,7 +454,7 @@ bool imencode( const String& ext, InputArray _image, } /****************************************************************************************\ -* HighGUI loading & saving function implementation * +* Imgcodecs loading & saving function implementation * \****************************************************************************************/ CV_IMPL int diff --git a/modules/imgcodecs/src/precomp.hpp b/modules/imgcodecs/src/precomp.hpp index 88959a036f..19e6fb9e3c 100644 --- a/modules/imgcodecs/src/precomp.hpp +++ b/modules/imgcodecs/src/precomp.hpp @@ -81,7 +81,4 @@ #define __END__ __CV_END__ #define EXIT __CV_EXIT__ -CVAPI(int) cvHaveImageReader(const char* filename); -CVAPI(int) cvHaveImageWriter(const char* filename); - -#endif /* __HIGHGUI_H_ */ +#endif /* __IMGCODECS_H_ */ diff --git a/modules/imgcodecs/test/test_drawing.cpp b/modules/imgcodecs/test/test_drawing.cpp index 7621ccf983..e4936f63a0 100644 --- a/modules/imgcodecs/test/test_drawing.cpp +++ b/modules/imgcodecs/test/test_drawing.cpp @@ -407,8 +407,8 @@ int CV_DrawingTest_C::checkLineIterator( Mat& _img ) } #ifdef HAVE_JPEG -TEST(Highgui_Drawing, cpp_regression) { CV_DrawingTest_CPP test; test.safe_run(); } -TEST(Highgui_Drawing, c_regression) { CV_DrawingTest_C test; test.safe_run(); } +TEST(Imgcodecs_Drawing, cpp_regression) { CV_DrawingTest_CPP test; test.safe_run(); } +TEST(Imgcodecs_Drawing, c_regression) { CV_DrawingTest_C test; test.safe_run(); } #endif class CV_FillConvexPolyTest : public cvtest::BaseTest @@ -443,4 +443,4 @@ protected: } }; -TEST(Highgui_Drawing, fillconvexpoly_clipping) { CV_FillConvexPolyTest test; test.safe_run(); } +TEST(Imgcodecs_Drawing, fillconvexpoly_clipping) { CV_FillConvexPolyTest test; test.safe_run(); } diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index 02851a0da6..9b06c5744c 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -222,12 +222,12 @@ public: #ifdef HAVE_PNG -TEST(Highgui_Image, write_big) { CV_GrfmtWriteBigImageTest test; test.safe_run(); } +TEST(Imgcodecs_Image, write_big) { CV_GrfmtWriteBigImageTest test; test.safe_run(); } #endif -TEST(Highgui_Image, write_imageseq) { CV_GrfmtWriteSequenceImageTest test; test.safe_run(); } +TEST(Imgcodecs_Image, write_imageseq) { CV_GrfmtWriteSequenceImageTest test; test.safe_run(); } -TEST(Highgui_Image, read_bmp_rle8) { CV_GrfmtReadBMPRLE8Test test; test.safe_run(); } +TEST(Imgcodecs_Image, read_bmp_rle8) { CV_GrfmtReadBMPRLE8Test test; test.safe_run(); } #ifdef HAVE_PNG class CV_GrfmtPNGEncodeTest : public cvtest::BaseTest @@ -256,9 +256,9 @@ public: } }; -TEST(Highgui_Image, encode_png) { CV_GrfmtPNGEncodeTest test; test.safe_run(); } +TEST(Imgcodecs_Image, encode_png) { CV_GrfmtPNGEncodeTest test; test.safe_run(); } -TEST(Highgui_ImreadVSCvtColor, regression) +TEST(Imgcodecs_ImreadVSCvtColor, regression) { cvtest::TS& ts = *cvtest::TS::ptr(); @@ -374,11 +374,11 @@ public: } }; -TEST(Highgui_Image, read_png_color_palette_with_alpha) { CV_GrfmtReadPNGColorPaletteWithAlphaTest test; test.safe_run(); } +TEST(Imgcodecs_Image, read_png_color_palette_with_alpha) { CV_GrfmtReadPNGColorPaletteWithAlphaTest test; test.safe_run(); } #endif #ifdef HAVE_JPEG -TEST(Highgui_Jpeg, encode_empty) +TEST(Imgcodecs_Jpeg, encode_empty) { cv::Mat img; std::vector jpegImg; @@ -386,7 +386,7 @@ TEST(Highgui_Jpeg, encode_empty) ASSERT_THROW(cv::imencode(".jpg", img, jpegImg), cv::Exception); } -TEST(Highgui_Jpeg, encode_decode_progressive_jpeg) +TEST(Imgcodecs_Jpeg, encode_decode_progressive_jpeg) { cvtest::TS& ts = *cvtest::TS::ptr(); string input = string(ts.get_data_path()) + "../cv/shared/lena.png"; @@ -410,7 +410,7 @@ TEST(Highgui_Jpeg, encode_decode_progressive_jpeg) remove(output_progressive.c_str()); } -TEST(Highgui_Jpeg, encode_decode_optimize_jpeg) +TEST(Imgcodecs_Jpeg, encode_decode_optimize_jpeg) { cvtest::TS& ts = *cvtest::TS::ptr(); string input = string(ts.get_data_path()) + "../cv/shared/lena.png"; @@ -446,9 +446,9 @@ TEST(Highgui_Jpeg, encode_decode_optimize_jpeg) #ifdef ANDROID // Test disabled as it uses a lot of memory. // It is killed with SIGKILL by out of memory killer. -TEST(Highgui_Tiff, DISABLED_decode_tile16384x16384) +TEST(Imgcodecs_Tiff, DISABLED_decode_tile16384x16384) #else -TEST(Highgui_Tiff, decode_tile16384x16384) +TEST(Imgcodecs_Tiff, decode_tile16384x16384) #endif { // see issue #2161 @@ -477,7 +477,7 @@ TEST(Highgui_Tiff, decode_tile16384x16384) remove(file4.c_str()); } -TEST(Highgui_Tiff, write_read_16bit_big_little_endian) +TEST(Imgcodecs_Tiff, write_read_16bit_big_little_endian) { // see issue #2601 "16-bit Grayscale TIFF Load Failures Due to Buffer Underflow and Endianness" @@ -560,7 +560,7 @@ public: } }; -TEST(Highgui_Tiff, decode_tile_remainder) +TEST(Imgcodecs_Tiff, decode_tile_remainder) { CV_GrfmtReadTifTiledWithNotFullTiles test; test.safe_run(); } @@ -569,7 +569,7 @@ TEST(Highgui_Tiff, decode_tile_remainder) #ifdef HAVE_WEBP -TEST(Highgui_WebP, encode_decode_lossless_webp) +TEST(Imgcodecs_WebP, encode_decode_lossless_webp) { cvtest::TS& ts = *cvtest::TS::ptr(); string input = string(ts.get_data_path()) + "../cv/shared/lena.png"; @@ -618,7 +618,7 @@ TEST(Highgui_WebP, encode_decode_lossless_webp) EXPECT_TRUE(cvtest::norm(img, img_webp, NORM_INF) == 0); } -TEST(Highgui_WebP, encode_decode_lossy_webp) +TEST(Imgcodecs_WebP, encode_decode_lossy_webp) { cvtest::TS& ts = *cvtest::TS::ptr(); std::string input = std::string(ts.get_data_path()) + "../cv/shared/lena.png"; @@ -642,7 +642,7 @@ TEST(Highgui_WebP, encode_decode_lossy_webp) } } -TEST(Highgui_WebP, encode_decode_with_alpha_webp) +TEST(Imgcodecs_WebP, encode_decode_with_alpha_webp) { cvtest::TS& ts = *cvtest::TS::ptr(); std::string input = std::string(ts.get_data_path()) + "../cv/shared/lena.png"; @@ -668,7 +668,7 @@ TEST(Highgui_WebP, encode_decode_with_alpha_webp) #endif -TEST(Highgui_Hdr, regression) +TEST(Imgcodecs_Hdr, regression) { string folder = string(cvtest::TS::ptr()->get_data_path()) + "/readwrite/"; string name_rle = folder + "rle.hdr"; diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 25c9352f4e..3e95b52ab4 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -6,7 +6,7 @@ if(IOS OR NOT PYTHON_EXECUTABLE OR NOT ANT_EXECUTABLE OR NOT (JNI_FOUND OR (ANDR endif() set(the_description "The java bindings") -ocv_add_module(java BINDINGS opencv_core opencv_imgproc OPTIONAL opencv_objdetect opencv_features2d opencv_video opencv_imgcodecs opencv_highgui opencv_ml opencv_calib3d opencv_photo opencv_nonfree opencv_contrib) +ocv_add_module(java BINDINGS opencv_core opencv_imgproc OPTIONAL opencv_objdetect opencv_features2d opencv_video opencv_imgcodecs opencv_videoio opencv_ml opencv_calib3d opencv_photo opencv_nonfree opencv_contrib) ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/generator/src/cpp") if(NOT ANDROID) diff --git a/modules/java/android_test/src/org/opencv/test/OpenCVTestCase.java b/modules/java/android_test/src/org/opencv/test/OpenCVTestCase.java index 97cdca783a..78eb738cb5 100644 --- a/modules/java/android_test/src/org/opencv/test/OpenCVTestCase.java +++ b/modules/java/android_test/src/org/opencv/test/OpenCVTestCase.java @@ -21,7 +21,7 @@ import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.core.DMatch; import org.opencv.core.KeyPoint; -import org.opencv.highgui.Highgui; +import org.opencv.imgcodecs.Imgcodecs; import android.util.Log; @@ -134,8 +134,8 @@ public class OpenCVTestCase extends TestCase { rgba0 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(0)); rgba128 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(128)); - rgbLena = Highgui.imread(OpenCVTestRunner.LENA_PATH); - grayChess = Highgui.imread(OpenCVTestRunner.CHESS_PATH, 0); + rgbLena = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH); + grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, 0); v1 = new Mat(1, 3, CvType.CV_32F); v1.put(0, 0, 1.0, 3.0, 2.0); diff --git a/modules/java/android_test/src/org/opencv/test/android/UtilsTest.java b/modules/java/android_test/src/org/opencv/test/android/UtilsTest.java index ac20139104..5494513158 100644 --- a/modules/java/android_test/src/org/opencv/test/android/UtilsTest.java +++ b/modules/java/android_test/src/org/opencv/test/android/UtilsTest.java @@ -5,7 +5,7 @@ import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.Scalar; -import org.opencv.highgui.Highgui; +import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.test.OpenCVTestCase; import org.opencv.test.OpenCVTestRunner; @@ -57,7 +57,7 @@ public class UtilsTest extends OpenCVTestCase { } public void testMatToBitmap() { - Mat imgBGR = Highgui.imread( OpenCVTestRunner.LENA_PATH ); + Mat imgBGR = Imgcodecs.imread( OpenCVTestRunner.LENA_PATH ); assertTrue(imgBGR != null && !imgBGR.empty() && imgBGR.channels() == 3); Mat m16 = new Mat(imgBGR.rows(), imgBGR.cols(), CvType.CV_8UC4); diff --git a/modules/java/android_test/src/org/opencv/test/features2d/Features2dTest.java b/modules/java/android_test/src/org/opencv/test/features2d/Features2dTest.java index 2118b53065..b9e8983fdc 100644 --- a/modules/java/android_test/src/org/opencv/test/features2d/Features2dTest.java +++ b/modules/java/android_test/src/org/opencv/test/features2d/Features2dTest.java @@ -18,7 +18,7 @@ import org.opencv.features2d.DescriptorMatcher; import org.opencv.features2d.FeatureDetector; import org.opencv.features2d.Features2d; import org.opencv.core.KeyPoint; -import org.opencv.highgui.Highgui; +import org.opencv.imgcodecs.Imgcodecs; import org.opencv.test.OpenCVTestCase; import org.opencv.test.OpenCVTestRunner; @@ -93,7 +93,7 @@ public class Features2dTest extends OpenCVTestCase { writeFile(extractorCfgFile, extractorCfg); extractor.read(extractorCfgFile); - Mat imgTrain = Highgui.imread(OpenCVTestRunner.LENA_PATH, Highgui.CV_LOAD_IMAGE_GRAYSCALE); + Mat imgTrain = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE); Mat imgQuery = imgTrain.submat(new Range(0, imgTrain.rows() - 100), Range.all()); MatOfKeyPoint trainKeypoints = new MatOfKeyPoint(); @@ -139,7 +139,7 @@ public class Features2dTest extends OpenCVTestCase { Mat outimg = new Mat(); Features2d.drawMatches(imgQuery, queryKeypoints, imgTrain, trainKeypoints, matches, outimg); String outputPath = OpenCVTestRunner.getOutputFileName("PTODresult.png"); - Highgui.imwrite(outputPath, outimg); + Imgcodecs.imwrite(outputPath, outimg); // OpenCVTestRunner.Log("Output image is saved to: " + outputPath); } } diff --git a/modules/java/android_test/src/org/opencv/test/highgui/HighguiTest.java b/modules/java/android_test/src/org/opencv/test/highgui/HighguiTest.java index b8e7c3b8b2..312462c3a5 100644 --- a/modules/java/android_test/src/org/opencv/test/highgui/HighguiTest.java +++ b/modules/java/android_test/src/org/opencv/test/highgui/HighguiTest.java @@ -2,7 +2,7 @@ package org.opencv.test.highgui; import org.opencv.core.MatOfByte; import org.opencv.core.MatOfInt; -import org.opencv.highgui.Highgui; +import org.opencv.imgcodecs.Imgcodecs; import org.opencv.test.OpenCVTestCase; import org.opencv.test.OpenCVTestRunner; @@ -15,29 +15,29 @@ public class HighguiTest extends OpenCVTestCase { public void testImencodeStringMatListOfByte() { MatOfByte buff = new MatOfByte(); assertEquals(0, buff.total()); - assertTrue( Highgui.imencode(".jpg", gray127, buff) ); + assertTrue( Imgcodecs.imencode(".jpg", gray127, buff) ); assertFalse(0 == buff.total()); } public void testImencodeStringMatListOfByteListOfInteger() { - MatOfInt params40 = new MatOfInt(Highgui.IMWRITE_JPEG_QUALITY, 40); - MatOfInt params90 = new MatOfInt(Highgui.IMWRITE_JPEG_QUALITY, 90); + MatOfInt params40 = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 40); + MatOfInt params90 = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 90); /* or MatOfInt params = new MatOfInt(); - params.fromArray(Highgui.IMWRITE_JPEG_QUALITY, 40); + params.fromArray(Imgcodecs.IMWRITE_JPEG_QUALITY, 40); */ MatOfByte buff40 = new MatOfByte(); MatOfByte buff90 = new MatOfByte(); - assertTrue( Highgui.imencode(".jpg", rgbLena, buff40, params40) ); - assertTrue( Highgui.imencode(".jpg", rgbLena, buff90, params90) ); + assertTrue( Imgcodecs.imencode(".jpg", rgbLena, buff40, params40) ); + assertTrue( Imgcodecs.imencode(".jpg", rgbLena, buff90, params90) ); assertTrue(buff40.total() > 0); assertTrue(buff40.total() < buff90.total()); } public void testImreadString() { - dst = Highgui.imread(OpenCVTestRunner.LENA_PATH); + dst = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH); assertTrue(!dst.empty()); assertEquals(3, dst.channels()); assertTrue(512 == dst.cols()); @@ -45,7 +45,7 @@ public class HighguiTest extends OpenCVTestCase { } public void testImreadStringInt() { - dst = Highgui.imread(OpenCVTestRunner.LENA_PATH, 0); + dst = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH, 0); assertTrue(!dst.empty()); assertEquals(1, dst.channels()); assertTrue(512 == dst.cols()); diff --git a/modules/java/android_test/src/org/opencv/test/highgui/VideoCaptureTest.java b/modules/java/android_test/src/org/opencv/test/highgui/VideoCaptureTest.java index ec7211a294..f4cccdf5ce 100644 --- a/modules/java/android_test/src/org/opencv/test/highgui/VideoCaptureTest.java +++ b/modules/java/android_test/src/org/opencv/test/highgui/VideoCaptureTest.java @@ -3,8 +3,8 @@ package org.opencv.test.highgui; import java.util.List; import org.opencv.core.Size; -import org.opencv.highgui.Highgui; -import org.opencv.highgui.VideoCapture; +import org.opencv.videoio.Videoio; +import org.opencv.videoio.VideoCapture; import org.opencv.test.OpenCVTestCase; @@ -26,8 +26,8 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testGet() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); - double frameWidth = capture.get(Highgui.CV_CAP_PROP_FRAME_WIDTH); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); + double frameWidth = capture.get(Videoio.CV_CAP_PROP_FRAME_WIDTH); assertTrue(0 != frameWidth); } finally { if (capture != null) capture.release(); @@ -36,7 +36,7 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testGetSupportedPreviewSizes() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); List sizes = capture.getSupportedPreviewSizes(); assertNotNull(sizes); assertFalse(sizes.isEmpty()); @@ -53,7 +53,7 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testGrabFromRealCamera() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); isSucceed = capture.grab(); assertTrue(isSucceed); } finally { @@ -68,7 +68,7 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testIsOpenedRealCamera() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); isOpened = capture.isOpened(); assertTrue(isOpened); } finally { @@ -79,7 +79,7 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testOpen() { try { capture = new VideoCapture(); - capture.open(Highgui.CV_CAP_ANDROID); + capture.open(Videoio.CV_CAP_ANDROID); isOpened = capture.isOpened(); assertTrue(isOpened); } finally { @@ -89,7 +89,7 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testRead() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); isSucceed = capture.read(dst); assertTrue(isSucceed); assertFalse(dst.empty()); @@ -101,7 +101,7 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testRelease() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); capture.release(); assertFalse(capture.isOpened()); capture = null; @@ -112,7 +112,7 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testRetrieveMat() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); capture.grab(); isSucceed = capture.retrieve(dst); assertTrue(isSucceed); @@ -125,9 +125,9 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testRetrieveMatInt() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); capture.grab(); - isSucceed = capture.retrieve(dst, Highgui.CV_CAP_ANDROID_GREY_FRAME); + isSucceed = capture.retrieve(dst, Videoio.CV_CAP_ANDROID_GREY_FRAME); assertTrue(isSucceed); assertFalse(dst.empty()); assertEquals(1, dst.channels()); @@ -138,10 +138,10 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testSet() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); - capture.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, 640); - capture.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, 480); - double frameWidth = capture.get(Highgui.CV_CAP_PROP_FRAME_WIDTH); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); + capture.set(Videoio.CV_CAP_PROP_FRAME_WIDTH, 640); + capture.set(Videoio.CV_CAP_PROP_FRAME_HEIGHT, 480); + double frameWidth = capture.get(Videoio.CV_CAP_PROP_FRAME_WIDTH); capture.read(dst); assertEquals(640.0, frameWidth); assertEquals(640, dst.cols()); @@ -158,7 +158,7 @@ public class VideoCaptureTest extends OpenCVTestCase { public void testVideoCaptureInt() { try { - capture = new VideoCapture(Highgui.CV_CAP_ANDROID); + capture = new VideoCapture(Videoio.CV_CAP_ANDROID); assertNotNull(capture); assertTrue(capture.isOpened()); } finally { diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index cce2708284..0f317d5248 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -11,7 +11,7 @@ except: class_ignore_list = ( #core "FileNode", "FileStorage", "KDTree", "KeyPoint", "DMatch", - #highgui + #videoio "VideoWriter", ) @@ -536,13 +536,13 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize """\n private static native String getSupportedPreviewSizes_0(long nativeObj);\n""", 'cpp_code' : """ -JNIEXPORT jstring JNICALL Java_org_opencv_highgui_VideoCapture_getSupportedPreviewSizes_10 +JNIEXPORT jstring JNICALL Java_org_opencv_videoio_VideoCapture_getSupportedPreviewSizes_10 (JNIEnv *env, jclass, jlong self); -JNIEXPORT jstring JNICALL Java_org_opencv_highgui_VideoCapture_getSupportedPreviewSizes_10 +JNIEXPORT jstring JNICALL Java_org_opencv_videoio_VideoCapture_getSupportedPreviewSizes_10 (JNIEnv *env, jclass, jlong self) { - static const char method_name[] = "highgui::VideoCapture_getSupportedPreviewSizes_10()"; + static const char method_name[] = "videoio::VideoCapture_getSupportedPreviewSizes_10()"; try { LOGD("%s", method_name); VideoCapture* me = (VideoCapture*) self; //TODO: check for NULL diff --git a/modules/java/generator/rst_parser.py b/modules/java/generator/rst_parser.py index 0fe3e5a3bd..80b09ac40b 100755 --- a/modules/java/generator/rst_parser.py +++ b/modules/java/generator/rst_parser.py @@ -2,7 +2,7 @@ from __future__ import print_function import os, sys, re, string, fnmatch -allmodules = ["core", "flann", "imgproc", "ml", "imgcodecs", "highgui", "video", "features2d", "calib3d", "objdetect", "legacy", "contrib", "cuda", "androidcamera", "java", "python", "stitching", "ts", "photo", "nonfree", "videostab", "softcascade", "superres"] +allmodules = ["core", "flann", "imgproc", "ml", "imgcodecs", "videoio", "highgui", "video", "features2d", "calib3d", "objdetect", "legacy", "contrib", "cuda", "androidcamera", "java", "python", "stitching", "ts", "photo", "nonfree", "videostab", "softcascade", "superres"] verbose = False show_warnings = True show_errors = True diff --git a/modules/java/generator/src/java/android+CameraBridgeViewBase.java b/modules/java/generator/src/java/android+CameraBridgeViewBase.java index c0c9f5bde7..67a7489cfd 100644 --- a/modules/java/generator/src/java/android+CameraBridgeViewBase.java +++ b/modules/java/generator/src/java/android+CameraBridgeViewBase.java @@ -6,7 +6,7 @@ import org.opencv.R; import org.opencv.android.Utils; import org.opencv.core.Mat; import org.opencv.core.Size; -import org.opencv.highgui.Highgui; +import org.opencv.videoio.Videoio; import android.app.Activity; import android.app.AlertDialog; @@ -46,7 +46,7 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac protected int mMaxHeight; protected int mMaxWidth; protected float mScale = 0; - protected int mPreviewFormat = Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA; + protected int mPreviewFormat = Videoio.CV_CAP_ANDROID_COLOR_FRAME_RGBA; protected int mCameraIndex = CAMERA_ID_ANY; protected boolean mEnabled; protected FpsMeter mFpsMeter = null; @@ -151,10 +151,10 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac public Mat onCameraFrame(CvCameraViewFrame inputFrame) { Mat result = null; switch (mPreviewFormat) { - case Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA: + case Videoio.CV_CAP_ANDROID_COLOR_FRAME_RGBA: result = mOldStyleListener.onCameraFrame(inputFrame.rgba()); break; - case Highgui.CV_CAP_ANDROID_GREY_FRAME: + case Videoio.CV_CAP_ANDROID_GREY_FRAME: result = mOldStyleListener.onCameraFrame(inputFrame.gray()); break; default: @@ -168,7 +168,7 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac mPreviewFormat = format; } - private int mPreviewFormat = Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA; + private int mPreviewFormat = Videoio.CV_CAP_ANDROID_COLOR_FRAME_RGBA; private CvCameraViewListener mOldStyleListener; }; diff --git a/modules/java/generator/src/java/android+NativeCameraView.java b/modules/java/generator/src/java/android+NativeCameraView.java index db146d8aed..47d6a27c23 100644 --- a/modules/java/generator/src/java/android+NativeCameraView.java +++ b/modules/java/generator/src/java/android+NativeCameraView.java @@ -2,8 +2,8 @@ package org.opencv.android; import org.opencv.core.Mat; import org.opencv.core.Size; -import org.opencv.highgui.Highgui; -import org.opencv.highgui.VideoCapture; +import org.opencv.videoio.Videoio; +import org.opencv.videoio.VideoCapture; import android.content.Context; import android.util.AttributeSet; @@ -88,9 +88,9 @@ public class NativeCameraView extends CameraBridgeViewBase { synchronized (this) { if (mCameraIndex == -1) - mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID); + mCamera = new VideoCapture(Videoio.CV_CAP_ANDROID); else - mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID + mCameraIndex); + mCamera = new VideoCapture(Videoio.CV_CAP_ANDROID + mCameraIndex); if (mCamera == null) return false; @@ -119,8 +119,8 @@ public class NativeCameraView extends CameraBridgeViewBase { AllocateCache(); - mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, frameSize.width); - mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, frameSize.height); + mCamera.set(Videoio.CV_CAP_PROP_FRAME_WIDTH, frameSize.width); + mCamera.set(Videoio.CV_CAP_PROP_FRAME_HEIGHT, frameSize.height); } Log.i(TAG, "Selected camera frame size = (" + mFrameWidth + ", " + mFrameHeight + ")"); @@ -139,13 +139,13 @@ public class NativeCameraView extends CameraBridgeViewBase { @Override public Mat rgba() { - mCapture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA); + mCapture.retrieve(mRgba, Videoio.CV_CAP_ANDROID_COLOR_FRAME_RGBA); return mRgba; } @Override public Mat gray() { - mCapture.retrieve(mGray, Highgui.CV_CAP_ANDROID_GREY_FRAME); + mCapture.retrieve(mGray, Videoio.CV_CAP_ANDROID_GREY_FRAME); return mGray; } diff --git a/modules/java/test/src/org/opencv/test/OpenCVTestCase.java b/modules/java/test/src/org/opencv/test/OpenCVTestCase.java index 496f96242b..864c17ef14 100644 --- a/modules/java/test/src/org/opencv/test/OpenCVTestCase.java +++ b/modules/java/test/src/org/opencv/test/OpenCVTestCase.java @@ -25,7 +25,7 @@ import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.core.DMatch; import org.opencv.core.KeyPoint; -import org.opencv.highgui.Highgui; +import org.opencv.imgcodecs.Imgcodecs; public class OpenCVTestCase extends TestCase { //change to 'true' to unblock fail on fail("Not yet implemented") @@ -164,8 +164,8 @@ public class OpenCVTestCase extends TestCase { rgba0 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(0)); rgba128 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(128)); - rgbLena = Highgui.imread(OpenCVTestRunner.LENA_PATH); - grayChess = Highgui.imread(OpenCVTestRunner.CHESS_PATH, 0); + rgbLena = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH); + grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, 0); v1 = new Mat(1, 3, CvType.CV_32F); v1.put(0, 0, 1.0, 3.0, 2.0); diff --git a/modules/matlab/CMakeLists.txt b/modules/matlab/CMakeLists.txt index a4c1c3b164..06b81696b9 100644 --- a/modules/matlab/CMakeLists.txt +++ b/modules/matlab/CMakeLists.txt @@ -85,7 +85,8 @@ endif() set(the_description "The Matlab/Octave bindings") ocv_add_module(matlab BINDINGS OPTIONAL opencv_core - opencv_imgproc opencv_ml opencv_highgui + opencv_imgproc opencv_ml + opencv_imgcodecs opencv_videoio opencv_highgui opencv_objdetect opencv_flann opencv_features2d opencv_photo opencv_video opencv_videostab opencv_calib opencv_calib3d diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index 44f3fe5008..af062cebc7 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -11,7 +11,7 @@ if(ANDROID OR IOS OR NOT PYTHONLIBS_FOUND OR NOT PYTHON_NUMPY_INCLUDE_DIRS) endif() set(the_description "The python bindings") -ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_imgcodecs opencv_highgui opencv_calib3d opencv_photo opencv_objdetect OPTIONAL opencv_nonfree) +ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_imgcodecs opencv_videoio opencv_highgui opencv_calib3d opencv_photo opencv_objdetect OPTIONAL opencv_nonfree) ocv_module_include_directories( "${PYTHON_INCLUDE_PATH}" @@ -32,6 +32,7 @@ set(opencv_hdrs "${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/tracking.hpp" "${OPENCV_MODULE_opencv_photo_LOCATION}/include/opencv2/photo.hpp" "${OPENCV_MODULE_opencv_imgcodecs_LOCATION}/include/opencv2/imgcodecs.hpp" + "${OPENCV_MODULE_opencv_videoio_LOCATION}/include/opencv2/videoio.hpp" "${OPENCV_MODULE_opencv_highgui_LOCATION}/include/opencv2/highgui.hpp" "${OPENCV_MODULE_opencv_ml_LOCATION}/include/opencv2/ml.hpp" "${OPENCV_MODULE_opencv_features2d_LOCATION}/include/opencv2/features2d.hpp" diff --git a/modules/python/src2/hdr_parser.py b/modules/python/src2/hdr_parser.py index 93b137b897..92f1b7347c 100755 --- a/modules/python/src2/hdr_parser.py +++ b/modules/python/src2/hdr_parser.py @@ -16,6 +16,7 @@ opencv_hdr_list = [ "../../video/include/opencv2/video/background_segm.hpp", "../../objdetect/include/opencv2/objdetect.hpp", "../../imgcodecs/include/opencv2/imgcodecs.hpp", +"../../videoio/include/opencv2/videoio.hpp", "../../highgui/include/opencv2/highgui.hpp" ] diff --git a/modules/superres/CMakeLists.txt b/modules/superres/CMakeLists.txt index c360303f6b..f85cf20736 100644 --- a/modules/superres/CMakeLists.txt +++ b/modules/superres/CMakeLists.txt @@ -5,4 +5,4 @@ endif() set(the_description "Super Resolution") ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127 -Wundef -Wshadow) ocv_define_module(superres opencv_imgproc opencv_video - OPTIONAL opencv_highgui opencv_cudaarithm opencv_cudafilters opencv_cudawarping opencv_cudaimgproc opencv_cudaoptflow opencv_cudacodec) + OPTIONAL opencv_videoio opencv_cudaarithm opencv_cudafilters opencv_cudawarping opencv_cudaimgproc opencv_cudaoptflow opencv_cudacodec) diff --git a/modules/superres/src/frame_source.cpp b/modules/superres/src/frame_source.cpp index c572c09a92..0f81efd5e1 100644 --- a/modules/superres/src/frame_source.cpp +++ b/modules/superres/src/frame_source.cpp @@ -80,7 +80,7 @@ Ptr cv::superres::createFrameSource_Empty() ////////////////////////////////////////////////////// // VideoFrameSource & CameraFrameSource -#ifndef HAVE_OPENCV_HIGHGUI +#ifndef HAVE_OPENCV_VIDEOIO Ptr cv::superres::createFrameSource_Video(const String& fileName) { @@ -96,7 +96,7 @@ Ptr cv::superres::createFrameSource_Camera(int deviceId) return Ptr(); } -#else // HAVE_OPENCV_HIGHGUI +#else // HAVE_OPENCV_VIDEOIO namespace { @@ -187,7 +187,7 @@ Ptr cv::superres::createFrameSource_Camera(int deviceId) return makePtr(deviceId); } -#endif // HAVE_OPENCV_HIGHGUI +#endif // HAVE_OPENCV_VIDEOIO ////////////////////////////////////////////////////// // VideoFrameSource_CUDA diff --git a/modules/superres/src/precomp.hpp b/modules/superres/src/precomp.hpp index c3aeb665d4..9f12c248d6 100644 --- a/modules/superres/src/precomp.hpp +++ b/modules/superres/src/precomp.hpp @@ -82,8 +82,8 @@ # include "opencv2/cudacodec.hpp" #endif -#ifdef HAVE_OPENCV_HIGHGUI - #include "opencv2/highgui.hpp" +#ifdef HAVE_OPENCV_VIDEOIO + #include "opencv2/videoio.hpp" #endif #include "opencv2/superres.hpp" diff --git a/modules/ts/CMakeLists.txt b/modules/ts/CMakeLists.txt index 9bab70accc..c923a29d8f 100644 --- a/modules/ts/CMakeLists.txt +++ b/modules/ts/CMakeLists.txt @@ -9,7 +9,7 @@ set(OPENCV_MODULE_IS_PART_OF_WORLD FALSE) ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef) -ocv_add_module(ts opencv_core opencv_imgproc opencv_imgcodecs opencv_highgui) +ocv_add_module(ts opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui) ocv_glob_module_sources() ocv_module_include_directories() diff --git a/modules/ts/include/opencv2/ts/cuda_perf.hpp b/modules/ts/include/opencv2/ts/cuda_perf.hpp index e503618ca0..c179b72499 100644 --- a/modules/ts/include/opencv2/ts/cuda_perf.hpp +++ b/modules/ts/include/opencv2/ts/cuda_perf.hpp @@ -45,6 +45,7 @@ #include "opencv2/core.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/ts/ts_perf.hpp" #include "cvconfig.h" diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp index 227fdfc049..3703b7b9f7 100644 --- a/modules/ts/include/opencv2/ts/ocl_test.hpp +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -47,6 +47,7 @@ #include "opencv2/ts.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/imgproc/types_c.h" diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt new file mode 100644 index 0000000000..527662b9da --- /dev/null +++ b/modules/videoio/CMakeLists.txt @@ -0,0 +1,233 @@ +set(the_description "Media I/O") +ocv_add_module(videoio opencv_imgproc opencv_imgcodecs OPTIONAL opencv_androidcamera) + +# ---------------------------------------------------------------------------- +# CMake file for videoio. See root CMakeLists.txt +# Some parts taken from version of Hartmut Seichter, HIT Lab NZ. +# Jose Luis Blanco, 2008 +# ---------------------------------------------------------------------------- + +if(HAVE_WINRT_CX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /ZW") +endif() + +if(APPLE) + ocv_include_directories(${ZLIB_INCLUDE_DIRS}) + list(APPEND VIDEOIO_LIBRARIES ${ZLIB_LIBRARIES}) +endif() + +set(videoio_hdrs + src/precomp.hpp + src/cap_ffmpeg_impl.hpp + ) + +set(videoio_srcs + src/cap.cpp + src/cap_images.cpp + src/cap_ffmpeg.cpp + ) + +file(GLOB videoio_ext_hdrs "include/opencv2/*.hpp" "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h") + +if(WIN32 AND NOT ARM) + list(APPEND videoio_srcs src/cap_cmu.cpp) +endif() + +if (WIN32 AND HAVE_DSHOW) + list(APPEND videoio_srcs src/cap_dshow.cpp) +endif() + +if (WIN32 AND HAVE_MSMF) + list(APPEND videoio_srcs src/cap_msmf.cpp) +endif() + +if (WIN32 AND HAVE_VFW) + list(APPEND videoio_srcs src/cap_vfw.cpp) +endif() + +if(HAVE_XINE) + list(APPEND videoio_srcs src/cap_xine.cpp) +endif(HAVE_XINE) + +if(HAVE_DC1394_2) + list(APPEND videoio_srcs src/cap_dc1394_v2.cpp) +endif(HAVE_DC1394_2) + +if(HAVE_DC1394) + list(APPEND videoio_srcs src/cap_dc1394.cpp) +endif(HAVE_DC1394) + +if(HAVE_GSTREAMER) + list(APPEND videoio_srcs src/cap_gstreamer.cpp) +endif(HAVE_GSTREAMER) + +if(HAVE_UNICAP) + list(APPEND videoio_srcs src/cap_unicap.cpp) +endif(HAVE_UNICAP) + +if(HAVE_LIBV4L) + list(APPEND videoio_srcs src/cap_libv4l.cpp) +elseif(HAVE_CAMV4L OR HAVE_CAMV4L2 OR HAVE_VIDEOIO) + list(APPEND videoio_srcs src/cap_v4l.cpp) +endif() + +if(HAVE_OPENNI) + list(APPEND videoio_srcs src/cap_openni.cpp) + ocv_include_directories(${OPENNI_INCLUDE_DIR}) + list(APPEND VIDEOIO_LIBRARIES ${OPENNI_LIBRARY}) +endif(HAVE_OPENNI) + +if(HAVE_opencv_androidcamera) + list(APPEND videoio_srcs src/cap_android.cpp) + add_definitions(-DHAVE_ANDROID_NATIVE_CAMERA)#TODO: remove this line +endif(HAVE_opencv_androidcamera) + +if(HAVE_XIMEA) + list(APPEND videoio_srcs src/cap_ximea.cpp) + ocv_include_directories(${XIMEA_PATH}) + if(XIMEA_LIBRARY_DIR) + link_directories("${XIMEA_LIBRARY_DIR}") + endif() + if(X86_64) + list(APPEND VIDEOIO_LIBRARIES m3apiX64) + else() + list(APPEND VIDEOIO_LIBRARIES m3api) + endif() +endif(HAVE_XIMEA) + +if(HAVE_FFMPEG) + if(UNIX AND BZIP2_LIBRARIES) + list(APPEND VIDEOIO_LIBRARIES ${BZIP2_LIBRARIES}) + endif() + if(APPLE) + list(APPEND VIDEOIO_LIBRARIES "-framework VideoDecodeAcceleration" bz2) + endif() +endif(HAVE_FFMPEG) + +if(HAVE_PVAPI) + add_definitions(-DHAVE_PVAPI) + add_definitions(${PVAPI_DEFINITIONS}) + ocv_include_directories(${PVAPI_INCLUDE_PATH}) + set(videoio_srcs src/cap_pvapi.cpp ${videoio_srcs}) + list(APPEND VIDEOIO_LIBRARIES ${PVAPI_LIBRARY}) +endif() + +if(HAVE_GIGE_API) + add_definitions(-DHAVE_GIGE_API) + ocv_include_directories(${GIGEAPI_INCLUDE_PATH}) + set(videoio_srcs src/cap_giganetix.cpp ${videoio_srcs}) + list(APPEND VIDEOIO_LIBRARIES ${GIGEAPI_LIBRARIES}) + list(APPEND videoio_srcs src/cap_giganetix.cpp) +endif(HAVE_GIGE_API) + +if(HAVE_AVFOUNDATION) + list(APPEND videoio_srcs src/cap_avfoundation.mm) + list(APPEND VIDEOIO_LIBRARIES "-framework AVFoundation" "-framework QuartzCore") +endif() + +if(HAVE_QUICKTIME) + list(APPEND videoio_srcs src/cap_qt.cpp) + list(APPEND VIDEOIO_LIBRARIES "-framework Carbon" "-framework QuickTime" "-framework CoreFoundation" "-framework QuartzCore") +elseif(HAVE_QTKIT) + list(APPEND videoio_srcs src/cap_qtkit.mm) + list(APPEND VIDEOIO_LIBRARIES "-framework QTKit" "-framework QuartzCore" "-framework AppKit") +endif() + +if(HAVE_INTELPERC) + list(APPEND videoio_srcs src/cap_intelperc.cpp) + ocv_include_directories(${INTELPERC_INCLUDE_DIR}) + list(APPEND VIDEOIO_LIBRARIES ${INTELPERC_LIBRARIES}) +endif(HAVE_INTELPERC) + +if(IOS) + add_definitions(-DHAVE_IOS=1) + list(APPEND videoio_srcs src/ios_conversions.mm src/cap_ios_abstract_camera.mm src/cap_ios_photo_camera.mm src/cap_ios_video_camera.mm) + list(APPEND VIDEOIO_LIBRARIES "-framework Accelerate" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreImage" "-framework CoreMedia" "-framework CoreVideo" "-framework QuartzCore" "-framework AssetsLibrary") +endif() + +if(WIN32) + link_directories("${OpenCV_SOURCE_DIR}/3rdparty/lib") # for ffmpeg wrapper only + include_directories(AFTER SYSTEM "${OpenCV_SOURCE_DIR}/3rdparty/include") # for directshow in VS2005 and multi-monitor support on MinGW + include_directories(AFTER SYSTEM "${OpenCV_SOURCE_DIR}/3rdparty/include/ffmpeg_") # for tests +endif() + +if(UNIX) + #these variables are set by CHECK_MODULE macro + foreach(P ${VIDEOIO_INCLUDE_DIRS}) + ocv_include_directories(${P}) + endforeach() + + foreach(P ${VIDEOIO_LIBRARY_DIRS}) + link_directories(${P}) + endforeach() +endif() + +source_group("Src" FILES ${videoio_srcs} ${videoio_hdrs}) +source_group("Include" FILES ${videoio_ext_hdrs}) +ocv_set_module_sources(HEADERS ${videoio_ext_hdrs} SOURCES ${videoio_srcs} ${videoio_hdrs}) +ocv_module_include_directories() + +ocv_create_module(${VIDEOIO_LIBRARIES}) + +if(APPLE) + ocv_check_flag_support(OBJCXX "-fobjc-exceptions" HAVE_OBJC_EXCEPTIONS) + if(HAVE_OBJC_EXCEPTIONS) + foreach(source ${OPENCV_MODULE_${the_module}_SOURCES}) + if("${source}" MATCHES "\\.mm$") + get_source_file_property(flags "${source}" COMPILE_FLAGS) + if(flags) + set(flags "${_flags} -fobjc-exceptions") + else() + set(flags "-fobjc-exceptions") + endif() + + set_source_files_properties("${source}" PROPERTIES COMPILE_FLAGS "${flags}") + endif() + endforeach() + endif() +endif() + +if(BUILD_SHARED_LIBS) + add_definitions(-DVIDEOIO_EXPORTS) +endif() + +if(MSVC) + set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /NODEFAULTLIB:libcmt.lib /DEBUG") +endif() + +#stop automatic dependencies propagation for this module +set_target_properties(${the_module} PROPERTIES LINK_INTERFACE_LIBRARIES "") + +ocv_add_precompiled_headers(${the_module}) +ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated-declarations) + +if(WIN32 AND WITH_FFMPEG) + #copy ffmpeg dll to the output folder + if(MSVC64 OR MINGW64) + set(FFMPEG_SUFFIX _64) + endif() + + set(ffmpeg_bare_name "opencv_ffmpeg${FFMPEG_SUFFIX}.dll") + set(ffmpeg_bare_name_ver "opencv_ffmpeg${OPENCV_DLLVERSION}${FFMPEG_SUFFIX}.dll") + set(ffmpeg_path "${OpenCV_SOURCE_DIR}/3rdparty/ffmpeg/${ffmpeg_bare_name}") + + if(MSVC_IDE) + add_custom_command(TARGET ${the_module} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Release/${ffmpeg_bare_name_ver}" + COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Debug/${ffmpeg_bare_name_ver}" + COMMENT "Copying ${ffmpeg_path} to the output directory") + elseif(MSVC AND (CMAKE_GENERATOR MATCHES "Visual")) + add_custom_command(TARGET ${the_module} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/${ffmpeg_bare_name_ver}" + COMMENT "Copying ${ffmpeg_path} to the output directory") + else() + add_custom_command(TARGET ${the_module} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${ffmpeg_bare_name_ver}" + COMMENT "Copying ${ffmpeg_path} to the output directory") + endif() + + install(FILES "${ffmpeg_path}" DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT libs RENAME "${ffmpeg_bare_name_ver}") +endif() + +ocv_add_accuracy_tests() +ocv_add_perf_tests() diff --git a/modules/highgui/doc/reading_and_writing_video.rst b/modules/videoio/doc/reading_and_writing_video.rst similarity index 100% rename from modules/highgui/doc/reading_and_writing_video.rst rename to modules/videoio/doc/reading_and_writing_video.rst diff --git a/modules/videoio/doc/videoio.rst b/modules/videoio/doc/videoio.rst new file mode 100644 index 0000000000..fee114bd05 --- /dev/null +++ b/modules/videoio/doc/videoio.rst @@ -0,0 +1,12 @@ +******************* +videoio. Media I/O +******************* + +videoio provides easy interface to: + +* Read video from camera or file and write video to a file. + +.. toctree:: + :maxdepth: 2 + + reading_and_writing_video diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp new file mode 100644 index 0000000000..a144c65dc0 --- /dev/null +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -0,0 +1,389 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOIO_HPP__ +#define __OPENCV_VIDEOIO_HPP__ + +#include "opencv2/core.hpp" + + +////////////////////////////////// video io ///////////////////////////////// + +typedef struct CvCapture CvCapture; +typedef struct CvVideoWriter CvVideoWriter; + +namespace cv +{ + +// Camera API +enum { CAP_ANY = 0, // autodetect + CAP_VFW = 200, // platform native + CAP_V4L = 200, + CAP_V4L2 = CAP_V4L, + CAP_FIREWARE = 300, // IEEE 1394 drivers + CAP_FIREWIRE = CAP_FIREWARE, + CAP_IEEE1394 = CAP_FIREWARE, + CAP_DC1394 = CAP_FIREWARE, + CAP_CMU1394 = CAP_FIREWARE, + CAP_QT = 500, // QuickTime + CAP_UNICAP = 600, // Unicap drivers + CAP_DSHOW = 700, // DirectShow (via videoInput) + CAP_PVAPI = 800, // PvAPI, Prosilica GigE SDK + CAP_OPENNI = 900, // OpenNI (for Kinect) + CAP_OPENNI_ASUS = 910, // OpenNI (for Asus Xtion) + CAP_ANDROID = 1000, // Android + CAP_XIAPI = 1100, // XIMEA Camera API + CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) + CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK + CAP_MSMF = 1400, // Microsoft Media Foundation (via videoInput) + CAP_INTELPERC = 1500 // Intel Perceptual Computing SDK + }; + +// generic properties (based on DC1394 properties) +enum { CAP_PROP_POS_MSEC =0, + CAP_PROP_POS_FRAMES =1, + CAP_PROP_POS_AVI_RATIO =2, + CAP_PROP_FRAME_WIDTH =3, + CAP_PROP_FRAME_HEIGHT =4, + CAP_PROP_FPS =5, + CAP_PROP_FOURCC =6, + CAP_PROP_FRAME_COUNT =7, + CAP_PROP_FORMAT =8, + CAP_PROP_MODE =9, + CAP_PROP_BRIGHTNESS =10, + CAP_PROP_CONTRAST =11, + CAP_PROP_SATURATION =12, + CAP_PROP_HUE =13, + CAP_PROP_GAIN =14, + CAP_PROP_EXPOSURE =15, + CAP_PROP_CONVERT_RGB =16, + CAP_PROP_WHITE_BALANCE_BLUE_U =17, + CAP_PROP_RECTIFICATION =18, + CAP_PROP_MONOCROME =19, + CAP_PROP_SHARPNESS =20, + CAP_PROP_AUTO_EXPOSURE =21, // DC1394: exposure control done by camera, user can adjust refernce level using this feature + CAP_PROP_GAMMA =22, + CAP_PROP_TEMPERATURE =23, + CAP_PROP_TRIGGER =24, + CAP_PROP_TRIGGER_DELAY =25, + CAP_PROP_WHITE_BALANCE_RED_V =26, + CAP_PROP_ZOOM =27, + CAP_PROP_FOCUS =28, + CAP_PROP_GUID =29, + CAP_PROP_ISO_SPEED =30, + CAP_PROP_BACKLIGHT =32, + CAP_PROP_PAN =33, + CAP_PROP_TILT =34, + CAP_PROP_ROLL =35, + CAP_PROP_IRIS =36, + CAP_PROP_SETTINGS =37 + }; + + +// DC1394 only +// modes of the controlling registers (can be: auto, manual, auto single push, absolute Latter allowed with any other mode) +// every feature can have only one mode turned on at a time +enum { CAP_PROP_DC1394_OFF = -4, //turn the feature off (not controlled manually nor automatically) + CAP_PROP_DC1394_MODE_MANUAL = -3, //set automatically when a value of the feature is set by the user + CAP_PROP_DC1394_MODE_AUTO = -2, + CAP_PROP_DC1394_MODE_ONE_PUSH_AUTO = -1, + CAP_PROP_DC1394_MAX = 31 + }; + + +// OpenNI map generators +enum { CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, + CAP_OPENNI_IMAGE_GENERATOR = 1 << 30, + CAP_OPENNI_GENERATORS_MASK = CAP_OPENNI_DEPTH_GENERATOR + CAP_OPENNI_IMAGE_GENERATOR + }; + +// Properties of cameras available through OpenNI interfaces +enum { CAP_PROP_OPENNI_OUTPUT_MODE = 100, + CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, // in mm + CAP_PROP_OPENNI_BASELINE = 102, // in mm + CAP_PROP_OPENNI_FOCAL_LENGTH = 103, // in pixels + CAP_PROP_OPENNI_REGISTRATION = 104, // flag that synchronizes the remapping depth map to image map + // by changing depth generator's view point (if the flag is "on") or + // sets this view point to its normal one (if the flag is "off"). + CAP_PROP_OPENNI_REGISTRATION_ON = CAP_PROP_OPENNI_REGISTRATION, + CAP_PROP_OPENNI_APPROX_FRAME_SYNC = 105, + CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, + CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, + CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, + CAP_PROP_OPENNI_GENERATOR_PRESENT = 109 + }; + +// OpenNI shortcats +enum { CAP_OPENNI_IMAGE_GENERATOR_PRESENT = CAP_OPENNI_IMAGE_GENERATOR + CAP_PROP_OPENNI_GENERATOR_PRESENT, + CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CAP_OPENNI_IMAGE_GENERATOR + CAP_PROP_OPENNI_OUTPUT_MODE, + CAP_OPENNI_DEPTH_GENERATOR_BASELINE = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_BASELINE, + CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_FOCAL_LENGTH, + CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_REGISTRATION, + CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION_ON = CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION + }; + +// OpenNI data given from depth generator +enum { CAP_OPENNI_DEPTH_MAP = 0, // Depth values in mm (CV_16UC1) + CAP_OPENNI_POINT_CLOUD_MAP = 1, // XYZ in meters (CV_32FC3) + CAP_OPENNI_DISPARITY_MAP = 2, // Disparity in pixels (CV_8UC1) + CAP_OPENNI_DISPARITY_MAP_32F = 3, // Disparity in pixels (CV_32FC1) + CAP_OPENNI_VALID_DEPTH_MASK = 4, // CV_8UC1 + + // Data given from RGB image generator + CAP_OPENNI_BGR_IMAGE = 5, + CAP_OPENNI_GRAY_IMAGE = 6 + }; + +// Supported output modes of OpenNI image generator +enum { CAP_OPENNI_VGA_30HZ = 0, + CAP_OPENNI_SXGA_15HZ = 1, + CAP_OPENNI_SXGA_30HZ = 2, + CAP_OPENNI_QVGA_30HZ = 3, + CAP_OPENNI_QVGA_60HZ = 4 + }; + + +// GStreamer +enum { CAP_PROP_GSTREAMER_QUEUE_LENGTH = 200 // default is 1 + }; + + +// PVAPI +enum { CAP_PROP_PVAPI_MULTICASTIP = 300, // ip for anable multicast master mode. 0 for disable multicast + CAP_PROP_PVAPI_FRAMESTARTTRIGGERMODE = 301 // FrameStartTriggerMode: Determines how a frame is initiated + }; + +// PVAPI: FrameStartTriggerMode +enum { CAP_PVAPI_FSTRIGMODE_FREERUN = 0, // Freerun + CAP_PVAPI_FSTRIGMODE_SYNCIN1 = 1, // SyncIn1 + CAP_PVAPI_FSTRIGMODE_SYNCIN2 = 2, // SyncIn2 + CAP_PVAPI_FSTRIGMODE_FIXEDRATE = 3, // FixedRate + CAP_PVAPI_FSTRIGMODE_SOFTWARE = 4 // Software + }; + +// Properties of cameras available through XIMEA SDK interface +enum { CAP_PROP_XI_DOWNSAMPLING = 400, // Change image resolution by binning or skipping. + CAP_PROP_XI_DATA_FORMAT = 401, // Output data format. + CAP_PROP_XI_OFFSET_X = 402, // Horizontal offset from the origin to the area of interest (in pixels). + CAP_PROP_XI_OFFSET_Y = 403, // Vertical offset from the origin to the area of interest (in pixels). + CAP_PROP_XI_TRG_SOURCE = 404, // Defines source of trigger. + CAP_PROP_XI_TRG_SOFTWARE = 405, // Generates an internal trigger. PRM_TRG_SOURCE must be set to TRG_SOFTWARE. + CAP_PROP_XI_GPI_SELECTOR = 406, // Selects general purpose input + CAP_PROP_XI_GPI_MODE = 407, // Set general purpose input mode + CAP_PROP_XI_GPI_LEVEL = 408, // Get general purpose level + CAP_PROP_XI_GPO_SELECTOR = 409, // Selects general purpose output + CAP_PROP_XI_GPO_MODE = 410, // Set general purpose output mode + CAP_PROP_XI_LED_SELECTOR = 411, // Selects camera signalling LED + CAP_PROP_XI_LED_MODE = 412, // Define camera signalling LED functionality + CAP_PROP_XI_MANUAL_WB = 413, // Calculates White Balance(must be called during acquisition) + CAP_PROP_XI_AUTO_WB = 414, // Automatic white balance + CAP_PROP_XI_AEAG = 415, // Automatic exposure/gain + CAP_PROP_XI_EXP_PRIORITY = 416, // Exposure priority (0.5 - exposure 50%, gain 50%). + CAP_PROP_XI_AE_MAX_LIMIT = 417, // Maximum limit of exposure in AEAG procedure + CAP_PROP_XI_AG_MAX_LIMIT = 418, // Maximum limit of gain in AEAG procedure + CAP_PROP_XI_AEAG_LEVEL = 419, // Average intensity of output signal AEAG should achieve(in %) + CAP_PROP_XI_TIMEOUT = 420 // Image capture timeout in milliseconds + }; + + +// Properties for Android cameras +enum { CAP_PROP_ANDROID_AUTOGRAB = 1024, + CAP_PROP_ANDROID_PREVIEW_SIZES_STRING = 1025, // readonly, tricky property, returns const char* indeed + CAP_PROP_ANDROID_PREVIEW_FORMAT = 1026, // readonly, tricky property, returns const char* indeed + CAP_PROP_ANDROID_FLASH_MODE = 8001, + CAP_PROP_ANDROID_FOCUS_MODE = 8002, + CAP_PROP_ANDROID_WHITE_BALANCE = 8003, + CAP_PROP_ANDROID_ANTIBANDING = 8004, + CAP_PROP_ANDROID_FOCAL_LENGTH = 8005, + CAP_PROP_ANDROID_FOCUS_DISTANCE_NEAR = 8006, + CAP_PROP_ANDROID_FOCUS_DISTANCE_OPTIMAL = 8007, + CAP_PROP_ANDROID_FOCUS_DISTANCE_FAR = 8008 + }; + + +// Android camera output formats +enum { CAP_ANDROID_COLOR_FRAME_BGR = 0, //BGR + CAP_ANDROID_COLOR_FRAME = CAP_ANDROID_COLOR_FRAME_BGR, + CAP_ANDROID_GREY_FRAME = 1, //Y + CAP_ANDROID_COLOR_FRAME_RGB = 2, + CAP_ANDROID_COLOR_FRAME_BGRA = 3, + CAP_ANDROID_COLOR_FRAME_RGBA = 4 + }; + + +// Android camera flash modes +enum { CAP_ANDROID_FLASH_MODE_AUTO = 0, + CAP_ANDROID_FLASH_MODE_OFF = 1, + CAP_ANDROID_FLASH_MODE_ON = 2, + CAP_ANDROID_FLASH_MODE_RED_EYE = 3, + CAP_ANDROID_FLASH_MODE_TORCH = 4 + }; + + +// Android camera focus modes +enum { CAP_ANDROID_FOCUS_MODE_AUTO = 0, + CAP_ANDROID_FOCUS_MODE_CONTINUOUS_VIDEO = 1, + CAP_ANDROID_FOCUS_MODE_EDOF = 2, + CAP_ANDROID_FOCUS_MODE_FIXED = 3, + CAP_ANDROID_FOCUS_MODE_INFINITY = 4, + CAP_ANDROID_FOCUS_MODE_MACRO = 5 + }; + + +// Android camera white balance modes +enum { CAP_ANDROID_WHITE_BALANCE_AUTO = 0, + CAP_ANDROID_WHITE_BALANCE_CLOUDY_DAYLIGHT = 1, + CAP_ANDROID_WHITE_BALANCE_DAYLIGHT = 2, + CAP_ANDROID_WHITE_BALANCE_FLUORESCENT = 3, + CAP_ANDROID_WHITE_BALANCE_INCANDESCENT = 4, + CAP_ANDROID_WHITE_BALANCE_SHADE = 5, + CAP_ANDROID_WHITE_BALANCE_TWILIGHT = 6, + CAP_ANDROID_WHITE_BALANCE_WARM_FLUORESCENT = 7 + }; + + +// Android camera antibanding modes +enum { CAP_ANDROID_ANTIBANDING_50HZ = 0, + CAP_ANDROID_ANTIBANDING_60HZ = 1, + CAP_ANDROID_ANTIBANDING_AUTO = 2, + CAP_ANDROID_ANTIBANDING_OFF = 3 + }; + + +// Properties of cameras available through AVFOUNDATION interface +enum { CAP_PROP_IOS_DEVICE_FOCUS = 9001, + CAP_PROP_IOS_DEVICE_EXPOSURE = 9002, + CAP_PROP_IOS_DEVICE_FLASH = 9003, + CAP_PROP_IOS_DEVICE_WHITEBALANCE = 9004, + CAP_PROP_IOS_DEVICE_TORCH = 9005 + }; + + +// Properties of cameras available through Smartek Giganetix Ethernet Vision interface +/* --- Vladimir Litvinenko (litvinenko.vladimir@gmail.com) --- */ +enum { CAP_PROP_GIGA_FRAME_OFFSET_X = 10001, + CAP_PROP_GIGA_FRAME_OFFSET_Y = 10002, + CAP_PROP_GIGA_FRAME_WIDTH_MAX = 10003, + CAP_PROP_GIGA_FRAME_HEIGH_MAX = 10004, + CAP_PROP_GIGA_FRAME_SENS_WIDTH = 10005, + CAP_PROP_GIGA_FRAME_SENS_HEIGH = 10006 + }; + +enum { CAP_PROP_INTELPERC_PROFILE_COUNT = 11001, + CAP_PROP_INTELPERC_PROFILE_IDX = 11002, + CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE = 11003, + CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE = 11004, + CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD = 11005, + CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_HORZ = 11006, + CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT = 11007 + }; + +// Intel PerC streams +enum { CAP_INTELPERC_DEPTH_GENERATOR = 1 << 29, + CAP_INTELPERC_IMAGE_GENERATOR = 1 << 28, + CAP_INTELPERC_GENERATORS_MASK = CAP_INTELPERC_DEPTH_GENERATOR + CAP_INTELPERC_IMAGE_GENERATOR + }; + +enum { CAP_INTELPERC_DEPTH_MAP = 0, // Each pixel is a 16-bit integer. The value indicates the distance from an object to the camera's XY plane or the Cartesian depth. + CAP_INTELPERC_UVDEPTH_MAP = 1, // Each pixel contains two 32-bit floating point values in the range of 0-1, representing the mapping of depth coordinates to the color coordinates. + CAP_INTELPERC_IR_MAP = 2, // Each pixel is a 16-bit integer. The value indicates the intensity of the reflected laser beam. + CAP_INTELPERC_IMAGE = 3 + }; + + +class IVideoCapture; +class CV_EXPORTS_W VideoCapture +{ +public: + CV_WRAP VideoCapture(); + CV_WRAP VideoCapture(const String& filename); + CV_WRAP VideoCapture(int device); + + virtual ~VideoCapture(); + CV_WRAP virtual bool open(const String& filename); + CV_WRAP virtual bool open(int device); + CV_WRAP virtual bool isOpened() const; + CV_WRAP virtual void release(); + + CV_WRAP virtual bool grab(); + CV_WRAP virtual bool retrieve(OutputArray image, int flag = 0); + virtual VideoCapture& operator >> (CV_OUT Mat& image); + virtual VideoCapture& operator >> (CV_OUT UMat& image); + CV_WRAP virtual bool read(OutputArray image); + + CV_WRAP virtual bool set(int propId, double value); + CV_WRAP virtual double get(int propId); + +protected: + Ptr cap; + Ptr icap; +private: + static Ptr createCameraCapture(int index); +}; + +class CV_EXPORTS_W VideoWriter +{ +public: + CV_WRAP VideoWriter(); + CV_WRAP VideoWriter(const String& filename, int fourcc, double fps, + Size frameSize, bool isColor = true); + + virtual ~VideoWriter(); + CV_WRAP virtual bool open(const String& filename, int fourcc, double fps, + Size frameSize, bool isColor = true); + CV_WRAP virtual bool isOpened() const; + CV_WRAP virtual void release(); + virtual VideoWriter& operator << (const Mat& image); + CV_WRAP virtual void write(const Mat& image); + + CV_WRAP static int fourcc(char c1, char c2, char c3, char c4); + +protected: + Ptr writer; +}; + +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvCapture* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvVideoWriter* obj) const; + +} // cv + +#endif //__OPENCV_VIDEOIO_HPP__ diff --git a/modules/highgui/include/opencv2/highgui/cap_ios.h b/modules/videoio/include/opencv2/videoio/cap_ios.h similarity index 100% rename from modules/highgui/include/opencv2/highgui/cap_ios.h rename to modules/videoio/include/opencv2/videoio/cap_ios.h diff --git a/modules/highgui/include/opencv2/highgui/ios.h b/modules/videoio/include/opencv2/videoio/videoio.hpp similarity index 90% rename from modules/highgui/include/opencv2/highgui/ios.h rename to modules/videoio/include/opencv2/videoio/videoio.hpp index a7f0395d71..ec84cf7a68 100644 --- a/modules/highgui/include/opencv2/highgui/ios.h +++ b/modules/videoio/include/opencv2/videoio/videoio.hpp @@ -1,4 +1,3 @@ - /*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. @@ -13,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -41,9 +41,8 @@ // //M*/ -#include "opencv2/core/core.hpp" -#import "opencv2/highgui/cap_ios.h" +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif -UIImage* MatToUIImage(const cv::Mat& image); -void UIImageToMat(const UIImage* image, - cv::Mat& m, bool alphaExist = false); +#include "opencv2/videoio.hpp" diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h new file mode 100644 index 0000000000..85cb07c73a --- /dev/null +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -0,0 +1,416 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOIO_H__ +#define __OPENCV_VIDEOIO_H__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/****************************************************************************************\ +* Working with Video Files and Cameras * +\****************************************************************************************/ + +/* "black box" capture structure */ +typedef struct CvCapture CvCapture; + +/* start capturing frames from video file */ +CVAPI(CvCapture*) cvCreateFileCapture( const char* filename ); + +enum +{ + CV_CAP_ANY =0, // autodetect + + CV_CAP_MIL =100, // MIL proprietary drivers + + CV_CAP_VFW =200, // platform native + CV_CAP_V4L =200, + CV_CAP_V4L2 =200, + + CV_CAP_FIREWARE =300, // IEEE 1394 drivers + CV_CAP_FIREWIRE =300, + CV_CAP_IEEE1394 =300, + CV_CAP_DC1394 =300, + CV_CAP_CMU1394 =300, + + CV_CAP_STEREO =400, // TYZX proprietary drivers + CV_CAP_TYZX =400, + CV_TYZX_LEFT =400, + CV_TYZX_RIGHT =401, + CV_TYZX_COLOR =402, + CV_TYZX_Z =403, + + CV_CAP_QT =500, // QuickTime + + CV_CAP_UNICAP =600, // Unicap drivers + + CV_CAP_DSHOW =700, // DirectShow (via videoInput) + CV_CAP_MSMF =1400, // Microsoft Media Foundation (via videoInput) + + CV_CAP_PVAPI =800, // PvAPI, Prosilica GigE SDK + + CV_CAP_OPENNI =900, // OpenNI (for Kinect) + CV_CAP_OPENNI_ASUS =910, // OpenNI (for Asus Xtion) + + CV_CAP_ANDROID =1000, // Android + CV_CAP_ANDROID_BACK =CV_CAP_ANDROID+99, // Android back camera + CV_CAP_ANDROID_FRONT =CV_CAP_ANDROID+98, // Android front camera + + CV_CAP_XIAPI =1100, // XIMEA Camera API + + CV_CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) + + CV_CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK + + CV_CAP_INTELPERC = 1500 // Intel Perceptual Computing SDK +}; + +/* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */ +CVAPI(CvCapture*) cvCreateCameraCapture( int index ); + +/* grab a frame, return 1 on success, 0 on fail. + this function is thought to be fast */ +CVAPI(int) cvGrabFrame( CvCapture* capture ); + +/* get the frame grabbed with cvGrabFrame(..) + This function may apply some frame processing like + frame decompression, flipping etc. + !!!DO NOT RELEASE or MODIFY the retrieved frame!!! */ +CVAPI(IplImage*) cvRetrieveFrame( CvCapture* capture, int streamIdx CV_DEFAULT(0) ); + +/* Just a combination of cvGrabFrame and cvRetrieveFrame + !!!DO NOT RELEASE or MODIFY the retrieved frame!!! */ +CVAPI(IplImage*) cvQueryFrame( CvCapture* capture ); + +/* stop capturing/reading and free resources */ +CVAPI(void) cvReleaseCapture( CvCapture** capture ); + +enum +{ + // modes of the controlling registers (can be: auto, manual, auto single push, absolute Latter allowed with any other mode) + // every feature can have only one mode turned on at a time + CV_CAP_PROP_DC1394_OFF = -4, //turn the feature off (not controlled manually nor automatically) + CV_CAP_PROP_DC1394_MODE_MANUAL = -3, //set automatically when a value of the feature is set by the user + CV_CAP_PROP_DC1394_MODE_AUTO = -2, + CV_CAP_PROP_DC1394_MODE_ONE_PUSH_AUTO = -1, + CV_CAP_PROP_POS_MSEC =0, + CV_CAP_PROP_POS_FRAMES =1, + CV_CAP_PROP_POS_AVI_RATIO =2, + CV_CAP_PROP_FRAME_WIDTH =3, + CV_CAP_PROP_FRAME_HEIGHT =4, + CV_CAP_PROP_FPS =5, + CV_CAP_PROP_FOURCC =6, + CV_CAP_PROP_FRAME_COUNT =7, + CV_CAP_PROP_FORMAT =8, + CV_CAP_PROP_MODE =9, + CV_CAP_PROP_BRIGHTNESS =10, + CV_CAP_PROP_CONTRAST =11, + CV_CAP_PROP_SATURATION =12, + CV_CAP_PROP_HUE =13, + CV_CAP_PROP_GAIN =14, + CV_CAP_PROP_EXPOSURE =15, + CV_CAP_PROP_CONVERT_RGB =16, + CV_CAP_PROP_WHITE_BALANCE_BLUE_U =17, + CV_CAP_PROP_RECTIFICATION =18, + CV_CAP_PROP_MONOCROME =19, + CV_CAP_PROP_SHARPNESS =20, + CV_CAP_PROP_AUTO_EXPOSURE =21, // exposure control done by camera, + // user can adjust refernce level + // using this feature + CV_CAP_PROP_GAMMA =22, + CV_CAP_PROP_TEMPERATURE =23, + CV_CAP_PROP_TRIGGER =24, + CV_CAP_PROP_TRIGGER_DELAY =25, + CV_CAP_PROP_WHITE_BALANCE_RED_V =26, + CV_CAP_PROP_ZOOM =27, + CV_CAP_PROP_FOCUS =28, + CV_CAP_PROP_GUID =29, + CV_CAP_PROP_ISO_SPEED =30, + CV_CAP_PROP_MAX_DC1394 =31, + CV_CAP_PROP_BACKLIGHT =32, + CV_CAP_PROP_PAN =33, + CV_CAP_PROP_TILT =34, + CV_CAP_PROP_ROLL =35, + CV_CAP_PROP_IRIS =36, + CV_CAP_PROP_SETTINGS =37, + + CV_CAP_PROP_AUTOGRAB =1024, // property for videoio class CvCapture_Android only + CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING=1025, // readonly, tricky property, returns cpnst char* indeed + CV_CAP_PROP_PREVIEW_FORMAT=1026, // readonly, tricky property, returns cpnst char* indeed + + // OpenNI map generators + CV_CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, + CV_CAP_OPENNI_IMAGE_GENERATOR = 1 << 30, + CV_CAP_OPENNI_GENERATORS_MASK = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_OPENNI_IMAGE_GENERATOR, + + // Properties of cameras available through OpenNI interfaces + CV_CAP_PROP_OPENNI_OUTPUT_MODE = 100, + CV_CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, // in mm + CV_CAP_PROP_OPENNI_BASELINE = 102, // in mm + CV_CAP_PROP_OPENNI_FOCAL_LENGTH = 103, // in pixels + CV_CAP_PROP_OPENNI_REGISTRATION = 104, // flag + CV_CAP_PROP_OPENNI_REGISTRATION_ON = CV_CAP_PROP_OPENNI_REGISTRATION, // flag that synchronizes the remapping depth map to image map + // by changing depth generator's view point (if the flag is "on") or + // sets this view point to its normal one (if the flag is "off"). + CV_CAP_PROP_OPENNI_APPROX_FRAME_SYNC = 105, + CV_CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, + CV_CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, + CV_CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, + + CV_CAP_PROP_OPENNI_GENERATOR_PRESENT = 109, + + CV_CAP_OPENNI_IMAGE_GENERATOR_PRESENT = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_GENERATOR_PRESENT, + CV_CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_OUTPUT_MODE, + CV_CAP_OPENNI_DEPTH_GENERATOR_BASELINE = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_BASELINE, + CV_CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_FOCAL_LENGTH, + CV_CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_REGISTRATION, + CV_CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION_ON = CV_CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION, + + // Properties of cameras available through GStreamer interface + CV_CAP_GSTREAMER_QUEUE_LENGTH = 200, // default is 1 + + // PVAPI + CV_CAP_PROP_PVAPI_MULTICASTIP = 300, // ip for anable multicast master mode. 0 for disable multicast + CV_CAP_PROP_PVAPI_FRAMESTARTTRIGGERMODE = 301, // FrameStartTriggerMode: Determines how a frame is initiated + + // Properties of cameras available through XIMEA SDK interface + CV_CAP_PROP_XI_DOWNSAMPLING = 400, // Change image resolution by binning or skipping. + CV_CAP_PROP_XI_DATA_FORMAT = 401, // Output data format. + CV_CAP_PROP_XI_OFFSET_X = 402, // Horizontal offset from the origin to the area of interest (in pixels). + CV_CAP_PROP_XI_OFFSET_Y = 403, // Vertical offset from the origin to the area of interest (in pixels). + CV_CAP_PROP_XI_TRG_SOURCE = 404, // Defines source of trigger. + CV_CAP_PROP_XI_TRG_SOFTWARE = 405, // Generates an internal trigger. PRM_TRG_SOURCE must be set to TRG_SOFTWARE. + CV_CAP_PROP_XI_GPI_SELECTOR = 406, // Selects general purpose input + CV_CAP_PROP_XI_GPI_MODE = 407, // Set general purpose input mode + CV_CAP_PROP_XI_GPI_LEVEL = 408, // Get general purpose level + CV_CAP_PROP_XI_GPO_SELECTOR = 409, // Selects general purpose output + CV_CAP_PROP_XI_GPO_MODE = 410, // Set general purpose output mode + CV_CAP_PROP_XI_LED_SELECTOR = 411, // Selects camera signalling LED + CV_CAP_PROP_XI_LED_MODE = 412, // Define camera signalling LED functionality + CV_CAP_PROP_XI_MANUAL_WB = 413, // Calculates White Balance(must be called during acquisition) + CV_CAP_PROP_XI_AUTO_WB = 414, // Automatic white balance + CV_CAP_PROP_XI_AEAG = 415, // Automatic exposure/gain + CV_CAP_PROP_XI_EXP_PRIORITY = 416, // Exposure priority (0.5 - exposure 50%, gain 50%). + CV_CAP_PROP_XI_AE_MAX_LIMIT = 417, // Maximum limit of exposure in AEAG procedure + CV_CAP_PROP_XI_AG_MAX_LIMIT = 418, // Maximum limit of gain in AEAG procedure + CV_CAP_PROP_XI_AEAG_LEVEL = 419, // Average intensity of output signal AEAG should achieve(in %) + CV_CAP_PROP_XI_TIMEOUT = 420, // Image capture timeout in milliseconds + + // Properties for Android cameras + CV_CAP_PROP_ANDROID_FLASH_MODE = 8001, + CV_CAP_PROP_ANDROID_FOCUS_MODE = 8002, + CV_CAP_PROP_ANDROID_WHITE_BALANCE = 8003, + CV_CAP_PROP_ANDROID_ANTIBANDING = 8004, + CV_CAP_PROP_ANDROID_FOCAL_LENGTH = 8005, + CV_CAP_PROP_ANDROID_FOCUS_DISTANCE_NEAR = 8006, + CV_CAP_PROP_ANDROID_FOCUS_DISTANCE_OPTIMAL = 8007, + CV_CAP_PROP_ANDROID_FOCUS_DISTANCE_FAR = 8008, + CV_CAP_PROP_ANDROID_EXPOSE_LOCK = 8009, + CV_CAP_PROP_ANDROID_WHITEBALANCE_LOCK = 8010, + + // Properties of cameras available through AVFOUNDATION interface + CV_CAP_PROP_IOS_DEVICE_FOCUS = 9001, + CV_CAP_PROP_IOS_DEVICE_EXPOSURE = 9002, + CV_CAP_PROP_IOS_DEVICE_FLASH = 9003, + CV_CAP_PROP_IOS_DEVICE_WHITEBALANCE = 9004, + CV_CAP_PROP_IOS_DEVICE_TORCH = 9005, + + // Properties of cameras available through Smartek Giganetix Ethernet Vision interface + /* --- Vladimir Litvinenko (litvinenko.vladimir@gmail.com) --- */ + CV_CAP_PROP_GIGA_FRAME_OFFSET_X = 10001, + CV_CAP_PROP_GIGA_FRAME_OFFSET_Y = 10002, + CV_CAP_PROP_GIGA_FRAME_WIDTH_MAX = 10003, + CV_CAP_PROP_GIGA_FRAME_HEIGH_MAX = 10004, + CV_CAP_PROP_GIGA_FRAME_SENS_WIDTH = 10005, + CV_CAP_PROP_GIGA_FRAME_SENS_HEIGH = 10006, + + CV_CAP_PROP_INTELPERC_PROFILE_COUNT = 11001, + CV_CAP_PROP_INTELPERC_PROFILE_IDX = 11002, + CV_CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE = 11003, + CV_CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE = 11004, + CV_CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD = 11005, + CV_CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_HORZ = 11006, + CV_CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT = 11007, + + // Intel PerC streams + CV_CAP_INTELPERC_DEPTH_GENERATOR = 1 << 29, + CV_CAP_INTELPERC_IMAGE_GENERATOR = 1 << 28, + CV_CAP_INTELPERC_GENERATORS_MASK = CV_CAP_INTELPERC_DEPTH_GENERATOR + CV_CAP_INTELPERC_IMAGE_GENERATOR +}; + +enum +{ + // Data given from depth generator. + CV_CAP_OPENNI_DEPTH_MAP = 0, // Depth values in mm (CV_16UC1) + CV_CAP_OPENNI_POINT_CLOUD_MAP = 1, // XYZ in meters (CV_32FC3) + CV_CAP_OPENNI_DISPARITY_MAP = 2, // Disparity in pixels (CV_8UC1) + CV_CAP_OPENNI_DISPARITY_MAP_32F = 3, // Disparity in pixels (CV_32FC1) + CV_CAP_OPENNI_VALID_DEPTH_MASK = 4, // CV_8UC1 + + // Data given from RGB image generator. + CV_CAP_OPENNI_BGR_IMAGE = 5, + CV_CAP_OPENNI_GRAY_IMAGE = 6 +}; + +// Supported output modes of OpenNI image generator +enum +{ + CV_CAP_OPENNI_VGA_30HZ = 0, + CV_CAP_OPENNI_SXGA_15HZ = 1, + CV_CAP_OPENNI_SXGA_30HZ = 2, + CV_CAP_OPENNI_QVGA_30HZ = 3, + CV_CAP_OPENNI_QVGA_60HZ = 4 +}; + +//supported by Android camera output formats +enum +{ + CV_CAP_ANDROID_COLOR_FRAME_BGR = 0, //BGR + CV_CAP_ANDROID_COLOR_FRAME = CV_CAP_ANDROID_COLOR_FRAME_BGR, + CV_CAP_ANDROID_GREY_FRAME = 1, //Y + CV_CAP_ANDROID_COLOR_FRAME_RGB = 2, + CV_CAP_ANDROID_COLOR_FRAME_BGRA = 3, + CV_CAP_ANDROID_COLOR_FRAME_RGBA = 4 +}; + +// supported Android camera flash modes +enum +{ + CV_CAP_ANDROID_FLASH_MODE_AUTO = 0, + CV_CAP_ANDROID_FLASH_MODE_OFF, + CV_CAP_ANDROID_FLASH_MODE_ON, + CV_CAP_ANDROID_FLASH_MODE_RED_EYE, + CV_CAP_ANDROID_FLASH_MODE_TORCH +}; + +// supported Android camera focus modes +enum +{ + CV_CAP_ANDROID_FOCUS_MODE_AUTO = 0, + CV_CAP_ANDROID_FOCUS_MODE_CONTINUOUS_PICTURE, + CV_CAP_ANDROID_FOCUS_MODE_CONTINUOUS_VIDEO, + CV_CAP_ANDROID_FOCUS_MODE_EDOF, + CV_CAP_ANDROID_FOCUS_MODE_FIXED, + CV_CAP_ANDROID_FOCUS_MODE_INFINITY, + CV_CAP_ANDROID_FOCUS_MODE_MACRO +}; + +// supported Android camera white balance modes +enum +{ + CV_CAP_ANDROID_WHITE_BALANCE_AUTO = 0, + CV_CAP_ANDROID_WHITE_BALANCE_CLOUDY_DAYLIGHT, + CV_CAP_ANDROID_WHITE_BALANCE_DAYLIGHT, + CV_CAP_ANDROID_WHITE_BALANCE_FLUORESCENT, + CV_CAP_ANDROID_WHITE_BALANCE_INCANDESCENT, + CV_CAP_ANDROID_WHITE_BALANCE_SHADE, + CV_CAP_ANDROID_WHITE_BALANCE_TWILIGHT, + CV_CAP_ANDROID_WHITE_BALANCE_WARM_FLUORESCENT +}; + +// supported Android camera antibanding modes +enum +{ + CV_CAP_ANDROID_ANTIBANDING_50HZ = 0, + CV_CAP_ANDROID_ANTIBANDING_60HZ, + CV_CAP_ANDROID_ANTIBANDING_AUTO, + CV_CAP_ANDROID_ANTIBANDING_OFF +}; + +enum +{ + CV_CAP_INTELPERC_DEPTH_MAP = 0, // Each pixel is a 16-bit integer. The value indicates the distance from an object to the camera's XY plane or the Cartesian depth. + CV_CAP_INTELPERC_UVDEPTH_MAP = 1, // Each pixel contains two 32-bit floating point values in the range of 0-1, representing the mapping of depth coordinates to the color coordinates. + CV_CAP_INTELPERC_IR_MAP = 2, // Each pixel is a 16-bit integer. The value indicates the intensity of the reflected laser beam. + CV_CAP_INTELPERC_IMAGE = 3 +}; + +/* retrieve or set capture properties */ +CVAPI(double) cvGetCaptureProperty( CvCapture* capture, int property_id ); +CVAPI(int) cvSetCaptureProperty( CvCapture* capture, int property_id, double value ); + +// Return the type of the capturer (eg, CV_CAP_V4W, CV_CAP_UNICAP), which is unknown if created with CV_CAP_ANY +CVAPI(int) cvGetCaptureDomain( CvCapture* capture); + +/* "black box" video file writer structure */ +typedef struct CvVideoWriter CvVideoWriter; + +#define CV_FOURCC_MACRO(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24)) + +CV_INLINE int CV_FOURCC(char c1, char c2, char c3, char c4) +{ + return CV_FOURCC_MACRO(c1, c2, c3, c4); +} + +#define CV_FOURCC_PROMPT -1 /* Open Codec Selection Dialog (Windows only) */ +#define CV_FOURCC_DEFAULT CV_FOURCC('I', 'Y', 'U', 'V') /* Use default codec for specified filename (Linux only) */ + +/* initialize video file writer */ +CVAPI(CvVideoWriter*) cvCreateVideoWriter( const char* filename, int fourcc, + double fps, CvSize frame_size, + int is_color CV_DEFAULT(1)); + +/* write frame to video file */ +CVAPI(int) cvWriteFrame( CvVideoWriter* writer, const IplImage* image ); + +/* close video file writer */ +CVAPI(void) cvReleaseVideoWriter( CvVideoWriter** writer ); + +/****************************************************************************************\ +* Obsolete functions/synonyms * +\****************************************************************************************/ + +#define cvCaptureFromFile cvCreateFileCapture +#define cvCaptureFromCAM cvCreateCameraCapture +#define cvCaptureFromAVI cvCaptureFromFile +#define cvCreateAVIWriter cvCreateVideoWriter +#define cvWriteToAVI cvWriteFrame + + +#ifdef __cplusplus +} +#endif + +#endif //__OPENCV_VIDEOIO_H__ diff --git a/modules/highgui/perf/perf_input.cpp b/modules/videoio/perf/perf_input.cpp similarity index 100% rename from modules/highgui/perf/perf_input.cpp rename to modules/videoio/perf/perf_input.cpp diff --git a/modules/highgui/perf/perf_main.cpp b/modules/videoio/perf/perf_main.cpp similarity index 51% rename from modules/highgui/perf/perf_main.cpp rename to modules/videoio/perf/perf_main.cpp index ebe94ab7cc..12b47807b6 100644 --- a/modules/highgui/perf/perf_main.cpp +++ b/modules/videoio/perf/perf_main.cpp @@ -1,3 +1,3 @@ #include "perf_precomp.hpp" -CV_PERF_TEST_MAIN(highgui) +CV_PERF_TEST_MAIN(videoio) diff --git a/modules/highgui/perf/perf_output.cpp b/modules/videoio/perf/perf_output.cpp similarity index 100% rename from modules/highgui/perf/perf_output.cpp rename to modules/videoio/perf/perf_output.cpp diff --git a/modules/highgui/perf/perf_precomp.hpp b/modules/videoio/perf/perf_precomp.hpp similarity index 97% rename from modules/highgui/perf/perf_precomp.hpp rename to modules/videoio/perf/perf_precomp.hpp index a5286691f6..bd27700a9f 100644 --- a/modules/highgui/perf/perf_precomp.hpp +++ b/modules/videoio/perf/perf_precomp.hpp @@ -11,7 +11,7 @@ #include "opencv2/ts.hpp" #include "opencv2/imgcodecs.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/videoio.hpp" #ifdef GTEST_CREATE_SHARED_LIBRARY #error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined diff --git a/modules/highgui/src/cap.cpp b/modules/videoio/src/cap.cpp similarity index 100% rename from modules/highgui/src/cap.cpp rename to modules/videoio/src/cap.cpp diff --git a/modules/highgui/src/cap_android.cpp b/modules/videoio/src/cap_android.cpp similarity index 97% rename from modules/highgui/src/cap_android.cpp rename to modules/videoio/src/cap_android.cpp index dac245d2b3..700e397421 100644 --- a/modules/highgui/src/cap_android.cpp +++ b/modules/videoio/src/cap_android.cpp @@ -57,7 +57,7 @@ #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) -class HighguiAndroidCameraActivity; +class VideoIOAndroidCameraActivity; class CvCapture_Android : public CvCapture { @@ -133,14 +133,14 @@ private: bool convertYUV2Grey(int width, int height, const unsigned char* yuv, cv::Mat& resmat); bool convertYUV2BGR(int width, int height, const unsigned char* yuv, cv::Mat& resmat, bool inRGBorder, bool withAlpha); - friend class HighguiAndroidCameraActivity; + friend class VideoIOAndroidCameraActivity; }; -class HighguiAndroidCameraActivity : public CameraActivity +class VideoIOAndroidCameraActivity : public CameraActivity { public: - HighguiAndroidCameraActivity(CvCapture_Android* capture) + VideoIOAndroidCameraActivity(CvCapture_Android* capture) { m_capture = capture; m_framesReceived = 0; @@ -204,7 +204,7 @@ CvCapture_Android::CvCapture_Android(int cameraId) //try connect to camera LOGD("CvCapture_Android::CvCapture_Android(%i)", cameraId); - m_activity = new HighguiAndroidCameraActivity(this); + m_activity = new VideoIOAndroidCameraActivity(this); if (m_activity == 0) return; @@ -232,7 +232,7 @@ CvCapture_Android::~CvCapture_Android() { if (m_activity) { - ((HighguiAndroidCameraActivity*)m_activity)->LogFramesRate(); + ((VideoIOAndroidCameraActivity*)m_activity)->LogFramesRate(); pthread_mutex_lock(&m_nextFrameMutex); @@ -344,7 +344,7 @@ bool CvCapture_Android::setProperty( int propIdx, double propValue ) // Only changes in frame size require camera restart if ((propIdx == CV_CAP_PROP_FRAME_WIDTH) || (propIdx == CV_CAP_PROP_FRAME_HEIGHT)) - { // property for highgui class CvCapture_Android only + { // property for videoio class CvCapture_Android only m_CameraParamsChanged = true; } @@ -475,7 +475,7 @@ void CvCapture_Android::setFrame(const void* buffer, int bufferSize) cv::Mat m_frameYUV420next_ref = m_frameYUV420next; memcpy(m_frameYUV420next_ref.ptr(), buffer, bufferSize); // LOGD("CvCapture_Android::setFrame -- memcpy is done"); - // ((HighguiAndroidCameraActivity*)m_activity)->LogFramesRate(); + // ((VideoIOAndroidCameraActivity*)m_activity)->LogFramesRate(); m_dataState = CVCAPTURE_ANDROID_STATE_HAS_NEW_FRAME_UNGRABBED; m_waitingNextFrame = false;//set flag that no more frames required at this moment diff --git a/modules/highgui/src/cap_avfoundation.mm b/modules/videoio/src/cap_avfoundation.mm similarity index 99% rename from modules/highgui/src/cap_avfoundation.mm rename to modules/videoio/src/cap_avfoundation.mm index e24ae32976..e66f03a8da 100644 --- a/modules/highgui/src/cap_avfoundation.mm +++ b/modules/videoio/src/cap_avfoundation.mm @@ -428,7 +428,7 @@ void CvCaptureCAM::setWidthHeight() { [localpool drain]; } -//added macros into headers in highgui_c.h +//added macros into headers in videoio_c.h /* #define CV_CAP_PROP_IOS_DEVICE_FOCUS 9001 #define CV_CAP_PROP_IOS_DEVICE_EXPOSURE 9002 diff --git a/modules/highgui/src/cap_cmu.cpp b/modules/videoio/src/cap_cmu.cpp similarity index 100% rename from modules/highgui/src/cap_cmu.cpp rename to modules/videoio/src/cap_cmu.cpp diff --git a/modules/highgui/src/cap_dc1394.cpp b/modules/videoio/src/cap_dc1394.cpp similarity index 99% rename from modules/highgui/src/cap_dc1394.cpp rename to modules/videoio/src/cap_dc1394.cpp index 9706bd12e3..acae61ecb4 100644 --- a/modules/highgui/src/cap_dc1394.cpp +++ b/modules/videoio/src/cap_dc1394.cpp @@ -1,5 +1,5 @@ /* This is the contributed code: -Firewire and video4linux camera support for highgui +Firewire and video4linux camera support for videoio 2003-03-12 Magnus Lundin lundin@mlu.mine.nu @@ -17,21 +17,21 @@ INSTALLATION Install OpenCV Install v4l Install dc1394 raw1394 - coriander should work with your camera - Backup highgui folder + Backup videoio folder Copy new files - cd into highgui folder + cd into videoio folder make clean (cvcap.cpp must be rebuilt) make make install -The build is controlled by the following entries in the highgui Makefile: +The build is controlled by the following entries in the videoio Makefile: -libhighgui_la_LIBADD = -L/usr/X11R6/lib -lXm -lMrm -lUil -lpng -ljpeg -lz -ltiff -lavcodec -lraw1394 -ldc1394_control +libvideoio_la_LIBADD = -L/usr/X11R6/lib -lXm -lMrm -lUil -lpng -ljpeg -lz -ltiff -lavcodec -lraw1394 -ldc1394_control DEFS = -DHAVE_CONFIG_H -DHAVE_DC1394 HAVE_CAMV4L -Now it should be possible to use highgui camera functions, works for me. +Now it should be possible to use videoio camera functions, works for me. THINGS TO DO diff --git a/modules/highgui/src/cap_dc1394_v2.cpp b/modules/videoio/src/cap_dc1394_v2.cpp similarity index 100% rename from modules/highgui/src/cap_dc1394_v2.cpp rename to modules/videoio/src/cap_dc1394_v2.cpp diff --git a/modules/highgui/src/cap_dshow.cpp b/modules/videoio/src/cap_dshow.cpp similarity index 100% rename from modules/highgui/src/cap_dshow.cpp rename to modules/videoio/src/cap_dshow.cpp diff --git a/modules/highgui/src/cap_ffmpeg.cpp b/modules/videoio/src/cap_ffmpeg.cpp similarity index 100% rename from modules/highgui/src/cap_ffmpeg.cpp rename to modules/videoio/src/cap_ffmpeg.cpp diff --git a/modules/highgui/src/cap_ffmpeg_api.hpp b/modules/videoio/src/cap_ffmpeg_api.hpp similarity index 100% rename from modules/highgui/src/cap_ffmpeg_api.hpp rename to modules/videoio/src/cap_ffmpeg_api.hpp diff --git a/modules/highgui/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp similarity index 100% rename from modules/highgui/src/cap_ffmpeg_impl.hpp rename to modules/videoio/src/cap_ffmpeg_impl.hpp diff --git a/modules/highgui/src/cap_giganetix.cpp b/modules/videoio/src/cap_giganetix.cpp similarity index 100% rename from modules/highgui/src/cap_giganetix.cpp rename to modules/videoio/src/cap_giganetix.cpp diff --git a/modules/highgui/src/cap_gstreamer.cpp b/modules/videoio/src/cap_gstreamer.cpp similarity index 100% rename from modules/highgui/src/cap_gstreamer.cpp rename to modules/videoio/src/cap_gstreamer.cpp diff --git a/modules/highgui/src/cap_images.cpp b/modules/videoio/src/cap_images.cpp similarity index 100% rename from modules/highgui/src/cap_images.cpp rename to modules/videoio/src/cap_images.cpp diff --git a/modules/highgui/src/cap_intelperc.cpp b/modules/videoio/src/cap_intelperc.cpp similarity index 100% rename from modules/highgui/src/cap_intelperc.cpp rename to modules/videoio/src/cap_intelperc.cpp diff --git a/modules/highgui/src/cap_intelperc.hpp b/modules/videoio/src/cap_intelperc.hpp similarity index 100% rename from modules/highgui/src/cap_intelperc.hpp rename to modules/videoio/src/cap_intelperc.hpp diff --git a/modules/highgui/src/cap_ios_abstract_camera.mm b/modules/videoio/src/cap_ios_abstract_camera.mm similarity index 99% rename from modules/highgui/src/cap_ios_abstract_camera.mm rename to modules/videoio/src/cap_ios_abstract_camera.mm index b40b3648de..08547663ca 100644 --- a/modules/highgui/src/cap_ios_abstract_camera.mm +++ b/modules/videoio/src/cap_ios_abstract_camera.mm @@ -30,7 +30,7 @@ */ -#import "opencv2/highgui/cap_ios.h" +#import "opencv2/videoio/cap_ios.h" #include "precomp.hpp" #pragma mark - Private Interface diff --git a/modules/highgui/src/cap_ios_photo_camera.mm b/modules/videoio/src/cap_ios_photo_camera.mm similarity index 99% rename from modules/highgui/src/cap_ios_photo_camera.mm rename to modules/videoio/src/cap_ios_photo_camera.mm index f05cfa5f87..c6c93a8cf0 100644 --- a/modules/highgui/src/cap_ios_photo_camera.mm +++ b/modules/videoio/src/cap_ios_photo_camera.mm @@ -29,7 +29,7 @@ */ -#import "opencv2/highgui/cap_ios.h" +#import "opencv2/videoio/cap_ios.h" #include "precomp.hpp" #pragma mark - Private Interface diff --git a/modules/highgui/src/cap_ios_video_camera.mm b/modules/videoio/src/cap_ios_video_camera.mm similarity index 99% rename from modules/highgui/src/cap_ios_video_camera.mm rename to modules/videoio/src/cap_ios_video_camera.mm index 20973c3133..c094de79c1 100644 --- a/modules/highgui/src/cap_ios_video_camera.mm +++ b/modules/videoio/src/cap_ios_video_camera.mm @@ -29,7 +29,7 @@ * */ -#import "opencv2/highgui/cap_ios.h" +#import "opencv2/videoio/cap_ios.h" #include "precomp.hpp" #import diff --git a/modules/highgui/src/cap_libv4l.cpp b/modules/videoio/src/cap_libv4l.cpp similarity index 96% rename from modules/highgui/src/cap_libv4l.cpp rename to modules/videoio/src/cap_libv4l.cpp index e7aa5b5dfe..a3a02d9ef9 100644 --- a/modules/highgui/src/cap_libv4l.cpp +++ b/modules/videoio/src/cap_libv4l.cpp @@ -1,7 +1,7 @@ /* This is the contributed code: File: cvcap_v4l.cpp -Current Location: ../opencv-0.9.6/otherlibs/highgui +Current Location: ../opencv-0.9.6/otherlibs/videoio Original Version: 2003-03-12 Magnus Lundin lundin@mlu.mine.nu Original Comments: @@ -71,7 +71,7 @@ For Release: OpenCV-Linux Beta4 Opencv-0.9.6 [FD] I modified the following: - handle YUV420P, YUV420, and YUV411P palettes (for many webcams) without using floating-point - cvGrabFrame should not wait for the end of the first frame, and should return quickly - (see highgui doc) + (see videoio doc) - cvRetrieveFrame should in turn wait for the end of frame capture, and should not trigger the capture of the next frame (the user choses when to do it using GrabFrame) To get the old behavior, re-call cvRetrieveFrame just after cvGrabFrame. @@ -179,7 +179,7 @@ make & enjoy! Planning for future rewrite of this whole library (July/August 2010) 15th patch: May 12, 2010, Filipe Almeida filipe.almeida@ist.utl.pt -- Broken compile of library (include "_highgui.h") +- Broken compile of library (include "_videoio.h") */ /*M/////////////////////////////////////////////////////////////////////////////////////// @@ -654,7 +654,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { /* Nope. */ - fprintf( stderr, "HIGHGUI ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName); + fprintf( stderr, "VIDEOIO ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName); icvCloseCAM_V4L(capture); return -1; } @@ -673,7 +673,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) /* V4L2 have a status field from selected video mode */ if (-1 == xioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp)) { - fprintf (stderr, "HIGHGUI ERROR: V4L2: Aren't able to set channel number\n"); + fprintf (stderr, "VIDEOIO ERROR: V4L2: Aren't able to set channel number\n"); icvCloseCAM_V4L (capture); return -1; } @@ -684,7 +684,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) { - fprintf( stderr, "HIGHGUI ERROR: V4L2: Could not obtain specifics of capture window.\n\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L2: Could not obtain specifics of capture window.\n\n"); icvCloseCAM_V4L(capture); return -1; } @@ -698,12 +698,12 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) capture->form.fmt.pix.height = capture->height; if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) { - fprintf(stderr, "HIGHGUI ERROR: libv4l unable to ioctl S_FMT\n"); + fprintf(stderr, "VIDEOIO ERROR: libv4l unable to ioctl S_FMT\n"); return -1; } if (V4L2_PIX_FMT_BGR24 != capture->form.fmt.pix.pixelformat) { - fprintf( stderr, "HIGHGUI ERROR: libv4l unable convert to requested pixfmt\n"); + fprintf( stderr, "VIDEOIO ERROR: libv4l unable convert to requested pixfmt\n"); return -1; } @@ -829,7 +829,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) if (detect_v4l == -1) { - fprintf (stderr, "HIGHGUI ERROR: V4L" + fprintf (stderr, "VIDEOIO ERROR: V4L" ": device %s: Unable to open for READ ONLY\n", deviceName); return -1; @@ -837,7 +837,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) if (detect_v4l <= 0) { - fprintf (stderr, "HIGHGUI ERROR: V4L" + fprintf (stderr, "VIDEOIO ERROR: V4L" ": device %s: Unable to query number of channels\n", deviceName); return -1; @@ -846,7 +846,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) { if ((capture->capability.type & VID_TYPE_CAPTURE) == 0) { /* Nope. */ - fprintf( stderr, "HIGHGUI ERROR: V4L: " + fprintf( stderr, "VIDEOIO ERROR: V4L: " "device %s is unable to capture video memory.\n",deviceName); icvCloseCAM_V4L(capture); return -1; @@ -884,7 +884,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) { if(v4l1_ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) == -1) { - fprintf( stderr, "HIGHGUI ERROR: V4L: " + fprintf( stderr, "VIDEOIO ERROR: V4L: " "Could not obtain specifics of capture window.\n\n"); icvCloseCAM_V4L(capture); return -1; @@ -894,7 +894,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) { if(v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L: Unable to determine size of incoming image\n"); icvCloseCAM_V4L(capture); return -1; } @@ -902,17 +902,17 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) capture->imageProperties.palette = VIDEO_PALETTE_RGB24; capture->imageProperties.depth = 24; if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0) { - fprintf( stderr, "HIGHGUI ERROR: libv4l unable to ioctl VIDIOCSPICT\n\n"); + fprintf( stderr, "VIDEOIO ERROR: libv4l unable to ioctl VIDIOCSPICT\n\n"); icvCloseCAM_V4L(capture); return -1; } if (v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) { - fprintf( stderr, "HIGHGUI ERROR: libv4l unable to ioctl VIDIOCGPICT\n\n"); + fprintf( stderr, "VIDEOIO ERROR: libv4l unable to ioctl VIDIOCGPICT\n\n"); icvCloseCAM_V4L(capture); return -1; } if (capture->imageProperties.palette != VIDEO_PALETTE_RGB24) { - fprintf( stderr, "HIGHGUI ERROR: libv4l unable convert to requested pixfmt\n\n"); + fprintf( stderr, "VIDEOIO ERROR: libv4l unable convert to requested pixfmt\n\n"); icvCloseCAM_V4L(capture); return -1; } @@ -929,7 +929,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) capture->deviceHandle, 0); if (capture->memoryMap == MAP_FAILED) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno)); + fprintf( stderr, "VIDEOIO ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno)); icvCloseCAM_V4L(capture); return -1; } @@ -939,7 +939,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) capture->mmaps = (struct video_mmap *) (malloc(capture->memoryBuffer.frames * sizeof(struct video_mmap))); if (!capture->mmaps) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Could not memory map video frames.\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L: Could not memory map video frames.\n"); icvCloseCAM_V4L(capture); return -1; } @@ -972,14 +972,14 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) //search index in indexList if ( (index>-1) && ! ((1 << index) & indexList) ) { - fprintf( stderr, "HIGHGUI ERROR: V4L: index %d is not correct!\n",index); + fprintf( stderr, "VIDEOIO ERROR: V4L: index %d is not correct!\n",index); return NULL; /* Did someone ask for not correct video source number? */ } /* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL the handles for V4L processing */ CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L)); if (!capture) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Could not allocate memory for capture process.\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L: Could not allocate memory for capture process.\n"); return NULL; } @@ -1161,7 +1161,7 @@ static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette; if (v4l1_ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n"); return 0; } } @@ -1208,7 +1208,7 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { /* [FD] this really belongs here */ if (v4l1_ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno)); + fprintf( stderr, "VIDEOIO ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno)); } } @@ -1266,7 +1266,7 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { break; default: fprintf( stderr, - "HIGHGUI ERROR: V4L: Cannot convert from palette %d to RGB\n", + "VIDEOIO ERROR: V4L: Cannot convert from palette %d to RGB\n", capture->imageProperties.palette); return 0; } @@ -1291,7 +1291,7 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, /* display an error message, and return an error code */ perror ("VIDIOC_G_FMT"); if (v4l1_ioctl (capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) { - fprintf (stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n"); + fprintf (stderr, " ERROR: V4L: Unable to determine size of incoming image\n"); icvCloseCAM_V4L(capture); return -1; } else { @@ -1333,7 +1333,7 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, /* all went well */ is_v4l2_device = 1; } else { - fprintf(stderr, "HIGHGUI ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno)); + fprintf(stderr, "VIDEOIO ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno)); } if (is_v4l2_device == 1) { @@ -1342,7 +1342,7 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, int v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id); if ((v4l2_min == -1) && (v4l2_max == -1)) { - fprintf(stderr, "HIGHGUI ERROR: V4L2: Property %s(%u) not supported by device\n", name, property_id); + fprintf(stderr, "VIDEOIO ERROR: V4L2: Property %s(%u) not supported by device\n", name, property_id); return -1; } @@ -1367,11 +1367,11 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, retval = capture->imageProperties.hue; break; case CV_CAP_PROP_GAIN: - fprintf(stderr, "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n"); return -1; break; case CV_CAP_PROP_EXPOSURE: - fprintf(stderr, "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n"); return -1; break; } @@ -1440,7 +1440,7 @@ static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) { /* Get window info again, to get the real value */ if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) { - fprintf(stderr, "HIGHGUI ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n"); icvCloseCAM_V4L(capture); @@ -1530,14 +1530,14 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double val v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id); if ((v4l2_min == -1) && (v4l2_max == -1)) { - fprintf(stderr, "HIGHGUI ERROR: V4L: Property %s(%u) not supported by device\n", name, property_id); + fprintf(stderr, "VIDEOIO ERROR: V4L: Property %s(%u) not supported by device\n", name, property_id); return -1; } if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &capture->control) == 0) { /* all went well */ } else { - fprintf(stderr, "HIGHGUI ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno)); + fprintf(stderr, "VIDEOIO ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno)); } if (v4l2_max != 0) { @@ -1558,7 +1558,7 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double val if (v4l2_ioctl(capture->deviceHandle, VIDIOC_S_CTRL, &c) != 0) { /* The driver may clamp the value or return ERANGE, ignored here */ if (errno != ERANGE) { - fprintf(stderr, "HIGHGUI ERROR: V4L2: Failed to set control \"%d\": %s (value %d)\n", c.id, strerror(errno), c.value); + fprintf(stderr, "VIDEOIO ERROR: V4L2: Failed to set control \"%d\": %s (value %d)\n", c.id, strerror(errno), c.value); is_v4l2 = 0; } else { return 0; @@ -1568,7 +1568,7 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double val } if (is_v4l2 == 0) { /* use v4l1_ioctl */ - fprintf(stderr, "HIGHGUI WARNING: Setting property %u through v4l2 failed. Trying with v4l1.\n", c.id); + fprintf(stderr, "VIDEOIO WARNING: Setting property %u through v4l2 failed. Trying with v4l1.\n", c.id); int v4l_value; /* scale the value to the wanted integer one */ v4l_value = (int)(0xFFFF * value); @@ -1587,18 +1587,18 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double val capture->imageProperties.hue = v4l_value; break; case CV_CAP_PROP_GAIN: - fprintf(stderr, "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n"); return -1; case CV_CAP_PROP_EXPOSURE: - fprintf(stderr, "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n"); return -1; default: - fprintf(stderr, "HIGHGUI ERROR: V4L: property #%d is not supported\n", property_id); + fprintf(stderr, "VIDEOIO ERROR: V4L: property #%d is not supported\n", property_id); return -1; } if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0){ - fprintf(stderr, "HIGHGUI ERROR: V4L: Unable to set video informations\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to set video informations\n"); icvCloseCAM_V4L(capture); return -1; } @@ -1643,7 +1643,7 @@ static int icvSetPropertyCAM_V4L(CvCaptureCAM_V4L* capture, int property_id, dou setfps.parm.capture.timeperframe.numerator = 1; setfps.parm.capture.timeperframe.denominator = value; if (xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps) < 0){ - fprintf(stderr, "HIGHGUI ERROR: V4L: Unable to set camera FPS\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to set camera FPS\n"); retval=0; } break; diff --git a/modules/highgui/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp similarity index 100% rename from modules/highgui/src/cap_msmf.cpp rename to modules/videoio/src/cap_msmf.cpp diff --git a/modules/highgui/src/cap_msmf.hpp b/modules/videoio/src/cap_msmf.hpp similarity index 99% rename from modules/highgui/src/cap_msmf.hpp rename to modules/videoio/src/cap_msmf.hpp index c212ca910d..3ecd43cb57 100644 --- a/modules/highgui/src/cap_msmf.hpp +++ b/modules/videoio/src/cap_msmf.hpp @@ -2277,7 +2277,7 @@ protected: /* Be sure to declare webcam device capability in manifest For better media capture support, add the following snippet with correct module name to the project manifest - (highgui needs DLL activation class factoryentry points): + (videoio needs DLL activation class factoryentry points): diff --git a/modules/highgui/src/cap_openni.cpp b/modules/videoio/src/cap_openni.cpp similarity index 100% rename from modules/highgui/src/cap_openni.cpp rename to modules/videoio/src/cap_openni.cpp diff --git a/modules/highgui/src/cap_pvapi.cpp b/modules/videoio/src/cap_pvapi.cpp similarity index 100% rename from modules/highgui/src/cap_pvapi.cpp rename to modules/videoio/src/cap_pvapi.cpp diff --git a/modules/highgui/src/cap_qt.cpp b/modules/videoio/src/cap_qt.cpp similarity index 100% rename from modules/highgui/src/cap_qt.cpp rename to modules/videoio/src/cap_qt.cpp diff --git a/modules/highgui/src/cap_qtkit.mm b/modules/videoio/src/cap_qtkit.mm similarity index 100% rename from modules/highgui/src/cap_qtkit.mm rename to modules/videoio/src/cap_qtkit.mm diff --git a/modules/highgui/src/cap_unicap.cpp b/modules/videoio/src/cap_unicap.cpp similarity index 100% rename from modules/highgui/src/cap_unicap.cpp rename to modules/videoio/src/cap_unicap.cpp diff --git a/modules/highgui/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp similarity index 97% rename from modules/highgui/src/cap_v4l.cpp rename to modules/videoio/src/cap_v4l.cpp index c9fca05819..efa9a8b44c 100644 --- a/modules/highgui/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -1,7 +1,7 @@ /* This is the contributed code: File: cvcap_v4l.cpp -Current Location: ../opencv-0.9.6/otherlibs/highgui +Current Location: ../opencv-0.9.6/otherlibs/videoio Original Version: 2003-03-12 Magnus Lundin lundin@mlu.mine.nu Original Comments: @@ -71,7 +71,7 @@ For Release: OpenCV-Linux Beta4 Opencv-0.9.6 [FD] I modified the following: - handle YUV420P, YUV420, and YUV411P palettes (for many webcams) without using floating-point - cvGrabFrame should not wait for the end of the first frame, and should return quickly - (see highgui doc) + (see videoio doc) - cvRetrieveFrame should in turn wait for the end of frame capture, and should not trigger the capture of the next frame (the user choses when to do it using GrabFrame) To get the old behavior, re-call cvRetrieveFrame just after cvGrabFrame. @@ -590,7 +590,7 @@ static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) } else { - fprintf(stderr, "HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n"); icvCloseCAM_V4L(capture); return -1; } @@ -607,7 +607,7 @@ static int autosetup_capture_mode_v4l(CvCaptureCAM_V4L* capture) { if(ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L: Unable to determine size of incoming image\n"); icvCloseCAM_V4L(capture); return -1; } @@ -627,7 +627,7 @@ static int autosetup_capture_mode_v4l(CvCaptureCAM_V4L* capture) //printf("negotiated palette YUV420P\n"); } else { - fprintf(stderr, "HIGHGUI ERROR: V4L: Pixel format of incoming image is unsupported by OpenCV\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L: Pixel format of incoming image is unsupported by OpenCV\n"); icvCloseCAM_V4L(capture); return -1; } @@ -829,7 +829,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { /* Nope. */ - fprintf( stderr, "HIGHGUI ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName); + fprintf( stderr, "VIDEOIO ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName); icvCloseCAM_V4L(capture); return -1; } @@ -848,7 +848,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) /* V4L2 have a status field from selected video mode */ if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp)) { - fprintf (stderr, "HIGHGUI ERROR: V4L2: Aren't able to set channel number\n"); + fprintf (stderr, "VIDEOIO ERROR: V4L2: Aren't able to set channel number\n"); icvCloseCAM_V4L (capture); return -1; } @@ -859,7 +859,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) { - fprintf( stderr, "HIGHGUI ERROR: V4L2: Could not obtain specifics of capture window.\n\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L2: Could not obtain specifics of capture window.\n\n"); icvCloseCAM_V4L(capture); return -1; } @@ -990,7 +990,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) if ((detect_v4l == -1) ) { - fprintf (stderr, "HIGHGUI ERROR: V4L" + fprintf (stderr, "VIDEOIO ERROR: V4L" ": device %s: Unable to open for READ ONLY\n", deviceName); return -1; @@ -999,7 +999,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) if ((detect_v4l <= 0) ) { - fprintf (stderr, "HIGHGUI ERROR: V4L" + fprintf (stderr, "VIDEOIO ERROR: V4L" ": device %s: Unable to query number of channels\n", deviceName); return -1; @@ -1008,7 +1008,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) { if ((capture->capability.type & VID_TYPE_CAPTURE) == 0) { /* Nope. */ - fprintf( stderr, "HIGHGUI ERROR: V4L: " + fprintf( stderr, "VIDEOIO ERROR: V4L: " "device %s is unable to capture video memory.\n",deviceName); icvCloseCAM_V4L(capture); return -1; @@ -1047,7 +1047,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) { if(ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) == -1) { - fprintf( stderr, "HIGHGUI ERROR: V4L: " + fprintf( stderr, "VIDEOIO ERROR: V4L: " "Could not obtain specifics of capture window.\n\n"); icvCloseCAM_V4L(capture); return -1; @@ -1072,7 +1072,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) capture->deviceHandle, 0); if (capture->memoryMap == MAP_FAILED) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno)); + fprintf( stderr, "VIDEOIO ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno)); icvCloseCAM_V4L(capture); } @@ -1081,7 +1081,7 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName) capture->mmaps = (struct video_mmap *) (malloc(capture->memoryBuffer.frames * sizeof(struct video_mmap))); if (!capture->mmaps) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Could not memory map video frames.\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L: Could not memory map video frames.\n"); icvCloseCAM_V4L(capture); return -1; } @@ -1116,14 +1116,14 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) //search index in indexList if ( (index>-1) && ! ((1 << index) & indexList) ) { - fprintf( stderr, "HIGHGUI ERROR: V4L: index %d is not correct!\n",index); + fprintf( stderr, "VIDEOIO ERROR: V4L: index %d is not correct!\n",index); return NULL; /* Did someone ask for not correct video source number? */ } /* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL the handles for V4L processing */ CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L)); if (!capture) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Could not allocate memory for capture process.\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L: Could not allocate memory for capture process.\n"); return NULL; } /* Select camera, or rather, V4L video source */ @@ -1317,7 +1317,7 @@ static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) { capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette; if (ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n"); + fprintf( stderr, "VIDEOIO ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n"); return 0; } } @@ -2098,7 +2098,7 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { /* [FD] this really belongs here */ if (ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) { - fprintf( stderr, "HIGHGUI ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno)); + fprintf( stderr, "VIDEOIO ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno)); } } @@ -2255,7 +2255,7 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { break; default: fprintf( stderr, - "HIGHGUI ERROR: V4L: Cannot convert from palette %d to RGB\n", + "VIDEOIO ERROR: V4L: Cannot convert from palette %d to RGB\n", capture->imageProperties.palette); return 0; @@ -2326,7 +2326,7 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, break; default: fprintf(stderr, - "HIGHGUI ERROR: V4L2: getting property #%d is not supported\n", + "VIDEOIO ERROR: V4L2: getting property #%d is not supported\n", property_id); return -1; } @@ -2334,7 +2334,7 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_CTRL, &capture->control)) { - fprintf( stderr, "HIGHGUI ERROR: V4L2: "); + fprintf( stderr, "VIDEOIO ERROR: V4L2: "); switch (property_id) { case CV_CAP_PROP_BRIGHTNESS: fprintf (stderr, "Brightness"); @@ -2405,7 +2405,7 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, if (ioctl (capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) { fprintf (stderr, - "HIGHGUI ERROR: V4L: " + "VIDEOIO ERROR: V4L: " "Unable to determine size of incoming image\n"); icvCloseCAM_V4L(capture); return -1; @@ -2432,17 +2432,17 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, break; case CV_CAP_PROP_GAIN: fprintf(stderr, - "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n"); + "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n"); return -1; break; case CV_CAP_PROP_EXPOSURE: fprintf(stderr, - "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n"); + "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n"); return -1; break; default: fprintf(stderr, - "HIGHGUI ERROR: V4L: getting property #%d is not supported\n", + "VIDEOIO ERROR: V4L: getting property #%d is not supported\n", property_id); } @@ -2470,7 +2470,7 @@ static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) { capture->cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl (capture->deviceHandle, VIDIOC_CROPCAP, &capture->cropcap) < 0) { - fprintf(stderr, "HIGHGUI ERROR: V4L/V4L2: VIDIOC_CROPCAP\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: VIDIOC_CROPCAP\n"); } else { CLEAR (capture->crop); @@ -2479,7 +2479,7 @@ static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) { /* set the crop area, but don't exit if the device don't support croping */ if (ioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop) < 0) { - fprintf(stderr, "HIGHGUI ERROR: V4L/V4L2: VIDIOC_S_CROP\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: VIDIOC_S_CROP\n"); } } @@ -2519,7 +2519,7 @@ static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) { /* Get window info again, to get the real value */ if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) { - fprintf(stderr, "HIGHGUI ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n"); + fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n"); icvCloseCAM_V4L(capture); @@ -2611,7 +2611,7 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, break; default: fprintf(stderr, - "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n", + "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n", property_id); return -1; } @@ -2678,7 +2678,7 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, break; default: fprintf(stderr, - "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n", + "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n", property_id); return -1; } @@ -2720,15 +2720,15 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, break; case CV_CAP_PROP_GAIN: fprintf(stderr, - "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n"); + "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n"); return -1; case CV_CAP_PROP_EXPOSURE: fprintf(stderr, - "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n"); + "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n"); return -1; default: fprintf(stderr, - "HIGHGUI ERROR: V4L: property #%d is not supported\n", + "VIDEOIO ERROR: V4L: property #%d is not supported\n", property_id); return -1; } @@ -2737,7 +2737,7 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, < 0) { fprintf(stderr, - "HIGHGUI ERROR: V4L: Unable to set video informations\n"); + "VIDEOIO ERROR: V4L: Unable to set video informations\n"); icvCloseCAM_V4L(capture); return -1; } @@ -2786,7 +2786,7 @@ static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, break; default: fprintf(stderr, - "HIGHGUI ERROR: V4L: setting property #%d is not supported\n", + "VIDEOIO ERROR: V4L: setting property #%d is not supported\n", property_id); } diff --git a/modules/highgui/src/cap_vfw.cpp b/modules/videoio/src/cap_vfw.cpp similarity index 100% rename from modules/highgui/src/cap_vfw.cpp rename to modules/videoio/src/cap_vfw.cpp diff --git a/modules/highgui/src/cap_ximea.cpp b/modules/videoio/src/cap_ximea.cpp similarity index 100% rename from modules/highgui/src/cap_ximea.cpp rename to modules/videoio/src/cap_ximea.cpp diff --git a/modules/highgui/src/cap_xine.cpp b/modules/videoio/src/cap_xine.cpp similarity index 100% rename from modules/highgui/src/cap_xine.cpp rename to modules/videoio/src/cap_xine.cpp diff --git a/modules/highgui/src/ffmpeg_codecs.hpp b/modules/videoio/src/ffmpeg_codecs.hpp similarity index 100% rename from modules/highgui/src/ffmpeg_codecs.hpp rename to modules/videoio/src/ffmpeg_codecs.hpp diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp new file mode 100644 index 0000000000..ec4c00a360 --- /dev/null +++ b/modules/videoio/src/precomp.hpp @@ -0,0 +1,178 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __VIDEOIO_H_ +#define __VIDEOIO_H_ + +#include "opencv2/videoio.hpp" + +#include "opencv2/core/utility.hpp" +#include "opencv2/core/private.hpp" + +#include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/imgcodecs/imgcodecs_c.h" +#include "opencv2/videoio/videoio_c.h" + +#include +#include +#include +#include +#include +#include + +#if defined WIN32 || defined WINCE + #if !defined _WIN32_WINNT + #ifdef HAVE_MSMF + #define _WIN32_WINNT 0x0600 // Windows Vista + #else + #define _WIN32_WINNT 0x0500 // Windows 2000 + #endif + #endif + + #include + #undef small + #undef min + #undef max + #undef abs +#endif + +#ifdef HAVE_TEGRA_OPTIMIZATION +#include "opencv2/videoio/videoio_tegra.hpp" +#endif + +#define __BEGIN__ __CV_BEGIN__ +#define __END__ __CV_END__ +#define EXIT __CV_EXIT__ + +/***************************** CvCapture structure ******************************/ + +struct CvCapture +{ + virtual ~CvCapture() {} + virtual double getProperty(int) { return 0; } + virtual bool setProperty(int, double) { return 0; } + virtual bool grabFrame() { return true; } + virtual IplImage* retrieveFrame(int) { return 0; } + virtual int getCaptureDomain() { return CV_CAP_ANY; } // Return the type of the capture object: CV_CAP_VFW, etc... +}; + +/*************************** CvVideoWriter structure ****************************/ + +struct CvVideoWriter +{ + virtual ~CvVideoWriter() {} + virtual bool writeFrame(const IplImage*) { return false; } +}; + +CvCapture * cvCreateCameraCapture_V4L( int index ); +CvCapture * cvCreateCameraCapture_DC1394( int index ); +CvCapture * cvCreateCameraCapture_DC1394_2( int index ); +CvCapture* cvCreateCameraCapture_MIL( int index ); +CvCapture* cvCreateCameraCapture_Giganetix( int index ); +CvCapture * cvCreateCameraCapture_CMU( int index ); +CV_IMPL CvCapture * cvCreateCameraCapture_TYZX( int index ); +CvCapture* cvCreateFileCapture_Win32( const char* filename ); +CvCapture* cvCreateCameraCapture_VFW( int index ); +CvCapture* cvCreateFileCapture_VFW( const char* filename ); +CvVideoWriter* cvCreateVideoWriter_Win32( const char* filename, int fourcc, + double fps, CvSize frameSize, int is_color ); +CvVideoWriter* cvCreateVideoWriter_VFW( const char* filename, int fourcc, + double fps, CvSize frameSize, int is_color ); +CvCapture* cvCreateCameraCapture_DShow( int index ); +CvCapture* cvCreateCameraCapture_MSMF( int index ); +CvCapture* cvCreateFileCapture_MSMF (const char* filename); +CvVideoWriter* cvCreateVideoWriter_MSMF( const char* filename, int fourcc, + double fps, CvSize frameSize, int is_color ); +CvCapture* cvCreateCameraCapture_OpenNI( int index ); +CvCapture* cvCreateFileCapture_OpenNI( const char* filename ); +CvCapture* cvCreateCameraCapture_Android( int index ); +CvCapture* cvCreateCameraCapture_XIMEA( int index ); +CvCapture* cvCreateCameraCapture_AVFoundation(int index); + +CvCapture* cvCreateFileCapture_Images(const char* filename); +CvVideoWriter* cvCreateVideoWriter_Images(const char* filename); + +CvCapture* cvCreateFileCapture_XINE (const char* filename); + + +#define CV_CAP_GSTREAMER_1394 0 +#define CV_CAP_GSTREAMER_V4L 1 +#define CV_CAP_GSTREAMER_V4L2 2 +#define CV_CAP_GSTREAMER_FILE 3 + +CvCapture* cvCreateCapture_GStreamer(int type, const char *filename); +CvCapture* cvCreateFileCapture_FFMPEG_proxy(const char* filename); + + +CvVideoWriter* cvCreateVideoWriter_FFMPEG_proxy( const char* filename, int fourcc, + double fps, CvSize frameSize, int is_color ); + +CvCapture * cvCreateFileCapture_QT (const char * filename); +CvCapture * cvCreateCameraCapture_QT (const int index); + +CvVideoWriter* cvCreateVideoWriter_QT ( const char* filename, int fourcc, + double fps, CvSize frameSize, int is_color ); + +CvCapture* cvCreateFileCapture_AVFoundation (const char * filename); +CvVideoWriter* cvCreateVideoWriter_AVFoundation( const char* filename, int fourcc, + double fps, CvSize frameSize, int is_color ); + + +CvCapture * cvCreateCameraCapture_Unicap (const int index); +CvCapture * cvCreateCameraCapture_PvAPI (const int index); +CvVideoWriter* cvCreateVideoWriter_GStreamer( const char* filename, int fourcc, + double fps, CvSize frameSize, int is_color ); + +namespace cv +{ + class IVideoCapture + { + public: + virtual ~IVideoCapture() {} + virtual double getProperty(int) { return 0; } + virtual bool setProperty(int, double) { return 0; } + virtual bool grabFrame() = 0; + virtual bool retrieveFrame(int, cv::OutputArray) = 0; + virtual int getCaptureDomain() { return CAP_ANY; } // Return the type of the capture object: CAP_VFW, etc... + }; +}; + +#endif /* __VIDEOIO_H_ */ diff --git a/modules/highgui/test/test_ffmpeg.cpp b/modules/videoio/test/test_ffmpeg.cpp similarity index 98% rename from modules/highgui/test/test_ffmpeg.cpp rename to modules/videoio/test/test_ffmpeg.cpp index 61fc3d49a4..2f95cb21d1 100644 --- a/modules/highgui/test/test_ffmpeg.cpp +++ b/modules/videoio/test/test_ffmpeg.cpp @@ -41,7 +41,7 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/videoio.hpp" using namespace cv; @@ -145,7 +145,7 @@ public: } }; -TEST(Highgui_Video, ffmpeg_writebig) { CV_FFmpegWriteBigVideoTest test; test.safe_run(); } +TEST(Videoio_Video, ffmpeg_writebig) { CV_FFmpegWriteBigVideoTest test; test.safe_run(); } class CV_FFmpegReadImageTest : public cvtest::BaseTest { @@ -174,7 +174,7 @@ public: } }; -TEST(Highgui_Video, ffmpeg_image) { CV_FFmpegReadImageTest test; test.safe_run(); } +TEST(Videoio_Video, ffmpeg_image) { CV_FFmpegReadImageTest test; test.safe_run(); } #endif @@ -360,7 +360,7 @@ private: bool ReadImageAndTest::next; -TEST(Highgui_Video_parallel_writers_and_readers, accuracy) +TEST(Videoio_Video_parallel_writers_and_readers, accuracy) { const unsigned int threadsCount = 4; cvtest::TS* ts = cvtest::TS::ptr(); diff --git a/modules/highgui/test/test_fourcc.cpp b/modules/videoio/test/test_fourcc.cpp similarity index 99% rename from modules/highgui/test/test_fourcc.cpp rename to modules/videoio/test/test_fourcc.cpp index 82f699b098..15bf7118ac 100644 --- a/modules/highgui/test/test_fourcc.cpp +++ b/modules/videoio/test/test_fourcc.cpp @@ -41,7 +41,7 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/videoio.hpp" #undef DEFINE_GUID #define DEFINE_GUID(n, fourcc, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) fourcc, @@ -101,7 +101,7 @@ DEFINE_GUID(PIN_CATEGORY_PREVIEW,0xfb6c4282,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0x 0}; -TEST(Highgui_dshow, fourcc_conversion) +TEST(Videoio_dshow, fourcc_conversion) { for(int i = 0; allfourcc[i]; ++i) { diff --git a/modules/highgui/test/test_framecount.cpp b/modules/videoio/test/test_framecount.cpp similarity index 97% rename from modules/highgui/test/test_framecount.cpp rename to modules/videoio/test/test_framecount.cpp index 30f6e67ce6..94ddbf800a 100644 --- a/modules/highgui/test/test_framecount.cpp +++ b/modules/videoio/test/test_framecount.cpp @@ -41,7 +41,7 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui/highgui_c.h" +#include "opencv2/videoio/videoio_c.h" #include using namespace cv; @@ -110,5 +110,5 @@ void CV_FramecountTest::run(int) } } #if BUILD_WITH_VIDEO_INPUT_SUPPORT && defined HAVE_FFMPEG -TEST(Highgui_Video, framecount) {CV_FramecountTest test; test.safe_run();} +TEST(Videoio_Video, framecount) {CV_FramecountTest test; test.safe_run();} #endif diff --git a/modules/videoio/test/test_main.cpp b/modules/videoio/test/test_main.cpp new file mode 100644 index 0000000000..3ef2a376ea --- /dev/null +++ b/modules/videoio/test/test_main.cpp @@ -0,0 +1,3 @@ +#include "test_precomp.hpp" + +CV_TEST_MAIN("videoio") diff --git a/modules/highgui/test/test_positioning.cpp b/modules/videoio/test/test_positioning.cpp similarity index 97% rename from modules/highgui/test/test_positioning.cpp rename to modules/videoio/test/test_positioning.cpp index 993a76cb43..398a160a25 100644 --- a/modules/highgui/test/test_positioning.cpp +++ b/modules/videoio/test/test_positioning.cpp @@ -41,7 +41,7 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui/highgui_c.h" +#include "opencv2/videoio/videoio_c.h" #include using namespace cv; @@ -218,6 +218,6 @@ void CV_VideoRandomPositioningTest::run(int) } #if BUILD_WITH_VIDEO_INPUT_SUPPORT && defined HAVE_FFMPEG -TEST (Highgui_Video, seek_progressive) { CV_VideoProgressivePositioningTest test; test.safe_run(); } -TEST (Highgui_Video, seek_random) { CV_VideoRandomPositioningTest test; test.safe_run(); } +TEST (Videoio_Video, seek_progressive) { CV_VideoProgressivePositioningTest test; test.safe_run(); } +TEST (Videoio_Video, seek_random) { CV_VideoRandomPositioningTest test; test.safe_run(); } #endif diff --git a/modules/videoio/test/test_precomp.hpp b/modules/videoio/test/test_precomp.hpp new file mode 100644 index 0000000000..0dd9caa819 --- /dev/null +++ b/modules/videoio/test/test_precomp.hpp @@ -0,0 +1,91 @@ +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-declarations" +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic ignored "-Wmissing-prototypes" +# pragma GCC diagnostic ignored "-Wextra" +# endif +#endif + +#ifndef __OPENCV_TEST_PRECOMP_HPP__ +#define __OPENCV_TEST_PRECOMP_HPP__ + +#include +#include "opencv2/ts.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" +#include "opencv2/imgproc/imgproc_c.h" + +#include "opencv2/core/private.hpp" + +#if defined(HAVE_DSHOW) || \ + defined(HAVE_TYZX) || \ + defined(HAVE_VFW) || \ + defined(HAVE_LIBV4L) || \ + (defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)) || \ + defined(HAVE_GSTREAMER) || \ + defined(HAVE_DC1394_2) || \ + defined(HAVE_DC1394) || \ + defined(HAVE_CMU1394) || \ + defined(HAVE_MIL) || \ + defined(HAVE_QUICKTIME) || \ + defined(HAVE_QTKIT) || \ + defined(HAVE_UNICAP) || \ + defined(HAVE_PVAPI) || \ + defined(HAVE_OPENNI) || \ + defined(HAVE_XIMEA) || \ + defined(HAVE_AVFOUNDATION) || \ + defined(HAVE_GIGE_API) || \ + defined(HAVE_INTELPERC) || \ + (0) + //defined(HAVE_ANDROID_NATIVE_CAMERA) || - enable after #1193 +# define BUILD_WITH_CAMERA_SUPPORT 1 +#else +# define BUILD_WITH_CAMERA_SUPPORT 0 +#endif + +#if defined(HAVE_XINE) || \ + defined(HAVE_GSTREAMER) || \ + defined(HAVE_QUICKTIME) || \ + defined(HAVE_QTKIT) || \ + defined(HAVE_AVFOUNDATION) || \ + /*defined(HAVE_OPENNI) || too specialized */ \ + defined(HAVE_FFMPEG) || \ + defined(HAVE_MSMF) +# define BUILD_WITH_VIDEO_INPUT_SUPPORT 1 +#else +# define BUILD_WITH_VIDEO_INPUT_SUPPORT 0 +#endif + +#if /*defined(HAVE_XINE) || */\ + defined(HAVE_GSTREAMER) || \ + defined(HAVE_QUICKTIME) || \ + defined(HAVE_QTKIT) || \ + defined(HAVE_AVFOUNDATION) || \ + defined(HAVE_FFMPEG) || \ + defined(HAVE_MSMF) +# define BUILD_WITH_VIDEO_OUTPUT_SUPPORT 1 +#else +# define BUILD_WITH_VIDEO_OUTPUT_SUPPORT 0 +#endif + +namespace cvtest +{ + +string fourccToString(int fourcc); + +struct VideoFormat +{ + VideoFormat() { fourcc = -1; } + VideoFormat(const string& _ext, int _fourcc) : ext(_ext), fourcc(_fourcc) {} + bool empty() const { return ext.empty(); } + + string ext; + int fourcc; +}; + +extern const VideoFormat g_specific_fmt_list[]; + +} + +#endif diff --git a/modules/highgui/test/test_video_io.cpp b/modules/videoio/test/test_video_io.cpp similarity index 95% rename from modules/highgui/test/test_video_io.cpp rename to modules/videoio/test/test_video_io.cpp index f380e0d26b..b3d13e7c2f 100644 --- a/modules/highgui/test/test_video_io.cpp +++ b/modules/videoio/test/test_video_io.cpp @@ -41,7 +41,7 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui/highgui_c.h" +#include "opencv2/videoio/videoio_c.h" using namespace cv; using namespace std; @@ -99,7 +99,7 @@ const VideoFormat g_specific_fmt_list[] = } -class CV_HighGuiTest : public cvtest::BaseTest +class CV_VideoIOTest : public cvtest::BaseTest { protected: void ImageTest (const string& dir); @@ -107,12 +107,12 @@ protected: void SpecificImageTest (const string& dir); void SpecificVideoTest (const string& dir, const cvtest::VideoFormat& fmt); - CV_HighGuiTest() {} - ~CV_HighGuiTest() {} + CV_VideoIOTest() {} + ~CV_VideoIOTest() {} virtual void run(int) = 0; }; -class CV_ImageTest : public CV_HighGuiTest +class CV_ImageTest : public CV_VideoIOTest { public: CV_ImageTest() {} @@ -120,7 +120,7 @@ public: void run(int); }; -class CV_SpecificImageTest : public CV_HighGuiTest +class CV_SpecificImageTest : public CV_VideoIOTest { public: CV_SpecificImageTest() {} @@ -128,7 +128,7 @@ public: void run(int); }; -class CV_VideoTest : public CV_HighGuiTest +class CV_VideoTest : public CV_VideoIOTest { public: CV_VideoTest() {} @@ -136,7 +136,7 @@ public: void run(int); }; -class CV_SpecificVideoTest : public CV_HighGuiTest +class CV_SpecificVideoTest : public CV_VideoIOTest { public: CV_SpecificVideoTest() {} @@ -145,7 +145,7 @@ public: }; -void CV_HighGuiTest::ImageTest(const string& dir) +void CV_VideoIOTest::ImageTest(const string& dir) { string _name = dir + string("../cv/shared/baboon.png"); ts->printf(ts->LOG, "reading image : %s\n", _name.c_str()); @@ -251,7 +251,7 @@ void CV_HighGuiTest::ImageTest(const string& dir) } -void CV_HighGuiTest::VideoTest(const string& dir, const cvtest::VideoFormat& fmt) +void CV_VideoIOTest::VideoTest(const string& dir, const cvtest::VideoFormat& fmt) { string src_file = dir + "../cv/shared/video_for_test.avi"; string tmp_name = cv::tempfile((cvtest::fourccToString(fmt.fourcc) + "." + fmt.ext).c_str()); @@ -337,7 +337,7 @@ void CV_HighGuiTest::VideoTest(const string& dir, const cvtest::VideoFormat& fmt ts->printf(ts->LOG, "end test function : ImagesVideo \n"); } -void CV_HighGuiTest::SpecificImageTest(const string& dir) +void CV_VideoIOTest::SpecificImageTest(const string& dir) { const size_t IMAGE_COUNT = 10; @@ -423,7 +423,7 @@ void CV_HighGuiTest::SpecificImageTest(const string& dir) } -void CV_HighGuiTest::SpecificVideoTest(const string& dir, const cvtest::VideoFormat& fmt) +void CV_VideoIOTest::SpecificVideoTest(const string& dir, const cvtest::VideoFormat& fmt) { string ext = fmt.ext; int fourcc = fmt.fourcc; @@ -568,12 +568,12 @@ void CV_SpecificVideoTest::run(int) } #ifdef HAVE_JPEG -TEST(Highgui_Image, regression) { CV_ImageTest test; test.safe_run(); } +TEST(Videoio_Image, regression) { CV_ImageTest test; test.safe_run(); } #endif #if BUILD_WITH_VIDEO_INPUT_SUPPORT && BUILD_WITH_VIDEO_OUTPUT_SUPPORT && !defined(__APPLE__) -TEST(Highgui_Video, regression) { CV_VideoTest test; test.safe_run(); } -TEST(Highgui_Video, write_read) { CV_SpecificVideoTest test; test.safe_run(); } +TEST(Videoio_Video, regression) { CV_VideoTest test; test.safe_run(); } +TEST(Videoio_Video, write_read) { CV_SpecificVideoTest test; test.safe_run(); } #endif -TEST(Highgui_Image, write_read) { CV_SpecificImageTest test; test.safe_run(); } +TEST(Videoio_Image, write_read) { CV_SpecificImageTest test; test.safe_run(); } diff --git a/modules/highgui/test/test_video_pos.cpp b/modules/videoio/test/test_video_pos.cpp similarity index 93% rename from modules/highgui/test/test_video_pos.cpp rename to modules/videoio/test/test_video_pos.cpp index c8fe4050da..cd21bc2e23 100644 --- a/modules/highgui/test/test_video_pos.cpp +++ b/modules/videoio/test/test_video_pos.cpp @@ -41,7 +41,7 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/highgui.hpp" +#include "opencv2/videoio.hpp" using namespace cv; using namespace std; @@ -114,7 +114,7 @@ public: cap.set(CAP_PROP_POS_FRAMES, 0); int N = (int)cap.get(CAP_PROP_FRAME_COUNT); - // See the same hack in CV_HighGuiTest::SpecificVideoTest for explanation. + // See the same hack in CV_VideoIOTest::SpecificVideoTest for explanation. int allowed_extra_frames = 0; if (fmt.fourcc == VideoWriter::fourcc('M', 'P', 'E', 'G') && fmt.ext == "mkv") allowed_extra_frames = 1; @@ -148,8 +148,6 @@ public: idx1, idx); ts->printf(ts->LOG, "Saving both frames ...\n"); ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT); - // imwrite("opencv_test_highgui_postest_actual.png", img); - // imwrite("opencv_test_highgui_postest_expected.png", img0); return; } @@ -167,8 +165,6 @@ public: ts->printf(ts->LOG, "The frame read after positioning to %d is incorrect (PSNR=%g)\n", idx, err); ts->printf(ts->LOG, "Saving both frames ...\n"); ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT); - // imwrite("opencv_test_highgui_postest_actual.png", img); - // imwrite("opencv_test_highgui_postest_expected.png", img0); return; } } @@ -179,5 +175,5 @@ public: }; #if BUILD_WITH_VIDEO_INPUT_SUPPORT && BUILD_WITH_VIDEO_OUTPUT_SUPPORT && defined HAVE_FFMPEG -TEST(Highgui_Video, seek_random_synthetic) { CV_PositioningTest test; test.safe_run(); } +TEST(Videoio_Video, seek_random_synthetic) { CV_PositioningTest test; test.safe_run(); } #endif diff --git a/modules/videostab/CMakeLists.txt b/modules/videostab/CMakeLists.txt index de82e22239..e252bdbf53 100644 --- a/modules/videostab/CMakeLists.txt +++ b/modules/videostab/CMakeLists.txt @@ -1,3 +1,3 @@ set(the_description "Video stabilization") ocv_define_module(videostab opencv_imgproc opencv_features2d opencv_video opencv_photo opencv_calib3d - OPTIONAL opencv_cuda opencv_cudawarping opencv_cudaoptflow opencv_highgui) + OPTIONAL opencv_cuda opencv_cudawarping opencv_cudaoptflow opencv_videoio) diff --git a/modules/videostab/src/frame_source.cpp b/modules/videostab/src/frame_source.cpp index 7ca4b73de7..9db9d52a05 100644 --- a/modules/videostab/src/frame_source.cpp +++ b/modules/videostab/src/frame_source.cpp @@ -45,8 +45,8 @@ #include "opencv2/videostab/ring_buffer.hpp" #include "opencv2/opencv_modules.hpp" -#ifdef HAVE_OPENCV_HIGHGUI -# include "opencv2/highgui.hpp" +#ifdef HAVE_OPENCV_VIDEOIO +# include "opencv2/videoio.hpp" #endif namespace cv @@ -64,7 +64,7 @@ public: virtual void reset() { -#ifdef HAVE_OPENCV_HIGHGUI +#ifdef HAVE_OPENCV_VIDEOIO vc.release(); vc.open(path_); if (!vc.isOpened()) @@ -77,13 +77,13 @@ public: virtual Mat nextFrame() { Mat frame; -#ifdef HAVE_OPENCV_HIGHGUI +#ifdef HAVE_OPENCV_VIDEOIO vc >> frame; #endif return volatileFrame_ ? frame : frame.clone(); } -#ifdef HAVE_OPENCV_HIGHGUI +#ifdef HAVE_OPENCV_VIDEOIO int width() {return static_cast(vc.get(CAP_PROP_FRAME_WIDTH));} int height() {return static_cast(vc.get(CAP_PROP_FRAME_HEIGHT));} int count() {return static_cast(vc.get(CAP_PROP_FRAME_COUNT));} @@ -98,7 +98,7 @@ public: private: String path_; bool volatileFrame_; -#ifdef HAVE_OPENCV_HIGHGUI +#ifdef HAVE_OPENCV_VIDEOIO VideoCapture vc; #endif }; diff --git a/samples/android/CMakeLists.txt b/samples/android/CMakeLists.txt index b82c297a67..1ca60fbb91 100644 --- a/samples/android/CMakeLists.txt +++ b/samples/android/CMakeLists.txt @@ -19,9 +19,9 @@ add_subdirectory(native-activity) # hello-android sample if(HAVE_opencv_highgui) - ocv_include_modules_recurse(opencv_imgcodecs opencv_highgui opencv_core) + ocv_include_modules_recurse(opencv_imgcodecs opencv_videoio opencv_highgui opencv_core) add_executable(hello-android hello-android/main.cpp) - target_link_libraries(hello-android ${OPENCV_LINKER_LIBS} opencv_imgcodecs opencv_highgui opencv_core) + target_link_libraries(hello-android ${OPENCV_LINKER_LIBS} opencv_imgcodecs opencv_videoio opencv_highgui opencv_core) set_target_properties(hello-android PROPERTIES OUTPUT_NAME hello-android RUNTIME_OUTPUT_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") add_dependencies(opencv_android_examples hello-android) endif() diff --git a/samples/cpp/CMakeLists.txt b/samples/cpp/CMakeLists.txt index 732df786b5..f22483cf6e 100644 --- a/samples/cpp/CMakeLists.txt +++ b/samples/cpp/CMakeLists.txt @@ -4,8 +4,9 @@ # ---------------------------------------------------------------------------- SET(OPENCV_CPP_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_flann - opencv_imgcodecs opencv_highgui opencv_ml opencv_video opencv_objdetect opencv_photo opencv_nonfree - opencv_features2d opencv_calib3d opencv_stitching opencv_videostab opencv_shape) + opencv_imgcodecs opencv_videoio opencv_highgui opencv_ml opencv_video + opencv_objdetect opencv_photo opencv_nonfree opencv_features2d opencv_calib3d + opencv_stitching opencv_videostab opencv_shape) ocv_check_dependencies(${OPENCV_CPP_SAMPLES_REQUIRED_DEPS}) diff --git a/samples/cpp/bgfg_gmg.cpp b/samples/cpp/bgfg_gmg.cpp index 226eea4635..a70bec9ee0 100644 --- a/samples/cpp/bgfg_gmg.cpp +++ b/samples/cpp/bgfg_gmg.cpp @@ -6,6 +6,7 @@ */ #include "opencv2/video.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include #include diff --git a/samples/cpp/bgfg_segm.cpp b/samples/cpp/bgfg_segm.cpp index a3d02009a7..31c7da05f7 100644 --- a/samples/cpp/bgfg_segm.cpp +++ b/samples/cpp/bgfg_segm.cpp @@ -2,6 +2,7 @@ #include #include "opencv2/imgproc.hpp" #include "opencv2/video/background_segm.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/calibration.cpp b/samples/cpp/calibration.cpp index ffd665fa8c..9a71715b3d 100644 --- a/samples/cpp/calibration.cpp +++ b/samples/cpp/calibration.cpp @@ -3,6 +3,7 @@ #include "opencv2/imgproc.hpp" #include "opencv2/calib3d.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/camshiftdemo.cpp b/samples/cpp/camshiftdemo.cpp index 6439cef78e..6400f1ec7d 100644 --- a/samples/cpp/camshiftdemo.cpp +++ b/samples/cpp/camshiftdemo.cpp @@ -1,6 +1,7 @@ #include #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/dbt_face_detection.cpp b/samples/cpp/dbt_face_detection.cpp index a66b90282d..d7409bf5b5 100644 --- a/samples/cpp/dbt_face_detection.cpp +++ b/samples/cpp/dbt_face_detection.cpp @@ -2,6 +2,7 @@ #include // Gaussian Blur #include // Basic OpenCV structures (cv::Mat, Scalar) +#include #include // OpenCV window I/O #include #include diff --git a/samples/cpp/facedetect.cpp b/samples/cpp/facedetect.cpp index 80b57b2c87..0c747d394b 100644 --- a/samples/cpp/facedetect.cpp +++ b/samples/cpp/facedetect.cpp @@ -1,9 +1,11 @@ #include "opencv2/objdetect.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/core/utility.hpp" +#include "opencv2/videoio/videoio_c.h" #include "opencv2/highgui/highgui_c.h" #include diff --git a/samples/cpp/fback.cpp b/samples/cpp/fback.cpp index 5293fd1f7f..476cfe6548 100644 --- a/samples/cpp/fback.cpp +++ b/samples/cpp/fback.cpp @@ -1,5 +1,6 @@ #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/ffilldemo.cpp b/samples/cpp/ffilldemo.cpp index 251f2a06a1..46d08186a3 100644 --- a/samples/cpp/ffilldemo.cpp +++ b/samples/cpp/ffilldemo.cpp @@ -1,5 +1,6 @@ #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/image_sequence.cpp b/samples/cpp/image_sequence.cpp index a68017d56f..b87b3043e2 100644 --- a/samples/cpp/image_sequence.cpp +++ b/samples/cpp/image_sequence.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/samples/cpp/intelperc_capture.cpp b/samples/cpp/intelperc_capture.cpp index 40349e0fbf..5726ccdf4f 100644 --- a/samples/cpp/intelperc_capture.cpp +++ b/samples/cpp/intelperc_capture.cpp @@ -1,6 +1,7 @@ // testOpenCVCam.cpp : Defines the entry point for the console application. // +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/laplace.cpp b/samples/cpp/laplace.cpp index 45264e3107..bac432ca50 100644 --- a/samples/cpp/laplace.cpp +++ b/samples/cpp/laplace.cpp @@ -1,3 +1,4 @@ +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" diff --git a/samples/cpp/linemod.cpp b/samples/cpp/linemod.cpp index 4d11da36b5..f13bac2196 100644 --- a/samples/cpp/linemod.cpp +++ b/samples/cpp/linemod.cpp @@ -3,6 +3,7 @@ #include // cvFindContours #include #include +#include #include #include #include diff --git a/samples/cpp/lkdemo.cpp b/samples/cpp/lkdemo.cpp index c665cfdfe2..82c1fac2d0 100644 --- a/samples/cpp/lkdemo.cpp +++ b/samples/cpp/lkdemo.cpp @@ -1,5 +1,6 @@ #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/cpp/motempl.cpp b/samples/cpp/motempl.cpp index 76b69ade7b..66449981e7 100644 --- a/samples/cpp/motempl.cpp +++ b/samples/cpp/motempl.cpp @@ -1,5 +1,6 @@ #include "opencv2/video/tracking_c.h" #include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/videoio/videoio_c.h" #include "opencv2/highgui/highgui_c.h" #include #include diff --git a/samples/cpp/openni_capture.cpp b/samples/cpp/openni_capture.cpp index 802b474207..76b092298a 100644 --- a/samples/cpp/openni_capture.cpp +++ b/samples/cpp/openni_capture.cpp @@ -1,3 +1,4 @@ +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" diff --git a/samples/cpp/phase_corr.cpp b/samples/cpp/phase_corr.cpp index cfee809412..5e8685fcfa 100644 --- a/samples/cpp/phase_corr.cpp +++ b/samples/cpp/phase_corr.cpp @@ -1,4 +1,5 @@ #include "opencv2/core/core.hpp" +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" diff --git a/samples/cpp/polar_transforms.cpp b/samples/cpp/polar_transforms.cpp index 8ce4831637..3e2810e74b 100644 --- a/samples/cpp/polar_transforms.cpp +++ b/samples/cpp/polar_transforms.cpp @@ -1,4 +1,5 @@ #include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/videoio/videoio_c.h" #include "opencv2/highgui/highgui_c.h" #include diff --git a/samples/cpp/segment_objects.cpp b/samples/cpp/segment_objects.cpp index 852fa15be8..32c1f39768 100644 --- a/samples/cpp/segment_objects.cpp +++ b/samples/cpp/segment_objects.cpp @@ -1,4 +1,5 @@ #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/video/background_segm.hpp" #include diff --git a/samples/cpp/select3dobj.cpp b/samples/cpp/select3dobj.cpp index c0c526e178..7df95d17c5 100644 --- a/samples/cpp/select3dobj.cpp +++ b/samples/cpp/select3dobj.cpp @@ -13,6 +13,7 @@ #include "opencv2/imgproc.hpp" #include "opencv2/calib3d.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/smiledetect.cpp b/samples/cpp/smiledetect.cpp index 61f990cd2d..305cdad8d7 100644 --- a/samples/cpp/smiledetect.cpp +++ b/samples/cpp/smiledetect.cpp @@ -3,6 +3,7 @@ #include "opencv2/imgproc.hpp" #include "opencv2/core/utility.hpp" +#include "opencv2/videoio/videoio_c.h" #include "opencv2/highgui/highgui_c.h" #include diff --git a/samples/cpp/starter_video.cpp b/samples/cpp/starter_video.cpp index 3cc4467a81..34f23d376c 100644 --- a/samples/cpp/starter_video.cpp +++ b/samples/cpp/starter_video.cpp @@ -12,6 +12,7 @@ */ #include +#include #include #include diff --git a/samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video-input-psnr-ssim.cpp b/samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video-input-psnr-ssim.cpp index bee1c5b200..4c5bf9f586 100644 --- a/samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video-input-psnr-ssim.cpp +++ b/samples/cpp/tutorial_code/HighGUI/video-input-psnr-ssim/video-input-psnr-ssim.cpp @@ -5,6 +5,7 @@ #include // Basic OpenCV structures (cv::Mat, Scalar) #include // Gaussian Blur +#include #include // OpenCV window I/O using namespace std; diff --git a/samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp b/samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp index d3b8e44303..9218cf2d31 100644 --- a/samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp +++ b/samples/cpp/tutorial_code/HighGUI/video-write/video-write.cpp @@ -2,7 +2,7 @@ #include // for strings #include // Basic OpenCV structures (cv::Mat) -#include // Video write +#include // Video write using namespace std; using namespace cv; diff --git a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp index 4cd9a85d84..34e2504c6e 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp @@ -7,7 +7,8 @@ #include #include #include -#include "opencv2/imgcodecs.hpp" +#include +#include #include #ifndef _CRT_SECURE_NO_WARNINGS diff --git a/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp b/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp index e7dc3e98fc..fbd76e4f08 100644 --- a/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp +++ b/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp @@ -1,4 +1,5 @@ #include "opencv2/objdetect.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" diff --git a/samples/cpp/tutorial_code/objectDetection/objectDetection2.cpp b/samples/cpp/tutorial_code/objectDetection/objectDetection2.cpp index 3264858398..d28fa2bba6 100644 --- a/samples/cpp/tutorial_code/objectDetection/objectDetection2.cpp +++ b/samples/cpp/tutorial_code/objectDetection/objectDetection2.cpp @@ -4,6 +4,7 @@ * @brief A simplified version of facedetect.cpp, show how to load a cascade classifier and how to find objects (Face + eyes) in a video stream - Using LBP here */ #include "opencv2/objdetect.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" diff --git a/samples/cpp/tutorial_code/video/bg_sub.cpp b/samples/cpp/tutorial_code/video/bg_sub.cpp index 6faa020b80..ace8220587 100644 --- a/samples/cpp/tutorial_code/video/bg_sub.cpp +++ b/samples/cpp/tutorial_code/video/bg_sub.cpp @@ -6,6 +6,7 @@ //opencv #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include #include //C diff --git a/samples/cpp/ufacedetect.cpp b/samples/cpp/ufacedetect.cpp index e7e85d5633..a4a027157a 100644 --- a/samples/cpp/ufacedetect.cpp +++ b/samples/cpp/ufacedetect.cpp @@ -1,5 +1,6 @@ #include "opencv2/objdetect.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/core/utility.hpp" diff --git a/samples/cpp/video_homography.cpp b/samples/cpp/video_homography.cpp index cefdc891ab..1b12fa04d9 100644 --- a/samples/cpp/video_homography.cpp +++ b/samples/cpp/video_homography.cpp @@ -6,6 +6,7 @@ */ #include "opencv2/calib3d/calib3d.hpp" +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/features2d/features2d.hpp" diff --git a/samples/cpp/videostab.cpp b/samples/cpp/videostab.cpp index 675d483f3d..261badd45f 100644 --- a/samples/cpp/videostab.cpp +++ b/samples/cpp/videostab.cpp @@ -7,6 +7,7 @@ #include #include "opencv2/video.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/videostab.hpp" #include "opencv2/opencv_modules.hpp" diff --git a/samples/java/clojure/simple-sample/src/simple_sample/core.clj b/samples/java/clojure/simple-sample/src/simple_sample/core.clj index 86a1b31130..fa25727b92 100644 --- a/samples/java/clojure/simple-sample/src/simple_sample/core.clj +++ b/samples/java/clojure/simple-sample/src/simple_sample/core.clj @@ -4,13 +4,13 @@ (ns simple-sample.core (:import [org.opencv.core Point Rect Mat CvType Size Scalar] - org.opencv.highgui.Highgui + org.opencv.imgcodecs.Imgcodecs org.opencv.imgproc.Imgproc)) (defn -main [& args] - (let [lena (Highgui/imread "resources/images/lena.png") + (let [lena (Imgcodecs/imread "resources/images/lena.png") blurred (Mat. 512 512 CvType/CV_8UC3)] (print "Blurring...") (Imgproc/GaussianBlur lena blurred (Size. 5 5) 3 3) - (Highgui/imwrite "resources/images/blurred.png" blurred) + (Imgcodecs/imwrite "resources/images/blurred.png" blurred) (println "done!"))) diff --git a/samples/java/sbt/src/main/java/DetectFaceDemo.java b/samples/java/sbt/src/main/java/DetectFaceDemo.java index 07b4202e6a..686df02f93 100644 --- a/samples/java/sbt/src/main/java/DetectFaceDemo.java +++ b/samples/java/sbt/src/main/java/DetectFaceDemo.java @@ -4,7 +4,7 @@ import org.opencv.core.MatOfRect; import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Scalar; -import org.opencv.highgui.Highgui; +import org.opencv.imgcodecs.Imgcodecs; import org.opencv.objdetect.CascadeClassifier; /* @@ -19,7 +19,7 @@ public class DetectFaceDemo { // directory. CascadeClassifier faceDetector = new CascadeClassifier(getClass() .getResource("/lbpcascade_frontalface.xml").getPath()); - Mat image = Highgui.imread(getClass().getResource( + Mat image = Imgcodecs.imread(getClass().getResource( "/AverageMaleFace.jpg").getPath()); // Detect faces in the image. @@ -39,6 +39,6 @@ public class DetectFaceDemo { // Save the visualized detection. String filename = "faceDetection.png"; System.out.println(String.format("Writing %s", filename)); - Highgui.imwrite(filename, image); + Imgcodecs.imwrite(filename, image); } } diff --git a/samples/java/sbt/src/main/scala/ScalaCorrespondenceMatchingDemo.scala b/samples/java/sbt/src/main/scala/ScalaCorrespondenceMatchingDemo.scala index ea50200c9a..e8259827a3 100644 --- a/samples/java/sbt/src/main/scala/ScalaCorrespondenceMatchingDemo.scala +++ b/samples/java/sbt/src/main/scala/ScalaCorrespondenceMatchingDemo.scala @@ -1,4 +1,4 @@ -import org.opencv.highgui.Highgui +import org.opencv.imgcodecs.Imgcodecs import org.opencv.features2d.DescriptorExtractor import org.opencv.features2d.Features2d import org.opencv.core.MatOfKeyPoint @@ -45,8 +45,8 @@ object ScalaCorrespondenceMatchingDemo { } // Load the images from the |resources| directory. - val leftImage = Highgui.imread(getClass.getResource("/img1.png").getPath) - val rightImage = Highgui.imread(getClass.getResource("/img2.png").getPath) + val leftImage = Imgcodecs.imread(getClass.getResource("/img1.png").getPath) + val rightImage = Imgcodecs.imread(getClass.getResource("/img2.png").getPath) // Detect KeyPoints and extract descriptors. val (leftKeyPoints, leftDescriptors) = detectAndExtract(leftImage) @@ -64,6 +64,6 @@ object ScalaCorrespondenceMatchingDemo { Features2d.drawMatches(leftImage, leftKeyPoints, rightImage, rightKeyPoints, dmatches, correspondenceImage) val filename = "scalaCorrespondences.png" println(s"Writing ${filename}") - assert(Highgui.imwrite(filename, correspondenceImage)) + assert(Imgcodecs.imwrite(filename, correspondenceImage)) } } diff --git a/samples/java/sbt/src/main/scala/ScalaDetectFaceDemo.scala b/samples/java/sbt/src/main/scala/ScalaDetectFaceDemo.scala index 85fdeb0d7f..479a7ec7fb 100644 --- a/samples/java/sbt/src/main/scala/ScalaDetectFaceDemo.scala +++ b/samples/java/sbt/src/main/scala/ScalaDetectFaceDemo.scala @@ -2,7 +2,7 @@ import org.opencv.core.Core import org.opencv.core.MatOfRect import org.opencv.core.Point import org.opencv.core.Scalar -import org.opencv.highgui.Highgui +import org.opencv.imgcodecs.Imgcodecs import org.opencv.objdetect.CascadeClassifier import reflect._ @@ -16,7 +16,7 @@ object ScalaDetectFaceDemo { // Create a face detector from the cascade file in the resources directory. val faceDetector = new CascadeClassifier(getClass.getResource("/lbpcascade_frontalface.xml").getPath) - val image = Highgui.imread(getClass.getResource("/AverageMaleFace.jpg").getPath) + val image = Imgcodecs.imread(getClass.getResource("/AverageMaleFace.jpg").getPath) // Detect faces in the image. // MatOfRect is a special container class for Rect. @@ -38,6 +38,6 @@ object ScalaDetectFaceDemo { // Save the visualized detection. val filename = "scalaFaceDetection.png" println(s"Writing ${filename}") - assert(Highgui.imwrite(filename, image)) + assert(Imgcodecs.imwrite(filename, image)) } } diff --git a/samples/tapi/CMakeLists.txt b/samples/tapi/CMakeLists.txt index 25436bb710..cf88f3a98f 100644 --- a/samples/tapi/CMakeLists.txt +++ b/samples/tapi/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(OPENCV_TAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_video opencv_imgcodecs opencv_highgui opencv_objdetect opencv_features2d opencv_calib3d opencv_nonfree opencv_flann) +SET(OPENCV_TAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_video opencv_imgcodecs opencv_videoio opencv_highgui opencv_objdetect opencv_features2d opencv_calib3d opencv_nonfree opencv_flann) ocv_check_dependencies(${OPENCV_TAPI_SAMPLES_REQUIRED_DEPS}) diff --git a/samples/tapi/bgfg_segm.cpp b/samples/tapi/bgfg_segm.cpp index 2fa12bba9d..b9facd6324 100644 --- a/samples/tapi/bgfg_segm.cpp +++ b/samples/tapi/bgfg_segm.cpp @@ -4,6 +4,7 @@ #include "opencv2/core.hpp" #include "opencv2/core/ocl.hpp" #include "opencv2/core/utility.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/video.hpp" diff --git a/samples/tapi/camshift.cpp b/samples/tapi/camshift.cpp index 22c65bf698..c0f1d8fb69 100644 --- a/samples/tapi/camshift.cpp +++ b/samples/tapi/camshift.cpp @@ -2,6 +2,7 @@ #include "opencv2/core/ocl.hpp" #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/videoio/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include diff --git a/samples/tapi/clahe.cpp b/samples/tapi/clahe.cpp index 9f9404d35d..905ea1f1ae 100644 --- a/samples/tapi/clahe.cpp +++ b/samples/tapi/clahe.cpp @@ -4,6 +4,7 @@ #include "opencv2/core/utility.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui/highgui.hpp" using namespace cv; diff --git a/samples/tapi/hog.cpp b/samples/tapi/hog.cpp index ac227fc0c9..389e1e5bef 100644 --- a/samples/tapi/hog.cpp +++ b/samples/tapi/hog.cpp @@ -7,6 +7,8 @@ #include #include #include "opencv2/imgcodecs.hpp" +#include +#include #include #include #include diff --git a/samples/tapi/pyrlk_optical_flow.cpp b/samples/tapi/pyrlk_optical_flow.cpp index cc48374a6e..9cdbd7c5bf 100644 --- a/samples/tapi/pyrlk_optical_flow.cpp +++ b/samples/tapi/pyrlk_optical_flow.cpp @@ -4,7 +4,8 @@ #include "opencv2/core/utility.hpp" #include "opencv2/imgcodecs.hpp" -#include "opencv2/highgui/highgui.hpp" +#include "opencv2/videoio.hpp" +#include "opencv2/highgui.hpp" #include "opencv2/core/ocl.hpp" #include "opencv2/video/video.hpp" diff --git a/samples/tapi/tvl1_optical_flow.cpp b/samples/tapi/tvl1_optical_flow.cpp index b37c5bb764..f7bebacbeb 100644 --- a/samples/tapi/tvl1_optical_flow.cpp +++ b/samples/tapi/tvl1_optical_flow.cpp @@ -5,6 +5,7 @@ #include "opencv2/core/ocl.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/video/video.hpp" From ca307669d468b3846ade6e762c39f73f90504230 Mon Sep 17 00:00:00 2001 From: VBystricky Date: Mon, 14 Jul 2014 23:30:50 +0400 Subject: [PATCH 061/136] Refresh code. Fix merge conflict --- modules/videoio/CMakeLists.txt | 1 + modules/{highgui => videoio}/src/cap_dshow.hpp | 0 2 files changed, 1 insertion(+) rename modules/{highgui => videoio}/src/cap_dshow.hpp (100%) diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index 527662b9da..2ac7811c75 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -35,6 +35,7 @@ endif() if (WIN32 AND HAVE_DSHOW) list(APPEND videoio_srcs src/cap_dshow.cpp) + list(APPEND videoio_hdrs src/cap_dshow.hpp) endif() if (WIN32 AND HAVE_MSMF) diff --git a/modules/highgui/src/cap_dshow.hpp b/modules/videoio/src/cap_dshow.hpp similarity index 100% rename from modules/highgui/src/cap_dshow.hpp rename to modules/videoio/src/cap_dshow.hpp From 7171431e7c6095e3a59bbea49d15e8f58f0e6c23 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 15 Jul 2014 12:32:53 +0800 Subject: [PATCH 062/136] Changed cv::log to std::log --- modules/imgproc/src/histogram.cpp | 4 ++-- modules/imgproc/test/test_histograms.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 97ca3deda5..909601fd22 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -2335,7 +2335,7 @@ double cv::compareHist( InputArray _H1, InputArray _H2, int method ) if( fabs(q) <= DBL_EPSILON ) { q = 1e-10; } - result += p * cv::log( p / q ); + result += p * std::log( p / q ); } } else @@ -2462,7 +2462,7 @@ double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method ) double v2 = PH2->value(node->idx, (size_t*)&node->hashval); if( !v2 ) v2 = 1e-10; - result += v1 * cv::log( v1 / v2 ); + result += v1 * std::log( v1 / v2 ); } } else diff --git a/modules/imgproc/test/test_histograms.cpp b/modules/imgproc/test/test_histograms.cpp index 51c3aab985..e9db6fcde0 100644 --- a/modules/imgproc/test/test_histograms.cpp +++ b/modules/imgproc/test/test_histograms.cpp @@ -1058,7 +1058,7 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ ) continue; if (!v1) v1 = 1e-10; - result0[CV_COMP_KL_DIV] += v0 * cv::log( v0 / v1 ); + result0[CV_COMP_KL_DIV] += v0 * std::log( v0 / v1 ); } } From 7a77cf584a64a5a929c1928bc2da3e442d2be083 Mon Sep 17 00:00:00 2001 From: Petr Glotov Date: Fri, 16 May 2014 22:52:07 -0700 Subject: [PATCH 063/136] added timelapse --- .../opencv2/stitching/detail/matchers.hpp | 14 +++ .../opencv2/stitching/detail/timelapsers.hpp | 86 ++++++++++++++ .../include/opencv2/stitching/detail/util.hpp | 1 + modules/stitching/src/matchers.cpp | 34 ++++++ modules/stitching/src/precomp.hpp | 1 + modules/stitching/src/timelapsers.cpp | 107 ++++++++++++++++++ modules/stitching/src/util.cpp | 15 +++ samples/cpp/stitching_detailed.cpp | 74 ++++++++++-- 8 files changed, 322 insertions(+), 10 deletions(-) create mode 100644 modules/stitching/include/opencv2/stitching/detail/timelapsers.hpp create mode 100644 modules/stitching/src/timelapsers.cpp diff --git a/modules/stitching/include/opencv2/stitching/detail/matchers.hpp b/modules/stitching/include/opencv2/stitching/detail/matchers.hpp index 8c3284a466..d87a1fff44 100644 --- a/modules/stitching/include/opencv2/stitching/detail/matchers.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/matchers.hpp @@ -183,6 +183,20 @@ protected: Ptr impl_; }; +class CV_EXPORTS BestOf2NearestRangeMatcher : public BestOf2NearestMatcher +{ +public: + BestOf2NearestRangeMatcher(int range_width = 5, bool try_use_gpu = false, float match_conf = 0.3f, + int num_matches_thresh1 = 6, int num_matches_thresh2 = 6); + + void operator ()(const std::vector &features, std::vector &pairwise_matches, + const cv::UMat &mask = cv::UMat()); + + +protected: + int range_width_; +}; + } // namespace detail } // namespace cv diff --git a/modules/stitching/include/opencv2/stitching/detail/timelapsers.hpp b/modules/stitching/include/opencv2/stitching/detail/timelapsers.hpp new file mode 100644 index 0000000000..f881a9b934 --- /dev/null +++ b/modules/stitching/include/opencv2/stitching/detail/timelapsers.hpp @@ -0,0 +1,86 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + +#ifndef __OPENCV_STITCHING_TIMELAPSERS_HPP__ +#define __OPENCV_STITCHING_TIMELAPSERS_HPP__ + +#include "opencv2/core.hpp" + +namespace cv { +namespace detail { + +// Base Timelapser class, takes a sequence of images, applies appropriate shift, stores result in dst_. + +class CV_EXPORTS Timelapser +{ +public: + + enum {AS_IS, CROP}; + + virtual ~Timelapser() {} + + static Ptr createDefault(int type); + + virtual void initialize(const std::vector &corners, const std::vector &sizes); + virtual void process(InputArray img, InputArray mask, Point tl); + virtual const UMat& getDst() {return dst_;} + +protected: + + virtual bool test_point(Point pt); + + UMat dst_; + Rect dst_roi_; +}; + + +class CV_EXPORTS TimelapserCrop : public Timelapser +{ +public: + virtual void initialize(const std::vector &corners, const std::vector &sizes); +}; + +} // namespace detail +} // namespace cv + +#endif // __OPENCV_STITCHING_TIMELAPSERS_HPP__ diff --git a/modules/stitching/include/opencv2/stitching/detail/util.hpp b/modules/stitching/include/opencv2/stitching/detail/util.hpp index 6b1c5f34f3..23c413d5c2 100644 --- a/modules/stitching/include/opencv2/stitching/detail/util.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/util.hpp @@ -148,6 +148,7 @@ private: CV_EXPORTS bool overlapRoi(Point tl1, Point tl2, Size sz1, Size sz2, Rect &roi); CV_EXPORTS Rect resultRoi(const std::vector &corners, const std::vector &images); CV_EXPORTS Rect resultRoi(const std::vector &corners, const std::vector &sizes); +CV_EXPORTS Rect resultRoiIntersection(const std::vector &corners, const std::vector &sizes); CV_EXPORTS Point resultTl(const std::vector &corners); // Returns random 'count' element subset of the {0,1,...,size-1} set diff --git a/modules/stitching/src/matchers.cpp b/modules/stitching/src/matchers.cpp index c303c4aaba..a512e35254 100644 --- a/modules/stitching/src/matchers.cpp +++ b/modules/stitching/src/matchers.cpp @@ -646,5 +646,39 @@ void BestOf2NearestMatcher::collectGarbage() impl_->collectGarbage(); } + +BestOf2NearestRangeMatcher::BestOf2NearestRangeMatcher(int range_width, bool try_use_gpu, float match_conf, int num_matches_thresh1, int num_matches_thresh2): BestOf2NearestMatcher(try_use_gpu, match_conf, num_matches_thresh1, num_matches_thresh2) +{ + range_width_ = range_width; +} + + +void BestOf2NearestRangeMatcher::operator ()(const std::vector &features, std::vector &pairwise_matches, + const UMat &mask) +{ + const int num_images = static_cast(features.size()); + + CV_Assert(mask.empty() || (mask.type() == CV_8U && mask.cols == num_images && mask.rows)); + Mat_ mask_(mask.getMat(ACCESS_READ)); + if (mask_.empty()) + mask_ = Mat::ones(num_images, num_images, CV_8U); + + std::vector > near_pairs; + for (int i = 0; i < num_images - 1; ++i) + for (int j = i + 1; j < std::min(num_images, i + range_width_); ++j) + if (features[i].keypoints.size() > 0 && features[j].keypoints.size() > 0 && mask_(i, j)) + near_pairs.push_back(std::make_pair(i, j)); + + pairwise_matches.resize(num_images * num_images); + MatchPairsBody body(*this, features, pairwise_matches, near_pairs); + + if (is_thread_safe_) + parallel_for_(Range(0, static_cast(near_pairs.size())), body); + else + body(Range(0, static_cast(near_pairs.size()))); + LOGLN_CHAT(""); +} + + } // namespace detail } // namespace cv diff --git a/modules/stitching/src/precomp.hpp b/modules/stitching/src/precomp.hpp index 18ce413094..759d03635d 100644 --- a/modules/stitching/src/precomp.hpp +++ b/modules/stitching/src/precomp.hpp @@ -59,6 +59,7 @@ #include "opencv2/stitching.hpp" #include "opencv2/stitching/detail/autocalib.hpp" #include "opencv2/stitching/detail/blenders.hpp" +#include "opencv2/stitching/detail/timelapsers.hpp" #include "opencv2/stitching/detail/camera.hpp" #include "opencv2/stitching/detail/exposure_compensate.hpp" #include "opencv2/stitching/detail/matchers.hpp" diff --git a/modules/stitching/src/timelapsers.cpp b/modules/stitching/src/timelapsers.cpp new file mode 100644 index 0000000000..d78ad86a57 --- /dev/null +++ b/modules/stitching/src/timelapsers.cpp @@ -0,0 +1,107 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "precomp.hpp" +#include "opencl_kernels.hpp" + +namespace cv { +namespace detail { + +Ptr Timelapser::createDefault(int type) +{ + if (type == AS_IS) + return makePtr(); + if (type == CROP) + return makePtr(); + CV_Error(Error::StsBadArg, "unsupported timelapsing method"); + return Ptr(); +} + + +void Timelapser::initialize(const std::vector &corners, const std::vector &sizes) +{ + dst_roi_ = resultRoi(corners, sizes); + dst_.create(dst_roi_.size(), CV_16SC3); +} + +void Timelapser::process(InputArray _img, InputArray /*_mask*/, Point tl) +{ + dst_.setTo(Scalar::all(0)); + + Mat img = _img.getMat(); + Mat dst = dst_.getMat(ACCESS_RW); + + CV_Assert(img.type() == CV_16SC3); + int dx = tl.x - dst_roi_.x; + int dy = tl.y - dst_roi_.y; + + for (int y = 0; y < img.rows; ++y) + { + const Point3_ *src_row = img.ptr >(y); + + for (int x = 0; x < img.cols; ++x) + { + if (test_point(Point(tl.x + x, tl.y + y))) + { + Point3_ *dst_row = dst.ptr >(dy + y); + dst_row[dx + x] = src_row[x]; + } + } + } +} + + +bool Timelapser::test_point(Point pt) +{ + return dst_roi_.contains(pt); +} + + +void TimelapserCrop::initialize(const std::vector &corners, const std::vector &sizes) +{ + dst_roi_ = resultRoiIntersection(corners, sizes); + dst_.create(dst_roi_.size(), CV_16SC3); +} + + +} // namespace detail +} // namespace cv diff --git a/modules/stitching/src/util.cpp b/modules/stitching/src/util.cpp index 5e026f0989..ce36d9df3e 100644 --- a/modules/stitching/src/util.cpp +++ b/modules/stitching/src/util.cpp @@ -137,6 +137,21 @@ Rect resultRoi(const std::vector &corners, const std::vector &sizes return Rect(tl, br); } +Rect resultRoiIntersection(const std::vector &corners, const std::vector &sizes) +{ + CV_Assert(sizes.size() == corners.size()); + Point tl(std::numeric_limits::min(), std::numeric_limits::min()); + Point br(std::numeric_limits::max(), std::numeric_limits::max()); + for (size_t i = 0; i < corners.size(); ++i) + { + tl.x = std::max(tl.x, corners[i].x); + tl.y = std::max(tl.y, corners[i].y); + br.x = std::min(br.x, corners[i].x + sizes[i].width); + br.y = std::min(br.y, corners[i].y + sizes[i].height); + } + return Rect(tl, br); +} + Point resultTl(const std::vector &corners) { diff --git a/samples/cpp/stitching_detailed.cpp b/samples/cpp/stitching_detailed.cpp index df0a9abc84..bc66694cc7 100644 --- a/samples/cpp/stitching_detailed.cpp +++ b/samples/cpp/stitching_detailed.cpp @@ -49,6 +49,7 @@ #include "opencv2/highgui.hpp" #include "opencv2/stitching/detail/autocalib.hpp" #include "opencv2/stitching/detail/blenders.hpp" +#include "opencv2/stitching/detail/timelapsers.hpp" #include "opencv2/stitching/detail/camera.hpp" #include "opencv2/stitching/detail/exposure_compensate.hpp" #include "opencv2/stitching/detail/matchers.hpp" @@ -116,7 +117,9 @@ static void printUsage() " --blend_strength \n" " Blending strength from [0,100] range. The default is 5.\n" " --output \n" - " The default is 'result.jpg'.\n"; + " The default is 'result.jpg'.\n" + " --timelapse (as_is|crop) (range_width)\n" + " Output warped images separately as frames of a time lapse movie, with 'fixed_' prepended to input file names.\n"; } @@ -140,8 +143,12 @@ int expos_comp_type = ExposureCompensator::GAIN_BLOCKS; float match_conf = 0.3f; string seam_find_type = "gc_color"; int blend_type = Blender::MULTI_BAND; +int timelapse_type = Timelapser::AS_IS; float blend_strength = 5; string result_name = "result.jpg"; +bool timelapse = false; +int timelapse_range = 5; + static int parseCmdArgs(int argc, char** argv) { @@ -304,6 +311,24 @@ static int parseCmdArgs(int argc, char** argv) } i++; } + else if (string(argv[i]) == "--timelapse") + { + timelapse = true; + + if (string(argv[i + 1]) == "as_is") + timelapse_type = Timelapser::AS_IS; + else if (string(argv[i + 1]) == "crop") + timelapse_type = Timelapser::CROP; + else + { + cout << "Bad timelapse method\n"; + return -1; + } + i++; + + timelapse_range = atoi(argv[i + 1]); + i++; + } else if (string(argv[i]) == "--blend_strength") { blend_strength = static_cast(atof(argv[i + 1])); @@ -432,9 +457,19 @@ int main(int argc, char* argv[]) t = getTickCount(); #endif vector pairwise_matches; - BestOf2NearestMatcher matcher(try_cuda, match_conf); - matcher(features, pairwise_matches); - matcher.collectGarbage(); + if (!timelapse) + { + BestOf2NearestMatcher matcher(try_cuda, match_conf); + matcher(features, pairwise_matches); + matcher.collectGarbage(); + } + else + { + BestOf2NearestRangeMatcher matcher(timelapse_range, try_cuda, match_conf); + matcher(features, pairwise_matches); + matcher.collectGarbage(); + } + LOGLN("Pairwise matching, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); // Check if we should save matches graph @@ -679,6 +714,7 @@ int main(int argc, char* argv[]) Mat img_warped, img_warped_s; Mat dilated_mask, seam_mask, mask, mask_warped; Ptr blender; + Ptr timelapser; //double compose_seam_aspect = 1; double compose_work_aspect = 1; @@ -755,7 +791,7 @@ int main(int argc, char* argv[]) resize(dilated_mask, seam_mask, mask_warped.size()); mask_warped = seam_mask & mask_warped; - if (!blender) + if (!blender && !timelapse) { blender = Blender::createDefault(blend_type, try_cuda); Size dst_sz = resultRoi(corners, sizes).size(); @@ -776,17 +812,35 @@ int main(int argc, char* argv[]) } blender->prepare(corners, sizes); } + else if (!timelapser) + { + CV_Assert(timelapse); + timelapser = Timelapser::createDefault(timelapse_type); + timelapser->initialize(corners, sizes); + } // Blend the current image - blender->feed(img_warped_s, mask_warped, corners[img_idx]); + if (timelapse) + { + timelapser->process(img_warped_s, Mat::ones(img_warped_s.size(), CV_8UC1), corners[img_idx]); + + imwrite("fixed_" + img_names[img_idx], timelapser->getDst()); + } + else + { + blender->feed(img_warped_s, mask_warped, corners[img_idx]); + } } - Mat result, result_mask; - blender->blend(result, result_mask); + if (!timelapse) + { + Mat result, result_mask; + blender->blend(result, result_mask); - LOGLN("Compositing, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); + LOGLN("Compositing, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); - imwrite(result_name, result); + imwrite(result_name, result); + } LOGLN("Finished, total time: " << ((getTickCount() - app_start_time) / getTickFrequency()) << " sec"); return 0; From 8b32235854c7a724fd5b0eafcb9e388e3c36b77d Mon Sep 17 00:00:00 2001 From: Lars Glud Date: Tue, 1 Jul 2014 10:07:01 +0200 Subject: [PATCH 064/136] Openni2 support --- CMakeLists.txt | 8 + cmake/OpenCVFindLibsVideo.cmake | 5 + cmake/OpenCVFindOpenNI2.cmake | 61 ++ cmake/templates/cvconfig.h.in | 3 + modules/highgui/CMakeLists.txt | 6 + modules/highgui/include/opencv2/highgui.hpp | 32 +- .../include/opencv2/highgui/highgui_c.h | 7 +- modules/highgui/src/cap.cpp | 12 + modules/highgui/src/cap_openni2.cpp | 921 ++++++++++++++++++ 9 files changed, 1040 insertions(+), 15 deletions(-) create mode 100644 cmake/OpenCVFindOpenNI2.cmake create mode 100644 modules/highgui/src/cap_openni2.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5abf449804..96e7a8c126 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ # # ---------------------------------------------------------------------------- + + include(cmake/OpenCVMinDepVersions.cmake) if(CMAKE_GENERATOR MATCHES Xcode AND XCODE_VERSION VERSION_GREATER 4.3) @@ -135,6 +137,7 @@ OCV_OPTION(WITH_WEBP "Include WebP support" ON OCV_OPTION(WITH_OPENEXR "Include ILM support via OpenEXR" ON IF (NOT IOS) ) OCV_OPTION(WITH_OPENGL "Include OpenGL support" OFF IF (NOT ANDROID) ) OCV_OPTION(WITH_OPENNI "Include OpenNI support" OFF IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_OPENNI2 "Include OpenNI2 support" OFF IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_PNG "Include PNG support" ON) OCV_OPTION(WITH_PVAPI "Include Prosilica GigE support" ON IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_GIGEAPI "Include Smartek GigE support" ON IF (NOT ANDROID AND NOT IOS) ) @@ -865,6 +868,11 @@ if(DEFINED WITH_OPENNI) THEN "YES (${OPENNI_PRIME_SENSOR_MODULE})" ELSE NO) endif(DEFINED WITH_OPENNI) +if(DEFINED WITH_OPENNI2) + status(" OpenNI2:" HAVE_OPENNI2 THEN "YES (ver ${OPENNI2_VERSION_STRING}, build ${OPENNI2_VERSION_BUILD})" + ELSE NO) +endif(DEFINED WITH_OPENNI2) + if(DEFINED WITH_PVAPI) status(" PvAPI:" HAVE_PVAPI THEN YES ELSE NO) endif(DEFINED WITH_PVAPI) diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 5520d05521..54b4d0a2bb 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -166,6 +166,11 @@ if(WITH_OPENNI) include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindOpenNI.cmake") endif(WITH_OPENNI) +ocv_clear_vars(HAVE_OPENNI2) +if(WITH_OPENNI2) + include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindOpenNI2.cmake") +endif(WITH_OPENNI2) + # --- XIMEA --- ocv_clear_vars(HAVE_XIMEA) if(WITH_XIMEA) diff --git a/cmake/OpenCVFindOpenNI2.cmake b/cmake/OpenCVFindOpenNI2.cmake new file mode 100644 index 0000000000..8a5f47ca7c --- /dev/null +++ b/cmake/OpenCVFindOpenNI2.cmake @@ -0,0 +1,61 @@ +# Main variables: +# OPENNI2_LIBRARY and OPENNI2_INCLUDES to link OpenCV modules with OpenNI2 +# HAVE_OPENNI2 for conditional compilation OpenCV with/without OpenNI2 + +if(NOT "${OPENNI2_LIB_DIR}" STREQUAL "${OPENNI2_LIB_DIR_INTERNAL}") + unset(OPENNI2_LIBRARY CACHE) + unset(OPENNI2_LIB_DIR CACHE) +endif() + +if(NOT "${OPENNI2_INCLUDE_DIR}" STREQUAL "${OPENNI2_INCLUDE_DIR_INTERNAL}") + unset(OPENNI2_INCLUDES CACHE) + unset(OPENNI2_INCLUDE_DIR CACHE) +endif() + +if(WIN32) + if(NOT (MSVC64 OR MINGW64)) + find_file(OPENNI2_INCLUDES "OpenNI.h" PATHS "$ENV{OPEN_NI_INSTALL_PATH}Include" DOC "OpenNI2 c++ interface header") + find_library(OPENNI2_LIBRARY "OpenNI2" PATHS $ENV{OPENNI2_LIB} DOC "OpenNI2 library") + else() + find_file(OPENNI2_INCLUDES "OpenNI.h" PATHS "$ENV{OPEN_NI_INSTALL_PATH64}Include" DOC "OpenNI2 c++ interface header") + find_library(OPENNI2_LIBRARY "OpenNI2" PATHS $ENV{OPENNI2_LIB64} DOC "OpenNI2 library") + endif() +elseif(UNIX OR APPLE) + find_file(OPENNI_INCLUDES "OpenNI.h" PATHS "/usr/include/ni2" "/usr/include/openni2" DOC "OpenNI2 c++ interface header") + find_library(OPENNI_LIBRARY "OpenNI2" PATHS "/usr/lib" DOC "OpenNI2 library") +endif() + +if(OPENNI2_LIBRARY AND OPENNI2_INCLUDES) + set(HAVE_OPENNI2 TRUE) +endif() #if(OPENNI_LIBRARY AND OPENNI_INCLUDES) + +get_filename_component(OPENNI2_LIB_DIR "${OPENNI2_LIBRARY}" PATH) +get_filename_component(OPENNI2_INCLUDE_DIR ${OPENNI2_INCLUDES} PATH) + +if(HAVE_OPENNI2) + set(OPENNI2_LIB_DIR "${OPENNI2_LIB_DIR}" CACHE PATH "Path to OpenNI2 libraries" FORCE) + set(OPENNI2_INCLUDE_DIR "${OPENNI2_INCLUDE_DIR}" CACHE PATH "Path to OpenNI2 headers" FORCE) +endif() + +if(OPENNI2_LIBRARY) + set(OPENNI2_LIB_DIR_INTERNAL "${OPENNI2_LIB_DIR}" CACHE INTERNAL "This is the value of the last time OPENNI_LIB_DIR was set successfully." FORCE) +else() + message( WARNING, " OpenNI2 library directory (set by OPENNI2_LIB_DIR variable) is not found or does not have OpenNI2 libraries." ) +endif() + +if(OPENNI2_INCLUDES) + set(OPENNI2_INCLUDE_DIR_INTERNAL "${OPENNI2_INCLUDE_DIR}" CACHE INTERNAL "This is the value of the last time OPENNI2_INCLUDE_DIR was set successfully." FORCE) +else() + message( WARNING, " OpenNI2 include directory (set by OPENNI2_INCLUDE_DIR variable) is not found or does not have OpenNI2 include files." ) +endif() + +mark_as_advanced(FORCE OPENNI2_LIBRARY) +mark_as_advanced(FORCE OPENNI2_INCLUDES) + +if(HAVE_OPENNI2) + ocv_parse_header("${OPENNI2_INCLUDE_DIR}/OniVersion.h" ONI_VERSION_LINE ONI_VERSION_MAJOR ONI_VERSION_MINOR ONI_VERSION_MAINTENANCE ONI_VERSION_BUILD) + if(ONI_VERSION_MAJOR) + set(OPENNI2_VERSION_STRING ${ONI_VERSION_MAJOR}.${ONI_VERSION_MINOR}.${ONI_VERSION_MAINTENANCE} CACHE INTERNAL "OpenNI2 version") + set(OPENNI2_VERSION_BUILD ${ONI_VERSION_BUILD} CACHE INTERNAL "OpenNI2 build version") + endif() +endif() diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index f81049495a..3f77a1bbe7 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -129,6 +129,9 @@ /* OpenNI library */ #cmakedefine HAVE_OPENNI +/* OpenNI library */ +#cmakedefine HAVE_OPENNI2 + /* PNG codec */ #cmakedefine HAVE_PNG diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index efe31a1cac..781df9b92f 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -124,6 +124,12 @@ if(HAVE_OPENNI) list(APPEND HIGHGUI_LIBRARIES ${OPENNI_LIBRARY}) endif(HAVE_OPENNI) +if(HAVE_OPENNI2) + list(APPEND highgui_srcs src/cap_openni2.cpp) + ocv_include_directories(${OPENNI2_INCLUDE_DIR}) + list(APPEND HIGHGUI_LIBRARIES ${OPENNI2_LIBRARY}) +endif(HAVE_OPENNI2) + if(HAVE_opencv_androidcamera) list(APPEND highgui_srcs src/cap_android.cpp) add_definitions(-DHAVE_ANDROID_NATIVE_CAMERA)#TODO: remove this line diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index e0f40b9292..74849ab635 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -231,7 +231,8 @@ enum { CAP_ANY = 0, // autodetect CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK CAP_MSMF = 1400, // Microsoft Media Foundation (via videoInput) - CAP_INTELPERC = 1500 // Intel Perceptual Computing SDK + CAP_INTELPERC = 1500, // Intel Perceptual Computing SDK + CAP_OPENNI2 = 1600 // OpenNI2 (for Kinect) }; // generic properties (based on DC1394 properties) @@ -293,19 +294,22 @@ enum { CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, }; // Properties of cameras available through OpenNI interfaces -enum { CAP_PROP_OPENNI_OUTPUT_MODE = 100, - CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, // in mm - CAP_PROP_OPENNI_BASELINE = 102, // in mm - CAP_PROP_OPENNI_FOCAL_LENGTH = 103, // in pixels - CAP_PROP_OPENNI_REGISTRATION = 104, // flag that synchronizes the remapping depth map to image map - // by changing depth generator's view point (if the flag is "on") or - // sets this view point to its normal one (if the flag is "off"). - CAP_PROP_OPENNI_REGISTRATION_ON = CAP_PROP_OPENNI_REGISTRATION, - CAP_PROP_OPENNI_APPROX_FRAME_SYNC = 105, - CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, - CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, - CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, - CAP_PROP_OPENNI_GENERATOR_PRESENT = 109 +enum { + CAP_PROP_OPENNI_OUTPUT_MODE = 100, + CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, // in mm + CAP_PROP_OPENNI_BASELINE = 102, // in mm + CAP_PROP_OPENNI_FOCAL_LENGTH = 103, // in pixels + CAP_PROP_OPENNI_REGISTRATION = 104, // flag that synchronizes the remapping depth map to image map + // by changing depth generator's view point (if the flag is "on") or + // sets this view point to its normal one (if the flag is "off"). + CAP_PROP_OPENNI_REGISTRATION_ON = CAP_PROP_OPENNI_REGISTRATION, + CAP_PROP_OPENNI_APPROX_FRAME_SYNC = 105, + CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, + CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, + CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, + CAP_PROP_OPENNI_GENERATOR_PRESENT = 109, + CAP_PROP_OPENNI2_SYNC = 110, + CAP_PROP_OPENNI2_MIRROR = 111 }; // OpenNI shortcats diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index a94e69601b..1d7e94ba16 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -249,6 +249,7 @@ enum CV_CAP_PVAPI =800, // PvAPI, Prosilica GigE SDK CV_CAP_OPENNI =900, // OpenNI (for Kinect) + CV_CAP_OPENNI_ASUS =910, // OpenNI (for Asus Xtion) CV_CAP_ANDROID =1000, // Android @@ -261,7 +262,9 @@ enum CV_CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK - CV_CAP_INTELPERC = 1500 // Intel Perceptual Computing SDK + CV_CAP_INTELPERC = 1500, // Intel Perceptual Computing SDK + + CV_CAP_OPENNI2 = 1600 // OpenNI2 (for Kinect) }; /* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */ @@ -357,6 +360,8 @@ enum CV_CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, CV_CAP_PROP_OPENNI_GENERATOR_PRESENT = 109, + CV_CAP_PROP_OPENNI2_SYNC = 110, + CV_CAP_PROP_OPENNI2_MIRROR = 111, CV_CAP_OPENNI_IMAGE_GENERATOR_PRESENT = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_GENERATOR_PRESENT, CV_CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_OUTPUT_MODE, diff --git a/modules/highgui/src/cap.cpp b/modules/highgui/src/cap.cpp index 17cbf6191c..e36dc05730 100644 --- a/modules/highgui/src/cap.cpp +++ b/modules/highgui/src/cap.cpp @@ -143,6 +143,9 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) #ifdef HAVE_OPENNI CV_CAP_OPENNI, #endif +#ifdef HAVE_OPENNI2 + CV_CAP_OPENNI2, +#endif #ifdef HAVE_ANDROID_NATIVE_CAMERA CV_CAP_ANDROID, #endif @@ -190,6 +193,7 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) defined(HAVE_UNICAP) || \ defined(HAVE_PVAPI) || \ defined(HAVE_OPENNI) || \ + defined(HAVE_OPENNI2) || \ defined(HAVE_XIMEA) || \ defined(HAVE_AVFOUNDATION) || \ defined(HAVE_ANDROID_NATIVE_CAMERA) || \ @@ -305,6 +309,14 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) break; #endif +#ifdef HAVE_OPENNI2 + case CV_CAP_OPENNI2: + capture = cvCreateCameraCapture_OpenNI(index); + if (capture) + return capture; + break; +#endif + #ifdef HAVE_ANDROID_NATIVE_CAMERA case CV_CAP_ANDROID: capture = cvCreateCameraCapture_Android (index); diff --git a/modules/highgui/src/cap_openni2.cpp b/modules/highgui/src/cap_openni2.cpp new file mode 100644 index 0000000000..4d12e5eb14 --- /dev/null +++ b/modules/highgui/src/cap_openni2.cpp @@ -0,0 +1,921 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ +#include "precomp.hpp" +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" + +#ifdef HAVE_OPENNI2 + +#if defined TBB_INTERFACE_VERSION && TBB_INTERFACE_VERSION < 5000 +# undef HAVE_TBB +#endif + +#include + +#ifndef i386 +# define i386 0 +#endif +#ifndef __arm__ +# define __arm__ 0 +#endif +#ifndef _ARC +# define _ARC 0 +#endif +#ifndef __APPLE__ +# define __APPLE__ 0 +#endif + +#define CV_STREAM_TIMEOUT 2000 + +#define CV_DEPTH_STREAM 0 +#define CV_COLOR_STREAM 1 + +#define CV_NUM_STREAMS 2 + +#include "OpenNI.h" +#include "PS1080.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class CvCapture_OpenNI2 : public CvCapture +{ +public: + enum { DEVICE_DEFAULT=0, DEVICE_MS_KINECT=0, DEVICE_ASUS_XTION=1, DEVICE_MAX=1 }; + + static const int INVALID_PIXEL_VAL = 0; + static const int INVALID_COORDINATE_VAL = 0; + +#ifdef HAVE_TBB + static const int DEFAULT_MAX_BUFFER_SIZE = 8; +#else + static const int DEFAULT_MAX_BUFFER_SIZE = 2; +#endif + static const int DEFAULT_IS_CIRCLE_BUFFER = 0; + static const int DEFAULT_MAX_TIME_DURATION = 20; + + CvCapture_OpenNI2(int index = 0); + CvCapture_OpenNI2(const char * filename); + virtual ~CvCapture_OpenNI2(); + + virtual double getProperty(int propIdx); + virtual bool setProperty(int probIdx, double propVal); + virtual bool grabFrame(); + virtual IplImage* retrieveFrame(int outputType); + + bool isOpened() const; + +protected: + struct OutputMap + { + public: + cv::Mat mat; + IplImage* getIplImagePtr(); + private: + IplImage iplHeader; + }; + + static const int outputMapsTypesCount = 7; + + static openni::VideoMode defaultColorOutputMode(); + static openni::VideoMode defaultDepthOutputMode(); + + IplImage* retrieveDepthMap(); + IplImage* retrievePointCloudMap(); + IplImage* retrieveDisparityMap(); + IplImage* retrieveDisparityMap_32F(); + IplImage* retrieveValidDepthMask(); + IplImage* retrieveBGRImage(); + IplImage* retrieveGrayImage(); + + bool readCamerasParams(); + + double getDepthGeneratorProperty(int propIdx); + bool setDepthGeneratorProperty(int propIdx, double propVal); + double getImageGeneratorProperty(int propIdx); + bool setImageGeneratorProperty(int propIdx, double propVal); + double getCommonProperty(int propIdx); + bool setCommonProperty(int propIdx, double propVal); + + // OpenNI context + openni::Device device; + bool isContextOpened; + openni::Recorder recorder; + + // Data generators with its metadata + openni::VideoStream depth, color, **streams; + openni::VideoFrameRef depthFrame, colorFrame; + cv::Mat depthImage, colorImage; + + int maxBufferSize, maxTimeDuration; // for approx sync + bool isCircleBuffer; + //cv::Ptr approxSyncGrabber; + + // Cameras settings: + // TODO find in OpenNI function to convert z->disparity and remove fields "baseline" and depthFocalLength_VGA + // Distance between IR projector and IR camera (in meters) + double baseline; + // Focal length for the IR camera in VGA resolution (in pixels) + int depthFocalLength_VGA; + + // The value for shadow (occluded pixels) + int shadowValue; + // The value for pixels without a valid disparity measurement + int noSampleValue; + + int currentStream; + + std::vector outputMaps; +}; + +IplImage* CvCapture_OpenNI2::OutputMap::getIplImagePtr() +{ + if( mat.empty() ) + return 0; + + iplHeader = IplImage(mat); + return &iplHeader; +} + +bool CvCapture_OpenNI2::isOpened() const +{ + return isContextOpened; +} + +openni::VideoMode CvCapture_OpenNI2::defaultColorOutputMode() +{ + openni::VideoMode mode; + mode.setResolution(640, 480); + mode.setFps(30); + mode.setPixelFormat(openni::PIXEL_FORMAT_RGB888); + return mode; +} + +openni::VideoMode CvCapture_OpenNI2::defaultDepthOutputMode() +{ + openni::VideoMode mode; + mode.setResolution(640, 480); + mode.setFps(30); + mode.setPixelFormat(openni::PIXEL_FORMAT_DEPTH_1_MM); + return mode; +} + +CvCapture_OpenNI2::CvCapture_OpenNI2( int index ) +{ + const char* deviceURI = openni::ANY_DEVICE; + openni::Status status; + int deviceType = DEVICE_DEFAULT; + + noSampleValue = shadowValue = 0; + + isContextOpened = false; + maxBufferSize = DEFAULT_MAX_BUFFER_SIZE; + isCircleBuffer = DEFAULT_IS_CIRCLE_BUFFER; + maxTimeDuration = DEFAULT_MAX_TIME_DURATION; + + if( index >= 10 ) + { + deviceType = index / 10; + index %= 10; + } + + if( deviceType > DEVICE_MAX ) + return; + + // Initialize and configure the context. + status = openni::OpenNI::initialize(); + + if (status != openni::STATUS_OK) + { + CV_Error(CV_StsError, cv::format("Failed to initialize:", openni::OpenNI::getExtendedError())); + return; + } + + status = device.open(deviceURI); + if( status != openni::STATUS_OK ) + { + CV_Error(CV_StsError, cv::format("OpenCVKinect: Device open failed see: %s\n", openni::OpenNI::getExtendedError())); + openni::OpenNI::shutdown(); + return; + } + + //device.setDepthColorSyncEnabled(true); + + + status = depth.create(device, openni::SENSOR_DEPTH); + if (status == openni::STATUS_OK) + { + if (depth.isValid()) + { + CV_DbgAssert(depth.setVideoMode(defaultDepthOutputMode()) == openni::STATUS_OK); // xn::DepthGenerator supports VGA only! (Jan 2011) + } + + status = depth.start(); + if (status != openni::STATUS_OK) + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::CvCapture_OpenNI2 : Couldn't start depth stream: %s\n", openni::OpenNI::getExtendedError())); + depth.destroy(); + return; + } + } + else + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::CvCapture_OpenNI2 : Couldn't find depth stream:: %s\n", openni::OpenNI::getExtendedError())); + return; + } + // create a color object + status = color.create(device, openni::SENSOR_COLOR); + if (status == openni::STATUS_OK) + { + // Set map output mode. + if (color.isValid()) + { + CV_DbgAssert(color.setVideoMode(defaultColorOutputMode()) == openni::STATUS_OK); + } + status = color.start(); + if (status != openni::STATUS_OK) + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::CvCapture_OpenNI2 : Couldn't start color stream: %s\n", openni::OpenNI::getExtendedError())); + color.destroy(); + return; + } + } + else + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::CvCapture_OpenNI2 : Couldn't find color stream: %s\n", openni::OpenNI::getExtendedError())); + return; + } + + +// if( deviceType == DEVICE_ASUS_XTION ) +// { +// //ps/asus specific +// imageGenerator.SetIntProperty("InputFormat", 1 /*XN_IO_IMAGE_FORMAT_YUV422*/); +// imageGenerator.SetPixelFormat(XN_PIXEL_FORMAT_RGB24); +// depthGenerator.SetIntProperty("RegistrationType", 1 /*XN_PROCESSING_HARDWARE*/); +// } + + if( !readCamerasParams() ) + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::CvCapture_OpenNI2 : Could not read cameras parameters\n")); + return; + } + streams = new openni::VideoStream*[CV_NUM_STREAMS]; + streams[CV_DEPTH_STREAM] = &depth; + streams[CV_COLOR_STREAM] = &color; + + outputMaps.resize( outputMapsTypesCount ); + + isContextOpened = true; + + setProperty(CV_CAP_PROP_OPENNI_REGISTRATION, 1.0); +} + +CvCapture_OpenNI2::CvCapture_OpenNI2(const char * filename) +{ + openni::Status status; + + isContextOpened = false; + maxBufferSize = DEFAULT_MAX_BUFFER_SIZE; + isCircleBuffer = DEFAULT_IS_CIRCLE_BUFFER; + maxTimeDuration = DEFAULT_MAX_TIME_DURATION; + + // Initialize and configure the context. + status = openni::OpenNI::initialize(); + + if (status != openni::STATUS_OK) + { + CV_Error(CV_StsError, cv::format("Failed to initialize:", openni::OpenNI::getExtendedError())); + return; + } + + // Open file + status = device.open(filename); + if( status != openni::STATUS_OK ) + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::CvCapture_OpenNI2 : Failed to open input file (%s): %s\n", filename, openni::OpenNI::getExtendedError())); + return; + } + + if( !readCamerasParams() ) + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::CvCapture_OpenNI2 : Could not read cameras parameters\n")); + return; + } + + outputMaps.resize( outputMapsTypesCount ); + + isContextOpened = true; +} + +CvCapture_OpenNI2::~CvCapture_OpenNI2() +{ + this->depthFrame.release(); + this->colorFrame.release(); + this->depth.stop(); + this->color.stop(); + openni::OpenNI::shutdown(); +} + +bool CvCapture_OpenNI2::readCamerasParams() +{ + double pixelSize = 0; + if (depth.getProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, &pixelSize) != openni::STATUS_OK) + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::readCamerasParams : Could not read pixel size!\n")); + return false; + } + + // pixel size @ VGA = pixel size @ SXGA x 2 + pixelSize *= 2.0; // in mm + + // focal length of IR camera in pixels for VGA resolution + int zeroPlanDistance; // in mm + if (depth.getProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, &zeroPlanDistance) != openni::STATUS_OK) + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::readCamerasParams : Could not read virtual plane distance!\n")); + return false; + } + + if (depth.getProperty(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, &baseline) != openni::STATUS_OK) + { + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::readCamerasParams : Could not read base line!\n")); + return false; + } + + // baseline from cm -> mm + baseline *= 10; + + // focal length from mm -> pixels (valid for 640x480) + depthFocalLength_VGA = (int)((double)zeroPlanDistance / (double)pixelSize); + + return true; +} + +double CvCapture_OpenNI2::getProperty( int propIdx ) +{ + double propValue = 0; + + if( isOpened() ) + { + int purePropIdx = propIdx & ~CV_CAP_OPENNI_GENERATORS_MASK; + + if( (propIdx & CV_CAP_OPENNI_GENERATORS_MASK) == CV_CAP_OPENNI_IMAGE_GENERATOR ) + { + propValue = getImageGeneratorProperty( purePropIdx ); + } + else if( (propIdx & CV_CAP_OPENNI_GENERATORS_MASK) == CV_CAP_OPENNI_DEPTH_GENERATOR ) + { + propValue = getDepthGeneratorProperty( purePropIdx ); + } + else + { + propValue = getCommonProperty( purePropIdx ); + } + } + + return propValue; +} + +bool CvCapture_OpenNI2::setProperty( int propIdx, double propValue ) +{ + bool isSet = false; + if( isOpened() ) + { + int purePropIdx = propIdx & ~CV_CAP_OPENNI_GENERATORS_MASK; + + if( (propIdx & CV_CAP_OPENNI_GENERATORS_MASK) == CV_CAP_OPENNI_IMAGE_GENERATOR ) + { + isSet = setImageGeneratorProperty( purePropIdx, propValue ); + } + else if( (propIdx & CV_CAP_OPENNI_GENERATORS_MASK) == CV_CAP_OPENNI_DEPTH_GENERATOR ) + { + isSet = setDepthGeneratorProperty( purePropIdx, propValue ); + } + else + { + isSet = setCommonProperty( purePropIdx, propValue ); + } + } + + return isSet; +} + +double CvCapture_OpenNI2::getCommonProperty( int propIdx ) +{ + double propValue = 0; + + switch( propIdx ) + { + // There is a set of properties that correspond to depth generator by default + // (is they are pass without particular generator flag). Two reasons of this: + // 1) We can assume that depth generator is the main one for depth sensor. + // 2) In the initial vertions of OpenNI integration to OpenCV the value of + // flag CV_CAP_OPENNI_DEPTH_GENERATOR was 0 (it isn't zero now). + case CV_CAP_PROP_OPENNI_GENERATOR_PRESENT : + case CV_CAP_PROP_FRAME_WIDTH : + case CV_CAP_PROP_FRAME_HEIGHT : + case CV_CAP_PROP_FPS : + case CV_CAP_PROP_OPENNI_FRAME_MAX_DEPTH : + case CV_CAP_PROP_OPENNI_BASELINE : + case CV_CAP_PROP_OPENNI_FOCAL_LENGTH : + case CV_CAP_PROP_OPENNI_REGISTRATION : + propValue = getDepthGeneratorProperty( propIdx ); + break; + case CV_CAP_PROP_OPENNI2_SYNC : + propValue = device.getDepthColorSyncEnabled(); + case CV_CAP_PROP_OPENNI2_MIRROR: + { + bool isMirroring = color.getMirroringEnabled() && depth.getMirroringEnabled(); + propValue = isMirroring ? 1.0 : 0.0; + break; + } + default : + CV_Error( CV_StsBadArg, cv::format("Such parameter (propIdx=%d) isn't supported for getting.\n", propIdx) ); + } + + return propValue; +} + +bool CvCapture_OpenNI2::setCommonProperty( int propIdx, double propValue ) +{ + bool isSet = false; + + switch( propIdx ) + { + case CV_CAP_PROP_OPENNI2_MIRROR: + { + bool mirror = propValue > 0 ? true : false; + isSet = color.setMirroringEnabled(mirror) == openni::STATUS_OK; + isSet = depth.setMirroringEnabled(mirror) == openni::STATUS_OK; + } + break; + // There is a set of properties that correspond to depth generator by default + // (is they are pass without particular generator flag). + case CV_CAP_PROP_OPENNI_REGISTRATION: + isSet = setDepthGeneratorProperty( propIdx, propValue ); + break; + case CV_CAP_PROP_OPENNI2_SYNC: + isSet = device.setDepthColorSyncEnabled(propValue) == openni::STATUS_OK; + break; + default: + CV_Error( CV_StsBadArg, cv::format("Such parameter (propIdx=%d) isn't supported for setting.\n", propIdx) ); + } + + return isSet; +} + +double CvCapture_OpenNI2::getDepthGeneratorProperty( int propIdx ) +{ + double propValue = 0; + if( !depth.isValid() ) + return propValue; + + openni::VideoMode mode; + + switch( propIdx ) + { + case CV_CAP_PROP_OPENNI_GENERATOR_PRESENT : + CV_DbgAssert(depth.isValid()); + propValue = 1.; + break; + case CV_CAP_PROP_FRAME_WIDTH : + propValue = depth.getVideoMode().getResolutionX(); + break; + case CV_CAP_PROP_FRAME_HEIGHT : + propValue = depth.getVideoMode().getResolutionY(); + break; + case CV_CAP_PROP_FPS : + mode = depth.getVideoMode(); + propValue = mode.getFps(); + break; + case CV_CAP_PROP_OPENNI_FRAME_MAX_DEPTH : + propValue = depth.getMaxPixelValue(); + break; + case CV_CAP_PROP_OPENNI_BASELINE : + propValue = baseline; + break; + case CV_CAP_PROP_OPENNI_FOCAL_LENGTH : + propValue = (double)depthFocalLength_VGA; + break; + case CV_CAP_PROP_OPENNI_REGISTRATION : + propValue = device.getImageRegistrationMode(); + break; + case CV_CAP_PROP_POS_MSEC : + propValue = (double)depthFrame.getTimestamp(); + break; + case CV_CAP_PROP_POS_FRAMES : + propValue = depthFrame.getFrameIndex(); + break; + default : + CV_Error( CV_StsBadArg, cv::format("Depth generator does not support such parameter (propIdx=%d) for getting.\n", propIdx) ); + } + + return propValue; +} + +bool CvCapture_OpenNI2::setDepthGeneratorProperty( int propIdx, double propValue ) +{ + bool isSet = false; + + CV_Assert( depth.isValid() ); + + switch( propIdx ) + { + case CV_CAP_PROP_OPENNI_REGISTRATION: + { + if( propValue < 1.0 ) // "on" + { + // if there isn't image generator (i.e. ASUS XtionPro doesn't have it) + // then the property isn't avaliable + if ( color.isValid() ) + { + openni::ImageRegistrationMode mode = propValue < 1.0 ? openni::IMAGE_REGISTRATION_OFF : openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR; + if( !device.getImageRegistrationMode() == mode ) + { + if (device.isImageRegistrationModeSupported(mode)) + { + openni::Status status = device.setImageRegistrationMode(mode); + if( status != openni::STATUS_OK ) + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::setDepthGeneratorProperty : %s\n", openni::OpenNI::getExtendedError())); + else + isSet = true; + } + else + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::setDepthGeneratorProperty : Unsupported viewpoint.\n")); + } + else + isSet = true; + } + } + else // "off" + { + openni::Status status = device.setImageRegistrationMode(openni::IMAGE_REGISTRATION_OFF); + if( status != openni::STATUS_OK ) + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::setDepthGeneratorProperty : %s\n", openni::OpenNI::getExtendedError())); + else + isSet = true; + } + } + break; + default: + CV_Error( CV_StsBadArg, cv::format("Depth generator does not support such parameter (propIdx=%d) for setting.\n", propIdx) ); + } + + return isSet; +} + +double CvCapture_OpenNI2::getImageGeneratorProperty( int propIdx ) +{ + double propValue = 0.; + if( !color.isValid() ) + return propValue; + + openni::VideoMode mode; + switch( propIdx ) + { + case CV_CAP_PROP_OPENNI_GENERATOR_PRESENT : + CV_DbgAssert( color.isValid() ); + propValue = 1.; + break; + case CV_CAP_PROP_FRAME_WIDTH : + propValue = color.getVideoMode().getResolutionX(); + break; + case CV_CAP_PROP_FRAME_HEIGHT : + propValue = color.getVideoMode().getResolutionY(); + break; + case CV_CAP_PROP_FPS : + propValue = color.getVideoMode().getFps(); + break; + case CV_CAP_PROP_POS_MSEC : + propValue = (double)colorFrame.getTimestamp(); + break; + case CV_CAP_PROP_POS_FRAMES : + propValue = (double)colorFrame.getFrameIndex(); + break; + default : + CV_Error( CV_StsBadArg, cv::format("Image generator does not support such parameter (propIdx=%d) for getting.\n", propIdx) ); + } + + return propValue; +} + +bool CvCapture_OpenNI2::setImageGeneratorProperty(int propIdx, double propValue) +{ + bool isSet = false; + if( !color.isValid() ) + return isSet; + + switch( propIdx ) + { + case CV_CAP_PROP_OPENNI_OUTPUT_MODE : + { + openni::VideoMode mode; + + switch( cvRound(propValue) ) + { + case CV_CAP_OPENNI_VGA_30HZ : + mode.setResolution(640,480); + mode.setFps(30); + break; + case CV_CAP_OPENNI_SXGA_15HZ : + mode.setResolution(1280, 960); + mode.setFps(15); + break; + case CV_CAP_OPENNI_SXGA_30HZ : + mode.setResolution(1280, 960); + mode.setFps(30); + break; + case CV_CAP_OPENNI_QVGA_30HZ : + mode.setResolution(320, 240); + mode.setFps(30); + break; + case CV_CAP_OPENNI_QVGA_60HZ : + mode.setResolution(320, 240); + mode.setFps(60); + break; + default : + CV_Error( CV_StsBadArg, "Unsupported image generator output mode.\n"); + } + + openni::Status status = color.setVideoMode( mode ); + if( status != openni::STATUS_OK ) + CV_Error(CV_StsError, cv::format("CvCapture_OpenNI2::setImageGeneratorProperty : %s\n", openni::OpenNI::getExtendedError())); + else + isSet = true; + break; + } + default: + CV_Error( CV_StsBadArg, cv::format("Image generator does not support such parameter (propIdx=%d) for setting.\n", propIdx) ); + } + + return isSet; +} + +bool CvCapture_OpenNI2::grabFrame() +{ + if( !isOpened() ) + return false; + + bool isGrabbed = false; + + openni::Status status = openni::OpenNI::waitForAnyStream(streams, CV_NUM_STREAMS, ¤tStream, CV_STREAM_TIMEOUT); + if( status != openni::STATUS_OK ) + return false; + + if( depth.isValid() ) + depth.readFrame(&depthFrame); + if (color.isValid()) + color.readFrame(&colorFrame); + isGrabbed = true; + + return isGrabbed; +} + +inline void getDepthMapFromMetaData(const openni::VideoFrameRef& depthMetaData, cv::Mat& depthMap, int noSampleValue, int shadowValue) +{ + depthMap.create(depthMetaData.getHeight(), depthMetaData.getWidth(), CV_16UC1); + depthMap.data = (uchar*)depthMetaData.getData(); + + cv::Mat badMask = (depthMap == (double)noSampleValue) | (depthMap == (double)shadowValue) | (depthMap == 0); + + // mask the pixels with invalid depth + depthMap.setTo( cv::Scalar::all( CvCapture_OpenNI2::INVALID_PIXEL_VAL ), badMask ); +} + +IplImage* CvCapture_OpenNI2::retrieveDepthMap() +{ + if( !depth.isValid() ) + return 0; + + getDepthMapFromMetaData( depthFrame, outputMaps[CV_CAP_OPENNI_DEPTH_MAP].mat, noSampleValue, shadowValue ); + + return outputMaps[CV_CAP_OPENNI_DEPTH_MAP].getIplImagePtr(); +} + +IplImage* CvCapture_OpenNI2::retrievePointCloudMap() +{ + if( !depthFrame.isValid() ) + return 0; + + cv::Mat depthImg; + getDepthMapFromMetaData(depthFrame, depthImg, noSampleValue, shadowValue); + + const int badPoint = INVALID_PIXEL_VAL; + const float badCoord = INVALID_COORDINATE_VAL; + int cols = depthFrame.getWidth(), rows = depthFrame.getHeight(); + cv::Mat pointCloud_XYZ( rows, cols, CV_32FC3, cv::Scalar::all(badPoint) ); + + float worldX, worldY, worldZ; + for( int y = 0; y < rows; y++ ) + { + for (int x = 0; x < cols; x++) + { + openni::CoordinateConverter::convertDepthToWorld(depth, x, y, depthImg.at(y, x), &worldX, &worldY, &worldZ); + + if (depthImg.at(y, x) == badPoint) // not valid + pointCloud_XYZ.at(y, x) = cv::Point3f(badCoord, badCoord, badCoord); + else + { + pointCloud_XYZ.at(y, x) = cv::Point3f(worldX*0.001f, worldY*0.001f, worldZ*0.001f); // from mm to meters + } + } + } + + outputMaps[CV_CAP_OPENNI_POINT_CLOUD_MAP].mat = pointCloud_XYZ; + + return outputMaps[CV_CAP_OPENNI_POINT_CLOUD_MAP].getIplImagePtr(); +} + +static void computeDisparity_32F( const openni::VideoFrameRef& depthMetaData, cv::Mat& disp, double baseline, int F, int noSampleValue, int shadowValue) +{ + cv::Mat depth; + getDepthMapFromMetaData( depthMetaData, depth, noSampleValue, shadowValue ); + CV_Assert( depth.type() == CV_16UC1 ); + + // disparity = baseline * F / z; + + float mult = (float)(baseline /*mm*/ * F /*pixels*/); + + disp.create( depth.size(), CV_32FC1); + disp = cv::Scalar::all( CvCapture_OpenNI2::INVALID_PIXEL_VAL ); + for( int y = 0; y < disp.rows; y++ ) + { + for( int x = 0; x < disp.cols; x++ ) + { + unsigned short curDepth = depth.at(y,x); + if( curDepth != CvCapture_OpenNI2::INVALID_PIXEL_VAL ) + disp.at(y,x) = mult / curDepth; + } + } +} + +IplImage* CvCapture_OpenNI2::retrieveDisparityMap() +{ + if (!depthFrame.isValid()) + return 0; + + cv::Mat disp32; + computeDisparity_32F(depthFrame, disp32, baseline, depthFocalLength_VGA, noSampleValue, shadowValue); + + disp32.convertTo( outputMaps[CV_CAP_OPENNI_DISPARITY_MAP].mat, CV_8UC1 ); + + return outputMaps[CV_CAP_OPENNI_DISPARITY_MAP].getIplImagePtr(); +} + +IplImage* CvCapture_OpenNI2::retrieveDisparityMap_32F() +{ + if (!depthFrame.isValid()) + return 0; + + computeDisparity_32F(depthFrame, outputMaps[CV_CAP_OPENNI_DISPARITY_MAP_32F].mat, baseline, depthFocalLength_VGA, noSampleValue, shadowValue); + + return outputMaps[CV_CAP_OPENNI_DISPARITY_MAP_32F].getIplImagePtr(); +} + +IplImage* CvCapture_OpenNI2::retrieveValidDepthMask() +{ + if (!depthFrame.isValid()) + return 0; + + cv::Mat depth; + getDepthMapFromMetaData(depthFrame, depth, noSampleValue, shadowValue); + + outputMaps[CV_CAP_OPENNI_VALID_DEPTH_MASK].mat = depth != CvCapture_OpenNI2::INVALID_PIXEL_VAL; + + return outputMaps[CV_CAP_OPENNI_VALID_DEPTH_MASK].getIplImagePtr(); +} + +inline void getBGRImageFromMetaData( const openni::VideoFrameRef& imageMetaData, cv::Mat& bgrImage ) +{ + cv::Mat bufferImage; + if( imageMetaData.getVideoMode().getPixelFormat() != openni::PIXEL_FORMAT_RGB888 ) + CV_Error( CV_StsUnsupportedFormat, "Unsupported format of grabbed image\n" ); + + bgrImage.create(imageMetaData.getHeight(), imageMetaData.getWidth(), CV_8UC3); + bufferImage.create(imageMetaData.getHeight(), imageMetaData.getWidth(), CV_8UC3); + bufferImage.data = (uchar*)imageMetaData.getData(); + + cv::cvtColor(bufferImage, bgrImage, cv::COLOR_RGB2BGR); +} + +IplImage* CvCapture_OpenNI2::retrieveBGRImage() +{ + if( !color.isValid() ) + return 0; + + getBGRImageFromMetaData( colorFrame, outputMaps[CV_CAP_OPENNI_BGR_IMAGE].mat ); + + return outputMaps[CV_CAP_OPENNI_BGR_IMAGE].getIplImagePtr(); +} + +IplImage* CvCapture_OpenNI2::retrieveGrayImage() +{ + if (!colorFrame.isValid()) + return 0; + + CV_Assert(colorFrame.getVideoMode().getPixelFormat() == openni::PIXEL_FORMAT_RGB888); // RGB + + cv::Mat rgbImage; + getBGRImageFromMetaData(colorFrame, rgbImage); + cv::cvtColor( rgbImage, outputMaps[CV_CAP_OPENNI_GRAY_IMAGE].mat, CV_BGR2GRAY ); + + return outputMaps[CV_CAP_OPENNI_GRAY_IMAGE].getIplImagePtr(); +} + +IplImage* CvCapture_OpenNI2::retrieveFrame( int outputType ) +{ + IplImage* image = 0; + CV_Assert( outputType < outputMapsTypesCount && outputType >= 0); + + if( outputType == CV_CAP_OPENNI_DEPTH_MAP ) + { + image = retrieveDepthMap(); + } + else if( outputType == CV_CAP_OPENNI_POINT_CLOUD_MAP ) + { + image = retrievePointCloudMap(); + } + else if( outputType == CV_CAP_OPENNI_DISPARITY_MAP ) + { + image = retrieveDisparityMap(); + } + else if( outputType == CV_CAP_OPENNI_DISPARITY_MAP_32F ) + { + image = retrieveDisparityMap_32F(); + } + else if( outputType == CV_CAP_OPENNI_VALID_DEPTH_MASK ) + { + image = retrieveValidDepthMask(); + } + else if( outputType == CV_CAP_OPENNI_BGR_IMAGE ) + { + image = retrieveBGRImage(); + } + else if( outputType == CV_CAP_OPENNI_GRAY_IMAGE ) + { + image = retrieveGrayImage(); + } + + return image; +} + +CvCapture* cvCreateCameraCapture_OpenNI( int index ) +{ + CvCapture_OpenNI2* capture = new CvCapture_OpenNI2( index ); + + if( capture->isOpened() ) + return capture; + + delete capture; + return 0; +} + +CvCapture* cvCreateFileCapture_OpenNI( const char* filename ) +{ + CvCapture_OpenNI2* capture = new CvCapture_OpenNI2( filename ); + + if( capture->isOpened() ) + return capture; + + delete capture; + return 0; +} + +#endif From d848704b35318c2498b4950ddd82e341c1dd28ca Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 23 Jun 2014 13:55:09 -0700 Subject: [PATCH 065/136] cuda::DisparityBilateralFilter no longer uses constant memory for parameters Now multiple filters can be used in the same context without stepping on each other. --- .../src/cuda/disparity_bilateral_filter.cu | 44 +++++-------------- .../src/disparity_bilateral_filter.cpp | 8 ++-- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/modules/cudastereo/src/cuda/disparity_bilateral_filter.cu b/modules/cudastereo/src/cuda/disparity_bilateral_filter.cu index b5de989ae7..5b16f8c108 100644 --- a/modules/cudastereo/src/cuda/disparity_bilateral_filter.cu +++ b/modules/cudastereo/src/cuda/disparity_bilateral_filter.cu @@ -49,30 +49,6 @@ namespace cv { namespace cuda { namespace device { namespace disp_bilateral_filter { - __constant__ float* ctable_color; - __constant__ float* ctable_space; - __constant__ size_t ctable_space_step; - - __constant__ int cndisp; - __constant__ int cradius; - - __constant__ short cedge_disc; - __constant__ short cmax_disc; - - void disp_load_constants(float* table_color, PtrStepSzf table_space, int ndisp, int radius, short edge_disc, short max_disc) - { - cudaSafeCall( cudaMemcpyToSymbol(ctable_color, &table_color, sizeof(table_color)) ); - cudaSafeCall( cudaMemcpyToSymbol(ctable_space, &table_space.data, sizeof(table_space.data)) ); - size_t table_space_step = table_space.step / sizeof(float); - cudaSafeCall( cudaMemcpyToSymbol(ctable_space_step, &table_space_step, sizeof(size_t)) ); - - cudaSafeCall( cudaMemcpyToSymbol(cndisp, &ndisp, sizeof(int)) ); - cudaSafeCall( cudaMemcpyToSymbol(cradius, &radius, sizeof(int)) ); - - cudaSafeCall( cudaMemcpyToSymbol(cedge_disc, &edge_disc, sizeof(short)) ); - cudaSafeCall( cudaMemcpyToSymbol(cmax_disc, &max_disc, sizeof(short)) ); - } - template struct DistRgbMax { @@ -95,7 +71,11 @@ namespace cv { namespace cuda { namespace device }; template - __global__ void disp_bilateral_filter(int t, T* disp, size_t disp_step, const uchar* img, size_t img_step, int h, int w) + __global__ void disp_bilateral_filter(int t, T* disp, size_t disp_step, + const uchar* img, size_t img_step, int h, int w, + const float* ctable_color, const float * ctable_space, size_t ctable_space_step, + int cradius, + short cedge_disc, short cmax_disc) { const int y = blockIdx.y * blockDim.y + threadIdx.y; const int x = ((blockIdx.x * blockDim.x + threadIdx.x) << 1) + ((y + t) & 1); @@ -178,7 +158,7 @@ namespace cv { namespace cuda { namespace device } template - void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream) + void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, const float *table_color, const float* table_space, size_t table_step, int radius, short edge_disc, short max_disc, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -190,20 +170,20 @@ namespace cv { namespace cuda { namespace device case 1: for (int i = 0; i < iters; ++i) { - disp_bilateral_filter<1><<>>(0, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols); + disp_bilateral_filter<1><<>>(0, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols, table_color, table_space, table_step, radius, edge_disc, max_disc); cudaSafeCall( cudaGetLastError() ); - disp_bilateral_filter<1><<>>(1, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols); + disp_bilateral_filter<1><<>>(1, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols, table_color, table_space, table_step, radius, edge_disc, max_disc); cudaSafeCall( cudaGetLastError() ); } break; case 3: for (int i = 0; i < iters; ++i) { - disp_bilateral_filter<3><<>>(0, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols); + disp_bilateral_filter<3><<>>(0, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols, table_color, table_space, table_step, radius, edge_disc, max_disc); cudaSafeCall( cudaGetLastError() ); - disp_bilateral_filter<3><<>>(1, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols); + disp_bilateral_filter<3><<>>(1, disp.data, disp.step/sizeof(T), img.data, img.step, disp.rows, disp.cols, table_color, table_space, table_step, radius, edge_disc, max_disc); cudaSafeCall( cudaGetLastError() ); } break; @@ -215,8 +195,8 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaDeviceSynchronize() ); } - template void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream); - template void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream); + template void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, const float *table_color, const float *table_space, size_t table_step, int radius, short, short, cudaStream_t stream); + template void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, const float *table_color, const float *table_space, size_t table_step, int radius, short, short, cudaStream_t stream); } // namespace bilateral_filter }}} // namespace cv { namespace cuda { namespace cudev diff --git a/modules/cudastereo/src/disparity_bilateral_filter.cpp b/modules/cudastereo/src/disparity_bilateral_filter.cpp index 75cbce48a9..746d5d49cd 100644 --- a/modules/cudastereo/src/disparity_bilateral_filter.cpp +++ b/modules/cudastereo/src/disparity_bilateral_filter.cpp @@ -55,10 +55,8 @@ namespace cv { namespace cuda { namespace device { namespace disp_bilateral_filter { - void disp_load_constants(float* table_color, PtrStepSzf table_space, int ndisp, int radius, short edge_disc, short max_disc); - template - void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, cudaStream_t stream); + void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, const float *, const float *, size_t, int radius, short edge_disc, short max_disc, cudaStream_t stream); } }}} @@ -165,7 +163,7 @@ namespace const short edge_disc = std::max(short(1), short(ndisp * edge_threshold + 0.5)); const short max_disc = short(ndisp * max_disc_threshold + 0.5); - disp_load_constants(table_color.ptr(), table_space, ndisp, radius, edge_disc, max_disc); + size_t table_space_step = table_space.step / sizeof(float); _dst.create(disp.size(), disp.type()); GpuMat dst = _dst.getGpuMat(); @@ -173,7 +171,7 @@ namespace if (dst.data != disp.data) disp.copyTo(dst, stream); - disp_bilateral_filter(dst, img, img.channels(), iters, StreamAccessor::getStream(stream)); + disp_bilateral_filter(dst, img, img.channels(), iters, table_color.ptr(), (float *)table_space.data, table_space_step, radius, edge_disc, max_disc, StreamAccessor::getStream(stream)); } void DispBilateralFilterImpl::apply(InputArray _disp, InputArray _image, OutputArray dst, Stream& stream) From 1533d0448f130cbec92c9bba0e200f9864824d2f Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Tue, 24 Jun 2014 11:09:46 -0700 Subject: [PATCH 066/136] cdata_weight always positive; fewer multiplications. --- modules/cudastereo/src/cuda/stereocsbp.cu | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index b1426607dd..b10007e003 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -103,7 +103,7 @@ namespace cv { namespace cuda { namespace device { static __device__ __forceinline__ float compute(const uchar* left, const uchar* right) { - return fmin(cdata_weight * ::abs((int)*left - *right), cdata_weight * cmax_data_term); + return cdata_weight * fmin( ::abs((int)*left - *right), cmax_data_term); } }; template <> struct DataCostPerPixel<3> @@ -114,7 +114,7 @@ namespace cv { namespace cuda { namespace device float tg = 0.587f * ::abs((int)left[1] - right[1]); float tr = 0.299f * ::abs((int)left[2] - right[2]); - return fmin(cdata_weight * (tr + tg + tb), cdata_weight * cmax_data_term); + return cdata_weight * fmin(tr + tg + tb, cmax_data_term); } }; template <> struct DataCostPerPixel<4> @@ -128,7 +128,7 @@ namespace cv { namespace cuda { namespace device float tg = 0.587f * ::abs((int)l.y - r.y); float tr = 0.299f * ::abs((int)l.z - r.z); - return fmin(cdata_weight * (tr + tg + tb), cdata_weight * cmax_data_term); + return cdata_weight * fmin(tr + tg + tb, cmax_data_term); } }; From e532bd50d5f631cb27585176087096461012073d Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Thu, 26 Jun 2014 12:06:25 -0700 Subject: [PATCH 067/136] Move shared interface to header file rather than repeating. --- .../cudastereo/src/cuda/disparity_bilateral_filter.cu | 2 ++ .../cudastereo/src/cuda/disparity_bilateral_filter.hpp | 8 ++++++++ modules/cudastereo/src/disparity_bilateral_filter.cpp | 9 +-------- 3 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 modules/cudastereo/src/cuda/disparity_bilateral_filter.hpp diff --git a/modules/cudastereo/src/cuda/disparity_bilateral_filter.cu b/modules/cudastereo/src/cuda/disparity_bilateral_filter.cu index 5b16f8c108..a9f2d2650c 100644 --- a/modules/cudastereo/src/cuda/disparity_bilateral_filter.cu +++ b/modules/cudastereo/src/cuda/disparity_bilateral_filter.cu @@ -45,6 +45,8 @@ #include "opencv2/core/cuda/common.hpp" #include "opencv2/core/cuda/limits.hpp" +#include "cuda/disparity_bilateral_filter.hpp" + namespace cv { namespace cuda { namespace device { namespace disp_bilateral_filter diff --git a/modules/cudastereo/src/cuda/disparity_bilateral_filter.hpp b/modules/cudastereo/src/cuda/disparity_bilateral_filter.hpp new file mode 100644 index 0000000000..95be834573 --- /dev/null +++ b/modules/cudastereo/src/cuda/disparity_bilateral_filter.hpp @@ -0,0 +1,8 @@ +namespace cv { namespace cuda { namespace device +{ + namespace disp_bilateral_filter + { + template + void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, const float *, const float *, size_t, int radius, short edge_disc, short max_disc, cudaStream_t stream); + } +}}} diff --git a/modules/cudastereo/src/disparity_bilateral_filter.cpp b/modules/cudastereo/src/disparity_bilateral_filter.cpp index 746d5d49cd..c59e3b2cb4 100644 --- a/modules/cudastereo/src/disparity_bilateral_filter.cpp +++ b/modules/cudastereo/src/disparity_bilateral_filter.cpp @@ -51,14 +51,7 @@ Ptr cv::cuda::createDisparityBilateralFilter(int #else /* !defined (HAVE_CUDA) */ -namespace cv { namespace cuda { namespace device -{ - namespace disp_bilateral_filter - { - template - void disp_bilateral_filter(PtrStepSz disp, PtrStepSzb img, int channels, int iters, const float *, const float *, size_t, int radius, short edge_disc, short max_disc, cudaStream_t stream); - } -}}} +#include "cuda/disparity_bilateral_filter.hpp" namespace { From fe29ed461cb61f9e0105ac18a2ef8aa727156ca4 Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Thu, 26 Jun 2014 14:06:45 -0700 Subject: [PATCH 068/136] Move shared interface to header file rather than repeating. --- modules/cudastereo/src/cuda/stereocsbp.cu | 2 ++ modules/cudastereo/src/cuda/stereocsbp.hpp | 31 +++++++++++++++++++++ modules/cudastereo/src/stereocsbp.cpp | 32 +--------------------- 3 files changed, 34 insertions(+), 31 deletions(-) create mode 100644 modules/cudastereo/src/cuda/stereocsbp.hpp diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index b10007e003..dc3dbcce9e 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -48,6 +48,8 @@ #include "opencv2/core/cuda/reduce.hpp" #include "opencv2/core/cuda/functional.hpp" +#include "cuda/stereocsbp.hpp" + namespace cv { namespace cuda { namespace device { namespace stereocsbp diff --git a/modules/cudastereo/src/cuda/stereocsbp.hpp b/modules/cudastereo/src/cuda/stereocsbp.hpp new file mode 100644 index 0000000000..9b90732ffb --- /dev/null +++ b/modules/cudastereo/src/cuda/stereocsbp.hpp @@ -0,0 +1,31 @@ +namespace cv { namespace cuda { namespace device +{ + namespace stereocsbp + { + void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th, + const PtrStepSzb& left, const PtrStepSzb& right, const PtrStepSzb& temp); + + template + void init_data_cost(int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, + int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); + + template + void compute_data_cost(const T* disp_selected_pyr, T* data_cost, size_t msg_step, + int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); + + template + void init_message(T* u_new, T* d_new, T* l_new, T* r_new, + const T* u_cur, const T* d_cur, const T* l_cur, const T* r_cur, + T* selected_disp_pyr_new, const T* selected_disp_pyr_cur, + T* data_cost_selected, const T* data_cost, size_t msg_step, + int h, int w, int nr_plane, int h2, int w2, int nr_plane2, cudaStream_t stream); + + template + void calc_all_iterations(T* u, T* d, T* l, T* r, const T* data_cost_selected, + const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, cudaStream_t stream); + + template + void compute_disp(const T* u, const T* d, const T* l, const T* r, const T* data_cost_selected, const T* disp_selected, size_t msg_step, + const PtrStepSz& disp, int nr_plane, cudaStream_t stream); + } +}}} diff --git a/modules/cudastereo/src/stereocsbp.cpp b/modules/cudastereo/src/stereocsbp.cpp index 474562baf2..2d25bee37d 100644 --- a/modules/cudastereo/src/stereocsbp.cpp +++ b/modules/cudastereo/src/stereocsbp.cpp @@ -53,37 +53,7 @@ Ptr cv::cuda::createStereoConstantSpaceBP(int, int, #else /* !defined (HAVE_CUDA) */ -namespace cv { namespace cuda { namespace device -{ - namespace stereocsbp - { - void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th, - const PtrStepSzb& left, const PtrStepSzb& right, const PtrStepSzb& temp); - - template - void init_data_cost(int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, - int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); - - template - void compute_data_cost(const T* disp_selected_pyr, T* data_cost, size_t msg_step, - int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); - - template - void init_message(T* u_new, T* d_new, T* l_new, T* r_new, - const T* u_cur, const T* d_cur, const T* l_cur, const T* r_cur, - T* selected_disp_pyr_new, const T* selected_disp_pyr_cur, - T* data_cost_selected, const T* data_cost, size_t msg_step, - int h, int w, int nr_plane, int h2, int w2, int nr_plane2, cudaStream_t stream); - - template - void calc_all_iterations(T* u, T* d, T* l, T* r, const T* data_cost_selected, - const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, cudaStream_t stream); - - template - void compute_disp(const T* u, const T* d, const T* l, const T* r, const T* data_cost_selected, const T* disp_selected, size_t msg_step, - const PtrStepSz& disp, int nr_plane, cudaStream_t stream); - } -}}} +#include "cuda/stereocsbp.hpp" namespace { From 2982e77495356985e4dc8c4e453f2e2b399a1388 Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Thu, 26 Jun 2014 15:31:21 -0700 Subject: [PATCH 069/136] Pass in images and scratch space so that multiple copies can run concurrently. --- modules/cudastereo/src/cuda/stereocsbp.cu | 100 ++++++++++----------- modules/cudastereo/src/cuda/stereocsbp.hpp | 10 +-- modules/cudastereo/src/stereocsbp.cpp | 20 +++-- 3 files changed, 62 insertions(+), 68 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index dc3dbcce9e..a8c70c92de 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -72,13 +72,9 @@ namespace cv { namespace cuda { namespace device __constant__ size_t cdisp_step1; __constant__ size_t cdisp_step2; - __constant__ uchar* cleft; - __constant__ uchar* cright; - __constant__ uchar* ctemp; - void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th, - const PtrStepSzb& left, const PtrStepSzb& right, const PtrStepSzb& temp) + size_t leftstep) { cudaSafeCall( cudaMemcpyToSymbol(cndisp, &ndisp, sizeof(int)) ); @@ -89,11 +85,7 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cth, &min_disp_th, sizeof(int)) ); - cudaSafeCall( cudaMemcpyToSymbol(cimg_step, &left.step, sizeof(size_t)) ); - - cudaSafeCall( cudaMemcpyToSymbol(cleft, &left.data, sizeof(left.data)) ); - cudaSafeCall( cudaMemcpyToSymbol(cright, &right.data, sizeof(right.data)) ); - cudaSafeCall( cudaMemcpyToSymbol(ctemp, &temp.data, sizeof(temp.data)) ); + cudaSafeCall( cudaMemcpyToSymbol(cimg_step, &leftstep, sizeof(size_t)) ); } /////////////////////////////////////////////////////////////// @@ -135,7 +127,7 @@ namespace cv { namespace cuda { namespace device }; template - __global__ void get_first_k_initial_global(T* data_cost_selected_, T *selected_disp_pyr, int h, int w, int nr_plane) + __global__ void get_first_k_initial_global(uchar *ctemp, T* data_cost_selected_, T *selected_disp_pyr, int h, int w, int nr_plane) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -169,7 +161,7 @@ namespace cv { namespace cuda { namespace device template - __global__ void get_first_k_initial_local(T* data_cost_selected_, T* selected_disp_pyr, int h, int w, int nr_plane) + __global__ void get_first_k_initial_local(uchar *ctemp, T* data_cost_selected_, T* selected_disp_pyr, int h, int w, int nr_plane) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -225,7 +217,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost(int h, int w, int level) + __global__ void init_data_cost(uchar *cleft, uchar *cright, uchar *ctemp, int h, int w, int level) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -265,7 +257,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost_reduce(int level, int rows, int cols, int h) + __global__ void init_data_cost_reduce(uchar *cleft, uchar *cright, uchar *ctemp, int level, int rows, int cols, int h) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -313,7 +305,7 @@ namespace cv { namespace cuda { namespace device template - void init_data_cost_caller_(int /*rows*/, int /*cols*/, int h, int w, int level, int /*ndisp*/, int channels, cudaStream_t stream) + void init_data_cost_caller_(uchar *cleft, uchar *cright, uchar *ctemp, int /*rows*/, int /*cols*/, int h, int w, int level, int /*ndisp*/, int channels, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -323,15 +315,15 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost<<>>(h, w, level); break; - case 3: init_data_cost<<>>(h, w, level); break; - case 4: init_data_cost<<>>(h, w, level); break; + case 1: init_data_cost<<>>(cleft, cright, ctemp, h, w, level); break; + case 3: init_data_cost<<>>(cleft, cright, ctemp, h, w, level); break; + case 4: init_data_cost<<>>(cleft, cright, ctemp, h, w, level); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void init_data_cost_reduce_caller_(int rows, int cols, int h, int w, int level, int ndisp, int channels, cudaStream_t stream) + void init_data_cost_reduce_caller_(uchar *cleft, uchar *cright, uchar *ctemp, int rows, int cols, int h, int w, int level, int ndisp, int channels, cudaStream_t stream) { const int threadsNum = 256; const size_t smem_size = threadsNum * sizeof(float); @@ -342,19 +334,19 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost_reduce<<>>(level, rows, cols, h); break; - case 3: init_data_cost_reduce<<>>(level, rows, cols, h); break; - case 4: init_data_cost_reduce<<>>(level, rows, cols, h); break; + case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, level, rows, cols, h); break; + case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, level, rows, cols, h); break; + case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, level, rows, cols, h); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void init_data_cost(int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, + void init_data_cost(uchar *cleft, uchar *cright, uchar *ctemp, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream) { - typedef void (*InitDataCostCaller)(int cols, int rows, int w, int h, int level, int ndisp, int channels, cudaStream_t stream); + typedef void (*InitDataCostCaller)(uchar *cleft, uchar *cright, uchar *ctemp, int cols, int rows, int w, int h, int level, int ndisp, int channels, cudaStream_t stream); static const InitDataCostCaller init_data_cost_callers[] = { @@ -367,7 +359,7 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step, sizeof(size_t)) ); cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - init_data_cost_callers[level](rows, cols, h, w, level, ndisp, channels, stream); + init_data_cost_callers[level](cleft, cright, ctemp, rows, cols, h, w, level, ndisp, channels, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) @@ -380,9 +372,9 @@ namespace cv { namespace cuda { namespace device grid.y = divUp(h, threads.y); if (use_local_init_data_cost == true) - get_first_k_initial_local<<>> (data_cost_selected, disp_selected_pyr, h, w, nr_plane); + get_first_k_initial_local<<>> (ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane); else - get_first_k_initial_global<<>>(data_cost_selected, disp_selected_pyr, h, w, nr_plane); + get_first_k_initial_global<<>>(ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane); cudaSafeCall( cudaGetLastError() ); @@ -390,10 +382,10 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaDeviceSynchronize() ); } - template void init_data_cost(int rows, int cols, short* disp_selected_pyr, short* data_cost_selected, size_t msg_step, + template void init_data_cost(uchar *cleft, uchar *cright, uchar *ctemp, int rows, int cols, short* disp_selected_pyr, short* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); - template void init_data_cost(int rows, int cols, float* disp_selected_pyr, float* data_cost_selected, size_t msg_step, + template void init_data_cost(uchar *cleft, uchar *cright, uchar *ctemp, int rows, int cols, float* disp_selected_pyr, float* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); /////////////////////////////////////////////////////////////// @@ -401,7 +393,7 @@ namespace cv { namespace cuda { namespace device /////////////////////////////////////////////////////////////// template - __global__ void compute_data_cost(const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane) + __global__ void compute_data_cost(uchar *cleft, uchar *cright, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -444,7 +436,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void compute_data_cost_reduce(const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane) + __global__ void compute_data_cost_reduce(uchar *cleft, uchar *cright, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -494,7 +486,7 @@ namespace cv { namespace cuda { namespace device } template - void compute_data_cost_caller_(const T* disp_selected_pyr, T* data_cost, int /*rows*/, int /*cols*/, + void compute_data_cost_caller_(uchar *cleft, uchar *cright, const T* disp_selected_pyr, T* data_cost, int /*rows*/, int /*cols*/, int h, int w, int level, int nr_plane, int channels, cudaStream_t stream) { dim3 threads(32, 8, 1); @@ -505,15 +497,15 @@ namespace cv { namespace cuda { namespace device switch(channels) { - case 1: compute_data_cost<<>>(disp_selected_pyr, data_cost, h, w, level, nr_plane); break; - case 3: compute_data_cost<<>>(disp_selected_pyr, data_cost, h, w, level, nr_plane); break; - case 4: compute_data_cost<<>>(disp_selected_pyr, data_cost, h, w, level, nr_plane); break; + case 1: compute_data_cost<<>>(cleft, cright, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; + case 3: compute_data_cost<<>>(cleft, cright, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; + case 4: compute_data_cost<<>>(cleft, cright, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void compute_data_cost_reduce_caller_(const T* disp_selected_pyr, T* data_cost, int rows, int cols, + void compute_data_cost_reduce_caller_(uchar *cleft, uchar *cright, const T* disp_selected_pyr, T* data_cost, int rows, int cols, int h, int w, int level, int nr_plane, int channels, cudaStream_t stream) { const int threadsNum = 256; @@ -525,18 +517,18 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: compute_data_cost_reduce<<>>(disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; - case 3: compute_data_cost_reduce<<>>(disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; - case 4: compute_data_cost_reduce<<>>(disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; + case 1: compute_data_cost_reduce<<>>(cleft, cright, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; + case 3: compute_data_cost_reduce<<>>(cleft, cright, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; + case 4: compute_data_cost_reduce<<>>(cleft, cright, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void compute_data_cost(const T* disp_selected_pyr, T* data_cost, size_t msg_step, + void compute_data_cost(uchar *cleft, uchar *cright, const T* disp_selected_pyr, T* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream) { - typedef void (*ComputeDataCostCaller)(const T* disp_selected_pyr, T* data_cost, int rows, int cols, + typedef void (*ComputeDataCostCaller)(uchar *cleft, uchar *cright, const T* disp_selected_pyr, T* data_cost, int rows, int cols, int h, int w, int level, int nr_plane, int channels, cudaStream_t stream); static const ComputeDataCostCaller callers[] = @@ -552,17 +544,17 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cdisp_step2, &disp_step2, sizeof(size_t)) ); cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - callers[level](disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, stream); + callers[level](cleft, cright, disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } - template void compute_data_cost(const short* disp_selected_pyr, short* data_cost, size_t msg_step, + template void compute_data_cost(uchar *cleft, uchar *cright, const short* disp_selected_pyr, short* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); - template void compute_data_cost(const float* disp_selected_pyr, float* data_cost, size_t msg_step, + template void compute_data_cost(uchar *cleft, uchar *cright, const float* disp_selected_pyr, float* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); @@ -605,7 +597,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_message(T* u_new_, T* d_new_, T* l_new_, T* r_new_, + __global__ void init_message(uchar *ctemp, T* u_new_, T* d_new_, T* l_new_, T* r_new_, const T* u_cur_, const T* d_cur_, const T* l_cur_, const T* r_cur_, T* selected_disp_pyr_new, const T* selected_disp_pyr_cur, T* data_cost_selected_, const T* data_cost_, @@ -655,7 +647,7 @@ namespace cv { namespace cuda { namespace device template - void init_message(T* u_new, T* d_new, T* l_new, T* r_new, + void init_message(uchar *ctemp, T* u_new, T* d_new, T* l_new, T* r_new, const T* u_cur, const T* d_cur, const T* l_cur, const T* r_cur, T* selected_disp_pyr_new, const T* selected_disp_pyr_cur, T* data_cost_selected, const T* data_cost, size_t msg_step, @@ -674,7 +666,7 @@ namespace cv { namespace cuda { namespace device grid.x = divUp(w, threads.x); grid.y = divUp(h, threads.y); - init_message<<>>(u_new, d_new, l_new, r_new, + init_message<<>>(ctemp, u_new, d_new, l_new, r_new, u_cur, d_cur, l_cur, r_cur, selected_disp_pyr_new, selected_disp_pyr_cur, data_cost_selected, data_cost, @@ -686,13 +678,13 @@ namespace cv { namespace cuda { namespace device } - template void init_message(short* u_new, short* d_new, short* l_new, short* r_new, + template void init_message(uchar *ctemp, short* u_new, short* d_new, short* l_new, short* r_new, const short* u_cur, const short* d_cur, const short* l_cur, const short* r_cur, short* selected_disp_pyr_new, const short* selected_disp_pyr_cur, short* data_cost_selected, const short* data_cost, size_t msg_step, int h, int w, int nr_plane, int h2, int w2, int nr_plane2, cudaStream_t stream); - template void init_message(float* u_new, float* d_new, float* l_new, float* r_new, + template void init_message(uchar *ctemp, float* u_new, float* d_new, float* l_new, float* r_new, const float* u_cur, const float* d_cur, const float* l_cur, const float* r_cur, float* selected_disp_pyr_new, const float* selected_disp_pyr_cur, float* data_cost_selected, const float* data_cost, size_t msg_step, @@ -738,7 +730,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void compute_message(T* u_, T* d_, T* l_, T* r_, const T* data_cost_selected, const T* selected_disp_pyr_cur, int h, int w, int nr_plane, int i) + __global__ void compute_message(uchar *ctemp, T* u_, T* d_, T* l_, T* r_, const T* data_cost_selected, const T* selected_disp_pyr_cur, int h, int w, int nr_plane, int i) { int y = blockIdx.y * blockDim.y + threadIdx.y; int x = ((blockIdx.x * blockDim.x + threadIdx.x) << 1) + ((y + i) & 1); @@ -765,7 +757,7 @@ namespace cv { namespace cuda { namespace device template - void calc_all_iterations(T* u, T* d, T* l, T* r, const T* data_cost_selected, + void calc_all_iterations(uchar *ctemp, T* u, T* d, T* l, T* r, const T* data_cost_selected, const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, cudaStream_t stream) { size_t disp_step = msg_step * h; @@ -780,17 +772,17 @@ namespace cv { namespace cuda { namespace device for(int t = 0; t < iters; ++t) { - compute_message<<>>(u, d, l, r, data_cost_selected, selected_disp_pyr_cur, h, w, nr_plane, t & 1); + compute_message<<>>(ctemp, u, d, l, r, data_cost_selected, selected_disp_pyr_cur, h, w, nr_plane, t & 1); cudaSafeCall( cudaGetLastError() ); } if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); }; - template void calc_all_iterations(short* u, short* d, short* l, short* r, const short* data_cost_selected, const short* selected_disp_pyr_cur, size_t msg_step, + template void calc_all_iterations(uchar *ctemp, short* u, short* d, short* l, short* r, const short* data_cost_selected, const short* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, cudaStream_t stream); - template void calc_all_iterations(float* u, float* d, float* l, float* r, const float* data_cost_selected, const float* selected_disp_pyr_cur, size_t msg_step, + template void calc_all_iterations(uchar *ctemp, float* u, float* d, float* l, float* r, const float* data_cost_selected, const float* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, cudaStream_t stream); diff --git a/modules/cudastereo/src/cuda/stereocsbp.hpp b/modules/cudastereo/src/cuda/stereocsbp.hpp index 9b90732ffb..ff5e0e1f0c 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.hpp +++ b/modules/cudastereo/src/cuda/stereocsbp.hpp @@ -3,25 +3,25 @@ namespace cv { namespace cuda { namespace device namespace stereocsbp { void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th, - const PtrStepSzb& left, const PtrStepSzb& right, const PtrStepSzb& temp); + size_t leftstep); template - void init_data_cost(int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, + void init_data_cost(uchar *left, uchar *right, uchar *ctemp, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); template - void compute_data_cost(const T* disp_selected_pyr, T* data_cost, size_t msg_step, + void compute_data_cost(uchar *left, uchar *right, const T* disp_selected_pyr, T* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); template - void init_message(T* u_new, T* d_new, T* l_new, T* r_new, + void init_message(uchar *ctemp, T* u_new, T* d_new, T* l_new, T* r_new, const T* u_cur, const T* d_cur, const T* l_cur, const T* r_cur, T* selected_disp_pyr_new, const T* selected_disp_pyr_cur, T* data_cost_selected, const T* data_cost, size_t msg_step, int h, int w, int nr_plane, int h2, int w2, int nr_plane2, cudaStream_t stream); template - void calc_all_iterations(T* u, T* d, T* l, T* r, const T* data_cost_selected, + void calc_all_iterations(uchar *ctemp, T* u, T* d, T* l, T* r, const T* data_cost_selected, const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, cudaStream_t stream); template diff --git a/modules/cudastereo/src/stereocsbp.cpp b/modules/cudastereo/src/stereocsbp.cpp index 2d25bee37d..55afd8c6b9 100644 --- a/modules/cudastereo/src/stereocsbp.cpp +++ b/modules/cudastereo/src/stereocsbp.cpp @@ -222,7 +222,7 @@ namespace //////////////////////////////////////////////////////////////////////////// // Compute - load_constants(ndisp_, max_data_term_, data_weight_, max_disc_term_, disc_single_jump_, min_disp_th_, left, right, temp_); + load_constants(ndisp_, max_data_term_, data_weight_, max_disc_term_, disc_single_jump_, min_disp_th_, left.step); l[0].setTo(0, _stream); d[0].setTo(0, _stream); @@ -245,17 +245,18 @@ namespace { if (i == levels_ - 1) { - init_data_cost(left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), + init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), use_local_init_data_cost_, stream); } else { - compute_data_cost(disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, + compute_data_cost(left.ptr(), right.ptr(), disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), stream); int new_idx = (cur_idx + 1) & 1; - init_message(u[new_idx].ptr(), d[new_idx].ptr(), l[new_idx].ptr(), r[new_idx].ptr(), + init_message(temp_.ptr(), + u[new_idx].ptr(), d[new_idx].ptr(), l[new_idx].ptr(), r[new_idx].ptr(), u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), disp_selected_pyr[new_idx].ptr(), disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), data_cost.ptr(), elem_step, rows_pyr[i], @@ -264,7 +265,7 @@ namespace cur_idx = new_idx; } - calc_all_iterations(u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), + calc_all_iterations(temp_.ptr(), u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), data_cost_selected.ptr(), disp_selected_pyr[cur_idx].ptr(), elem_step, rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, stream); } @@ -275,17 +276,18 @@ namespace { if (i == levels_ - 1) { - init_data_cost(left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), + init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), use_local_init_data_cost_, stream); } else { - compute_data_cost(disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, + compute_data_cost(left.ptr(), right.ptr(), disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), stream); int new_idx = (cur_idx + 1) & 1; - init_message(u[new_idx].ptr(), d[new_idx].ptr(), l[new_idx].ptr(), r[new_idx].ptr(), + init_message(temp_.ptr(), + u[new_idx].ptr(), d[new_idx].ptr(), l[new_idx].ptr(), r[new_idx].ptr(), u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), disp_selected_pyr[new_idx].ptr(), disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), data_cost.ptr(), elem_step, rows_pyr[i], @@ -294,7 +296,7 @@ namespace cur_idx = new_idx; } - calc_all_iterations(u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), + calc_all_iterations(temp_.ptr(), u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), data_cost_selected.ptr(), disp_selected_pyr[cur_idx].ptr(), elem_step, rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, stream); } From d8d946a45838ab744f2f406d932f9f5ab1635d06 Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Thu, 26 Jun 2014 15:58:05 -0700 Subject: [PATCH 070/136] Constify cuda csbp --- modules/cudastereo/src/cuda/stereocsbp.cu | 32 +++++++++++----------- modules/cudastereo/src/cuda/stereocsbp.hpp | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index a8c70c92de..fa17742349 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -217,7 +217,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost(uchar *cleft, uchar *cright, uchar *ctemp, int h, int w, int level) + __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, int h, int w, int level) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -257,7 +257,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost_reduce(uchar *cleft, uchar *cright, uchar *ctemp, int level, int rows, int cols, int h) + __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, int level, int rows, int cols, int h) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -305,7 +305,7 @@ namespace cv { namespace cuda { namespace device template - void init_data_cost_caller_(uchar *cleft, uchar *cright, uchar *ctemp, int /*rows*/, int /*cols*/, int h, int w, int level, int /*ndisp*/, int channels, cudaStream_t stream) + void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, int /*rows*/, int /*cols*/, int h, int w, int level, int /*ndisp*/, int channels, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -323,7 +323,7 @@ namespace cv { namespace cuda { namespace device } template - void init_data_cost_reduce_caller_(uchar *cleft, uchar *cright, uchar *ctemp, int rows, int cols, int h, int w, int level, int ndisp, int channels, cudaStream_t stream) + void init_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, int rows, int cols, int h, int w, int level, int ndisp, int channels, cudaStream_t stream) { const int threadsNum = 256; const size_t smem_size = threadsNum * sizeof(float); @@ -342,11 +342,11 @@ namespace cv { namespace cuda { namespace device } template - void init_data_cost(uchar *cleft, uchar *cright, uchar *ctemp, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, + void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream) { - typedef void (*InitDataCostCaller)(uchar *cleft, uchar *cright, uchar *ctemp, int cols, int rows, int w, int h, int level, int ndisp, int channels, cudaStream_t stream); + typedef void (*InitDataCostCaller)(const uchar *cleft, const uchar *cright, uchar *ctemp, int cols, int rows, int w, int h, int level, int ndisp, int channels, cudaStream_t stream); static const InitDataCostCaller init_data_cost_callers[] = { @@ -382,10 +382,10 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaDeviceSynchronize() ); } - template void init_data_cost(uchar *cleft, uchar *cright, uchar *ctemp, int rows, int cols, short* disp_selected_pyr, short* data_cost_selected, size_t msg_step, + template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, int rows, int cols, short* disp_selected_pyr, short* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); - template void init_data_cost(uchar *cleft, uchar *cright, uchar *ctemp, int rows, int cols, float* disp_selected_pyr, float* data_cost_selected, size_t msg_step, + template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, int rows, int cols, float* disp_selected_pyr, float* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); /////////////////////////////////////////////////////////////// @@ -393,7 +393,7 @@ namespace cv { namespace cuda { namespace device /////////////////////////////////////////////////////////////// template - __global__ void compute_data_cost(uchar *cleft, uchar *cright, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane) + __global__ void compute_data_cost(const uchar *cleft, const uchar *cright, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -436,7 +436,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void compute_data_cost_reduce(uchar *cleft, uchar *cright, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane) + __global__ void compute_data_cost_reduce(const uchar *cleft, const uchar *cright, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -486,7 +486,7 @@ namespace cv { namespace cuda { namespace device } template - void compute_data_cost_caller_(uchar *cleft, uchar *cright, const T* disp_selected_pyr, T* data_cost, int /*rows*/, int /*cols*/, + void compute_data_cost_caller_(const uchar *cleft, const uchar *cright, const T* disp_selected_pyr, T* data_cost, int /*rows*/, int /*cols*/, int h, int w, int level, int nr_plane, int channels, cudaStream_t stream) { dim3 threads(32, 8, 1); @@ -505,7 +505,7 @@ namespace cv { namespace cuda { namespace device } template - void compute_data_cost_reduce_caller_(uchar *cleft, uchar *cright, const T* disp_selected_pyr, T* data_cost, int rows, int cols, + void compute_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, const T* disp_selected_pyr, T* data_cost, int rows, int cols, int h, int w, int level, int nr_plane, int channels, cudaStream_t stream) { const int threadsNum = 256; @@ -525,10 +525,10 @@ namespace cv { namespace cuda { namespace device } template - void compute_data_cost(uchar *cleft, uchar *cright, const T* disp_selected_pyr, T* data_cost, size_t msg_step, + void compute_data_cost(const uchar *cleft, const uchar *cright, const T* disp_selected_pyr, T* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream) { - typedef void (*ComputeDataCostCaller)(uchar *cleft, uchar *cright, const T* disp_selected_pyr, T* data_cost, int rows, int cols, + typedef void (*ComputeDataCostCaller)(const uchar *cleft, const uchar *cright, const T* disp_selected_pyr, T* data_cost, int rows, int cols, int h, int w, int level, int nr_plane, int channels, cudaStream_t stream); static const ComputeDataCostCaller callers[] = @@ -551,10 +551,10 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaDeviceSynchronize() ); } - template void compute_data_cost(uchar *cleft, uchar *cright, const short* disp_selected_pyr, short* data_cost, size_t msg_step, + template void compute_data_cost(const uchar *cleft, const uchar *cright, const short* disp_selected_pyr, short* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); - template void compute_data_cost(uchar *cleft, uchar *cright, const float* disp_selected_pyr, float* data_cost, size_t msg_step, + template void compute_data_cost(const uchar *cleft, const uchar *cright, const float* disp_selected_pyr, float* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); diff --git a/modules/cudastereo/src/cuda/stereocsbp.hpp b/modules/cudastereo/src/cuda/stereocsbp.hpp index ff5e0e1f0c..72b5ab04c7 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.hpp +++ b/modules/cudastereo/src/cuda/stereocsbp.hpp @@ -6,11 +6,11 @@ namespace cv { namespace cuda { namespace device size_t leftstep); template - void init_data_cost(uchar *left, uchar *right, uchar *ctemp, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, + void init_data_cost(const uchar *left, const uchar *right, uchar *ctemp, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); template - void compute_data_cost(uchar *left, uchar *right, const T* disp_selected_pyr, T* data_cost, size_t msg_step, + void compute_data_cost(const uchar *left, const uchar *right, const T* disp_selected_pyr, T* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); template From 2832cfdfe581c8a18c695d6737d8ab92f7f6f846 Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Fri, 27 Jun 2014 13:38:21 -0700 Subject: [PATCH 071/136] No longer use constant memory for image step. --- modules/cudastereo/src/cuda/stereocsbp.cu | 66 ++++++++++------------ modules/cudastereo/src/cuda/stereocsbp.hpp | 7 +-- modules/cudastereo/src/stereocsbp.cpp | 10 ++-- 3 files changed, 39 insertions(+), 44 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index fa17742349..d0097f3bee 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -67,14 +67,12 @@ namespace cv { namespace cuda { namespace device __constant__ int cth; - __constant__ size_t cimg_step; __constant__ size_t cmsg_step; __constant__ size_t cdisp_step1; __constant__ size_t cdisp_step2; - void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th, - size_t leftstep) + void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th) { cudaSafeCall( cudaMemcpyToSymbol(cndisp, &ndisp, sizeof(int)) ); @@ -84,8 +82,6 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cdisc_single_jump, &disc_single_jump, sizeof(float)) ); cudaSafeCall( cudaMemcpyToSymbol(cth, &min_disp_th, sizeof(int)) ); - - cudaSafeCall( cudaMemcpyToSymbol(cimg_step, &leftstep, sizeof(size_t)) ); } /////////////////////////////////////////////////////////////// @@ -217,7 +213,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, int h, int w, int level) + __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int h, int w, int level) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -257,7 +253,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, int level, int rows, int cols, int h) + __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int level, int rows, int cols, int h) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -305,7 +301,7 @@ namespace cv { namespace cuda { namespace device template - void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, int /*rows*/, int /*cols*/, int h, int w, int level, int /*ndisp*/, int channels, cudaStream_t stream) + void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int /*rows*/, int /*cols*/, int h, int w, int level, int /*ndisp*/, int channels, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -315,15 +311,15 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost<<>>(cleft, cright, ctemp, h, w, level); break; - case 3: init_data_cost<<>>(cleft, cright, ctemp, h, w, level); break; - case 4: init_data_cost<<>>(cleft, cright, ctemp, h, w, level); break; + case 1: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level); break; + case 3: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level); break; + case 4: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void init_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, int rows, int cols, int h, int w, int level, int ndisp, int channels, cudaStream_t stream) + void init_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, int h, int w, int level, int ndisp, int channels, cudaStream_t stream) { const int threadsNum = 256; const size_t smem_size = threadsNum * sizeof(float); @@ -334,19 +330,19 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, level, rows, cols, h); break; - case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, level, rows, cols, h); break; - case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, level, rows, cols, h); break; + case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h); break; + case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h); break; + case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, + void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream) { - typedef void (*InitDataCostCaller)(const uchar *cleft, const uchar *cright, uchar *ctemp, int cols, int rows, int w, int h, int level, int ndisp, int channels, cudaStream_t stream); + typedef void (*InitDataCostCaller)(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int cols, int rows, int w, int h, int level, int ndisp, int channels, cudaStream_t stream); static const InitDataCostCaller init_data_cost_callers[] = { @@ -359,7 +355,7 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step, sizeof(size_t)) ); cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - init_data_cost_callers[level](cleft, cright, ctemp, rows, cols, h, w, level, ndisp, channels, stream); + init_data_cost_callers[level](cleft, cright, ctemp, cimg_step, rows, cols, h, w, level, ndisp, channels, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) @@ -382,10 +378,10 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaDeviceSynchronize() ); } - template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, int rows, int cols, short* disp_selected_pyr, short* data_cost_selected, size_t msg_step, + template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, short* disp_selected_pyr, short* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); - template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, int rows, int cols, float* disp_selected_pyr, float* data_cost_selected, size_t msg_step, + template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, float* disp_selected_pyr, float* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); /////////////////////////////////////////////////////////////// @@ -393,7 +389,7 @@ namespace cv { namespace cuda { namespace device /////////////////////////////////////////////////////////////// template - __global__ void compute_data_cost(const uchar *cleft, const uchar *cright, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane) + __global__ void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -436,7 +432,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void compute_data_cost_reduce(const uchar *cleft, const uchar *cright, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane) + __global__ void compute_data_cost_reduce(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -486,7 +482,7 @@ namespace cv { namespace cuda { namespace device } template - void compute_data_cost_caller_(const uchar *cleft, const uchar *cright, const T* disp_selected_pyr, T* data_cost, int /*rows*/, int /*cols*/, + void compute_data_cost_caller_(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int /*rows*/, int /*cols*/, int h, int w, int level, int nr_plane, int channels, cudaStream_t stream) { dim3 threads(32, 8, 1); @@ -497,15 +493,15 @@ namespace cv { namespace cuda { namespace device switch(channels) { - case 1: compute_data_cost<<>>(cleft, cright, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; - case 3: compute_data_cost<<>>(cleft, cright, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; - case 4: compute_data_cost<<>>(cleft, cright, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; + case 1: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; + case 3: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; + case 4: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void compute_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, const T* disp_selected_pyr, T* data_cost, int rows, int cols, + void compute_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int rows, int cols, int h, int w, int level, int nr_plane, int channels, cudaStream_t stream) { const int threadsNum = 256; @@ -517,18 +513,18 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: compute_data_cost_reduce<<>>(cleft, cright, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; - case 3: compute_data_cost_reduce<<>>(cleft, cright, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; - case 4: compute_data_cost_reduce<<>>(cleft, cright, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; + case 1: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; + case 3: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; + case 4: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void compute_data_cost(const uchar *cleft, const uchar *cright, const T* disp_selected_pyr, T* data_cost, size_t msg_step, + void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream) { - typedef void (*ComputeDataCostCaller)(const uchar *cleft, const uchar *cright, const T* disp_selected_pyr, T* data_cost, int rows, int cols, + typedef void (*ComputeDataCostCaller)(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int rows, int cols, int h, int w, int level, int nr_plane, int channels, cudaStream_t stream); static const ComputeDataCostCaller callers[] = @@ -544,17 +540,17 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cdisp_step2, &disp_step2, sizeof(size_t)) ); cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - callers[level](cleft, cright, disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, stream); + callers[level](cleft, cright, cimg_step, disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } - template void compute_data_cost(const uchar *cleft, const uchar *cright, const short* disp_selected_pyr, short* data_cost, size_t msg_step, + template void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const short* disp_selected_pyr, short* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); - template void compute_data_cost(const uchar *cleft, const uchar *cright, const float* disp_selected_pyr, float* data_cost, size_t msg_step, + template void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const float* disp_selected_pyr, float* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); diff --git a/modules/cudastereo/src/cuda/stereocsbp.hpp b/modules/cudastereo/src/cuda/stereocsbp.hpp index 72b5ab04c7..0854a92a88 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.hpp +++ b/modules/cudastereo/src/cuda/stereocsbp.hpp @@ -2,15 +2,14 @@ namespace cv { namespace cuda { namespace device { namespace stereocsbp { - void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th, - size_t leftstep); + void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th); template - void init_data_cost(const uchar *left, const uchar *right, uchar *ctemp, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, + void init_data_cost(const uchar *left, const uchar *right, uchar *ctemp, size_t cimg_step, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); template - void compute_data_cost(const uchar *left, const uchar *right, const T* disp_selected_pyr, T* data_cost, size_t msg_step, + void compute_data_cost(const uchar *left, const uchar *right, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, size_t msg_step, int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); template diff --git a/modules/cudastereo/src/stereocsbp.cpp b/modules/cudastereo/src/stereocsbp.cpp index 55afd8c6b9..be4d8f1ee0 100644 --- a/modules/cudastereo/src/stereocsbp.cpp +++ b/modules/cudastereo/src/stereocsbp.cpp @@ -222,7 +222,7 @@ namespace //////////////////////////////////////////////////////////////////////////// // Compute - load_constants(ndisp_, max_data_term_, data_weight_, max_disc_term_, disc_single_jump_, min_disp_th_, left.step); + load_constants(ndisp_, max_data_term_, data_weight_, max_disc_term_, disc_single_jump_, min_disp_th_); l[0].setTo(0, _stream); d[0].setTo(0, _stream); @@ -245,12 +245,12 @@ namespace { if (i == levels_ - 1) { - init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), + init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.step, left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), use_local_init_data_cost_, stream); } else { - compute_data_cost(left.ptr(), right.ptr(), disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, + compute_data_cost(left.ptr(), right.ptr(), left.step, disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), stream); int new_idx = (cur_idx + 1) & 1; @@ -276,12 +276,12 @@ namespace { if (i == levels_ - 1) { - init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), + init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.step, left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), use_local_init_data_cost_, stream); } else { - compute_data_cost(left.ptr(), right.ptr(), disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, + compute_data_cost(left.ptr(), right.ptr(), left.step, disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), stream); int new_idx = (cur_idx + 1) & 1; From 0e2ea45c93bde7e92a61736654aaff9cc7318e5b Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 30 Jun 2014 08:46:14 -0700 Subject: [PATCH 072/136] ndisp no longer constant --- modules/cudastereo/src/cuda/stereocsbp.cu | 42 ++++++++++------------ modules/cudastereo/src/cuda/stereocsbp.hpp | 2 +- modules/cudastereo/src/stereocsbp.cpp | 2 +- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index d0097f3bee..4c3bde337f 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -58,8 +58,6 @@ namespace cv { namespace cuda { namespace device /////////////////////// load constants //////////////////////// /////////////////////////////////////////////////////////////// - __constant__ int cndisp; - __constant__ float cmax_data_term; __constant__ float cdata_weight; __constant__ float cmax_disc_term; @@ -72,10 +70,8 @@ namespace cv { namespace cuda { namespace device __constant__ size_t cdisp_step2; - void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th) + void load_constants(float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th) { - cudaSafeCall( cudaMemcpyToSymbol(cndisp, &ndisp, sizeof(int)) ); - cudaSafeCall( cudaMemcpyToSymbol(cmax_data_term, &max_data_term, sizeof(float)) ); cudaSafeCall( cudaMemcpyToSymbol(cdata_weight, &data_weight, sizeof(float)) ); cudaSafeCall( cudaMemcpyToSymbol(cmax_disc_term, &max_disc_term, sizeof(float)) ); @@ -123,7 +119,7 @@ namespace cv { namespace cuda { namespace device }; template - __global__ void get_first_k_initial_global(uchar *ctemp, T* data_cost_selected_, T *selected_disp_pyr, int h, int w, int nr_plane) + __global__ void get_first_k_initial_global(uchar *ctemp, T* data_cost_selected_, T *selected_disp_pyr, int h, int w, int nr_plane, int ndisp) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -138,7 +134,7 @@ namespace cv { namespace cuda { namespace device { T minimum = device::numeric_limits::max(); int id = 0; - for(int d = 0; d < cndisp; d++) + for(int d = 0; d < ndisp; d++) { T cur = data_cost[d * cdisp_step1]; if(cur < minimum) @@ -157,7 +153,7 @@ namespace cv { namespace cuda { namespace device template - __global__ void get_first_k_initial_local(uchar *ctemp, T* data_cost_selected_, T* selected_disp_pyr, int h, int w, int nr_plane) + __global__ void get_first_k_initial_local(uchar *ctemp, T* data_cost_selected_, T* selected_disp_pyr, int h, int w, int nr_plane, int ndisp) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -174,7 +170,7 @@ namespace cv { namespace cuda { namespace device T cur = data_cost[1 * cdisp_step1]; T next = data_cost[2 * cdisp_step1]; - for (int d = 1; d < cndisp - 1 && nr_local_minimum < nr_plane; d++) + for (int d = 1; d < ndisp - 1 && nr_local_minimum < nr_plane; d++) { if (cur < prev && cur < next) { @@ -195,7 +191,7 @@ namespace cv { namespace cuda { namespace device T minimum = numeric_limits::max(); int id = 0; - for (int d = 0; d < cndisp; d++) + for (int d = 0; d < ndisp; d++) { cur = data_cost[d * cdisp_step1]; if (cur < minimum) @@ -213,7 +209,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int h, int w, int level) + __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int h, int w, int level, int ndisp) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -228,7 +224,7 @@ namespace cv { namespace cuda { namespace device T* data_cost = (T*)ctemp + y * cmsg_step + x; - for(int d = 0; d < cndisp; ++d) + for(int d = 0; d < ndisp; ++d) { float val = 0.0f; for(int yi = y0; yi < yt; yi++) @@ -253,7 +249,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int level, int rows, int cols, int h) + __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int level, int rows, int cols, int h, int ndisp) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -261,7 +257,7 @@ namespace cv { namespace cuda { namespace device int tid = threadIdx.x; - if (d < cndisp) + if (d < ndisp) { int x0 = x_out << level; int y0 = y_out << level; @@ -301,7 +297,7 @@ namespace cv { namespace cuda { namespace device template - void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int /*rows*/, int /*cols*/, int h, int w, int level, int /*ndisp*/, int channels, cudaStream_t stream) + void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int /*rows*/, int /*cols*/, int h, int w, int level, int ndisp, int channels, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -311,9 +307,9 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level); break; - case 3: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level); break; - case 4: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level); break; + case 1: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp); break; + case 3: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp); break; + case 4: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } @@ -330,9 +326,9 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h); break; - case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h); break; - case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h); break; + case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp); break; + case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp); break; + case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } @@ -368,9 +364,9 @@ namespace cv { namespace cuda { namespace device grid.y = divUp(h, threads.y); if (use_local_init_data_cost == true) - get_first_k_initial_local<<>> (ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane); + get_first_k_initial_local<<>> (ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane, ndisp); else - get_first_k_initial_global<<>>(ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane); + get_first_k_initial_global<<>>(ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane, ndisp); cudaSafeCall( cudaGetLastError() ); diff --git a/modules/cudastereo/src/cuda/stereocsbp.hpp b/modules/cudastereo/src/cuda/stereocsbp.hpp index 0854a92a88..c9f3983256 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.hpp +++ b/modules/cudastereo/src/cuda/stereocsbp.hpp @@ -2,7 +2,7 @@ namespace cv { namespace cuda { namespace device { namespace stereocsbp { - void load_constants(int ndisp, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th); + void load_constants(float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th); template void init_data_cost(const uchar *left, const uchar *right, uchar *ctemp, size_t cimg_step, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, diff --git a/modules/cudastereo/src/stereocsbp.cpp b/modules/cudastereo/src/stereocsbp.cpp index be4d8f1ee0..946a14fb2b 100644 --- a/modules/cudastereo/src/stereocsbp.cpp +++ b/modules/cudastereo/src/stereocsbp.cpp @@ -222,7 +222,7 @@ namespace //////////////////////////////////////////////////////////////////////////// // Compute - load_constants(ndisp_, max_data_term_, data_weight_, max_disc_term_, disc_single_jump_, min_disp_th_); + load_constants(max_data_term_, data_weight_, max_disc_term_, disc_single_jump_, min_disp_th_); l[0].setTo(0, _stream); d[0].setTo(0, _stream); From 021b0cb4d53463b878b7b5a0bd1de3ccde5063db Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 30 Jun 2014 09:28:26 -0700 Subject: [PATCH 073/136] Pass max_disc_term as kernel parameter. --- modules/cudastereo/src/cuda/stereocsbp.cu | 26 ++++++++++------------ modules/cudastereo/src/cuda/stereocsbp.hpp | 4 ++-- modules/cudastereo/src/stereocsbp.cpp | 6 ++--- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index 4c3bde337f..582aaa6440 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -60,7 +60,6 @@ namespace cv { namespace cuda { namespace device __constant__ float cmax_data_term; __constant__ float cdata_weight; - __constant__ float cmax_disc_term; __constant__ float cdisc_single_jump; __constant__ int cth; @@ -70,11 +69,10 @@ namespace cv { namespace cuda { namespace device __constant__ size_t cdisp_step2; - void load_constants(float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th) + void load_constants(float max_data_term, float data_weight, float disc_single_jump, int min_disp_th) { cudaSafeCall( cudaMemcpyToSymbol(cmax_data_term, &max_data_term, sizeof(float)) ); cudaSafeCall( cudaMemcpyToSymbol(cdata_weight, &data_weight, sizeof(float)) ); - cudaSafeCall( cudaMemcpyToSymbol(cmax_disc_term, &max_disc_term, sizeof(float)) ); cudaSafeCall( cudaMemcpyToSymbol(cdisc_single_jump, &disc_single_jump, sizeof(float)) ); cudaSafeCall( cudaMemcpyToSymbol(cth, &min_disp_th, sizeof(int)) ); @@ -688,7 +686,7 @@ namespace cv { namespace cuda { namespace device template __device__ void message_per_pixel(const T* data, T* msg_dst, const T* msg1, const T* msg2, const T* msg3, - const T* dst_disp, const T* src_disp, int nr_plane, volatile T* temp) + const T* dst_disp, const T* src_disp, int nr_plane, int max_disc_term, volatile T* temp) { T minimum = numeric_limits::max(); @@ -706,7 +704,7 @@ namespace cv { namespace cuda { namespace device float sum = 0; for(int d = 0; d < nr_plane; d++) { - float cost_min = minimum + cmax_disc_term; + float cost_min = minimum + max_disc_term; T src_disp_reg = src_disp[d * cdisp_step1]; for(int d2 = 0; d2 < nr_plane; d2++) @@ -722,7 +720,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void compute_message(uchar *ctemp, T* u_, T* d_, T* l_, T* r_, const T* data_cost_selected, const T* selected_disp_pyr_cur, int h, int w, int nr_plane, int i) + __global__ void compute_message(uchar *ctemp, T* u_, T* d_, T* l_, T* r_, const T* data_cost_selected, const T* selected_disp_pyr_cur, int h, int w, int nr_plane, int i, int max_disc_term) { int y = blockIdx.y * blockDim.y + threadIdx.y; int x = ((blockIdx.x * blockDim.x + threadIdx.x) << 1) + ((y + i) & 1); @@ -740,17 +738,17 @@ namespace cv { namespace cuda { namespace device T* temp = (T*)ctemp + y * cmsg_step + x; - message_per_pixel(data, u, r - 1, u + cmsg_step, l + 1, disp, disp - cmsg_step, nr_plane, temp); - message_per_pixel(data, d, d - cmsg_step, r - 1, l + 1, disp, disp + cmsg_step, nr_plane, temp); - message_per_pixel(data, l, u + cmsg_step, d - cmsg_step, l + 1, disp, disp - 1, nr_plane, temp); - message_per_pixel(data, r, u + cmsg_step, d - cmsg_step, r - 1, disp, disp + 1, nr_plane, temp); + message_per_pixel(data, u, r - 1, u + cmsg_step, l + 1, disp, disp - cmsg_step, nr_plane, max_disc_term, temp); + message_per_pixel(data, d, d - cmsg_step, r - 1, l + 1, disp, disp + cmsg_step, nr_plane, max_disc_term, temp); + message_per_pixel(data, l, u + cmsg_step, d - cmsg_step, l + 1, disp, disp - 1, nr_plane, max_disc_term, temp); + message_per_pixel(data, r, u + cmsg_step, d - cmsg_step, r - 1, disp, disp + 1, nr_plane, max_disc_term, temp); } } template void calc_all_iterations(uchar *ctemp, T* u, T* d, T* l, T* r, const T* data_cost_selected, - const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, cudaStream_t stream) + const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, int max_disc_term, cudaStream_t stream) { size_t disp_step = msg_step * h; cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step, sizeof(size_t)) ); @@ -764,7 +762,7 @@ namespace cv { namespace cuda { namespace device for(int t = 0; t < iters; ++t) { - compute_message<<>>(ctemp, u, d, l, r, data_cost_selected, selected_disp_pyr_cur, h, w, nr_plane, t & 1); + compute_message<<>>(ctemp, u, d, l, r, data_cost_selected, selected_disp_pyr_cur, h, w, nr_plane, t & 1, max_disc_term); cudaSafeCall( cudaGetLastError() ); } if (stream == 0) @@ -772,10 +770,10 @@ namespace cv { namespace cuda { namespace device }; template void calc_all_iterations(uchar *ctemp, short* u, short* d, short* l, short* r, const short* data_cost_selected, const short* selected_disp_pyr_cur, size_t msg_step, - int h, int w, int nr_plane, int iters, cudaStream_t stream); + int h, int w, int nr_plane, int iters, int max_disc_term, cudaStream_t stream); template void calc_all_iterations(uchar *ctemp, float* u, float* d, float* l, float* r, const float* data_cost_selected, const float* selected_disp_pyr_cur, size_t msg_step, - int h, int w, int nr_plane, int iters, cudaStream_t stream); + int h, int w, int nr_plane, int iters, int max_disc_term, cudaStream_t stream); /////////////////////////////////////////////////////////////// diff --git a/modules/cudastereo/src/cuda/stereocsbp.hpp b/modules/cudastereo/src/cuda/stereocsbp.hpp index c9f3983256..80224754b9 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.hpp +++ b/modules/cudastereo/src/cuda/stereocsbp.hpp @@ -2,7 +2,7 @@ namespace cv { namespace cuda { namespace device { namespace stereocsbp { - void load_constants(float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th); + void load_constants(float max_data_term, float data_weight, float disc_single_jump, int min_disp_th); template void init_data_cost(const uchar *left, const uchar *right, uchar *ctemp, size_t cimg_step, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, @@ -21,7 +21,7 @@ namespace cv { namespace cuda { namespace device template void calc_all_iterations(uchar *ctemp, T* u, T* d, T* l, T* r, const T* data_cost_selected, - const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, cudaStream_t stream); + const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, int max_disc_term, cudaStream_t stream); template void compute_disp(const T* u, const T* d, const T* l, const T* r, const T* data_cost_selected, const T* disp_selected, size_t msg_step, diff --git a/modules/cudastereo/src/stereocsbp.cpp b/modules/cudastereo/src/stereocsbp.cpp index 946a14fb2b..12d673153d 100644 --- a/modules/cudastereo/src/stereocsbp.cpp +++ b/modules/cudastereo/src/stereocsbp.cpp @@ -222,7 +222,7 @@ namespace //////////////////////////////////////////////////////////////////////////// // Compute - load_constants(max_data_term_, data_weight_, max_disc_term_, disc_single_jump_, min_disp_th_); + load_constants(max_data_term_, data_weight_, disc_single_jump_, min_disp_th_); l[0].setTo(0, _stream); d[0].setTo(0, _stream); @@ -267,7 +267,7 @@ namespace calc_all_iterations(temp_.ptr(), u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), data_cost_selected.ptr(), disp_selected_pyr[cur_idx].ptr(), elem_step, - rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, stream); + rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, max_disc_term_, stream); } } else @@ -298,7 +298,7 @@ namespace calc_all_iterations(temp_.ptr(), u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), data_cost_selected.ptr(), disp_selected_pyr[cur_idx].ptr(), elem_step, - rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, stream); + rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, max_disc_term_, stream); } } From 3ab117df04d361c77a56d4a5400404f264256ff4 Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 30 Jun 2014 09:51:32 -0700 Subject: [PATCH 074/136] Change struct with single static function to function. --- modules/cudastereo/src/cuda/stereocsbp.cu | 53 ++++++++++------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index 582aaa6440..3ef665b05c 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -82,39 +82,30 @@ namespace cv { namespace cuda { namespace device /////////////////////// init data cost //////////////////////// /////////////////////////////////////////////////////////////// - template struct DataCostPerPixel; - template <> struct DataCostPerPixel<1> + template float __device__ pixeldiff(const uchar* left, const uchar* right); + template<> float __device__ __forceinline__ pixeldiff<1>(const uchar* left, const uchar* right) { - static __device__ __forceinline__ float compute(const uchar* left, const uchar* right) - { - return cdata_weight * fmin( ::abs((int)*left - *right), cmax_data_term); - } - }; - template <> struct DataCostPerPixel<3> + return cdata_weight * fmin( ::abs((int)*left - *right), cmax_data_term); + } + template <> float __device__ __forceinline__ pixeldiff<3>(const uchar* left, const uchar* right) { - static __device__ __forceinline__ float compute(const uchar* left, const uchar* right) - { - float tb = 0.114f * ::abs((int)left[0] - right[0]); - float tg = 0.587f * ::abs((int)left[1] - right[1]); - float tr = 0.299f * ::abs((int)left[2] - right[2]); + float tb = 0.114f * ::abs((int)left[0] - right[0]); + float tg = 0.587f * ::abs((int)left[1] - right[1]); + float tr = 0.299f * ::abs((int)left[2] - right[2]); - return cdata_weight * fmin(tr + tg + tb, cmax_data_term); - } - }; - template <> struct DataCostPerPixel<4> + return cdata_weight * fmin(tr + tg + tb, cmax_data_term); + } + template <> float __device__ __forceinline__ pixeldiff<4>(const uchar* left, const uchar* right) { - static __device__ __forceinline__ float compute(const uchar* left, const uchar* right) - { - uchar4 l = *((const uchar4*)left); - uchar4 r = *((const uchar4*)right); + uchar4 l = *((const uchar4*)left); + uchar4 r = *((const uchar4*)right); - float tb = 0.114f * ::abs((int)l.x - r.x); - float tg = 0.587f * ::abs((int)l.y - r.y); - float tr = 0.299f * ::abs((int)l.z - r.z); + float tb = 0.114f * ::abs((int)l.x - r.x); + float tg = 0.587f * ::abs((int)l.y - r.y); + float tr = 0.299f * ::abs((int)l.z - r.z); - return cdata_weight * fmin(tr + tg + tb, cmax_data_term); - } - }; + return cdata_weight * fmin(tr + tg + tb, cmax_data_term); + } template __global__ void get_first_k_initial_global(uchar *ctemp, T* data_cost_selected_, T *selected_disp_pyr, int h, int w, int nr_plane, int ndisp) @@ -237,7 +228,7 @@ namespace cv { namespace cuda { namespace device const uchar* lle = cleft + yi * cimg_step + xi * channels; const uchar* lri = cright + yi * cimg_step + xr * channels; - val += DataCostPerPixel::compute(lle, lri); + val += pixeldiff(lle, lri); } } } @@ -274,7 +265,7 @@ namespace cv { namespace cuda { namespace device for(int y = 0; y < len; ++y) { - val += DataCostPerPixel::compute(lle, lri); + val += pixeldiff(lle, lri); lle += cimg_step; lri += cimg_step; @@ -416,7 +407,7 @@ namespace cv { namespace cuda { namespace device const uchar* left_x = cleft + yi * cimg_step + xi * channels; const uchar* right_x = cright + yi * cimg_step + xr * channels; - val += DataCostPerPixel::compute(left_x, right_x); + val += pixeldiff(left_x, right_x); } } } @@ -458,7 +449,7 @@ namespace cv { namespace cuda { namespace device for(int y = 0; y < len; ++y) { - val += DataCostPerPixel::compute(lle, lri); + val += pixeldiff(lle, lri); lle += cimg_step; lri += cimg_step; From eed5cbc5db780e2c8ee5293f662cb663742c4e3e Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 30 Jun 2014 13:22:13 -0700 Subject: [PATCH 075/136] More constant removal. --- modules/cudastereo/src/cuda/stereocsbp.cu | 96 +++++++++++----------- modules/cudastereo/src/cuda/stereocsbp.hpp | 6 +- modules/cudastereo/src/stereocsbp.cpp | 10 +-- 3 files changed, 54 insertions(+), 58 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index 3ef665b05c..792df0c99c 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -58,8 +58,6 @@ namespace cv { namespace cuda { namespace device /////////////////////// load constants //////////////////////// /////////////////////////////////////////////////////////////// - __constant__ float cmax_data_term; - __constant__ float cdata_weight; __constant__ float cdisc_single_jump; __constant__ int cth; @@ -69,10 +67,8 @@ namespace cv { namespace cuda { namespace device __constant__ size_t cdisp_step2; - void load_constants(float max_data_term, float data_weight, float disc_single_jump, int min_disp_th) + void load_constants(float disc_single_jump, int min_disp_th) { - cudaSafeCall( cudaMemcpyToSymbol(cmax_data_term, &max_data_term, sizeof(float)) ); - cudaSafeCall( cudaMemcpyToSymbol(cdata_weight, &data_weight, sizeof(float)) ); cudaSafeCall( cudaMemcpyToSymbol(cdisc_single_jump, &disc_single_jump, sizeof(float)) ); cudaSafeCall( cudaMemcpyToSymbol(cth, &min_disp_th, sizeof(int)) ); @@ -82,20 +78,20 @@ namespace cv { namespace cuda { namespace device /////////////////////// init data cost //////////////////////// /////////////////////////////////////////////////////////////// - template float __device__ pixeldiff(const uchar* left, const uchar* right); - template<> float __device__ __forceinline__ pixeldiff<1>(const uchar* left, const uchar* right) + template static float __device__ pixeldiff(const uchar* left, const uchar* right, float max_data_term); + template<> __device__ __forceinline__ static float pixeldiff<1>(const uchar* left, const uchar* right, float max_data_term) { - return cdata_weight * fmin( ::abs((int)*left - *right), cmax_data_term); + return fmin( ::abs((int)*left - *right), max_data_term); } - template <> float __device__ __forceinline__ pixeldiff<3>(const uchar* left, const uchar* right) + template<> __device__ __forceinline__ static float pixeldiff<3>(const uchar* left, const uchar* right, float max_data_term) { float tb = 0.114f * ::abs((int)left[0] - right[0]); float tg = 0.587f * ::abs((int)left[1] - right[1]); float tr = 0.299f * ::abs((int)left[2] - right[2]); - return cdata_weight * fmin(tr + tg + tb, cmax_data_term); + return fmin(tr + tg + tb, max_data_term); } - template <> float __device__ __forceinline__ pixeldiff<4>(const uchar* left, const uchar* right) + template<> __device__ __forceinline__ static float pixeldiff<4>(const uchar* left, const uchar* right, float max_data_term) { uchar4 l = *((const uchar4*)left); uchar4 r = *((const uchar4*)right); @@ -104,7 +100,7 @@ namespace cv { namespace cuda { namespace device float tg = 0.587f * ::abs((int)l.y - r.y); float tr = 0.299f * ::abs((int)l.z - r.z); - return cdata_weight * fmin(tr + tg + tb, cmax_data_term); + return fmin(tr + tg + tb, max_data_term); } template @@ -198,7 +194,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int h, int w, int level, int ndisp) + __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int h, int w, int level, int ndisp, float data_weight, float max_data_term) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -222,13 +218,13 @@ namespace cv { namespace cuda { namespace device { int xr = xi - d; if(d < cth || xr < 0) - val += cdata_weight * cmax_data_term; + val += data_weight * max_data_term; else { const uchar* lle = cleft + yi * cimg_step + xi * channels; const uchar* lri = cright + yi * cimg_step + xr * channels; - val += pixeldiff(lle, lri); + val += data_weight * pixeldiff(lle, lri, max_data_term); } } } @@ -238,7 +234,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int level, int rows, int cols, int h, int ndisp) + __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int level, int rows, int cols, int h, int ndisp, float data_weight, float max_data_term) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -257,7 +253,7 @@ namespace cv { namespace cuda { namespace device if (x0 + tid < cols) { if (x0 + tid - d < 0 || d < cth) - val = cdata_weight * cmax_data_term * len; + val = data_weight * max_data_term * len; else { const uchar* lle = cleft + y0 * cimg_step + channels * (x0 + tid ); @@ -265,7 +261,7 @@ namespace cv { namespace cuda { namespace device for(int y = 0; y < len; ++y) { - val += pixeldiff(lle, lri); + val += data_weight * pixeldiff(lle, lri, max_data_term); lle += cimg_step; lri += cimg_step; @@ -286,7 +282,7 @@ namespace cv { namespace cuda { namespace device template - void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int /*rows*/, int /*cols*/, int h, int w, int level, int ndisp, int channels, cudaStream_t stream) + void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int /*rows*/, int /*cols*/, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -296,15 +292,15 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp); break; - case 3: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp); break; - case 4: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp); break; + case 1: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term); break; + case 3: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term); break; + case 4: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void init_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, int h, int w, int level, int ndisp, int channels, cudaStream_t stream) + void init_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, cudaStream_t stream) { const int threadsNum = 256; const size_t smem_size = threadsNum * sizeof(float); @@ -315,19 +311,19 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp); break; - case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp); break; - case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp); break; + case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term); break; + case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term); break; + case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, - int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream) + int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, bool use_local_init_data_cost, cudaStream_t stream) { - typedef void (*InitDataCostCaller)(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int cols, int rows, int w, int h, int level, int ndisp, int channels, cudaStream_t stream); + typedef void (*InitDataCostCaller)(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int cols, int rows, int w, int h, int level, int ndisp, int channels, float data_weight, float max_data_term, cudaStream_t stream); static const InitDataCostCaller init_data_cost_callers[] = { @@ -340,7 +336,7 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step, sizeof(size_t)) ); cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - init_data_cost_callers[level](cleft, cright, ctemp, cimg_step, rows, cols, h, w, level, ndisp, channels, stream); + init_data_cost_callers[level](cleft, cright, ctemp, cimg_step, rows, cols, h, w, level, ndisp, channels, data_weight, max_data_term, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) @@ -364,17 +360,17 @@ namespace cv { namespace cuda { namespace device } template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, short* disp_selected_pyr, short* data_cost_selected, size_t msg_step, - int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); + int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, bool use_local_init_data_cost, cudaStream_t stream); template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, float* disp_selected_pyr, float* data_cost_selected, size_t msg_step, - int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); + int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, bool use_local_init_data_cost, cudaStream_t stream); /////////////////////////////////////////////////////////////// ////////////////////// compute data cost ////////////////////// /////////////////////////////////////////////////////////////// template - __global__ void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane) + __global__ void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane, float data_weight, float max_data_term) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -401,13 +397,13 @@ namespace cv { namespace cuda { namespace device int xr = xi - sel_disp; if (xr < 0 || sel_disp < cth) - val += cdata_weight * cmax_data_term; + val += data_weight * max_data_term; else { const uchar* left_x = cleft + yi * cimg_step + xi * channels; const uchar* right_x = cright + yi * cimg_step + xr * channels; - val += pixeldiff(left_x, right_x); + val += data_weight * pixeldiff(left_x, right_x, max_data_term); } } } @@ -417,7 +413,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void compute_data_cost_reduce(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane) + __global__ void compute_data_cost_reduce(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane, float data_weight, float max_data_term) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -441,7 +437,7 @@ namespace cv { namespace cuda { namespace device if (x0 + tid < cols) { if (x0 + tid - sel_disp < 0 || sel_disp < cth) - val = cdata_weight * cmax_data_term * len; + val = data_weight * max_data_term * len; else { const uchar* lle = cleft + y0 * cimg_step + channels * (x0 + tid ); @@ -449,7 +445,7 @@ namespace cv { namespace cuda { namespace device for(int y = 0; y < len; ++y) { - val += pixeldiff(lle, lri); + val += data_weight * pixeldiff(lle, lri, max_data_term); lle += cimg_step; lri += cimg_step; @@ -468,7 +464,7 @@ namespace cv { namespace cuda { namespace device template void compute_data_cost_caller_(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int /*rows*/, int /*cols*/, - int h, int w, int level, int nr_plane, int channels, cudaStream_t stream) + int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -478,16 +474,16 @@ namespace cv { namespace cuda { namespace device switch(channels) { - case 1: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; - case 3: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; - case 4: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane); break; + case 1: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term); break; + case 3: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term); break; + case 4: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template void compute_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int rows, int cols, - int h, int w, int level, int nr_plane, int channels, cudaStream_t stream) + int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream) { const int threadsNum = 256; const size_t smem_size = threadsNum * sizeof(float); @@ -498,19 +494,19 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; - case 3: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; - case 4: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane); break; + case 1: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term); break; + case 3: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term); break; + case 4: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, size_t msg_step, - int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream) + int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream) { typedef void (*ComputeDataCostCaller)(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int rows, int cols, - int h, int w, int level, int nr_plane, int channels, cudaStream_t stream); + int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream); static const ComputeDataCostCaller callers[] = { @@ -525,7 +521,7 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cdisp_step2, &disp_step2, sizeof(size_t)) ); cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - callers[level](cleft, cright, cimg_step, disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, stream); + callers[level](cleft, cright, cimg_step, disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, data_weight, max_data_term, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) @@ -533,10 +529,10 @@ namespace cv { namespace cuda { namespace device } template void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const short* disp_selected_pyr, short* data_cost, size_t msg_step, - int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); + int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream); template void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const float* disp_selected_pyr, float* data_cost, size_t msg_step, - int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); + int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream); /////////////////////////////////////////////////////////////// diff --git a/modules/cudastereo/src/cuda/stereocsbp.hpp b/modules/cudastereo/src/cuda/stereocsbp.hpp index 80224754b9..04337bbd1d 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.hpp +++ b/modules/cudastereo/src/cuda/stereocsbp.hpp @@ -2,15 +2,15 @@ namespace cv { namespace cuda { namespace device { namespace stereocsbp { - void load_constants(float max_data_term, float data_weight, float disc_single_jump, int min_disp_th); + void load_constants(float disc_single_jump, int min_disp_th); template void init_data_cost(const uchar *left, const uchar *right, uchar *ctemp, size_t cimg_step, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, - int h, int w, int level, int nr_plane, int ndisp, int channels, bool use_local_init_data_cost, cudaStream_t stream); + int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, bool use_local_init_data_cost, cudaStream_t stream); template void compute_data_cost(const uchar *left, const uchar *right, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, size_t msg_step, - int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, cudaStream_t stream); + int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream); template void init_message(uchar *ctemp, T* u_new, T* d_new, T* l_new, T* r_new, diff --git a/modules/cudastereo/src/stereocsbp.cpp b/modules/cudastereo/src/stereocsbp.cpp index 12d673153d..14d6d2589f 100644 --- a/modules/cudastereo/src/stereocsbp.cpp +++ b/modules/cudastereo/src/stereocsbp.cpp @@ -222,7 +222,7 @@ namespace //////////////////////////////////////////////////////////////////////////// // Compute - load_constants(max_data_term_, data_weight_, disc_single_jump_, min_disp_th_); + load_constants(disc_single_jump_, min_disp_th_); l[0].setTo(0, _stream); d[0].setTo(0, _stream); @@ -246,12 +246,12 @@ namespace if (i == levels_ - 1) { init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.step, left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), - elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), use_local_init_data_cost_, stream); + elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), data_weight_, max_data_term_, use_local_init_data_cost_, stream); } else { compute_data_cost(left.ptr(), right.ptr(), left.step, disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, - left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), stream); + left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), data_weight_, max_data_term_, stream); int new_idx = (cur_idx + 1) & 1; @@ -277,12 +277,12 @@ namespace if (i == levels_ - 1) { init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.step, left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), - elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), use_local_init_data_cost_, stream); + elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), data_weight_, max_data_term_, use_local_init_data_cost_, stream); } else { compute_data_cost(left.ptr(), right.ptr(), left.step, disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, - left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), stream); + left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), data_weight_, max_data_term_, stream); int new_idx = (cur_idx + 1) & 1; From 9bc71f4cb61ac82ce166e4638b6cc0b8d5d5c5ae Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 30 Jun 2014 14:20:46 -0700 Subject: [PATCH 076/136] Deconstify minimum disparity. --- modules/cudastereo/src/cuda/stereocsbp.cu | 79 +++++++++++----------- modules/cudastereo/src/cuda/stereocsbp.hpp | 7 +- modules/cudastereo/src/stereocsbp.cpp | 10 +-- 3 files changed, 47 insertions(+), 49 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index 792df0c99c..fc6f4f3daf 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -60,18 +60,14 @@ namespace cv { namespace cuda { namespace device __constant__ float cdisc_single_jump; - __constant__ int cth; - __constant__ size_t cmsg_step; __constant__ size_t cdisp_step1; __constant__ size_t cdisp_step2; - void load_constants(float disc_single_jump, int min_disp_th) + void load_constants(float disc_single_jump) { cudaSafeCall( cudaMemcpyToSymbol(cdisc_single_jump, &disc_single_jump, sizeof(float)) ); - - cudaSafeCall( cudaMemcpyToSymbol(cth, &min_disp_th, sizeof(int)) ); } /////////////////////////////////////////////////////////////// @@ -194,7 +190,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int h, int w, int level, int ndisp, float data_weight, float max_data_term) + __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int h, int w, int level, int ndisp, float data_weight, float max_data_term, int min_disp) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -217,7 +213,7 @@ namespace cv { namespace cuda { namespace device for(int xi = x0; xi < xt; xi++) { int xr = xi - d; - if(d < cth || xr < 0) + if(d < min_disp || xr < 0) val += data_weight * max_data_term; else { @@ -234,7 +230,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int level, int rows, int cols, int h, int ndisp, float data_weight, float max_data_term) + __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int level, int rows, int cols, int h, int ndisp, float data_weight, float max_data_term, int min_disp) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -252,7 +248,7 @@ namespace cv { namespace cuda { namespace device float val = 0.0f; if (x0 + tid < cols) { - if (x0 + tid - d < 0 || d < cth) + if (x0 + tid - d < 0 || d < min_disp) val = data_weight * max_data_term * len; else { @@ -282,7 +278,7 @@ namespace cv { namespace cuda { namespace device template - void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int /*rows*/, int /*cols*/, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, cudaStream_t stream) + void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int /*rows*/, int /*cols*/, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -292,15 +288,15 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term); break; - case 3: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term); break; - case 4: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term); break; + case 1: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term, min_disp); break; + case 3: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term, min_disp); break; + case 4: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term, min_disp); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void init_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, cudaStream_t stream) + void init_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream) { const int threadsNum = 256; const size_t smem_size = threadsNum * sizeof(float); @@ -311,19 +307,19 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term); break; - case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term); break; - case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term); break; + case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term, min_disp); break; + case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term, min_disp); break; + case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term, min_disp); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, - int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, bool use_local_init_data_cost, cudaStream_t stream) + int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, bool use_local_init_data_cost, cudaStream_t stream) { - typedef void (*InitDataCostCaller)(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int cols, int rows, int w, int h, int level, int ndisp, int channels, float data_weight, float max_data_term, cudaStream_t stream); + typedef void (*InitDataCostCaller)(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int cols, int rows, int w, int h, int level, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream); static const InitDataCostCaller init_data_cost_callers[] = { @@ -336,7 +332,7 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step, sizeof(size_t)) ); cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - init_data_cost_callers[level](cleft, cright, ctemp, cimg_step, rows, cols, h, w, level, ndisp, channels, data_weight, max_data_term, stream); + init_data_cost_callers[level](cleft, cright, ctemp, cimg_step, rows, cols, h, w, level, ndisp, channels, data_weight, max_data_term, min_disp, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) @@ -359,18 +355,18 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaDeviceSynchronize() ); } - template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, short* disp_selected_pyr, short* data_cost_selected, size_t msg_step, - int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, bool use_local_init_data_cost, cudaStream_t stream); + template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, short* disp_selected_pyr, short* data_cost_selected, size_t msg_step, + int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, bool use_local_init_data_cost, cudaStream_t stream); - template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, float* disp_selected_pyr, float* data_cost_selected, size_t msg_step, - int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, bool use_local_init_data_cost, cudaStream_t stream); + template void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, float* disp_selected_pyr, float* data_cost_selected, size_t msg_step, + int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, bool use_local_init_data_cost, cudaStream_t stream); /////////////////////////////////////////////////////////////// ////////////////////// compute data cost ////////////////////// /////////////////////////////////////////////////////////////// template - __global__ void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane, float data_weight, float max_data_term) + __global__ void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane, float data_weight, float max_data_term, int min_disp) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -396,7 +392,7 @@ namespace cv { namespace cuda { namespace device int sel_disp = selected_disparity[d * cdisp_step2]; int xr = xi - sel_disp; - if (xr < 0 || sel_disp < cth) + if (xr < 0 || sel_disp < min_disp) val += data_weight * max_data_term; else { @@ -413,7 +409,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void compute_data_cost_reduce(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane, float data_weight, float max_data_term) + __global__ void compute_data_cost_reduce(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane, float data_weight, float max_data_term, int min_disp) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -436,7 +432,7 @@ namespace cv { namespace cuda { namespace device float val = 0.0f; if (x0 + tid < cols) { - if (x0 + tid - sel_disp < 0 || sel_disp < cth) + if (x0 + tid - sel_disp < 0 || sel_disp < min_disp) val = data_weight * max_data_term * len; else { @@ -464,7 +460,7 @@ namespace cv { namespace cuda { namespace device template void compute_data_cost_caller_(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int /*rows*/, int /*cols*/, - int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream) + int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -474,16 +470,16 @@ namespace cv { namespace cuda { namespace device switch(channels) { - case 1: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term); break; - case 3: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term); break; - case 4: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term); break; + case 1: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term, min_disp); break; + case 3: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term, min_disp); break; + case 4: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term, min_disp); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template void compute_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int rows, int cols, - int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream) + int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream) { const int threadsNum = 256; const size_t smem_size = threadsNum * sizeof(float); @@ -494,19 +490,20 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term); break; - case 3: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term); break; - case 4: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term); break; + case 1: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term, min_disp); break; + case 3: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term, min_disp); break; + case 4: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term, min_disp); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, size_t msg_step, - int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream) + int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, + int min_disp, cudaStream_t stream) { typedef void (*ComputeDataCostCaller)(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int rows, int cols, - int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream); + int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream); static const ComputeDataCostCaller callers[] = { @@ -521,7 +518,7 @@ namespace cv { namespace cuda { namespace device cudaSafeCall( cudaMemcpyToSymbol(cdisp_step2, &disp_step2, sizeof(size_t)) ); cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - callers[level](cleft, cright, cimg_step, disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, data_weight, max_data_term, stream); + callers[level](cleft, cright, cimg_step, disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, data_weight, max_data_term, min_disp, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) @@ -529,10 +526,10 @@ namespace cv { namespace cuda { namespace device } template void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const short* disp_selected_pyr, short* data_cost, size_t msg_step, - int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream); + int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream); template void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const float* disp_selected_pyr, float* data_cost, size_t msg_step, - int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream); + int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream); /////////////////////////////////////////////////////////////// diff --git a/modules/cudastereo/src/cuda/stereocsbp.hpp b/modules/cudastereo/src/cuda/stereocsbp.hpp index 04337bbd1d..95c5a47356 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.hpp +++ b/modules/cudastereo/src/cuda/stereocsbp.hpp @@ -2,15 +2,16 @@ namespace cv { namespace cuda { namespace device { namespace stereocsbp { - void load_constants(float disc_single_jump, int min_disp_th); + void load_constants(float disc_single_jump); template void init_data_cost(const uchar *left, const uchar *right, uchar *ctemp, size_t cimg_step, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, - int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, bool use_local_init_data_cost, cudaStream_t stream); + int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, bool use_local_init_data_cost, cudaStream_t stream); template void compute_data_cost(const uchar *left, const uchar *right, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, size_t msg_step, - int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, cudaStream_t stream); + int rows, int cols, int h, int w, int h2, int level, int nr_plane, int channels, float data_weight, float max_data_term, + int min_disp, cudaStream_t stream); template void init_message(uchar *ctemp, T* u_new, T* d_new, T* l_new, T* r_new, diff --git a/modules/cudastereo/src/stereocsbp.cpp b/modules/cudastereo/src/stereocsbp.cpp index 14d6d2589f..2515061e13 100644 --- a/modules/cudastereo/src/stereocsbp.cpp +++ b/modules/cudastereo/src/stereocsbp.cpp @@ -222,7 +222,7 @@ namespace //////////////////////////////////////////////////////////////////////////// // Compute - load_constants(disc_single_jump_, min_disp_th_); + load_constants(disc_single_jump_); l[0].setTo(0, _stream); d[0].setTo(0, _stream); @@ -246,12 +246,12 @@ namespace if (i == levels_ - 1) { init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.step, left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), - elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), data_weight_, max_data_term_, use_local_init_data_cost_, stream); + elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), data_weight_, max_data_term_, min_disp_th_, use_local_init_data_cost_, stream); } else { compute_data_cost(left.ptr(), right.ptr(), left.step, disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, - left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), data_weight_, max_data_term_, stream); + left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), data_weight_, max_data_term_, min_disp_th_, stream); int new_idx = (cur_idx + 1) & 1; @@ -277,12 +277,12 @@ namespace if (i == levels_ - 1) { init_data_cost(left.ptr(), right.ptr(), temp_.ptr(), left.step, left.rows, left.cols, disp_selected_pyr[cur_idx].ptr(), data_cost_selected.ptr(), - elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), data_weight_, max_data_term_, use_local_init_data_cost_, stream); + elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), data_weight_, max_data_term_, min_disp_th_, use_local_init_data_cost_, stream); } else { compute_data_cost(left.ptr(), right.ptr(), left.step, disp_selected_pyr[cur_idx].ptr(), data_cost.ptr(), elem_step, - left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), data_weight_, max_data_term_, stream); + left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), data_weight_, max_data_term_, min_disp_th_, stream); int new_idx = (cur_idx + 1) & 1; From 6d86d63ac59a9e581c0680c8a9580f75d9d98d4f Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Tue, 1 Jul 2014 10:44:52 -0700 Subject: [PATCH 077/136] Last of csbp load_constants() gone. --- modules/cudastereo/src/cuda/stereocsbp.cu | 30 ++++++++-------------- modules/cudastereo/src/cuda/stereocsbp.hpp | 4 +-- modules/cudastereo/src/stereocsbp.cpp | 6 ++--- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index fc6f4f3daf..04f6caced6 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -58,18 +58,10 @@ namespace cv { namespace cuda { namespace device /////////////////////// load constants //////////////////////// /////////////////////////////////////////////////////////////// - __constant__ float cdisc_single_jump; - __constant__ size_t cmsg_step; __constant__ size_t cdisp_step1; __constant__ size_t cdisp_step2; - - void load_constants(float disc_single_jump) - { - cudaSafeCall( cudaMemcpyToSymbol(cdisc_single_jump, &disc_single_jump, sizeof(float)) ); - } - /////////////////////////////////////////////////////////////// /////////////////////// init data cost //////////////////////// /////////////////////////////////////////////////////////////// @@ -670,7 +662,7 @@ namespace cv { namespace cuda { namespace device template __device__ void message_per_pixel(const T* data, T* msg_dst, const T* msg1, const T* msg2, const T* msg3, - const T* dst_disp, const T* src_disp, int nr_plane, int max_disc_term, volatile T* temp) + const T* dst_disp, const T* src_disp, int nr_plane, int max_disc_term, float disc_single_jump, volatile T* temp) { T minimum = numeric_limits::max(); @@ -692,7 +684,7 @@ namespace cv { namespace cuda { namespace device T src_disp_reg = src_disp[d * cdisp_step1]; for(int d2 = 0; d2 < nr_plane; d2++) - cost_min = fmin(cost_min, msg_dst[d2 * cdisp_step1] + cdisc_single_jump * ::abs(dst_disp[d2 * cdisp_step1] - src_disp_reg)); + cost_min = fmin(cost_min, msg_dst[d2 * cdisp_step1] + disc_single_jump * ::abs(dst_disp[d2 * cdisp_step1] - src_disp_reg)); temp[d * cdisp_step1] = saturate_cast(cost_min); sum += cost_min; @@ -704,7 +696,7 @@ namespace cv { namespace cuda { namespace device } template - __global__ void compute_message(uchar *ctemp, T* u_, T* d_, T* l_, T* r_, const T* data_cost_selected, const T* selected_disp_pyr_cur, int h, int w, int nr_plane, int i, int max_disc_term) + __global__ void compute_message(uchar *ctemp, T* u_, T* d_, T* l_, T* r_, const T* data_cost_selected, const T* selected_disp_pyr_cur, int h, int w, int nr_plane, int i, int max_disc_term, float disc_single_jump) { int y = blockIdx.y * blockDim.y + threadIdx.y; int x = ((blockIdx.x * blockDim.x + threadIdx.x) << 1) + ((y + i) & 1); @@ -722,17 +714,17 @@ namespace cv { namespace cuda { namespace device T* temp = (T*)ctemp + y * cmsg_step + x; - message_per_pixel(data, u, r - 1, u + cmsg_step, l + 1, disp, disp - cmsg_step, nr_plane, max_disc_term, temp); - message_per_pixel(data, d, d - cmsg_step, r - 1, l + 1, disp, disp + cmsg_step, nr_plane, max_disc_term, temp); - message_per_pixel(data, l, u + cmsg_step, d - cmsg_step, l + 1, disp, disp - 1, nr_plane, max_disc_term, temp); - message_per_pixel(data, r, u + cmsg_step, d - cmsg_step, r - 1, disp, disp + 1, nr_plane, max_disc_term, temp); + message_per_pixel(data, u, r - 1, u + cmsg_step, l + 1, disp, disp - cmsg_step, nr_plane, max_disc_term, disc_single_jump, temp); + message_per_pixel(data, d, d - cmsg_step, r - 1, l + 1, disp, disp + cmsg_step, nr_plane, max_disc_term, disc_single_jump, temp); + message_per_pixel(data, l, u + cmsg_step, d - cmsg_step, l + 1, disp, disp - 1, nr_plane, max_disc_term, disc_single_jump, temp); + message_per_pixel(data, r, u + cmsg_step, d - cmsg_step, r - 1, disp, disp + 1, nr_plane, max_disc_term, disc_single_jump, temp); } } template void calc_all_iterations(uchar *ctemp, T* u, T* d, T* l, T* r, const T* data_cost_selected, - const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, int max_disc_term, cudaStream_t stream) + const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, int max_disc_term, float disc_single_jump, cudaStream_t stream) { size_t disp_step = msg_step * h; cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step, sizeof(size_t)) ); @@ -746,7 +738,7 @@ namespace cv { namespace cuda { namespace device for(int t = 0; t < iters; ++t) { - compute_message<<>>(ctemp, u, d, l, r, data_cost_selected, selected_disp_pyr_cur, h, w, nr_plane, t & 1, max_disc_term); + compute_message<<>>(ctemp, u, d, l, r, data_cost_selected, selected_disp_pyr_cur, h, w, nr_plane, t & 1, max_disc_term, disc_single_jump); cudaSafeCall( cudaGetLastError() ); } if (stream == 0) @@ -754,10 +746,10 @@ namespace cv { namespace cuda { namespace device }; template void calc_all_iterations(uchar *ctemp, short* u, short* d, short* l, short* r, const short* data_cost_selected, const short* selected_disp_pyr_cur, size_t msg_step, - int h, int w, int nr_plane, int iters, int max_disc_term, cudaStream_t stream); + int h, int w, int nr_plane, int iters, int max_disc_term, float disc_single_jump, cudaStream_t stream); template void calc_all_iterations(uchar *ctemp, float* u, float* d, float* l, float* r, const float* data_cost_selected, const float* selected_disp_pyr_cur, size_t msg_step, - int h, int w, int nr_plane, int iters, int max_disc_term, cudaStream_t stream); + int h, int w, int nr_plane, int iters, int max_disc_term, float disc_single_jump, cudaStream_t stream); /////////////////////////////////////////////////////////////// diff --git a/modules/cudastereo/src/cuda/stereocsbp.hpp b/modules/cudastereo/src/cuda/stereocsbp.hpp index 95c5a47356..305497292d 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.hpp +++ b/modules/cudastereo/src/cuda/stereocsbp.hpp @@ -2,8 +2,6 @@ namespace cv { namespace cuda { namespace device { namespace stereocsbp { - void load_constants(float disc_single_jump); - template void init_data_cost(const uchar *left, const uchar *right, uchar *ctemp, size_t cimg_step, int rows, int cols, T* disp_selected_pyr, T* data_cost_selected, size_t msg_step, int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, bool use_local_init_data_cost, cudaStream_t stream); @@ -22,7 +20,7 @@ namespace cv { namespace cuda { namespace device template void calc_all_iterations(uchar *ctemp, T* u, T* d, T* l, T* r, const T* data_cost_selected, - const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, int max_disc_term, cudaStream_t stream); + const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, int max_disc_term, float disc_single_jump, cudaStream_t stream); template void compute_disp(const T* u, const T* d, const T* l, const T* r, const T* data_cost_selected, const T* disp_selected, size_t msg_step, diff --git a/modules/cudastereo/src/stereocsbp.cpp b/modules/cudastereo/src/stereocsbp.cpp index 2515061e13..ded5fa20e1 100644 --- a/modules/cudastereo/src/stereocsbp.cpp +++ b/modules/cudastereo/src/stereocsbp.cpp @@ -222,8 +222,6 @@ namespace //////////////////////////////////////////////////////////////////////////// // Compute - load_constants(disc_single_jump_); - l[0].setTo(0, _stream); d[0].setTo(0, _stream); r[0].setTo(0, _stream); @@ -267,7 +265,7 @@ namespace calc_all_iterations(temp_.ptr(), u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), data_cost_selected.ptr(), disp_selected_pyr[cur_idx].ptr(), elem_step, - rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, max_disc_term_, stream); + rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, max_disc_term_, disc_single_jump_, stream); } } else @@ -298,7 +296,7 @@ namespace calc_all_iterations(temp_.ptr(), u[cur_idx].ptr(), d[cur_idx].ptr(), l[cur_idx].ptr(), r[cur_idx].ptr(), data_cost_selected.ptr(), disp_selected_pyr[cur_idx].ptr(), elem_step, - rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, max_disc_term_, stream); + rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, max_disc_term_, disc_single_jump_, stream); } } From b792419cde59876969de2f803c1599920cf2a0f2 Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 7 Jul 2014 08:12:28 -0700 Subject: [PATCH 078/136] Remove compute_disp()'s use of constant memory. --- modules/cudastereo/src/cuda/stereocsbp.cu | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index 04f6caced6..79456a01fa 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -760,26 +760,26 @@ namespace cv { namespace cuda { namespace device template __global__ void compute_disp(const T* u_, const T* d_, const T* l_, const T* r_, const T* data_cost_selected, const T* disp_selected_pyr, - PtrStepSz disp, int nr_plane) + PtrStepSz disp, int nr_plane, size_t msg_step, size_t disp_step) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; if (y > 0 && y < disp.rows - 1 && x > 0 && x < disp.cols - 1) { - const T* data = data_cost_selected + y * cmsg_step + x; - const T* disp_selected = disp_selected_pyr + y * cmsg_step + x; + const T* data = data_cost_selected + y * msg_step + x; + const T* disp_selected = disp_selected_pyr + y * msg_step + x; - const T* u = u_ + (y+1) * cmsg_step + (x+0); - const T* d = d_ + (y-1) * cmsg_step + (x+0); - const T* l = l_ + (y+0) * cmsg_step + (x+1); - const T* r = r_ + (y+0) * cmsg_step + (x-1); + const T* u = u_ + (y+1) * msg_step + (x+0); + const T* d = d_ + (y-1) * msg_step + (x+0); + const T* l = l_ + (y+0) * msg_step + (x+1); + const T* r = r_ + (y+0) * msg_step + (x-1); int best = 0; T best_val = numeric_limits::max(); for (int i = 0; i < nr_plane; ++i) { - int idx = i * cdisp_step1; + int idx = i * disp_step; T val = data[idx]+ u[idx] + d[idx] + l[idx] + r[idx]; if (val < best_val) @@ -797,8 +797,6 @@ namespace cv { namespace cuda { namespace device const PtrStepSz& disp, int nr_plane, cudaStream_t stream) { size_t disp_step = disp.rows * msg_step; - cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step, sizeof(size_t)) ); - cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -806,7 +804,7 @@ namespace cv { namespace cuda { namespace device grid.x = divUp(disp.cols, threads.x); grid.y = divUp(disp.rows, threads.y); - compute_disp<<>>(u, d, l, r, data_cost_selected, disp_selected, disp, nr_plane); + compute_disp<<>>(u, d, l, r, data_cost_selected, disp_selected, disp, nr_plane, msg_step, disp_step); cudaSafeCall( cudaGetLastError() ); if (stream == 0) From 9b8002cd43c8735e6e2eb1ecab1930bad6325681 Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 7 Jul 2014 08:23:40 -0700 Subject: [PATCH 079/136] remove use of constant memory in calc_all_iterations/compute_message/message_per_pixel --- modules/cudastereo/src/cuda/stereocsbp.cu | 41 +++++++++++------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index 79456a01fa..8c38d91ae9 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -662,13 +662,14 @@ namespace cv { namespace cuda { namespace device template __device__ void message_per_pixel(const T* data, T* msg_dst, const T* msg1, const T* msg2, const T* msg3, - const T* dst_disp, const T* src_disp, int nr_plane, int max_disc_term, float disc_single_jump, volatile T* temp) + const T* dst_disp, const T* src_disp, int nr_plane, int max_disc_term, float disc_single_jump, volatile T* temp, + size_t disp_step) { T minimum = numeric_limits::max(); for(int d = 0; d < nr_plane; d++) { - int idx = d * cdisp_step1; + int idx = d * disp_step; T val = data[idx] + msg1[idx] + msg2[idx] + msg3[idx]; if(val < minimum) @@ -681,43 +682,43 @@ namespace cv { namespace cuda { namespace device for(int d = 0; d < nr_plane; d++) { float cost_min = minimum + max_disc_term; - T src_disp_reg = src_disp[d * cdisp_step1]; + T src_disp_reg = src_disp[d * disp_step]; for(int d2 = 0; d2 < nr_plane; d2++) - cost_min = fmin(cost_min, msg_dst[d2 * cdisp_step1] + disc_single_jump * ::abs(dst_disp[d2 * cdisp_step1] - src_disp_reg)); + cost_min = fmin(cost_min, msg_dst[d2 * disp_step] + disc_single_jump * ::abs(dst_disp[d2 * disp_step] - src_disp_reg)); - temp[d * cdisp_step1] = saturate_cast(cost_min); + temp[d * disp_step] = saturate_cast(cost_min); sum += cost_min; } sum /= nr_plane; for(int d = 0; d < nr_plane; d++) - msg_dst[d * cdisp_step1] = saturate_cast(temp[d * cdisp_step1] - sum); + msg_dst[d * disp_step] = saturate_cast(temp[d * disp_step] - sum); } template - __global__ void compute_message(uchar *ctemp, T* u_, T* d_, T* l_, T* r_, const T* data_cost_selected, const T* selected_disp_pyr_cur, int h, int w, int nr_plane, int i, int max_disc_term, float disc_single_jump) + __global__ void compute_message(uchar *ctemp, T* u_, T* d_, T* l_, T* r_, const T* data_cost_selected, const T* selected_disp_pyr_cur, int h, int w, int nr_plane, int i, int max_disc_term, float disc_single_jump, size_t msg_step, size_t disp_step) { int y = blockIdx.y * blockDim.y + threadIdx.y; int x = ((blockIdx.x * blockDim.x + threadIdx.x) << 1) + ((y + i) & 1); if (y > 0 && y < h - 1 && x > 0 && x < w - 1) { - const T* data = data_cost_selected + y * cmsg_step + x; + const T* data = data_cost_selected + y * msg_step + x; - T* u = u_ + y * cmsg_step + x; - T* d = d_ + y * cmsg_step + x; - T* l = l_ + y * cmsg_step + x; - T* r = r_ + y * cmsg_step + x; + T* u = u_ + y * msg_step + x; + T* d = d_ + y * msg_step + x; + T* l = l_ + y * msg_step + x; + T* r = r_ + y * msg_step + x; - const T* disp = selected_disp_pyr_cur + y * cmsg_step + x; + const T* disp = selected_disp_pyr_cur + y * msg_step + x; - T* temp = (T*)ctemp + y * cmsg_step + x; + T* temp = (T*)ctemp + y * msg_step + x; - message_per_pixel(data, u, r - 1, u + cmsg_step, l + 1, disp, disp - cmsg_step, nr_plane, max_disc_term, disc_single_jump, temp); - message_per_pixel(data, d, d - cmsg_step, r - 1, l + 1, disp, disp + cmsg_step, nr_plane, max_disc_term, disc_single_jump, temp); - message_per_pixel(data, l, u + cmsg_step, d - cmsg_step, l + 1, disp, disp - 1, nr_plane, max_disc_term, disc_single_jump, temp); - message_per_pixel(data, r, u + cmsg_step, d - cmsg_step, r - 1, disp, disp + 1, nr_plane, max_disc_term, disc_single_jump, temp); + message_per_pixel(data, u, r - 1, u + msg_step, l + 1, disp, disp - msg_step, nr_plane, max_disc_term, disc_single_jump, temp, disp_step); + message_per_pixel(data, d, d - msg_step, r - 1, l + 1, disp, disp + msg_step, nr_plane, max_disc_term, disc_single_jump, temp, disp_step); + message_per_pixel(data, l, u + msg_step, d - msg_step, l + 1, disp, disp - 1, nr_plane, max_disc_term, disc_single_jump, temp, disp_step); + message_per_pixel(data, r, u + msg_step, d - msg_step, r - 1, disp, disp + 1, nr_plane, max_disc_term, disc_single_jump, temp, disp_step); } } @@ -727,8 +728,6 @@ namespace cv { namespace cuda { namespace device const T* selected_disp_pyr_cur, size_t msg_step, int h, int w, int nr_plane, int iters, int max_disc_term, float disc_single_jump, cudaStream_t stream) { size_t disp_step = msg_step * h; - cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step, sizeof(size_t)) ); - cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -738,7 +737,7 @@ namespace cv { namespace cuda { namespace device for(int t = 0; t < iters; ++t) { - compute_message<<>>(ctemp, u, d, l, r, data_cost_selected, selected_disp_pyr_cur, h, w, nr_plane, t & 1, max_disc_term, disc_single_jump); + compute_message<<>>(ctemp, u, d, l, r, data_cost_selected, selected_disp_pyr_cur, h, w, nr_plane, t & 1, max_disc_term, disc_single_jump, msg_step, disp_step); cudaSafeCall( cudaGetLastError() ); } if (stream == 0) From 1ff270e41c4c69952361baf87ddf304ea0151a0e Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 7 Jul 2014 09:45:30 -0700 Subject: [PATCH 080/136] init_message no longer uses constant memory. --- modules/cudastereo/src/cuda/stereocsbp.cu | 68 +++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index 8c38d91ae9..6ebdee8e9a 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -534,7 +534,7 @@ namespace cv { namespace cuda { namespace device const T* u_cur, const T* d_cur, const T* l_cur, const T* r_cur, T* data_cost_selected, T* disparity_selected_new, T* data_cost_new, const T* data_cost_cur, const T* disparity_selected_cur, - int nr_plane, int nr_plane2) + int nr_plane, int nr_plane2, size_t disp_step1, size_t disp_step2) { for(int i = 0; i < nr_plane; i++) { @@ -550,15 +550,15 @@ namespace cv { namespace cuda { namespace device } } - data_cost_selected[i * cdisp_step1] = data_cost_cur[id * cdisp_step1]; - disparity_selected_new[i * cdisp_step1] = disparity_selected_cur[id * cdisp_step2]; + data_cost_selected[i * disp_step1] = data_cost_cur[id * disp_step1]; + disparity_selected_new[i * disp_step1] = disparity_selected_cur[id * disp_step2]; - u_new[i * cdisp_step1] = u_cur[id * cdisp_step2]; - d_new[i * cdisp_step1] = d_cur[id * cdisp_step2]; - l_new[i * cdisp_step1] = l_cur[id * cdisp_step2]; - r_new[i * cdisp_step1] = r_cur[id * cdisp_step2]; + u_new[i * disp_step1] = u_cur[id * disp_step2]; + d_new[i * disp_step1] = d_cur[id * disp_step2]; + l_new[i * disp_step1] = l_cur[id * disp_step2]; + r_new[i * disp_step1] = r_cur[id * disp_step2]; - data_cost_new[id * cdisp_step1] = numeric_limits::max(); + data_cost_new[id * disp_step1] = numeric_limits::max(); } } @@ -567,47 +567,49 @@ namespace cv { namespace cuda { namespace device const T* u_cur_, const T* d_cur_, const T* l_cur_, const T* r_cur_, T* selected_disp_pyr_new, const T* selected_disp_pyr_cur, T* data_cost_selected_, const T* data_cost_, - int h, int w, int nr_plane, int h2, int w2, int nr_plane2) + int h, int w, int nr_plane, int h2, int w2, int nr_plane2, + size_t msg_step, size_t disp_step1, size_t disp_step2) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; if (y < h && x < w) { - const T* u_cur = u_cur_ + ::min(h2-1, y/2 + 1) * cmsg_step + x/2; - const T* d_cur = d_cur_ + ::max(0, y/2 - 1) * cmsg_step + x/2; - const T* l_cur = l_cur_ + (y/2) * cmsg_step + ::min(w2-1, x/2 + 1); - const T* r_cur = r_cur_ + (y/2) * cmsg_step + ::max(0, x/2 - 1); + const T* u_cur = u_cur_ + ::min(h2-1, y/2 + 1) * msg_step + x/2; + const T* d_cur = d_cur_ + ::max(0, y/2 - 1) * msg_step + x/2; + const T* l_cur = l_cur_ + (y/2) * msg_step + ::min(w2-1, x/2 + 1); + const T* r_cur = r_cur_ + (y/2) * msg_step + ::max(0, x/2 - 1); - T* data_cost_new = (T*)ctemp + y * cmsg_step + x; + T* data_cost_new = (T*)ctemp + y * msg_step + x; - const T* disparity_selected_cur = selected_disp_pyr_cur + y/2 * cmsg_step + x/2; - const T* data_cost = data_cost_ + y * cmsg_step + x; + const T* disparity_selected_cur = selected_disp_pyr_cur + y/2 * msg_step + x/2; + const T* data_cost = data_cost_ + y * msg_step + x; for(int d = 0; d < nr_plane2; d++) { - int idx2 = d * cdisp_step2; + int idx2 = d * disp_step2; - T val = data_cost[d * cdisp_step1] + u_cur[idx2] + d_cur[idx2] + l_cur[idx2] + r_cur[idx2]; - data_cost_new[d * cdisp_step1] = val; + T val = data_cost[d * disp_step1] + u_cur[idx2] + d_cur[idx2] + l_cur[idx2] + r_cur[idx2]; + data_cost_new[d * disp_step1] = val; } - T* data_cost_selected = data_cost_selected_ + y * cmsg_step + x; - T* disparity_selected_new = selected_disp_pyr_new + y * cmsg_step + x; + T* data_cost_selected = data_cost_selected_ + y * msg_step + x; + T* disparity_selected_new = selected_disp_pyr_new + y * msg_step + x; - T* u_new = u_new_ + y * cmsg_step + x; - T* d_new = d_new_ + y * cmsg_step + x; - T* l_new = l_new_ + y * cmsg_step + x; - T* r_new = r_new_ + y * cmsg_step + x; + T* u_new = u_new_ + y * msg_step + x; + T* d_new = d_new_ + y * msg_step + x; + T* l_new = l_new_ + y * msg_step + x; + T* r_new = r_new_ + y * msg_step + x; - u_cur = u_cur_ + y/2 * cmsg_step + x/2; - d_cur = d_cur_ + y/2 * cmsg_step + x/2; - l_cur = l_cur_ + y/2 * cmsg_step + x/2; - r_cur = r_cur_ + y/2 * cmsg_step + x/2; + u_cur = u_cur_ + y/2 * msg_step + x/2; + d_cur = d_cur_ + y/2 * msg_step + x/2; + l_cur = l_cur_ + y/2 * msg_step + x/2; + r_cur = r_cur_ + y/2 * msg_step + x/2; get_first_k_element_increase(u_new, d_new, l_new, r_new, u_cur, d_cur, l_cur, r_cur, data_cost_selected, disparity_selected_new, data_cost_new, - data_cost, disparity_selected_cur, nr_plane, nr_plane2); + data_cost, disparity_selected_cur, nr_plane, nr_plane2, + disp_step1, disp_step2); } } @@ -622,9 +624,6 @@ namespace cv { namespace cuda { namespace device size_t disp_step1 = msg_step * h; size_t disp_step2 = msg_step * h2; - cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step1, sizeof(size_t)) ); - cudaSafeCall( cudaMemcpyToSymbol(cdisp_step2, &disp_step2, sizeof(size_t)) ); - cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -636,7 +635,8 @@ namespace cv { namespace cuda { namespace device u_cur, d_cur, l_cur, r_cur, selected_disp_pyr_new, selected_disp_pyr_cur, data_cost_selected, data_cost, - h, w, nr_plane, h2, w2, nr_plane2); + h, w, nr_plane, h2, w2, nr_plane2, + msg_step, disp_step1, disp_step2); cudaSafeCall( cudaGetLastError() ); if (stream == 0) From 52516085d98e3ca19d2785143acfe992b78c29a6 Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 7 Jul 2014 10:12:30 -0700 Subject: [PATCH 081/136] remove constant memory from init_data_cost --- modules/cudastereo/src/cuda/stereocsbp.cu | 92 ++++++++++++----------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index 6ebdee8e9a..974b503733 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -92,16 +92,17 @@ namespace cv { namespace cuda { namespace device } template - __global__ void get_first_k_initial_global(uchar *ctemp, T* data_cost_selected_, T *selected_disp_pyr, int h, int w, int nr_plane, int ndisp) + __global__ void get_first_k_initial_global(uchar *ctemp, T* data_cost_selected_, T *selected_disp_pyr, int h, int w, int nr_plane, int ndisp, + size_t msg_step, size_t disp_step) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; if (y < h && x < w) { - T* selected_disparity = selected_disp_pyr + y * cmsg_step + x; - T* data_cost_selected = data_cost_selected_ + y * cmsg_step + x; - T* data_cost = (T*)ctemp + y * cmsg_step + x; + T* selected_disparity = selected_disp_pyr + y * msg_step + x; + T* data_cost_selected = data_cost_selected_ + y * msg_step + x; + T* data_cost = (T*)ctemp + y * msg_step + x; for(int i = 0; i < nr_plane; i++) { @@ -109,7 +110,7 @@ namespace cv { namespace cuda { namespace device int id = 0; for(int d = 0; d < ndisp; d++) { - T cur = data_cost[d * cdisp_step1]; + T cur = data_cost[d * disp_step]; if(cur < minimum) { minimum = cur; @@ -117,46 +118,47 @@ namespace cv { namespace cuda { namespace device } } - data_cost_selected[i * cdisp_step1] = minimum; - selected_disparity[i * cdisp_step1] = id; - data_cost [id * cdisp_step1] = numeric_limits::max(); + data_cost_selected[i * disp_step] = minimum; + selected_disparity[i * disp_step] = id; + data_cost [id * disp_step] = numeric_limits::max(); } } } template - __global__ void get_first_k_initial_local(uchar *ctemp, T* data_cost_selected_, T* selected_disp_pyr, int h, int w, int nr_plane, int ndisp) + __global__ void get_first_k_initial_local(uchar *ctemp, T* data_cost_selected_, T* selected_disp_pyr, int h, int w, int nr_plane, int ndisp, + size_t msg_step, size_t disp_step) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; if (y < h && x < w) { - T* selected_disparity = selected_disp_pyr + y * cmsg_step + x; - T* data_cost_selected = data_cost_selected_ + y * cmsg_step + x; - T* data_cost = (T*)ctemp + y * cmsg_step + x; + T* selected_disparity = selected_disp_pyr + y * msg_step + x; + T* data_cost_selected = data_cost_selected_ + y * msg_step + x; + T* data_cost = (T*)ctemp + y * msg_step + x; int nr_local_minimum = 0; - T prev = data_cost[0 * cdisp_step1]; - T cur = data_cost[1 * cdisp_step1]; - T next = data_cost[2 * cdisp_step1]; + T prev = data_cost[0 * disp_step]; + T cur = data_cost[1 * disp_step]; + T next = data_cost[2 * disp_step]; for (int d = 1; d < ndisp - 1 && nr_local_minimum < nr_plane; d++) { if (cur < prev && cur < next) { - data_cost_selected[nr_local_minimum * cdisp_step1] = cur; - selected_disparity[nr_local_minimum * cdisp_step1] = d; + data_cost_selected[nr_local_minimum * disp_step] = cur; + selected_disparity[nr_local_minimum * disp_step] = d; - data_cost[d * cdisp_step1] = numeric_limits::max(); + data_cost[d * disp_step] = numeric_limits::max(); nr_local_minimum++; } prev = cur; cur = next; - next = data_cost[(d + 1) * cdisp_step1]; + next = data_cost[(d + 1) * disp_step]; } for (int i = nr_local_minimum; i < nr_plane; i++) @@ -166,23 +168,25 @@ namespace cv { namespace cuda { namespace device for (int d = 0; d < ndisp; d++) { - cur = data_cost[d * cdisp_step1]; + cur = data_cost[d * disp_step]; if (cur < minimum) { minimum = cur; id = d; } } - data_cost_selected[i * cdisp_step1] = minimum; - selected_disparity[i * cdisp_step1] = id; + data_cost_selected[i * disp_step] = minimum; + selected_disparity[i * disp_step] = id; - data_cost[id * cdisp_step1] = numeric_limits::max(); + data_cost[id * disp_step] = numeric_limits::max(); } } } template - __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int h, int w, int level, int ndisp, float data_weight, float max_data_term, int min_disp) + __global__ void init_data_cost(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, + int h, int w, int level, int ndisp, float data_weight, float max_data_term, + int min_disp, size_t msg_step, size_t disp_step) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -195,7 +199,7 @@ namespace cv { namespace cuda { namespace device int x0 = x << level; int xt = (x + 1) << level; - T* data_cost = (T*)ctemp + y * cmsg_step + x; + T* data_cost = (T*)ctemp + y * msg_step + x; for(int d = 0; d < ndisp; ++d) { @@ -216,13 +220,15 @@ namespace cv { namespace cuda { namespace device } } } - data_cost[cdisp_step1 * d] = saturate_cast(val); + data_cost[disp_step * d] = saturate_cast(val); } } } template - __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int level, int rows, int cols, int h, int ndisp, float data_weight, float max_data_term, int min_disp) + __global__ void init_data_cost_reduce(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, + int level, int rows, int cols, int h, int ndisp, float data_weight, float max_data_term, + int min_disp, size_t msg_step, size_t disp_step) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -261,16 +267,16 @@ namespace cv { namespace cuda { namespace device reduce(smem + winsz * threadIdx.z, val, tid, plus()); - T* data_cost = (T*)ctemp + y_out * cmsg_step + x_out; + T* data_cost = (T*)ctemp + y_out * msg_step + x_out; if (tid == 0) - data_cost[cdisp_step1 * d] = saturate_cast(val); + data_cost[disp_step * d] = saturate_cast(val); } } template - void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int /*rows*/, int /*cols*/, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream) + void init_data_cost_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int /*rows*/, int /*cols*/, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, size_t msg_step, size_t disp_step, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -280,15 +286,15 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term, min_disp); break; - case 3: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term, min_disp); break; - case 4: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term, min_disp); break; + case 1: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term, min_disp, msg_step, disp_step); break; + case 3: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term, min_disp, msg_step, disp_step); break; + case 4: init_data_cost<<>>(cleft, cright, ctemp, cimg_step, h, w, level, ndisp, data_weight, max_data_term, min_disp, msg_step, disp_step); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template - void init_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream) + void init_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int rows, int cols, int h, int w, int level, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, size_t msg_step, size_t disp_step, cudaStream_t stream) { const int threadsNum = 256; const size_t smem_size = threadsNum * sizeof(float); @@ -299,9 +305,9 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term, min_disp); break; - case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term, min_disp); break; - case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term, min_disp); break; + case 1: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term, min_disp, msg_step, disp_step); break; + case 3: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term, min_disp, msg_step, disp_step); break; + case 4: init_data_cost_reduce<<>>(cleft, cright, ctemp, cimg_step, level, rows, cols, h, ndisp, data_weight, max_data_term, min_disp, msg_step, disp_step); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } @@ -311,7 +317,7 @@ namespace cv { namespace cuda { namespace device int h, int w, int level, int nr_plane, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, bool use_local_init_data_cost, cudaStream_t stream) { - typedef void (*InitDataCostCaller)(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int cols, int rows, int w, int h, int level, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream); + typedef void (*InitDataCostCaller)(const uchar *cleft, const uchar *cright, uchar *ctemp, size_t cimg_step, int cols, int rows, int w, int h, int level, int ndisp, int channels, float data_weight, float max_data_term, int min_disp, size_t msg_step, size_t disp_step, cudaStream_t stream); static const InitDataCostCaller init_data_cost_callers[] = { @@ -321,10 +327,8 @@ namespace cv { namespace cuda { namespace device }; size_t disp_step = msg_step * h; - cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step, sizeof(size_t)) ); - cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - init_data_cost_callers[level](cleft, cright, ctemp, cimg_step, rows, cols, h, w, level, ndisp, channels, data_weight, max_data_term, min_disp, stream); + init_data_cost_callers[level](cleft, cright, ctemp, cimg_step, rows, cols, h, w, level, ndisp, channels, data_weight, max_data_term, min_disp, msg_step, disp_step, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) @@ -337,9 +341,9 @@ namespace cv { namespace cuda { namespace device grid.y = divUp(h, threads.y); if (use_local_init_data_cost == true) - get_first_k_initial_local<<>> (ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane, ndisp); + get_first_k_initial_local<<>> (ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane, ndisp, msg_step, disp_step); else - get_first_k_initial_global<<>>(ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane, ndisp); + get_first_k_initial_global<<>>(ctemp, data_cost_selected, disp_selected_pyr, h, w, nr_plane, ndisp, msg_step, disp_step); cudaSafeCall( cudaGetLastError() ); @@ -542,7 +546,7 @@ namespace cv { namespace cuda { namespace device int id = 0; for(int j = 0; j < nr_plane2; j++) { - T cur = data_cost_new[j * cdisp_step1]; + T cur = data_cost_new[j * disp_step1]; if(cur < minimum) { minimum = cur; From 85601e03dd345d88f59ebf5f6b81a42fd336ecaa Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Mon, 7 Jul 2014 10:28:47 -0700 Subject: [PATCH 082/136] remove constant memory use in compute_data_cost --- modules/cudastereo/src/cuda/stereocsbp.cu | 43 +++++++++++------------ 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index 974b503733..eb371c1881 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -362,7 +362,7 @@ namespace cv { namespace cuda { namespace device /////////////////////////////////////////////////////////////// template - __global__ void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane, float data_weight, float max_data_term, int min_disp) + __global__ void compute_data_cost(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int h, int w, int level, int nr_plane, float data_weight, float max_data_term, int min_disp, size_t msg_step, size_t disp_step1, size_t disp_step2) { int x = blockIdx.x * blockDim.x + threadIdx.x; int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -375,8 +375,8 @@ namespace cv { namespace cuda { namespace device int x0 = x << level; int xt = (x + 1) << level; - const T* selected_disparity = selected_disp_pyr + y/2 * cmsg_step + x/2; - T* data_cost = data_cost_ + y * cmsg_step + x; + const T* selected_disparity = selected_disp_pyr + y/2 * msg_step + x/2; + T* data_cost = data_cost_ + y * msg_step + x; for(int d = 0; d < nr_plane; d++) { @@ -385,7 +385,7 @@ namespace cv { namespace cuda { namespace device { for(int xi = x0; xi < xt; xi++) { - int sel_disp = selected_disparity[d * cdisp_step2]; + int sel_disp = selected_disparity[d * disp_step2]; int xr = xi - sel_disp; if (xr < 0 || sel_disp < min_disp) @@ -399,13 +399,13 @@ namespace cv { namespace cuda { namespace device } } } - data_cost[cdisp_step1 * d] = saturate_cast(val); + data_cost[disp_step1 * d] = saturate_cast(val); } } } template - __global__ void compute_data_cost_reduce(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane, float data_weight, float max_data_term, int min_disp) + __global__ void compute_data_cost_reduce(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* selected_disp_pyr, T* data_cost_, int level, int rows, int cols, int h, int nr_plane, float data_weight, float max_data_term, int min_disp, size_t msg_step, size_t disp_step1, size_t disp_step2) { int x_out = blockIdx.x; int y_out = blockIdx.y % h; @@ -413,12 +413,12 @@ namespace cv { namespace cuda { namespace device int tid = threadIdx.x; - const T* selected_disparity = selected_disp_pyr + y_out/2 * cmsg_step + x_out/2; - T* data_cost = data_cost_ + y_out * cmsg_step + x_out; + const T* selected_disparity = selected_disp_pyr + y_out/2 * msg_step + x_out/2; + T* data_cost = data_cost_ + y_out * msg_step + x_out; if (d < nr_plane) { - int sel_disp = selected_disparity[d * cdisp_step2]; + int sel_disp = selected_disparity[d * disp_step2]; int x0 = x_out << level; int y0 = y_out << level; @@ -450,13 +450,13 @@ namespace cv { namespace cuda { namespace device reduce(smem + winsz * threadIdx.z, val, tid, plus()); if (tid == 0) - data_cost[cdisp_step1 * d] = saturate_cast(val); + data_cost[disp_step1 * d] = saturate_cast(val); } } template void compute_data_cost_caller_(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int /*rows*/, int /*cols*/, - int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream) + int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, size_t msg_step, size_t disp_step1, size_t disp_step2, cudaStream_t stream) { dim3 threads(32, 8, 1); dim3 grid(1, 1, 1); @@ -466,16 +466,16 @@ namespace cv { namespace cuda { namespace device switch(channels) { - case 1: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term, min_disp); break; - case 3: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term, min_disp); break; - case 4: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term, min_disp); break; + case 1: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term, min_disp, msg_step, disp_step1, disp_step2); break; + case 3: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term, min_disp, msg_step, disp_step1, disp_step2); break; + case 4: compute_data_cost<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, h, w, level, nr_plane, data_weight, max_data_term, min_disp, msg_step, disp_step1, disp_step2); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } template void compute_data_cost_reduce_caller_(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int rows, int cols, - int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream) + int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, size_t msg_step, size_t disp_step1, size_t disp_step2, cudaStream_t stream) { const int threadsNum = 256; const size_t smem_size = threadsNum * sizeof(float); @@ -486,9 +486,9 @@ namespace cv { namespace cuda { namespace device switch (channels) { - case 1: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term, min_disp); break; - case 3: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term, min_disp); break; - case 4: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term, min_disp); break; + case 1: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term, min_disp, msg_step, disp_step1, disp_step2); break; + case 3: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term, min_disp, msg_step, disp_step1, disp_step2); break; + case 4: compute_data_cost_reduce<<>>(cleft, cright, cimg_step, disp_selected_pyr, data_cost, level, rows, cols, h, nr_plane, data_weight, max_data_term, min_disp, msg_step, disp_step1, disp_step2); break; default: CV_Error(cv::Error::BadNumChannels, "Unsupported channels count"); } } @@ -499,7 +499,7 @@ namespace cv { namespace cuda { namespace device int min_disp, cudaStream_t stream) { typedef void (*ComputeDataCostCaller)(const uchar *cleft, const uchar *cright, size_t cimg_step, const T* disp_selected_pyr, T* data_cost, int rows, int cols, - int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, cudaStream_t stream); + int h, int w, int level, int nr_plane, int channels, float data_weight, float max_data_term, int min_disp, size_t msg_step, size_t disp_step1, size_t disp_step2, cudaStream_t stream); static const ComputeDataCostCaller callers[] = { @@ -510,11 +510,8 @@ namespace cv { namespace cuda { namespace device size_t disp_step1 = msg_step * h; size_t disp_step2 = msg_step * h2; - cudaSafeCall( cudaMemcpyToSymbol(cdisp_step1, &disp_step1, sizeof(size_t)) ); - cudaSafeCall( cudaMemcpyToSymbol(cdisp_step2, &disp_step2, sizeof(size_t)) ); - cudaSafeCall( cudaMemcpyToSymbol(cmsg_step, &msg_step, sizeof(size_t)) ); - callers[level](cleft, cright, cimg_step, disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, data_weight, max_data_term, min_disp, stream); + callers[level](cleft, cright, cimg_step, disp_selected_pyr, data_cost, rows, cols, h, w, level, nr_plane, channels, data_weight, max_data_term, min_disp, msg_step, disp_step1, disp_step2, stream); cudaSafeCall( cudaGetLastError() ); if (stream == 0) From 4644689d5a31f0d80527e511b8f86fa05bc8681f Mon Sep 17 00:00:00 2001 From: Aaron Denney Date: Thu, 10 Jul 2014 23:53:44 -0700 Subject: [PATCH 083/136] And remove final vestiges. --- modules/cudastereo/src/cuda/stereocsbp.cu | 8 -------- 1 file changed, 8 deletions(-) diff --git a/modules/cudastereo/src/cuda/stereocsbp.cu b/modules/cudastereo/src/cuda/stereocsbp.cu index eb371c1881..dd535e8b20 100644 --- a/modules/cudastereo/src/cuda/stereocsbp.cu +++ b/modules/cudastereo/src/cuda/stereocsbp.cu @@ -54,14 +54,6 @@ namespace cv { namespace cuda { namespace device { namespace stereocsbp { - /////////////////////////////////////////////////////////////// - /////////////////////// load constants //////////////////////// - /////////////////////////////////////////////////////////////// - - __constant__ size_t cmsg_step; - __constant__ size_t cdisp_step1; - __constant__ size_t cdisp_step2; - /////////////////////////////////////////////////////////////// /////////////////////// init data cost //////////////////////// /////////////////////////////////////////////////////////////// From e82241cba52fbb22a71812549e452c164fc5f497 Mon Sep 17 00:00:00 2001 From: PhilLab Date: Thu, 17 Jul 2014 09:19:31 +0200 Subject: [PATCH 084/136] Function for drawing arrows Porting the [PR 2970](https://github.com/Itseez/opencv/pull/2970) To the new InputOutputArray type --- modules/core/doc/drawing_functions.rst | 31 ++++++++++++++++++++++++++ modules/core/include/opencv2/core.hpp | 4 ++++ modules/core/src/drawing.cpp | 18 +++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/modules/core/doc/drawing_functions.rst b/modules/core/doc/drawing_functions.rst index 60b744f6df..e4f6d2f230 100644 --- a/modules/core/doc/drawing_functions.rst +++ b/modules/core/doc/drawing_functions.rst @@ -361,6 +361,37 @@ The function ``line`` draws the line segment between ``pt1`` and ``pt2`` points Antialiased lines are drawn using Gaussian filtering. +arrowedLine +---------------- +Draws a arrow segment pointing from the first point to the second one. + +.. ocv:function:: void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0, double tipLength=0.1) + + :param img: Image. + + :param pt1: The point the arrow starts from. + + :param pt2: The point the arrow points to. + + :param color: Line color. + + :param thickness: Line thickness. + + :param lineType: Type of the line: + + * **8** (or omitted) - 8-connected line. + + * **4** - 4-connected line. + + * **CV_AA** - antialiased line. + + :param shift: Number of fractional bits in the point coordinates. + + :param tipLength: The length of the arrow tip in relation to the arrow length + +The function ``arrowedLine`` draws an arrow between ``pt1`` and ``pt2`` points in the image. See also :ocv:func:`line`. + + LineIterator ------------ .. ocv:class:: LineIterator diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index a5b9235152..b5249c9f50 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -510,6 +510,10 @@ CV_EXPORTS_W void randShuffle(InputOutputArray dst, double iterFactor = 1., RNG* CV_EXPORTS_W void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0); +//! draws an arrow from pt1 to pt2 in the image +CV_EXPORTS_W void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, + int thickness=1, int line_type=8, int shift=0, double tipLength=0.1); + //! draws the rectangle outline or a solid rectangle with the opposite corners pt1 and pt2 in the image CV_EXPORTS_W void rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, diff --git a/modules/core/src/drawing.cpp b/modules/core/src/drawing.cpp index 0ba932163d..0b11aea7ea 100644 --- a/modules/core/src/drawing.cpp +++ b/modules/core/src/drawing.cpp @@ -1584,6 +1584,24 @@ void line( InputOutputArray _img, Point pt1, Point pt2, const Scalar& color, ThickLine( img, pt1, pt2, buf, thickness, line_type, 3, shift ); } +void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, + int thickness, int line_type, int shift, double tipLength) +{ + const double tipSize = norm(pt1-pt2)*tipLength; // Factor to normalize the size of the tip depending on the length of the arrow + + line(img, pt1, pt2, color, thickness, line_type, shift); + + const double angle = atan2( (double) pt1.y - pt2.y, (double) pt1.x - pt2.x ); + + Point p(cvRound(pt2.x + tipSize * cos(angle + CV_PI / 4)), + cvRound(pt2.y + tipSize * sin(angle + CV_PI / 4))); + line(img, p, pt2, color, thickness, line_type, shift); + + p.x = cvRound(pt2.x + tipSize * cos(angle - CV_PI / 4)); + p.y = cvRound(pt2.y + tipSize * sin(angle - CV_PI / 4)); + line(img, p, pt2, color, thickness, line_type, shift); +} + void rectangle( InputOutputArray _img, Point pt1, Point pt2, const Scalar& color, int thickness, int lineType, int shift ) From 1242a6611930f0672f63426d635dc7e9dc001787 Mon Sep 17 00:00:00 2001 From: Lars Glud Date: Sun, 20 Jul 2014 14:49:47 +0200 Subject: [PATCH 085/136] Openni2 support --- modules/highgui/CMakeLists.txt | 6 ------ modules/highgui/include/opencv2/highgui.hpp | 5 ----- modules/highgui/include/opencv2/highgui/highgui_c.h | 4 ---- modules/videoio/CMakeLists.txt | 6 ++++++ modules/videoio/include/opencv2/videoio.hpp | 7 +++++-- modules/videoio/include/opencv2/videoio/videoio_c.h | 6 +++++- modules/{highgui => videoio}/src/cap_openni2.cpp | 4 ++-- 7 files changed, 18 insertions(+), 20 deletions(-) rename modules/{highgui => videoio}/src/cap_openni2.cpp (99%) diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index a80fe04408..b0c93a8eba 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -72,12 +72,6 @@ elseif(HAVE_COCOA) list(APPEND HIGHGUI_LIBRARIES "-framework Cocoa") endif() -if(HAVE_OPENNI2) - list(APPEND highgui_srcs src/cap_openni2.cpp) - ocv_include_directories(${OPENNI2_INCLUDE_DIR}) - list(APPEND HIGHGUI_LIBRARIES ${OPENNI2_LIBRARY}) -endif(HAVE_OPENNI2) - if(UNIX) #these variables are set by CHECK_MODULE macro foreach(P ${HIGHGUI_INCLUDE_DIRS}) diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index b23519065e..47b6547e85 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -201,9 +201,4 @@ CV_EXPORTS int createButton( const String& bar_name, ButtonCallback on_change, bool initial_button_state = false); } // cv - - CAP_OPENNI2 = 1600 // OpenNI2 (for Kinect) - CAP_PROP_OPENNI_OUTPUT_MODE = 100, - CAP_PROP_OPENNI2_SYNC = 110, - CAP_PROP_OPENNI2_MIRROR = 111 #endif diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 34c811d430..f45a71079d 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -208,10 +208,6 @@ CVAPI(void) cvUpdateWindow(const char* window_name); /****************************************************************************************\ - - CV_CAP_OPENNI2 = 1600 // OpenNI2 (for Kinect) - CV_CAP_PROP_OPENNI2_SYNC = 110, - CV_CAP_PROP_OPENNI2_MIRROR = 111, * Obsolete functions/synonyms * \****************************************************************************************/ diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index 2ac7811c75..bba3d33396 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -78,6 +78,12 @@ if(HAVE_OPENNI) list(APPEND VIDEOIO_LIBRARIES ${OPENNI_LIBRARY}) endif(HAVE_OPENNI) +if(HAVE_OPENNI2) + list(APPEND videoio_srcs src/cap_openni2.cpp) + ocv_include_directories(${OPENNI2_INCLUDE_DIR}) + list(APPEND VIDEOIO_LIBRARIES ${OPENNI2_LIBRARY}) +endif(HAVE_OPENNI2) + if(HAVE_opencv_androidcamera) list(APPEND videoio_srcs src/cap_android.cpp) add_definitions(-DHAVE_ANDROID_NATIVE_CAMERA)#TODO: remove this line diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index a144c65dc0..763c5bd435 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -75,7 +75,8 @@ enum { CAP_ANY = 0, // autodetect CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK CAP_MSMF = 1400, // Microsoft Media Foundation (via videoInput) - CAP_INTELPERC = 1500 // Intel Perceptual Computing SDK + CAP_INTELPERC = 1500, // Intel Perceptual Computing SDK + CAP_OPENNI2 = 1600 // OpenNI2 (for Kinect) }; // generic properties (based on DC1394 properties) @@ -149,7 +150,9 @@ enum { CAP_PROP_OPENNI_OUTPUT_MODE = 100, CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, - CAP_PROP_OPENNI_GENERATOR_PRESENT = 109 + CAP_PROP_OPENNI_GENERATOR_PRESENT = 109, + CAP_PROP_OPENNI2_SYNC = 110, + CAP_PROP_OPENNI2_MIRROR = 111 }; // OpenNI shortcats diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h index 85cb07c73a..0b08d03d9b 100644 --- a/modules/videoio/include/opencv2/videoio/videoio_c.h +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -104,7 +104,9 @@ enum CV_CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK - CV_CAP_INTELPERC = 1500 // Intel Perceptual Computing SDK + CV_CAP_INTELPERC = 1500, // Intel Perceptual Computing + + CV_CAP_OPENNI2 = 1600 // OpenNI2 (for Kinect) }; /* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */ @@ -200,6 +202,8 @@ enum CV_CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, CV_CAP_PROP_OPENNI_GENERATOR_PRESENT = 109, + CV_CAP_PROP_OPENNI2_SYNC = 110, + CV_CAP_PROP_OPENNI2_MIRROR = 111, CV_CAP_OPENNI_IMAGE_GENERATOR_PRESENT = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_GENERATOR_PRESENT, CV_CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_OUTPUT_MODE, diff --git a/modules/highgui/src/cap_openni2.cpp b/modules/videoio/src/cap_openni2.cpp similarity index 99% rename from modules/highgui/src/cap_openni2.cpp rename to modules/videoio/src/cap_openni2.cpp index 4d12e5eb14..62aacb2faa 100644 --- a/modules/highgui/src/cap_openni2.cpp +++ b/modules/videoio/src/cap_openni2.cpp @@ -481,7 +481,7 @@ bool CvCapture_OpenNI2::setCommonProperty( int propIdx, double propValue ) { case CV_CAP_PROP_OPENNI2_MIRROR: { - bool mirror = propValue > 0 ? true : false; + bool mirror = propValue > 0.0 ? true : false; isSet = color.setMirroringEnabled(mirror) == openni::STATUS_OK; isSet = depth.setMirroringEnabled(mirror) == openni::STATUS_OK; } @@ -492,7 +492,7 @@ bool CvCapture_OpenNI2::setCommonProperty( int propIdx, double propValue ) isSet = setDepthGeneratorProperty( propIdx, propValue ); break; case CV_CAP_PROP_OPENNI2_SYNC: - isSet = device.setDepthColorSyncEnabled(propValue) == openni::STATUS_OK; + isSet = device.setDepthColorSyncEnabled(propValue > 0.0) == openni::STATUS_OK; break; default: CV_Error( CV_StsBadArg, cv::format("Such parameter (propIdx=%d) isn't supported for setting.\n", propIdx) ); From cc703b01dfe9f9099bc02c06278a6eecd93e0553 Mon Sep 17 00:00:00 2001 From: VBystricky Date: Sun, 20 Jul 2014 18:27:14 +0400 Subject: [PATCH 086/136] Fix build errors with cap_v4l on Linux --- modules/videoio/src/precomp.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp index ec4c00a360..13c57023d7 100644 --- a/modules/videoio/src/precomp.hpp +++ b/modules/videoio/src/precomp.hpp @@ -47,6 +47,8 @@ #include "opencv2/core/utility.hpp" #include "opencv2/core/private.hpp" +#include "opencv2/imgcodecs.hpp" + #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/imgcodecs/imgcodecs_c.h" #include "opencv2/videoio/videoio_c.h" From d2493393dbfe0402eb8bedbdae7da584ff700657 Mon Sep 17 00:00:00 2001 From: Anish Pednekar Date: Sun, 20 Jul 2014 20:59:17 +0530 Subject: [PATCH 087/136] added macro guard to enable overriding ENABLE_LOG --- modules/stitching/include/opencv2/stitching/detail/util.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/stitching/include/opencv2/stitching/detail/util.hpp b/modules/stitching/include/opencv2/stitching/detail/util.hpp index 6b1c5f34f3..2769dc60b2 100644 --- a/modules/stitching/include/opencv2/stitching/detail/util.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/util.hpp @@ -46,7 +46,9 @@ #include #include "opencv2/core.hpp" +#ifndef ENABLE_LOG #define ENABLE_LOG 0 +#endif // TODO remove LOG macros, add logging class #if ENABLE_LOG From fd51c133dfadac7b6d6724b77559e647a3c49357 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Mon, 21 Jul 2014 15:10:41 +0400 Subject: [PATCH 088/136] Add depends from highgui to imgcodecs and videoio. And include header from imgcodecs and videoio to imgcodecs --- apps/traincascade/CMakeLists.txt | 2 +- modules/cudev/test/CMakeLists.txt | 2 +- modules/highgui/CMakeLists.txt | 2 +- modules/highgui/include/opencv2/highgui.hpp | 2 ++ modules/highgui/include/opencv2/highgui/highgui_c.h | 2 ++ samples/android/native-activity/CMakeLists.txt | 2 +- samples/directx/CMakeLists.txt | 2 +- samples/gpu/CMakeLists.txt | 2 +- 8 files changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/traincascade/CMakeLists.txt b/apps/traincascade/CMakeLists.txt index c815303d49..cca56361e3 100644 --- a/apps/traincascade/CMakeLists.txt +++ b/apps/traincascade/CMakeLists.txt @@ -1,4 +1,4 @@ -set(OPENCV_TRAINCASCADE_DEPS opencv_core opencv_ml opencv_imgproc opencv_photo opencv_objdetect opencv_imgcodecs opencv_highgui opencv_calib3d opencv_video opencv_features2d) +set(OPENCV_TRAINCASCADE_DEPS opencv_core opencv_ml opencv_imgproc opencv_photo opencv_objdetect opencv_imgcodecs opencv_videoio opencv_highgui opencv_calib3d opencv_video opencv_features2d) ocv_check_dependencies(${OPENCV_TRAINCASCADE_DEPS}) if(NOT OCV_DEPENDENCIES_FOUND) diff --git a/modules/cudev/test/CMakeLists.txt b/modules/cudev/test/CMakeLists.txt index 438e0a64c0..363970e4b7 100644 --- a/modules/cudev/test/CMakeLists.txt +++ b/modules/cudev/test/CMakeLists.txt @@ -1,4 +1,4 @@ -set(test_deps opencv_cudev opencv_core opencv_imgproc opencv_highgui opencv_ts ${OPENCV_MODULE_opencv_ts_DEPS}) +set(test_deps opencv_cudev opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui opencv_ts ${OPENCV_MODULE_opencv_ts_DEPS}) ocv_check_dependencies(${test_deps}) diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index b0c93a8eba..78d6bfb094 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -1,5 +1,5 @@ set(the_description "High-level GUI and Media I/O") -ocv_add_module(highgui opencv_imgproc opencv_imgcodecs OPTIONAL opencv_androidcamera) +ocv_add_module(highgui opencv_imgproc opencv_imgcodecs opencv_videoio OPTIONAL opencv_androidcamera) # ---------------------------------------------------------------------------- # CMake file for highgui. See root CMakeLists.txt diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index 3dfc7d7561..2f98bcc2cf 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -44,6 +44,8 @@ #define __OPENCV_HIGHGUI_HPP__ #include "opencv2/core.hpp" +#include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" ///////////////////////// graphical user interface ////////////////////////// diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 2d3e6bc108..57407b0d62 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -43,6 +43,8 @@ #define __OPENCV_HIGHGUI_H__ #include "opencv2/core/core_c.h" +#include "opencv2/imgcodecs/imgcodecs_c.h" +#include "opencv2/videoio/videoio_c.h" #ifdef __cplusplus extern "C" { diff --git a/samples/android/native-activity/CMakeLists.txt b/samples/android/native-activity/CMakeLists.txt index 1f6d97439a..0cc0571ed9 100644 --- a/samples/android/native-activity/CMakeLists.txt +++ b/samples/android/native-activity/CMakeLists.txt @@ -3,7 +3,7 @@ set(sample example-native-activity) if(BUILD_FAT_JAVA_LIB) set(native_deps opencv_java) else() - set(native_deps opencv_highgui opencv_imgproc) + set(native_deps opencv_videoio opencv_imgcodecs opencv_highgui opencv_imgproc) endif() add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 9 ${ANDROID_SDK_TARGET} NATIVE_DEPS ${native_deps}) diff --git a/samples/directx/CMakeLists.txt b/samples/directx/CMakeLists.txt index 97d7fc305c..1083894100 100644 --- a/samples/directx/CMakeLists.txt +++ b/samples/directx/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_highgui) +SET(OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui) ocv_check_dependencies(${OPENCV_DIRECTX_SAMPLES_REQUIRED_DEPS}) diff --git a/samples/gpu/CMakeLists.txt b/samples/gpu/CMakeLists.txt index 87beb1bea1..849e3109df 100644 --- a/samples/gpu/CMakeLists.txt +++ b/samples/gpu/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(OPENCV_CUDA_SAMPLES_REQUIRED_DEPS opencv_core opencv_flann opencv_imgproc opencv_imgcodecs opencv_highgui +SET(OPENCV_CUDA_SAMPLES_REQUIRED_DEPS opencv_core opencv_flann opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui opencv_ml opencv_video opencv_objdetect opencv_features2d opencv_calib3d opencv_legacy opencv_contrib opencv_cuda opencv_nonfree opencv_softcascade opencv_superres From bd144cfa64094966e9fdf95c18e6ea594c34fe82 Mon Sep 17 00:00:00 2001 From: Sergey Nikulov Date: Mon, 21 Jul 2014 18:56:35 +0400 Subject: [PATCH 089/136] upmerged pull req #2974 to master - added more jpeg options to imgcodecs --- .../imgcodecs/include/opencv2/imgcodecs.hpp | 19 ++++++---- .../include/opencv2/imgcodecs/imgcodecs_c.h | 3 ++ modules/imgcodecs/src/grfmt_jpeg.cpp | 37 +++++++++++++++++++ modules/imgcodecs/test/test_grfmt.cpp | 25 +++++++++++++ 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 81f8a45f65..94948525c9 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -56,14 +56,17 @@ enum { IMREAD_UNCHANGED = -1, // 8bit, color or not IMREAD_ANYCOLOR = 4 // ?, any color }; -enum { IMWRITE_JPEG_QUALITY = 1, - IMWRITE_JPEG_PROGRESSIVE = 2, - IMWRITE_JPEG_OPTIMIZE = 3, - IMWRITE_PNG_COMPRESSION = 16, - IMWRITE_PNG_STRATEGY = 17, - IMWRITE_PNG_BILEVEL = 18, - IMWRITE_PXM_BINARY = 32, - IMWRITE_WEBP_QUALITY = 64 +enum { IMWRITE_JPEG_QUALITY = 1, + IMWRITE_JPEG_PROGRESSIVE = 2, + IMWRITE_JPEG_OPTIMIZE = 3, + IMWRITE_JPEG_RST_INTERVAL = 4, + IMWRITE_JPEG_LUM_QUALITY = 5, + IMWRITE_JPEG_CHROM_QUALITY = 6, + IMWRITE_PNG_COMPRESSION = 16, + IMWRITE_PNG_STRATEGY = 17, + IMWRITE_PNG_BILEVEL = 18, + IMWRITE_PXM_BINARY = 32, + IMWRITE_WEBP_QUALITY = 64 }; enum { IMWRITE_PNG_STRATEGY_DEFAULT = 0, diff --git a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h index f0c2ae13fe..a36b454058 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h +++ b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h @@ -76,6 +76,9 @@ enum CV_IMWRITE_JPEG_QUALITY =1, CV_IMWRITE_JPEG_PROGRESSIVE =2, CV_IMWRITE_JPEG_OPTIMIZE =3, + CV_IMWRITE_JPEG_RST_INTERVAL =4, + CV_IMWRITE_JPEG_LUM_QUALITY =5, + CV_IMWRITE_JPEG_CHROM_QUALITY =6, CV_IMWRITE_PNG_COMPRESSION =16, CV_IMWRITE_PNG_STRATEGY =17, CV_IMWRITE_PNG_BILEVEL =18, diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp index 147f185e4c..3157ebfcb1 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.cpp +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp @@ -600,6 +600,9 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) int quality = 95; int progressive = 0; int optimize = 0; + int rst_interval = 0; + int lum_quality = 100; + int chrom_quality = 100; for( size_t i = 0; i < params.size(); i += 2 ) { @@ -618,15 +621,49 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) { optimize = params[i+1]; } + + if( params[i] == CV_IMWRITE_JPEG_LUM_QUALITY ) + { + lum_quality = params[i+1]; + lum_quality = MIN(MAX(lum_quality, 0), 100); + } + + if( params[i] == CV_IMWRITE_JPEG_CHROM_QUALITY ) + { + chrom_quality = params[i+1]; + chrom_quality = MIN(MAX(chrom_quality, 0), 100); + } + + if( params[i] == CV_IMWRITE_JPEG_RST_INTERVAL ) + { + rst_interval = params[i+1]; + rst_interval = MIN(MAX(rst_interval, 0), 65535L); + } } jpeg_set_defaults( &cinfo ); + cinfo.restart_interval = rst_interval; jpeg_set_quality( &cinfo, quality, TRUE /* limit to baseline-JPEG values */ ); if( progressive ) jpeg_simple_progression( &cinfo ); if( optimize ) cinfo.optimize_coding = TRUE; + +#if JPEG_LIB_VERSION >= 70 + cinfo.q_scale_factor[0] = jpeg_quality_scaling(lum_quality); + cinfo.q_scale_factor[1] = jpeg_quality_scaling(chrom_quality); + if ( lum_quality != chrom_quality ) + { + /* disable subsampling - ref. Libjpeg.txt */ + cinfo.comp_info[0].v_samp_factor = 1; + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[1].v_samp_factor = 1; + cinfo.comp_info[1].h_samp_factor = 1; + } + jpeg_default_qtables( &cinfo, TRUE ); +#endif // #if JPEG_LIB_VERSION >= 70 + jpeg_start_compress( &cinfo, TRUE ); if( channels > 1 ) diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index 9b06c5744c..05bd1227ff 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -433,6 +433,31 @@ TEST(Imgcodecs_Jpeg, encode_decode_optimize_jpeg) remove(output_optimized.c_str()); } + +TEST(Imgcodecs_Jpeg, encode_decode_rst_jpeg) +{ + cvtest::TS& ts = *cvtest::TS::ptr(); + string input = string(ts.get_data_path()) + "../cv/shared/lena.png"; + cv::Mat img = cv::imread(input); + ASSERT_FALSE(img.empty()); + + std::vector params; + params.push_back(IMWRITE_JPEG_RST_INTERVAL); + params.push_back(1); + + string output_rst = cv::tempfile(".jpg"); + EXPECT_NO_THROW(cv::imwrite(output_rst, img, params)); + cv::Mat img_jpg_rst = cv::imread(output_rst); + + string output_normal = cv::tempfile(".jpg"); + EXPECT_NO_THROW(cv::imwrite(output_normal, img)); + cv::Mat img_jpg_normal = cv::imread(output_normal); + + EXPECT_EQ(0, cvtest::norm(img_jpg_rst, img_jpg_normal, NORM_INF)); + + remove(output_optimized.c_str()); +} + #endif From 9d107fb2d5c0fdfe27273f4de1c9669517a82346 Mon Sep 17 00:00:00 2001 From: Sergey Nikulov Date: Mon, 21 Jul 2014 19:26:26 +0400 Subject: [PATCH 090/136] fixed test compilation --- modules/imgcodecs/test/test_grfmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index 05bd1227ff..09b0bdc89e 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -455,7 +455,7 @@ TEST(Imgcodecs_Jpeg, encode_decode_rst_jpeg) EXPECT_EQ(0, cvtest::norm(img_jpg_rst, img_jpg_normal, NORM_INF)); - remove(output_optimized.c_str()); + remove(output_rst.c_str()); } #endif From d1c7983fe5e94d064b274fbc5acf658ff8f7f07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20Kov=C3=A1cs?= Date: Mon, 21 Jul 2014 17:27:03 +0200 Subject: [PATCH 091/136] calibrateDebevec index fix (issue 3664) --- modules/photo/src/calibrate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/photo/src/calibrate.cpp b/modules/photo/src/calibrate.cpp index 23b612995a..e9fb461f5b 100644 --- a/modules/photo/src/calibrate.cpp +++ b/modules/photo/src/calibrate.cpp @@ -104,7 +104,7 @@ public: for(size_t i = 0; i < sample_points.size(); i++) { for(size_t j = 0; j < images.size(); j++) { - int val = images[j].ptr()[3*(sample_points[i].y * images[j].cols + sample_points[j].x) + channel]; + int val = images[j].ptr()[3*(sample_points[i].y * images[j].cols + sample_points[i].x) + channel]; A.at(eq, val) = w.at(val); A.at(eq, LDR_SIZE + (int)i) = -w.at(val); B.at(eq, 0) = w.at(val) * log(times.at((int)j)); From 716218cac4009a67eb95fc2570990c9e7a7fe266 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Tue, 22 Jul 2014 13:22:40 +0400 Subject: [PATCH 092/136] Optimize ocl version of warp_affine --- modules/imgproc/src/opencl/warp_affine.cl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/imgproc/src/opencl/warp_affine.cl b/modules/imgproc/src/opencl/warp_affine.cl index 8ee34d0d65..649f10db7a 100644 --- a/modules/imgproc/src/opencl/warp_affine.cl +++ b/modules/imgproc/src/opencl/warp_affine.cl @@ -98,15 +98,15 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of { int round_delta = (AB_SCALE >> 1); - int X0_ = rint(M[0] * dx * AB_SCALE); - int Y0_ = rint(M[3] * dx * AB_SCALE); + int X0 = rint(fma(M[0], dx, fma(M[1], dy0, M[2])) * AB_SCALE) + round_delta; + int Y0 = rint(fma(M[3], dx, fma(M[4], dy0, M[5])) * AB_SCALE) + round_delta; + + int XSTEP = (int)(M[1] * AB_SCALE); + int YSTEP = (int)(M[4] * AB_SCALE); int dst_index = mad24(dy0, dst_step, mad24(dx, pixsize, dst_offset)); for (int dy = dy0, dy1 = min(dst_rows, dy0 + rowsPerWI); dy < dy1; ++dy, dst_index += dst_step) { - int X0 = X0_ + rint(fma(M[1], dy, M[2]) * AB_SCALE) + round_delta; - int Y0 = Y0_ + rint(fma(M[4], dy, M[5]) * AB_SCALE) + round_delta; - short sx = convert_short_sat(X0 >> AB_BITS); short sy = convert_short_sat(Y0 >> AB_BITS); @@ -117,6 +117,9 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of } else storepix(scalar, dstptr + dst_index); + + X0 += XSTEP; + Y0 += YSTEP; } } } From 5dd92638485085805fc31034a7a64dc4a5e4e178 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Thu, 26 Jun 2014 10:09:15 +0400 Subject: [PATCH 093/136] Multi-radix with kernel generation --- modules/core/perf/opencl/perf_dxt.cpp | 6 +- modules/core/src/dxt.cpp | 257 +++++++++++++++++++++- modules/core/src/opencl/fft.cl | 297 ++++++++++++++++++++++++++ modules/core/test/ocl/test_dft.cpp | 73 +++++-- samples/cpp/dft.cpp | 69 +++++- 5 files changed, 666 insertions(+), 36 deletions(-) create mode 100644 modules/core/src/opencl/fft.cl diff --git a/modules/core/perf/opencl/perf_dxt.cpp b/modules/core/perf/opencl/perf_dxt.cpp index d0219913b5..09d657d7a1 100644 --- a/modules/core/perf/opencl/perf_dxt.cpp +++ b/modules/core/perf/opencl/perf_dxt.cpp @@ -57,9 +57,9 @@ namespace ocl { typedef tuple DftParams; typedef TestBaseWithParam DftFixture; -OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), - Values((int)DFT_ROWS, (int)DFT_SCALE, (int)DFT_INVERSE, - (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE))) +OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(/*OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, */Size(1024, 1024), Size(1024, 2048), Size(512, 512), Size(2048, 2048)), + Values((int)DFT_ROWS/*, (int) 0/*, (int)DFT_SCALE, (int)DFT_INVERSE, + (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE*/))) { const DftParams params = GetParam(); const Size srcSize = get<0>(params); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 2a08899167..68256eaa07 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -1960,7 +1960,7 @@ static void CL_CALLBACK oclCleanupCallback(cl_event e, cl_int, void *p) } -static bool ocl_dft(InputArray _src, OutputArray _dst, int flags) +static bool ocl_dft_amdfft(InputArray _src, OutputArray _dst, int flags) { int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); Size ssize = _src.size(); @@ -2029,12 +2029,257 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags) #endif // HAVE_CLAMDFFT +namespace cv +{ + +#ifdef HAVE_OPENCL + +static bool fft_radixN(InputArray _src, OutputArray _dst, int radix, int block_size, int nonzero_rows, int flags) +{ + int N = _src.size().width; + if (N % radix) + return false; + + UMat src = _src.getUMat(); + UMat dst = _dst.getUMat(); + + int thread_count = N / radix; + size_t globalsize[2] = { thread_count, nonzero_rows }; + String kernel_name = format("fft_radix%d", radix); + ocl::Kernel k(kernel_name.c_str(), ocl::core::fft_oclsrc, (flags & DFT_INVERSE) != 0 ? "-D INVERSE" : ""); + if (k.empty()) + return false; + + k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), block_size, thread_count, nonzero_rows); + return k.run(2, globalsize, NULL, false); +} + +static bool ocl_packToCCS(InputArray _buffer, OutputArray _dst, int flags) +{ + UMat buffer = _buffer.getUMat(); + UMat dst = _dst.getUMat(); + + buffer = buffer.reshape(1); + if ((flags & DFT_ROWS) == 0 && buffer.rows > 1) + { + // pack to CCS by rows + if (dst.cols > 2) + buffer.colRange(2, dst.cols + (dst.cols % 2)).copyTo(dst.colRange(1, dst.cols-1 + (dst.cols % 2))); + + Mat dst_mat = dst.getMat(ACCESS_WRITE); + Mat buffer_mat = buffer.getMat(ACCESS_READ); + + dst_mat.at(0,0) = buffer_mat.at(0,0); + dst_mat.at(dst_mat.rows-1,0) = buffer_mat.at(buffer.rows/2,0); + for (int i=1; i(i,0) = buffer_mat.at((i+1)/2,0); + dst_mat.at(i+1,0) = buffer_mat.at((i+1)/2,1); + } + + if (dst_mat.cols % 2 == 0) + { + dst_mat.at(0,dst_mat.cols-1) = buffer_mat.at(0,buffer.cols/2); + dst_mat.at(dst_mat.rows-1,dst_mat.cols-1) = buffer_mat.at(buffer.rows/2,buffer.cols/2); + + for (int i=1; i(i,dst_mat.cols-1) = buffer_mat.at((i+1)/2,buffer.cols/2); + dst_mat.at(i+1,dst_mat.cols-1) = buffer_mat.at((i+1)/2,buffer.cols/2+1); + } + } + } + else + { + // pack to CCS each row + buffer.colRange(0,1).copyTo(dst.colRange(0,1)); + buffer.colRange(2, (dst.cols+1)).copyTo(dst.colRange(1, dst.cols)); + } + return true; +} + +static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, int nonzero_rows, int flags) +{ + int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type); + UMat src = _src.getUMat(); + + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + if (depth == CV_64F && !doubleSupport) + return false; + + int factors[34]; + int nf = DFTFactorize( src.cols, factors ); + + int n = 1; + int factor_index = 0; + + String radix_processing; + int min_radix = INT_MAX; + // 1. 2^n transforms + if ( (factors[factor_index] & 1) == 0 ) + { + for( ; n < factors[factor_index]; ) + { + int radix = 2; + if (8*n <= factors[0]) + radix = 8; + else if (4*n <= factors[0]) + radix = 4; + + radix_processing += format("fft_radix%d(smem,x,%d,%d);", radix, n, src.cols/radix); + min_radix = min(radix, min_radix); + n *= radix; + } + factor_index++; + } + + // 2. all the other transforms + for( ; factor_index < nf; factor_index++ ) + { + int radix = factors[factor_index]; + radix_processing += format("fft_radix%d(smem,x,%d,%d);", radix, n, src.cols/radix); + min_radix = min(radix, min_radix); + n *= radix; + } + + UMat dst = _dst.getUMat(); + + int thread_count = src.cols / min_radix; + size_t globalsize[2] = { thread_count, nonzero_rows }; + size_t localsize[2] = { thread_count, 1 }; + + String buildOptions = format("-D LOCAL_SIZE=%d -D kercn=%d -D RADIX_PROCESS=%s", + src.cols, src.cols/thread_count, radix_processing.c_str()); + ocl::Kernel k("fft_multi_radix", ocl::core::fft_oclsrc, buildOptions); + if (k.empty()) + return false; + + k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), thread_count, nonzero_rows); + return k.run(2, globalsize, localsize, false); +} + +static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_rows) +{ + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + Size ssize = _src.size(); + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + if ( (!doubleSupport && depth == CV_64F) || + !(type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2)) + return false; + + // if is not a multiplication of prime numbers { 2, 3, 5 } + if (ssize.area() != getOptimalDFTSize(ssize.area())) + return false; + + UMat src = _src.getUMat(); + int complex_input = cn == 2 ? 1 : 0; + int complex_output = (flags & DFT_COMPLEX_OUTPUT) != 0; + int real_input = cn == 1 ? 1 : 0; + int real_output = (flags & DFT_REAL_OUTPUT) != 0; + bool inv = (flags & DFT_INVERSE) != 0 ? 1 : 0; + bool is1d = (flags & DFT_ROWS) != 0 || src.rows == 1; + + // if output format is not specified + if (complex_output + real_output == 0) + { + if (!inv) + { + if (real_input) + real_output = 1; + else + complex_output = 1; + } + } + + if (complex_output) + { + //if (is1d) + // _dst.create(Size(src.cols/2+1, src.rows), CV_MAKE_TYPE(depth, 2)); + //else + _dst.create(src.size(), CV_MAKE_TYPE(depth, 2)); + } + else + _dst.create(src.size(), CV_MAKE_TYPE(depth, 1)); + UMat dst = _dst.getUMat(); + + bool inplace = src.u == dst.u; + //UMat buffer; + + //if (complex_input) + //{ + // if (inplace) + // buffer = src; + // else + // src.copyTo(buffer); + //} + //else + //{ + // if (!inv) + // { + // // in case real input convert it to complex + // buffer.create(src.size(), CV_MAKE_TYPE(depth, 2)); + // std::vector planes; + // planes.push_back(src); + // planes.push_back(UMat::zeros(src.size(), CV_32F)); + // merge(planes, buffer); + // } + // else + // { + // // TODO: unpack from CCS format + // } + //} + + if( nonzero_rows <= 0 || nonzero_rows > _src.rows() ) + nonzero_rows = _src.rows(); + + + if (!ocl_dft_C2C_row(src, dst, nonzero_rows, flags)) + return false; + + if ((flags & DFT_ROWS) == 0 && nonzero_rows > 1) + { + transpose(dst, dst); + if (!ocl_dft_C2C_row(dst, dst, dst.rows, flags)) + return false; + transpose(dst, dst); + } + + //if (complex_output) + //{ + // if (real_input && is1d) + // _dst.assign(buffer.colRange(0, buffer.cols/2+1)); + // else + // _dst.assign(buffer); + //} + //else + //{ + // if (!inv) + // ocl_packToCCS(buffer, _dst, flags); + // else + // { + // // copy real part to dst + // } + //} + return true; +} + +#endif + +} // namespace cv; + + + void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) { #ifdef HAVE_CLAMDFFT CV_OCL_RUN(ocl::haveAmdFft() && ocl::Device::getDefault().type() != ocl::Device::TYPE_CPU && _dst.isUMat() && _src0.dims() <= 2 && nonzero_rows == 0, - ocl_dft(_src0, _dst, flags)) + ocl_dft_amdfft(_src0, _dst, flags)) +#endif + +#ifdef HAVE_OPENCL + CV_OCL_RUN(_dst.isUMat() && _src0.dims() <= 2, + ocl_dft(_src0, _dst, flags, nonzero_rows)) #endif static DFTFunc dft_tbl[6] = @@ -2046,10 +2291,8 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) (DFTFunc)RealDFT_64f, (DFTFunc)CCSIDFT_64f }; - AutoBuffer buf; void *spec = 0; - Mat src0 = _src0.getMat(), src = src0; int prev_len = 0, stage = 0; bool inv = (flags & DFT_INVERSE) != 0; @@ -2058,6 +2301,7 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) int elem_size = (int)src.elemSize1(), complex_elem_size = elem_size*2; int factors[34]; bool inplace_transform = false; + bool is1d = (flags & DFT_ROWS) != 0 || src.rows == 1; #ifdef USE_IPP_DFT AutoBuffer ippbuf; int ipp_norm_flag = !(flags & DFT_SCALE) ? 8 : inv ? 2 : 1; @@ -2066,7 +2310,10 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) CV_Assert( type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2 ); if( !inv && src.channels() == 1 && (flags & DFT_COMPLEX_OUTPUT) ) - _dst.create( src.size(), CV_MAKETYPE(depth, 2) ); + if (!is1d) + _dst.create( src.size(), CV_MAKETYPE(depth, 2) ); + else + _dst.create( Size(src.cols/2+1, src.rows), CV_MAKETYPE(depth, 2) ); else if( inv && src.channels() == 2 && (flags & DFT_REAL_OUTPUT) ) _dst.create( src.size(), depth ); else diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl new file mode 100644 index 0000000000..7006b92e68 --- /dev/null +++ b/modules/core/src/opencl/fft.cl @@ -0,0 +1,297 @@ +__constant float PI = 3.14159265f; +__constant float SQRT_2 = 0.707106781188f; + +__constant float sin_120 = 0.866025403784f; +__constant float fft5_2 = 0.559016994374f; +__constant float fft5_3 = -0.951056516295f; +__constant float fft5_4 = -1.538841768587f; +__constant float fft5_5 = 0.363271264002f; + +inline float2 mul_float2(float2 a, float2 b){ + float2 res; + res.x = a.x * b.x - a.y * b.y; + res.y = a.x * b.y + a.y * b.x; + return res; +} + +inline float2 sincos_float2(float alpha) { + float cs, sn; + sn = sincos(alpha, &cs); // sincos + return (float2)(cs, sn); +} + +inline float2 twiddle(float2 a) { + return (float2)(a.y, -a.x); +} + +inline float2 square(float2 a) { + return (float2)(a.x * a.x - a.y * a.y, 2.0f * a.x * a.y); +} + +inline float2 square3(float2 a) { + return (float2)(a.x * a.x - a.y * a.y, 3.0f * a.x * a.y); +} + +inline float2 mul_p1q4(float2 a) { + return (float2)(SQRT_2) * (float2)(a.x + a.y, -a.x + a.y); +} + +inline float2 mul_p3q4(float2 a) { + return (float2)(SQRT_2) * (float2)(-a.x + a.y, -a.x - a.y); +} + +__attribute__((always_inline)) +void fft_radix2(__local float2* smem, const int x, const int block_size, const int t) +{ + const int k = x & (block_size - 1); + float2 in1, temp; + + if (x < t) + { + in1 = smem[x]; + float2 in2 = smem[x+t]; + + float theta = -PI * k / block_size; + float cs; + float sn = sincos(theta, &cs); + temp = (float2) (in2.x * cs - in2.y * sn, + in2.y * cs + in2.x * sn); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t) + { + const int dst_ind = (x << 1) - k; + + smem[dst_ind] = in1 + temp; + smem[dst_ind+block_size] = in1 - temp; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + +__attribute__((always_inline)) +void fft_radix4(__local float2* smem, const int x, const int block_size, const int t) +{ + const int k = x & (block_size - 1); + float2 b0, b1, b2, b3; + + if (x < t) + { + float theta = -PI * k / (2 * block_size); + + float2 tw = sincos_float2(theta); + float2 a0 = smem[x]; + float2 a1 = mul_float2(tw, smem[x+t]); + float2 a2 = smem[x + 2*t]; + float2 a3 = mul_float2(tw, smem[x + 3*t]); + tw = square(tw); + a2 = mul_float2(tw, a2); + a3 = mul_float2(tw, a3); + + b0 = a0 + a2; + b1 = a0 - a2; + b2 = a1 + a3; + b3 = twiddle(a1 - a3); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t) + { + const int dst_ind = ((x - k) << 2) + k; + smem[dst_ind] = b0 + b2; + smem[dst_ind + block_size] = b1 + b3; + smem[dst_ind + 2*block_size] = b0 - b2; + smem[dst_ind + 3*block_size] = b1 - b3; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + +__attribute__((always_inline)) +void fft_radix8(__local float2* smem, const int x, const int block_size, const int t) +{ + const int k = x % block_size; + float2 a0, a1, a2, a3, a4, a5, a6, a7; + + if (x < t) + { + float theta = -PI * k / (4 * block_size); + + float2 tw = sincos_float2(theta); // W + a0 = smem[x]; + a1 = mul_float2(tw, smem[x + t]); + a2 = smem[x + 2 * t]; + a3 = mul_float2(tw, smem[x + 3 * t]); + a4 = smem[x + 4 * t]; + a5 = mul_float2(tw, smem[x + 5 * t]); + a6 = smem[x + 6 * t]; + a7 = mul_float2(tw, smem[x + 7 * t]); + + tw = square(tw); // W^2 + a2 = mul_float2(tw, a2); + a3 = mul_float2(tw, a3); + a6 = mul_float2(tw, a6); + a7 = mul_float2(tw, a7); + tw = square(tw); // W^4 + a4 = mul_float2(tw, a4); + a5 = mul_float2(tw, a5); + a6 = mul_float2(tw, a6); + a7 = mul_float2(tw, a7); + + float2 b0 = a0 + a4; + float2 b4 = a0 - a4; + float2 b1 = a1 + a5; + float2 b5 = mul_p1q4(a1 - a5); + float2 b2 = a2 + a6; + float2 b6 = twiddle(a2 - a6); + float2 b3 = a3 + a7; + float2 b7 = mul_p3q4(a3 - a7); + + a0 = b0 + b2; + a2 = b0 - b2; + a1 = b1 + b3; + a3 = twiddle(b1 - b3); + a4 = b4 + b6; + a6 = b4 - b6; + a5 = b5 + b7; + a7 = twiddle(b5 - b7); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t) + { + const int dst_ind = ((x - k) << 3) + k; + __local float2* dst = smem + dst_ind; + + dst[0] = a0 + a1; + dst[block_size] = a4 + a5; + dst[2 * block_size] = a2 + a3; + dst[3 * block_size] = a6 + a7; + dst[4 * block_size] = a0 - a1; + dst[5 * block_size] = a4 - a5; + dst[6 * block_size] = a2 - a3; + dst[7 * block_size] = a6 - a7; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + +__attribute__((always_inline)) +void fft_radix3(__local float2* smem, const int x, const int block_size, const int t) +{ + const int k = x % block_size; + float2 a0, a1, a2, b0, b1; + + if (x < t) + { + const float theta = -PI * k * 2 / (3 * block_size); + + a0 = smem[x]; + a1 = mul_float2(sincos_float2(theta), smem[x+t]); + a2 = mul_float2(sincos_float2(2 * theta), smem[x+2*t]); + b1 = a1 + a2; + a2 = twiddle((float2)sin_120*(a1 - a2)); + b0 = a0 - (float2)(0.5f)*b1; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t) + { + const int dst_ind = ((x - k) * 3) + k; + + smem[dst_ind] = a0 + b1; + smem[dst_ind + block_size] = b0 + a2; + smem[dst_ind + 2*block_size] = b0 - a2; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + +__attribute__((always_inline)) +void fft_radix5(__local float2* smem, const int x, const int block_size, const int t) +{ + const int k = x % block_size; + float2 a0, a1, a2, a3, a4, b0, b1, b2, b5; + + if (x < t) + { + const float theta = -PI * k * 2 / (5 * block_size); + + a0 = smem[x]; + a1 = mul_float2(sincos_float2(theta), smem[x + t]); + a2 = mul_float2(sincos_float2(theta*2),smem[x+2*t]); + a3 = mul_float2(sincos_float2(theta*3),smem[x+3*t]); + a4 = mul_float2(sincos_float2(theta*4),smem[x+4*t]); + + b1 = a1 + a4; + a1 -= a4; + + a4 = a3 + a2; + a3 -= a2; + + b2 = b1 + a4; + b0 = a0 - (float2)0.25f * b2; + + b1 = (float2)fft5_2 * (b1 - a4); + a4 = -(float2)fft5_3 * (a1 + a3); + a4 = twiddle(a4); + + b5 = (float2)(a4.x - fft5_5 * a1.y, a4.y + fft5_5 * a1.x); + + a4.x += fft5_4 * a3.y; + a4.y -= fft5_4 * a3.x; + + a1 = b0 + b1; + b0 -= b1; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t) + { + const int dst_ind = ((x - k) * 5) + k; + __local float2* dst = smem + dst_ind; + + dst[0] = a0 + b2; + dst[block_size] = a1 + a4; + dst[2 * block_size] = b0 + b5; + dst[3 * block_size] = b0 - b5; + dst[4 * block_size] = a1 - a4; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + +__kernel void fft_multi_radix(__global const uchar* srcptr, int src_step, int src_offset, + __global uchar* dstptr, int dst_step, int dst_offset, + const int t, const int nz) +{ + const int x = get_global_id(0); + const int y = get_group_id(1); + + if (y < nz) + { + __local float2 smem[LOCAL_SIZE]; + __global const float2* src = (__global const float2*)(srcptr + mad24(y, src_step, mad24(x, (int)(sizeof(float)*2), src_offset))); + __global float2* dst = (__global float2*)(dstptr + mad24(y, dst_step, mad24(x, (int)(sizeof(float)*2), dst_offset))); + + const int block_size = LOCAL_SIZE/kercn; + #pragma unroll + for (int i=0; i +#include +#include using namespace cv; using namespace std; @@ -24,6 +26,31 @@ const char* keys = int main(int argc, const char ** argv) { + //int cols = 4; + //int rows = 768; + //srand(0); + //Mat input(Size(cols, rows), CV_32FC2); + //for (int i=0; i(j,i) = Vec2f((float) rand() / RAND_MAX, (float) rand() / RAND_MAX); + //Mat dst; + // + //UMat gpu_input, gpu_dst; + //input.copyTo(gpu_input); + //auto start = std::chrono::system_clock::now(); + //dft(input, dst, DFT_ROWS); + //auto cpu_duration = chrono::duration_cast(chrono::system_clock::now() - start); + // + //start = std::chrono::system_clock::now(); + //dft(gpu_input, gpu_dst, DFT_ROWS); + //auto gpu_duration = chrono::duration_cast(chrono::system_clock::now() - start); + + //double n = norm(dst, gpu_dst); + //cout << "norm = " << n << endl; + //cout << "CPU time: " << cpu_duration.count() << "ms" << endl; + //cout << "GPU time: " << gpu_duration.count() << "ms" << endl; + + help(); CommandLineParser parser(argc, argv, keys); string filename = parser.get(0); @@ -35,16 +62,46 @@ int main(int argc, const char ** argv) printf("Cannot read image file: %s\n", filename.c_str()); return -1; } - int M = getOptimalDFTSize( img.rows ); - int N = getOptimalDFTSize( img.cols ); + + Mat small_img = img(Rect(0,0,6,6)); + + int M = getOptimalDFTSize( small_img.rows ); + int N = getOptimalDFTSize( small_img.cols ); Mat padded; - copyMakeBorder(img, padded, 0, M - img.rows, 0, N - img.cols, BORDER_CONSTANT, Scalar::all(0)); + copyMakeBorder(small_img, padded, 0, M - small_img.rows, 0, N - small_img.cols, BORDER_CONSTANT, Scalar::all(0)); - Mat planes[] = {Mat_(padded), Mat::zeros(padded.size(), CV_32F)}; - Mat complexImg; + Mat planes[] = {Mat_(padded), Mat::ones(padded.size(), CV_32F)}; + Mat complexImg, complexImg1, complexInput; merge(planes, 2, complexImg); - dft(complexImg, complexImg); + Mat realInput; + padded.convertTo(realInput, CV_32F); + complexInput = complexImg; + //cout << complexImg << endl; + //dft(complexImg, complexImg, DFT_REAL_OUTPUT); + //cout << "Complex to Complex" << endl; + //cout << complexImg << endl; + cout << "Complex input" << endl << complexInput << endl; + cout << "Real input" << endl << realInput << endl; + + dft(complexInput, complexImg1, DFT_COMPLEX_OUTPUT); + cout << "Complex to Complex image: " << endl; + cout << endl << complexImg1 << endl; + + Mat realImg1; + dft(complexInput, realImg1, DFT_REAL_OUTPUT); + cout << "Complex to Real image: " << endl; + cout << endl << realImg1 << endl; + + Mat realOut; + dft(complexImg1, realOut, DFT_INVERSE | DFT_COMPLEX_OUTPUT); + cout << "Complex to Complex (inverse):" << endl; + cout << realOut << endl; + + Mat complexOut; + dft(realImg1, complexOut, DFT_INVERSE | DFT_REAL_OUTPUT | DFT_SCALE); + cout << "Complex to Real (inverse):" << endl; + cout << complexOut << endl; // compute log(1 + sqrt(Re(DFT(img))**2 + Im(DFT(img))**2)) split(complexImg, planes); From 0318d2772086d5aaf6ca07bc994e2bed0943b64b Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Thu, 10 Jul 2014 18:10:46 +0400 Subject: [PATCH 094/136] Enabled precalculated wave --- modules/core/include/opencv2/core/cvdef.h | 1 + modules/core/perf/opencl/perf_dxt.cpp | 4 +- modules/core/src/dxt.cpp | 127 +++++++----- modules/core/src/opencl/fft.cl | 226 ++++++++++------------ modules/core/test/ocl/test_dft.cpp | 8 +- 5 files changed, 183 insertions(+), 183 deletions(-) diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 8108a61e60..765c54cbe1 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -244,6 +244,7 @@ typedef signed char schar; /* fundamental constants */ #define CV_PI 3.1415926535897932384626433832795 +#define CV_TWO_PI 6.283185307179586476925286766559 #define CV_LOG2 0.69314718055994530941723212145818 /****************************************************************************************\ diff --git a/modules/core/perf/opencl/perf_dxt.cpp b/modules/core/perf/opencl/perf_dxt.cpp index 09d657d7a1..c0da96b373 100644 --- a/modules/core/perf/opencl/perf_dxt.cpp +++ b/modules/core/perf/opencl/perf_dxt.cpp @@ -57,8 +57,8 @@ namespace ocl { typedef tuple DftParams; typedef TestBaseWithParam DftFixture; -OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(/*OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, */Size(1024, 1024), Size(1024, 2048), Size(512, 512), Size(2048, 2048)), - Values((int)DFT_ROWS/*, (int) 0/*, (int)DFT_SCALE, (int)DFT_INVERSE, +OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(1024, 1024), Size(1024, 2048), Size(512, 512), Size(2048, 2048)), + Values((int)DFT_ROWS, (int) 0/*, (int)DFT_SCALE, (int)DFT_INVERSE, (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE*/))) { const DftParams params = GetParam(); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 68256eaa07..de17f07b23 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2034,26 +2034,6 @@ namespace cv #ifdef HAVE_OPENCL -static bool fft_radixN(InputArray _src, OutputArray _dst, int radix, int block_size, int nonzero_rows, int flags) -{ - int N = _src.size().width; - if (N % radix) - return false; - - UMat src = _src.getUMat(); - UMat dst = _dst.getUMat(); - - int thread_count = N / radix; - size_t globalsize[2] = { thread_count, nonzero_rows }; - String kernel_name = format("fft_radix%d", radix); - ocl::Kernel k(kernel_name.c_str(), ocl::core::fft_oclsrc, (flags & DFT_INVERSE) != 0 ? "-D INVERSE" : ""); - if (k.empty()) - return false; - - k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), block_size, thread_count, nonzero_rows); - return k.run(2, globalsize, NULL, false); -} - static bool ocl_packToCCS(InputArray _buffer, OutputArray _dst, int flags) { UMat buffer = _buffer.getUMat(); @@ -2098,24 +2078,18 @@ static bool ocl_packToCCS(InputArray _buffer, OutputArray _dst, int flags) return true; } -static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, int nonzero_rows, int flags) +static std::vector ocl_getRadixes(int cols, int& min_radix) { - int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type); - UMat src = _src.getUMat(); - - bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - if (depth == CV_64F && !doubleSupport) - return false; - int factors[34]; - int nf = DFTFactorize( src.cols, factors ); + int nf = DFTFactorize( cols, factors ); int n = 1; int factor_index = 0; - - String radix_processing; - int min_radix = INT_MAX; - // 1. 2^n transforms + + // choose radix order + std::vector radixes; + + // 2^n transforms if ( (factors[factor_index] & 1) == 0 ) { for( ; n < factors[factor_index]; ) @@ -2126,24 +2100,76 @@ static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, int nonzero_rows, else if (4*n <= factors[0]) radix = 4; - radix_processing += format("fft_radix%d(smem,x,%d,%d);", radix, n, src.cols/radix); - min_radix = min(radix, min_radix); + radixes.push_back(radix); + min_radix = min(min_radix, radix); n *= radix; } factor_index++; } - // 2. all the other transforms + // all the other transforms for( ; factor_index < nf; factor_index++ ) { - int radix = factors[factor_index]; - radix_processing += format("fft_radix%d(smem,x,%d,%d);", radix, n, src.cols/radix); - min_radix = min(radix, min_radix); + radixes.push_back(factors[factor_index]); + min_radix = min(min_radix, factors[factor_index]); + } + return radixes; +} + +static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, InputOutputArray _twiddles, int nonzero_rows, int flags) +{ + int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type); + UMat src = _src.getUMat(); + + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + if (depth == CV_64F && !doubleSupport) + return false; + + int min_radix = INT_MAX; + std::vector radixes = ocl_getRadixes(src.cols, min_radix); + + // generate string with radix calls + String radix_processing; + int n = 1, twiddle_index = 0; + for (size_t i=0; i(); + int ptr_index = 0; + + int n = 1; + for (size_t i=0; i _src.rows() ) nonzero_rows = _src.rows(); + UMat buffer; - if (!ocl_dft_C2C_row(src, dst, nonzero_rows, flags)) + if (!ocl_dft_C2C_row(src, dst, buffer, nonzero_rows, flags)) return false; if ((flags & DFT_ROWS) == 0 && nonzero_rows > 1) { transpose(dst, dst); - if (!ocl_dft_C2C_row(dst, dst, dst.rows, flags)) + if (!ocl_dft_C2C_row(dst, dst, buffer, dst.rows, flags)) return false; transpose(dst, dst); } - //if (complex_output) - //{ - // if (real_input && is1d) - // _dst.assign(buffer.colRange(0, buffer.cols/2+1)); - // else - // _dst.assign(buffer); - //} + if (complex_output) + { + if (real_input && is1d) + _dst.assign(dst.colRange(0, dst.cols/2+1)); + else + _dst.assign(dst); + } //else //{ // if (!inv) diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index 7006b92e68..bd2b863c6c 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -7,55 +7,36 @@ __constant float fft5_3 = -0.951056516295f; __constant float fft5_4 = -1.538841768587f; __constant float fft5_5 = 0.363271264002f; -inline float2 mul_float2(float2 a, float2 b){ +__attribute__((always_inline)) +float2 mul_float2(float2 a, float2 b){ float2 res; res.x = a.x * b.x - a.y * b.y; res.y = a.x * b.y + a.y * b.x; return res; } -inline float2 sincos_float2(float alpha) { +__attribute__((always_inline)) +float2 sincos_float2(float alpha) { float cs, sn; sn = sincos(alpha, &cs); // sincos return (float2)(cs, sn); } -inline float2 twiddle(float2 a) { +__attribute__((always_inline)) +float2 twiddle(float2 a) { return (float2)(a.y, -a.x); } -inline float2 square(float2 a) { - return (float2)(a.x * a.x - a.y * a.y, 2.0f * a.x * a.y); -} - -inline float2 square3(float2 a) { - return (float2)(a.x * a.x - a.y * a.y, 3.0f * a.x * a.y); -} - -inline float2 mul_p1q4(float2 a) { - return (float2)(SQRT_2) * (float2)(a.x + a.y, -a.x + a.y); -} - -inline float2 mul_p3q4(float2 a) { - return (float2)(SQRT_2) * (float2)(-a.x + a.y, -a.x - a.y); -} - __attribute__((always_inline)) -void fft_radix2(__local float2* smem, const int x, const int block_size, const int t) +void fft_radix2(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { const int k = x & (block_size - 1); - float2 in1, temp; + float2 a0, a1; if (x < t) { - in1 = smem[x]; - float2 in2 = smem[x+t]; - - float theta = -PI * k / block_size; - float cs; - float sn = sincos(theta, &cs); - temp = (float2) (in2.x * cs - in2.y * sn, - in2.y * cs + in2.x * sn); + a0 = smem[x]; + a1 = mul_float2(twiddles[k],smem[x+t]); } barrier(CLK_LOCAL_MEM_FENCE); @@ -64,36 +45,25 @@ void fft_radix2(__local float2* smem, const int x, const int block_size, const i { const int dst_ind = (x << 1) - k; - smem[dst_ind] = in1 + temp; - smem[dst_ind+block_size] = in1 - temp; + smem[dst_ind] = a0 + a1; + smem[dst_ind+block_size] = a0 - a1; } barrier(CLK_LOCAL_MEM_FENCE); } __attribute__((always_inline)) -void fft_radix4(__local float2* smem, const int x, const int block_size, const int t) +void fft_radix4(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { const int k = x & (block_size - 1); - float2 b0, b1, b2, b3; + float2 a0, a1, a2, a3; if (x < t) { - float theta = -PI * k / (2 * block_size); - - float2 tw = sincos_float2(theta); - float2 a0 = smem[x]; - float2 a1 = mul_float2(tw, smem[x+t]); - float2 a2 = smem[x + 2*t]; - float2 a3 = mul_float2(tw, smem[x + 3*t]); - tw = square(tw); - a2 = mul_float2(tw, a2); - a3 = mul_float2(tw, a3); - - b0 = a0 + a2; - b1 = a0 - a2; - b2 = a1 + a3; - b3 = twiddle(a1 - a3); + a0 = smem[x]; + a1 = mul_float2(twiddles[3*k],smem[x+t]); + a2 = mul_float2(twiddles[3*k + 1],smem[x+2*t]); + a3 = mul_float2(twiddles[3*k + 2],smem[x+3*t]); } barrier(CLK_LOCAL_MEM_FENCE); @@ -101,63 +71,62 @@ void fft_radix4(__local float2* smem, const int x, const int block_size, const i if (x < t) { const int dst_ind = ((x - k) << 2) + k; - smem[dst_ind] = b0 + b2; - smem[dst_ind + block_size] = b1 + b3; - smem[dst_ind + 2*block_size] = b0 - b2; - smem[dst_ind + 3*block_size] = b1 - b3; + + float2 b0 = a0 + a2; + a2 = a0 - a2; + float2 b1 = a1 + a3; + a3 = twiddle(a1 - a3); + + smem[dst_ind] = b0 + b1; + smem[dst_ind + block_size] = a2 + a3; + smem[dst_ind + 2*block_size] = b0 - b1; + smem[dst_ind + 3*block_size] = a2 - a3; } barrier(CLK_LOCAL_MEM_FENCE); } __attribute__((always_inline)) -void fft_radix8(__local float2* smem, const int x, const int block_size, const int t) +void fft_radix8(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { const int k = x % block_size; float2 a0, a1, a2, a3, a4, a5, a6, a7; if (x < t) { - float theta = -PI * k / (4 * block_size); + int tw_ind = block_size / 8; - float2 tw = sincos_float2(theta); // W a0 = smem[x]; - a1 = mul_float2(tw, smem[x + t]); - a2 = smem[x + 2 * t]; - a3 = mul_float2(tw, smem[x + 3 * t]); - a4 = smem[x + 4 * t]; - a5 = mul_float2(tw, smem[x + 5 * t]); - a6 = smem[x + 6 * t]; - a7 = mul_float2(tw, smem[x + 7 * t]); - - tw = square(tw); // W^2 - a2 = mul_float2(tw, a2); - a3 = mul_float2(tw, a3); - a6 = mul_float2(tw, a6); - a7 = mul_float2(tw, a7); - tw = square(tw); // W^4 - a4 = mul_float2(tw, a4); - a5 = mul_float2(tw, a5); - a6 = mul_float2(tw, a6); - a7 = mul_float2(tw, a7); - - float2 b0 = a0 + a4; - float2 b4 = a0 - a4; - float2 b1 = a1 + a5; - float2 b5 = mul_p1q4(a1 - a5); - float2 b2 = a2 + a6; - float2 b6 = twiddle(a2 - a6); - float2 b3 = a3 + a7; - float2 b7 = mul_p3q4(a3 - a7); - - a0 = b0 + b2; - a2 = b0 - b2; - a1 = b1 + b3; - a3 = twiddle(b1 - b3); - a4 = b4 + b6; - a6 = b4 - b6; - a5 = b5 + b7; - a7 = twiddle(b5 - b7); + a1 = mul_float2(twiddles[7*k], smem[x + t]); + a2 = mul_float2(twiddles[7*k+1],smem[x+2*t]); + a3 = mul_float2(twiddles[7*k+2],smem[x+3*t]); + a4 = mul_float2(twiddles[7*k+3],smem[x+4*t]); + a5 = mul_float2(twiddles[7*k+4],smem[x+5*t]); + a6 = mul_float2(twiddles[7*k+5],smem[x+6*t]); + a7 = mul_float2(twiddles[7*k+6],smem[x+7*t]); + + float2 b0, b1, b6, b7; + + b0 = a0 + a4; + a4 = a0 - a4; + b1 = a1 + a5; + a5 = a1 - a5; + a5 = (float2)(SQRT_2) * (float2)(a5.x + a5.y, -a5.x + a5.y); + b6 = twiddle(a2 - a6); + a2 = a2 + a6; + b7 = a3 - a7; + b7 = (float2)(SQRT_2) * (float2)(-b7.x + b7.y, -b7.x - b7.y); + a3 = a3 + a7; + + a0 = b0 + a2; + a2 = b0 - a2; + a1 = b1 + a3; + a3 = twiddle(b1 - a3); + a6 = a4 - b6; + a4 = a4 + b6; + a7 = twiddle(a5 - b7); + a5 = a5 + b7; + } barrier(CLK_LOCAL_MEM_FENCE); @@ -181,21 +150,16 @@ void fft_radix8(__local float2* smem, const int x, const int block_size, const i } __attribute__((always_inline)) -void fft_radix3(__local float2* smem, const int x, const int block_size, const int t) +void fft_radix3(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { const int k = x % block_size; - float2 a0, a1, a2, b0, b1; + float2 a0, a1, a2; if (x < t) { - const float theta = -PI * k * 2 / (3 * block_size); - a0 = smem[x]; - a1 = mul_float2(sincos_float2(theta), smem[x+t]); - a2 = mul_float2(sincos_float2(2 * theta), smem[x+2*t]); - b1 = a1 + a2; - a2 = twiddle((float2)sin_120*(a1 - a2)); - b0 = a0 - (float2)(0.5f)*b1; + a1 = mul_float2(twiddles[2*k], smem[x+t]); + a2 = mul_float2(twiddles[2*k+1], smem[x+2*t]); } barrier(CLK_LOCAL_MEM_FENCE); @@ -204,6 +168,10 @@ void fft_radix3(__local float2* smem, const int x, const int block_size, const i { const int dst_ind = ((x - k) * 3) + k; + float2 b1 = a1 + a2; + a2 = twiddle((float2)sin_120*(a1 - a2)); + float2 b0 = a0 - (float2)(0.5f)*b1; + smem[dst_ind] = a0 + b1; smem[dst_ind + block_size] = b0 + a2; smem[dst_ind + 2*block_size] = b0 - a2; @@ -213,20 +181,30 @@ void fft_radix3(__local float2* smem, const int x, const int block_size, const i } __attribute__((always_inline)) -void fft_radix5(__local float2* smem, const int x, const int block_size, const int t) +void fft_radix5(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { const int k = x % block_size; - float2 a0, a1, a2, a3, a4, b0, b1, b2, b5; + float2 a0, a1, a2, a3, a4; if (x < t) { - const float theta = -PI * k * 2 / (5 * block_size); - + int tw_ind = block_size / 5; + a0 = smem[x]; - a1 = mul_float2(sincos_float2(theta), smem[x + t]); - a2 = mul_float2(sincos_float2(theta*2),smem[x+2*t]); - a3 = mul_float2(sincos_float2(theta*3),smem[x+3*t]); - a4 = mul_float2(sincos_float2(theta*4),smem[x+4*t]); + a1 = mul_float2(twiddles[4*k], smem[x + t]); + a2 = mul_float2(twiddles[4*k+1],smem[x+2*t]); + a3 = mul_float2(twiddles[4*k+2],smem[x+3*t]); + a4 = mul_float2(twiddles[4*k+3],smem[x+4*t]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t) + { + const int dst_ind = ((x - k) * 5) + k; + __local float2* dst = smem + dst_ind; + + float2 b0, b1, b5; b1 = a1 + a4; a1 -= a4; @@ -234,13 +212,11 @@ void fft_radix5(__local float2* smem, const int x, const int block_size, const i a4 = a3 + a2; a3 -= a2; - b2 = b1 + a4; - b0 = a0 - (float2)0.25f * b2; - - b1 = (float2)fft5_2 * (b1 - a4); - a4 = -(float2)fft5_3 * (a1 + a3); - a4 = twiddle(a4); + a2 = b1 + a4; + b0 = a0 - (float2)0.25f * a2; + b1 = (float2)fft5_2 * (b1 - a4); + a4 = (float2)fft5_3 * (float2)(-a1.y - a3.y, a1.x + a3.x); b5 = (float2)(a4.x - fft5_5 * a1.y, a4.y + fft5_5 * a1.x); a4.x += fft5_4 * a3.y; @@ -248,16 +224,8 @@ void fft_radix5(__local float2* smem, const int x, const int block_size, const i a1 = b0 + b1; b0 -= b1; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (x < t) - { - const int dst_ind = ((x - k) * 5) + k; - __local float2* dst = smem + dst_ind; - dst[0] = a0 + b2; + dst[0] = a0 + a2; dst[block_size] = a1 + a4; dst[2 * block_size] = b0 + b5; dst[3 * block_size] = b0 - b5; @@ -267,8 +235,9 @@ void fft_radix5(__local float2* smem, const int x, const int block_size, const i barrier(CLK_LOCAL_MEM_FENCE); } -__kernel void fft_multi_radix(__global const uchar* srcptr, int src_step, int src_offset, - __global uchar* dstptr, int dst_step, int dst_offset, +__kernel void fft_multi_radix(__global const uchar* src_ptr, int src_step, int src_offset, + __global uchar* dst_ptr, int dst_step, int dst_offset, + __global const uchar* twiddles_ptr, int twiddles_step, int twiddles_offset, const int t, const int nz) { const int x = get_global_id(0); @@ -277,8 +246,9 @@ __kernel void fft_multi_radix(__global const uchar* srcptr, int src_step, int sr if (y < nz) { __local float2 smem[LOCAL_SIZE]; - __global const float2* src = (__global const float2*)(srcptr + mad24(y, src_step, mad24(x, (int)(sizeof(float)*2), src_offset))); - __global float2* dst = (__global float2*)(dstptr + mad24(y, dst_step, mad24(x, (int)(sizeof(float)*2), dst_offset))); + __global const float2* src = (__global const float2*)(src_ptr + mad24(y, src_step, mad24(x, (int)(sizeof(float)*2), src_offset))); + __global float2* dst = (__global float2*)(dst_ptr + mad24(y, dst_step, mad24(x, (int)(sizeof(float)*2), dst_offset))); + __global const float2* twiddles = (__global float2*) twiddles_ptr; const int block_size = LOCAL_SIZE/kercn; #pragma unroll @@ -292,6 +262,8 @@ __kernel void fft_multi_radix(__global const uchar* srcptr, int src_step, int sr // copy data to dst #pragma unroll for (int i=0; i Date: Fri, 11 Jul 2014 15:01:46 +0400 Subject: [PATCH 095/136] Added fftplan cache --- modules/core/src/dxt.cpp | 332 +++++++++++++++++------------ modules/core/src/opencl/fft.cl | 55 ++--- modules/core/test/ocl/test_dft.cpp | 4 +- 3 files changed, 226 insertions(+), 165 deletions(-) diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index de17f07b23..c11b699503 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2034,50 +2034,6 @@ namespace cv #ifdef HAVE_OPENCL -static bool ocl_packToCCS(InputArray _buffer, OutputArray _dst, int flags) -{ - UMat buffer = _buffer.getUMat(); - UMat dst = _dst.getUMat(); - - buffer = buffer.reshape(1); - if ((flags & DFT_ROWS) == 0 && buffer.rows > 1) - { - // pack to CCS by rows - if (dst.cols > 2) - buffer.colRange(2, dst.cols + (dst.cols % 2)).copyTo(dst.colRange(1, dst.cols-1 + (dst.cols % 2))); - - Mat dst_mat = dst.getMat(ACCESS_WRITE); - Mat buffer_mat = buffer.getMat(ACCESS_READ); - - dst_mat.at(0,0) = buffer_mat.at(0,0); - dst_mat.at(dst_mat.rows-1,0) = buffer_mat.at(buffer.rows/2,0); - for (int i=1; i(i,0) = buffer_mat.at((i+1)/2,0); - dst_mat.at(i+1,0) = buffer_mat.at((i+1)/2,1); - } - - if (dst_mat.cols % 2 == 0) - { - dst_mat.at(0,dst_mat.cols-1) = buffer_mat.at(0,buffer.cols/2); - dst_mat.at(dst_mat.rows-1,dst_mat.cols-1) = buffer_mat.at(buffer.rows/2,buffer.cols/2); - - for (int i=1; i(i,dst_mat.cols-1) = buffer_mat.at((i+1)/2,buffer.cols/2); - dst_mat.at(i+1,dst_mat.cols-1) = buffer_mat.at((i+1)/2,buffer.cols/2+1); - } - } - } - else - { - // pack to CCS each row - buffer.colRange(0,1).copyTo(dst.colRange(0,1)); - buffer.colRange(2, (dst.cols+1)).copyTo(dst.colRange(1, dst.cols)); - } - return true; -} - static std::vector ocl_getRadixes(int cols, int& min_radix) { int factors[34]; @@ -2116,72 +2072,175 @@ static std::vector ocl_getRadixes(int cols, int& min_radix) return radixes; } -static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, InputOutputArray _twiddles, int nonzero_rows, int flags) +struct OCL_FftPlan { - int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type); - UMat src = _src.getUMat(); + UMat twiddles; + String buildOptions; + int thread_count; - bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - if (depth == CV_64F && !doubleSupport) - return false; - - int min_radix = INT_MAX; - std::vector radixes = ocl_getRadixes(src.cols, min_radix); - - // generate string with radix calls - String radix_processing; - int n = 1, twiddle_index = 0; - for (size_t i=0; i radixes = ocl_getRadixes(dft_size, min_radix); + thread_count = dft_size / min_radix; + + // generate string with radix calls + String radix_processing; + int n = 1, twiddle_size = 0; + for (size_t i=0; i(); int ptr_index = 0; - int n = 1; + n = 1; for (size_t i=0; idft_size == dft_size) + { + return plan; + } + } - k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), ocl::KernelArg::ReadOnlyNoSize(twiddles), thread_count, nonzero_rows); - return k.run(2, globalsize, localsize, false); + OCL_FftPlan * newPlan = new OCL_FftPlan(dft_size, flags); + planStorage.push_back(newPlan); + return newPlan; + } + + ~OCL_FftPlanCache() + { + for (std::vector::iterator i = planStorage.begin(), end = planStorage.end(); i != end; ++i) + delete (*i); + planStorage.clear(); + } + +protected: + OCL_FftPlanCache() : + planStorage() + { + } + + std::vector planStorage; +}; + +static bool ocl_packToCCS(InputArray _src, OutputArray _dst, int flags) +{ + UMat src = _src.getUMat(); + _dst.create(src.size(), CV_32F); + UMat dst = _dst.getUMat(); + + src = src.reshape(1); + if ((flags & DFT_ROWS) == 0 && src.rows > 1) + { + // pack to CCS by rows + if (dst.cols > 2) + src.colRange(2, dst.cols + (dst.cols % 2)).copyTo(dst.colRange(1, dst.cols-1 + (dst.cols % 2))); + + Mat dst_mat = dst.getMat(ACCESS_WRITE); + Mat buffer_mat = src.getMat(ACCESS_READ); + + dst_mat.at(0,0) = buffer_mat.at(0,0); + dst_mat.at(dst_mat.rows-1,0) = buffer_mat.at(src.rows/2,0); + for (int i=1; i(i,0) = buffer_mat.at((i+1)/2,0); + dst_mat.at(i+1,0) = buffer_mat.at((i+1)/2,1); + } + + if (dst_mat.cols % 2 == 0) + { + dst_mat.at(0,dst_mat.cols-1) = buffer_mat.at(0,src.cols/2); + dst_mat.at(dst_mat.rows-1,dst_mat.cols-1) = buffer_mat.at(src.rows/2,src.cols/2); + + for (int i=1; i(i,dst_mat.cols-1) = buffer_mat.at((i+1)/2,src.cols/2); + dst_mat.at(i+1,dst_mat.cols-1) = buffer_mat.at((i+1)/2,src.cols/2+1); + } + } + } + else + { + // pack to CCS each row + src.colRange(0,1).copyTo(dst.colRange(0,1)); + src.colRange(2, (dst.cols+1)).copyTo(dst.colRange(1, dst.cols)); + } + return true; +} + +static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, int nonzero_rows, int flags) +{ + int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type); + + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + if (depth == CV_64F && !doubleSupport) + return false; + + const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.cols(), flags); + return plan->enqueueTransform(_src, _dst, nonzero_rows); } static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_rows) @@ -2217,76 +2276,71 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro } } - if (complex_output) + UMat input, output; + if (complex_input) { - //if (is1d) - // _dst.create(Size(src.cols/2+1, src.rows), CV_MAKE_TYPE(depth, 2)); - //else - _dst.create(src.size(), CV_MAKE_TYPE(depth, 2)); + input = src; } else - _dst.create(src.size(), CV_MAKE_TYPE(depth, 1)); - UMat dst = _dst.getUMat(); + { + if (!inv) + { + // in case real input convert it to complex + input.create(src.size(), CV_MAKE_TYPE(depth, 2)); + std::vector planes; + planes.push_back(src); + planes.push_back(UMat::zeros(src.size(), CV_32F)); + merge(planes, input); + } + else + { + // TODO: unpack from CCS format + } + } - bool inplace = src.u == dst.u; - //UMat buffer; - - //if (complex_input) - //{ - // if (inplace) - // buffer = src; - // else - // src.copyTo(buffer); - //} - //else - //{ - // if (!inv) - // { - // // in case real input convert it to complex - // buffer.create(src.size(), CV_MAKE_TYPE(depth, 2)); - // std::vector planes; - // planes.push_back(src); - // planes.push_back(UMat::zeros(src.size(), CV_32F)); - // merge(planes, buffer); - // } - // else - // { - // // TODO: unpack from CCS format - // } - //} + + UMat dst = _dst.getUMat(); + if (complex_output) + { + if (real_input && is1d && !inv) + output.create(src.size(), CV_32FC2); + else + output = dst; + } else + { + output.create(src.size(), CV_32FC2); + } if( nonzero_rows <= 0 || nonzero_rows > _src.rows() ) nonzero_rows = _src.rows(); - UMat buffer; - - if (!ocl_dft_C2C_row(src, dst, buffer, nonzero_rows, flags)) + if (!ocl_dft_C2C_row(input, output, nonzero_rows, flags)) return false; if ((flags & DFT_ROWS) == 0 && nonzero_rows > 1) { - transpose(dst, dst); - if (!ocl_dft_C2C_row(dst, dst, buffer, dst.rows, flags)) + transpose(output, output); + if (!ocl_dft_C2C_row(output, output, output.rows, flags)) return false; - transpose(dst, dst); + transpose(output, output); } if (complex_output) { - if (real_input && is1d) - _dst.assign(dst.colRange(0, dst.cols/2+1)); + if (real_input && is1d && !inv) + _dst.assign(output.colRange(0, output.cols/2+1)); else - _dst.assign(dst); - } - //else - //{ - // if (!inv) - // ocl_packToCCS(buffer, _dst, flags); - // else - // { - // // copy real part to dst - // } - //} + _dst.assign(output); + } + else + { + if (!inv) + ocl_packToCCS(output, _dst, flags); + else + { + // copy real part to dst + } + } return true; } diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index bd2b863c6c..34da79fafb 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -28,7 +28,7 @@ float2 twiddle(float2 a) { } __attribute__((always_inline)) -void fft_radix2(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { const int k = x & (block_size - 1); float2 a0, a1; @@ -53,17 +53,18 @@ void fft_radix2(__local float2* smem, __global const float2* twiddles, const int } __attribute__((always_inline)) -void fft_radix4(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix4(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { const int k = x & (block_size - 1); float2 a0, a1, a2, a3; if (x < t) { + const int twiddle_block = block_size / 4; a0 = smem[x]; - a1 = mul_float2(twiddles[3*k],smem[x+t]); - a2 = mul_float2(twiddles[3*k + 1],smem[x+2*t]); - a3 = mul_float2(twiddles[3*k + 2],smem[x+3*t]); + a1 = mul_float2(twiddles[k],smem[x+t]); + a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); + a3 = mul_float2(twiddles[k + 2*block_size],smem[x+3*t]); } barrier(CLK_LOCAL_MEM_FENCE); @@ -87,7 +88,7 @@ void fft_radix4(__local float2* smem, __global const float2* twiddles, const int } __attribute__((always_inline)) -void fft_radix8(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix8(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { const int k = x % block_size; float2 a0, a1, a2, a3, a4, a5, a6, a7; @@ -97,13 +98,13 @@ void fft_radix8(__local float2* smem, __global const float2* twiddles, const int int tw_ind = block_size / 8; a0 = smem[x]; - a1 = mul_float2(twiddles[7*k], smem[x + t]); - a2 = mul_float2(twiddles[7*k+1],smem[x+2*t]); - a3 = mul_float2(twiddles[7*k+2],smem[x+3*t]); - a4 = mul_float2(twiddles[7*k+3],smem[x+4*t]); - a5 = mul_float2(twiddles[7*k+4],smem[x+5*t]); - a6 = mul_float2(twiddles[7*k+5],smem[x+6*t]); - a7 = mul_float2(twiddles[7*k+6],smem[x+7*t]); + a1 = mul_float2(twiddles[k], smem[x + t]); + a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); + a3 = mul_float2(twiddles[k+2*block_size],smem[x+3*t]); + a4 = mul_float2(twiddles[k+3*block_size],smem[x+4*t]); + a5 = mul_float2(twiddles[k+4*block_size],smem[x+5*t]); + a6 = mul_float2(twiddles[k+5*block_size],smem[x+6*t]); + a7 = mul_float2(twiddles[k+6*block_size],smem[x+7*t]); float2 b0, b1, b6, b7; @@ -150,16 +151,23 @@ void fft_radix8(__local float2* smem, __global const float2* twiddles, const int } __attribute__((always_inline)) -void fft_radix3(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix3(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { const int k = x % block_size; float2 a0, a1, a2; if (x < t) { + //const int twiddle_block = block_size / 3; + //const float theta = -PI * k * 2 / (3 * block_size); + //float2 tw = sincos_float2(theta); + //printf("radix3 %d (%f,%f)(%f,%f)\n", k, tw.x, tw.y, twiddles[k].x, twiddles[k].y); + //tw = sincos_float2(2*theta); + //printf("radix3- %d %d (%f,%f)(%f,%f)\n", k, twiddle_block, tw.x, tw.y, twiddles[k+block_size].x, twiddles[k+block_size].y); + a0 = smem[x]; - a1 = mul_float2(twiddles[2*k], smem[x+t]); - a2 = mul_float2(twiddles[2*k+1], smem[x+2*t]); + a1 = mul_float2(twiddles[k], smem[x+t]); + a2 = mul_float2(twiddles[k+block_size], smem[x+2*t]); } barrier(CLK_LOCAL_MEM_FENCE); @@ -181,7 +189,7 @@ void fft_radix3(__local float2* smem, __global const float2* twiddles, const int } __attribute__((always_inline)) -void fft_radix5(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix5(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { const int k = x % block_size; float2 a0, a1, a2, a3, a4; @@ -191,10 +199,10 @@ void fft_radix5(__local float2* smem, __global const float2* twiddles, const int int tw_ind = block_size / 5; a0 = smem[x]; - a1 = mul_float2(twiddles[4*k], smem[x + t]); - a2 = mul_float2(twiddles[4*k+1],smem[x+2*t]); - a3 = mul_float2(twiddles[4*k+2],smem[x+3*t]); - a4 = mul_float2(twiddles[4*k+3],smem[x+4*t]); + a1 = mul_float2(twiddles[k], smem[x + t]); + a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); + a3 = mul_float2(twiddles[k+2*block_size],smem[x+3*t]); + a4 = mul_float2(twiddles[k+3*block_size],smem[x+4*t]); } barrier(CLK_LOCAL_MEM_FENCE); @@ -237,8 +245,7 @@ void fft_radix5(__local float2* smem, __global const float2* twiddles, const int __kernel void fft_multi_radix(__global const uchar* src_ptr, int src_step, int src_offset, __global uchar* dst_ptr, int dst_step, int dst_offset, - __global const uchar* twiddles_ptr, int twiddles_step, int twiddles_offset, - const int t, const int nz) + __constant float2 * twiddles_ptr, const int t, const int nz) { const int x = get_global_id(0); const int y = get_group_id(1); @@ -248,7 +255,7 @@ __kernel void fft_multi_radix(__global const uchar* src_ptr, int src_step, int s __local float2 smem[LOCAL_SIZE]; __global const float2* src = (__global const float2*)(src_ptr + mad24(y, src_step, mad24(x, (int)(sizeof(float)*2), src_offset))); __global float2* dst = (__global float2*)(dst_ptr + mad24(y, dst_step, mad24(x, (int)(sizeof(float)*2), dst_offset))); - __global const float2* twiddles = (__global float2*) twiddles_ptr; + __constant const float2* twiddles = (__constant float2*) twiddles_ptr; const int block_size = LOCAL_SIZE/kercn; #pragma unroll diff --git a/modules/core/test/ocl/test_dft.cpp b/modules/core/test/ocl/test_dft.cpp index 7a7a98852a..2529e949e0 100644 --- a/modules/core/test/ocl/test_dft.cpp +++ b/modules/core/test/ocl/test_dft.cpp @@ -181,9 +181,9 @@ OCL_TEST_P(MulSpectrums, Mat) OCL_INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MulSpectrums, testing::Combine(Bool(), Bool())); -OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(2, 3), cv::Size(5, 4), cv::Size(30, 20), +OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(1920, 1), cv::Size(5, 4), cv::Size(30, 20), cv::Size(512, 1), cv::Size(1024, 1024)), - Values((OCL_FFT_TYPE) C2C/*, (OCL_FFT_TYPE) R2R, (OCL_FFT_TYPE) R2C/*, (OCL_FFT_TYPE) C2R*/), + Values(/*(OCL_FFT_TYPE) C2C, (OCL_FFT_TYPE) R2C,*/ (OCL_FFT_TYPE) R2R/*, (OCL_FFT_TYPE) C2R*/), Bool() // DFT_ROWS ) ); From ed07241f89849c4d91a0c78494ed9a5823c09342 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Tue, 15 Jul 2014 18:25:46 +0400 Subject: [PATCH 096/136] Completed all forward transforms. --- modules/core/perf/opencl/perf_arithm.cpp | 2 +- modules/core/perf/opencl/perf_dxt.cpp | 33 +++- modules/core/src/dxt.cpp | 139 +++++++++++------ modules/core/src/opencl/fft.cl | 182 ++++++++++++++++++----- modules/core/test/ocl/test_dft.cpp | 21 +-- 5 files changed, 276 insertions(+), 101 deletions(-) diff --git a/modules/core/perf/opencl/perf_arithm.cpp b/modules/core/perf/opencl/perf_arithm.cpp index 17badca765..ba808b494f 100644 --- a/modules/core/perf/opencl/perf_arithm.cpp +++ b/modules/core/perf/opencl/perf_arithm.cpp @@ -292,7 +292,7 @@ OCL_PERF_TEST_P(MagnitudeFixture, Magnitude, ::testing::Combine( typedef Size_MatType TransposeFixture; OCL_PERF_TEST_P(TransposeFixture, Transpose, ::testing::Combine( - OCL_TEST_SIZES, OCL_TEST_TYPES_134)) + OCL_TEST_SIZES, Values(CV_8UC1, CV_32FC1, CV_8UC2, CV_32FC2, CV_8UC4, CV_32FC4))) { const Size_MatType_t params = GetParam(); const Size srcSize = get<0>(params); diff --git a/modules/core/perf/opencl/perf_dxt.cpp b/modules/core/perf/opencl/perf_dxt.cpp index c0da96b373..edeeda7f0c 100644 --- a/modules/core/perf/opencl/perf_dxt.cpp +++ b/modules/core/perf/opencl/perf_dxt.cpp @@ -54,21 +54,40 @@ namespace ocl { ///////////// dft //////////////////////// -typedef tuple DftParams; +enum OCL_FFT_TYPE +{ + R2R = 0, // real to real (CCS) + C2R = 1, // complex to real + R2C = 2, // real to complex + C2C = 3 // complex to complex +}; + +typedef tuple DftParams; typedef TestBaseWithParam DftFixture; -OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(1024, 1024), Size(1024, 2048), Size(512, 512), Size(2048, 2048)), +OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(C2C, R2R, C2R, R2C), + Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(1024, 1024), Size(512, 512), Size(2048, 2048)), Values((int)DFT_ROWS, (int) 0/*, (int)DFT_SCALE, (int)DFT_INVERSE, (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE*/))) { const DftParams params = GetParam(); - const Size srcSize = get<0>(params); - const int flags = get<1>(params); - - UMat src(srcSize, CV_32FC2), dst(srcSize, CV_32FC2); + const int dft_type = get<0>(params); + const Size srcSize = get<1>(params); + int flags = get<2>(params); + + int in_cn, out_cn; + switch (dft_type) + { + case R2R: flags |= cv::DFT_REAL_OUTPUT; in_cn = 1; out_cn = 1; break; + case C2R: flags |= cv::DFT_REAL_OUTPUT; in_cn = 2; out_cn = 2; break; + case R2C: flags |= cv::DFT_COMPLEX_OUTPUT; in_cn = 1; out_cn = 2; break; + case C2C: flags |= cv::DFT_COMPLEX_OUTPUT; in_cn = 2; out_cn = 2; break; + } + + UMat src(srcSize, CV_MAKE_TYPE(CV_32F, in_cn)), dst(srcSize, CV_MAKE_TYPE(CV_32F, out_cn)); declare.in(src, WARMUP_RNG).out(dst); - OCL_TEST_CYCLE() cv::dft(src, dst, flags | DFT_COMPLEX_OUTPUT); + OCL_TEST_CYCLE() cv::dft(src, dst, flags); SANITY_CHECK(dst, 1e-3); } diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index c11b699503..a3df694364 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2034,7 +2034,7 @@ namespace cv #ifdef HAVE_OPENCL -static std::vector ocl_getRadixes(int cols, int& min_radix) +static std::vector ocl_getRadixes(int cols, std::vector& radixes, std::vector& blocks, int& min_radix) { int factors[34]; int nf = DFTFactorize( cols, factors ); @@ -2042,9 +2042,6 @@ static std::vector ocl_getRadixes(int cols, int& min_radix) int n = 1; int factor_index = 0; - // choose radix order - std::vector radixes; - // 2^n transforms if ( (factors[factor_index] & 1) == 0 ) { @@ -2057,7 +2054,10 @@ static std::vector ocl_getRadixes(int cols, int& min_radix) radix = 4; radixes.push_back(radix); - min_radix = min(min_radix, radix); + if (radix == 2 && cols % 4 == 0) + min_radix = min(min_radix, 2*radix); + else + min_radix = min(min_radix, radix); n *= radix; } factor_index++; @@ -2067,7 +2067,10 @@ static std::vector ocl_getRadixes(int cols, int& min_radix) for( ; factor_index < nf; factor_index++ ) { radixes.push_back(factors[factor_index]); - min_radix = min(min_radix, factors[factor_index]); + if (factors[factor_index] == 3 && cols % 6 == 0) + min_radix = min(min_radix, 2*factors[factor_index]); + else + min_radix = min(min_radix, factors[factor_index]); } return radixes; } @@ -2084,8 +2087,16 @@ struct OCL_FftPlan OCL_FftPlan(int _size, int _flags): dft_size(_size), flags(_flags) { int min_radix = INT_MAX; - std::vector radixes = ocl_getRadixes(dft_size, min_radix); - thread_count = dft_size / min_radix; + std::vector radixes, blocks; + ocl_getRadixes(dft_size, radixes, blocks, min_radix); + thread_count = (dft_size + min_radix-1) / min_radix; + + printf("cols: %d - ", dft_size); + for (int i=0; i 0; - if (depth == CV_64F && !doubleSupport) - return false; - const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.cols(), flags); - return plan->enqueueTransform(_src, _dst, nonzero_rows); + return plan->enqueueTransform(_src, _dst, nonzero_rows, flags, true); +} + +static bool ocl_dft_C2C_cols(InputArray _src, OutputArray _dst, int flags) +{ + const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.rows(), flags); + return plan->enqueueTransform(_src, _dst, _src.cols(), flags, false); } static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_rows) @@ -2262,7 +2295,10 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro int real_input = cn == 1 ? 1 : 0; int real_output = (flags & DFT_REAL_OUTPUT) != 0; bool inv = (flags & DFT_INVERSE) != 0 ? 1 : 0; - bool is1d = (flags & DFT_ROWS) != 0 || src.rows == 1; + + if( nonzero_rows <= 0 || nonzero_rows > _src.rows() ) + nonzero_rows = _src.rows(); + bool is1d = (flags & DFT_ROWS) != 0 || nonzero_rows == 1; // if output format is not specified if (complex_output + real_output == 0) @@ -2276,6 +2312,19 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro } } + // Forward Complex to CCS not supported + if (complex_input && real_output && !inv) + { + real_output = 0; + complex_output = 1; + } + // Inverse CCS to Complex not supported + if (real_input && complex_output && inv) + { + complex_output = 0; + real_output = 1; + } + UMat input, output; if (complex_input) { @@ -2285,12 +2334,7 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro { if (!inv) { - // in case real input convert it to complex - input.create(src.size(), CV_MAKE_TYPE(depth, 2)); - std::vector planes; - planes.push_back(src); - planes.push_back(UMat::zeros(src.size(), CV_32F)); - merge(planes, input); + input = src; } else { @@ -2298,31 +2342,34 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro } } - - UMat dst = _dst.getUMat(); if (complex_output) { if (real_input && is1d && !inv) output.create(src.size(), CV_32FC2); else - output = dst; + { + _dst.create(src.size(), CV_32FC2); + output = _dst.getUMat(); + } } else { - output.create(src.size(), CV_32FC2); + // CCS + if (is1d) + { + _dst.create(src.size(), CV_32FC1); + output = _dst.getUMat(); + } + else + output.create(src.size(), CV_32FC2); } - if( nonzero_rows <= 0 || nonzero_rows > _src.rows() ) - nonzero_rows = _src.rows(); - - if (!ocl_dft_C2C_row(input, output, nonzero_rows, flags)) + if (!ocl_dft_C2C_rows(input, output, nonzero_rows, flags)) return false; - if ((flags & DFT_ROWS) == 0 && nonzero_rows > 1) + if (!is1d) { - transpose(output, output); - if (!ocl_dft_C2C_row(output, output, output.rows, flags)) + if (!ocl_dft_C2C_cols(output, output, flags)) return false; - transpose(output, output); } if (complex_output) @@ -2335,12 +2382,18 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro else { if (!inv) - ocl_packToCCS(output, _dst, flags); + { + if (!is1d) + ocl_packToCCS(output, _dst, flags); + else + _dst.assign(output); + } else { // copy real part to dst } } + //printf("OCL!\n"); return true; } diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index 34da79fafb..7803cdbc21 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -1,25 +1,13 @@ -__constant float PI = 3.14159265f; -__constant float SQRT_2 = 0.707106781188f; - -__constant float sin_120 = 0.866025403784f; -__constant float fft5_2 = 0.559016994374f; -__constant float fft5_3 = -0.951056516295f; -__constant float fft5_4 = -1.538841768587f; -__constant float fft5_5 = 0.363271264002f; +#define SQRT_2 0.707106781188f +#define sin_120 0.866025403784f +#define fft5_2 0.559016994374f +#define fft5_3 -0.951056516295f +#define fft5_4 -1.538841768587f +#define fft5_5 0.363271264002f __attribute__((always_inline)) -float2 mul_float2(float2 a, float2 b){ - float2 res; - res.x = a.x * b.x - a.y * b.y; - res.y = a.x * b.y + a.y * b.x; - return res; -} - -__attribute__((always_inline)) -float2 sincos_float2(float alpha) { - float cs, sn; - sn = sincos(alpha, &cs); // sincos - return (float2)(cs, sn); +float2 mul_float2(float2 a, float2 b) { + return (float2)(fma(a.x, b.x, -a.y * b.y), fma(a.x, b.y, a.y * b.x)); } __attribute__((always_inline)) @@ -52,6 +40,38 @@ void fft_radix2(__local float2* smem, __constant const float2* twiddles, const i barrier(CLK_LOCAL_MEM_FENCE); } +__attribute__((always_inline)) +void fft_radix2_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +{ + const int k1 = x & (block_size - 1); + const int x2 = x + (t+1)/2; + const int k2 = x2 & (block_size - 1); + float2 a0, a1, a2, a3; + + if (x < (t+1)/2) + { + a0 = smem[x]; + a1 = mul_float2(twiddles[k1],smem[x+t]); + a2 = smem[x2]; + a3 = mul_float2(twiddles[k2],smem[x2+t]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < (t+1)/2) + { + int dst_ind = (x << 1) - k1; + smem[dst_ind] = a0 + a1; + smem[dst_ind+block_size] = a0 - a1; + + dst_ind = (x2 << 1) - k2; + smem[dst_ind] = a2 + a3; + smem[dst_ind+block_size] = a2 - a3; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + __attribute__((always_inline)) void fft_radix4(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { @@ -158,13 +178,6 @@ void fft_radix3(__local float2* smem, __constant const float2* twiddles, const i if (x < t) { - //const int twiddle_block = block_size / 3; - //const float theta = -PI * k * 2 / (3 * block_size); - //float2 tw = sincos_float2(theta); - //printf("radix3 %d (%f,%f)(%f,%f)\n", k, tw.x, tw.y, twiddles[k].x, twiddles[k].y); - //tw = sincos_float2(2*theta); - //printf("radix3- %d %d (%f,%f)(%f,%f)\n", k, twiddle_block, tw.x, tw.y, twiddles[k+block_size].x, twiddles[k+block_size].y); - a0 = smem[x]; a1 = mul_float2(twiddles[k], smem[x+t]); a2 = mul_float2(twiddles[k+block_size], smem[x+2*t]); @@ -177,7 +190,7 @@ void fft_radix3(__local float2* smem, __constant const float2* twiddles, const i const int dst_ind = ((x - k) * 3) + k; float2 b1 = a1 + a2; - a2 = twiddle((float2)sin_120*(a1 - a2)); + a2 = twiddle(sin_120*(a1 - a2)); float2 b0 = a0 - (float2)(0.5f)*b1; smem[dst_ind] = a0 + b1; @@ -188,6 +201,53 @@ void fft_radix3(__local float2* smem, __constant const float2* twiddles, const i barrier(CLK_LOCAL_MEM_FENCE); } +__attribute__((always_inline)) +void fft_radix3_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +{ + const int k = x % block_size; + const int x2 = x + (t+1)/2; + const int k2 = x2 % block_size; + float2 a0, a1, a2, a3, a4, a5; + + if (x < (t+1)/2) + { + a0 = smem[x]; + a1 = mul_float2(twiddles[k], smem[x+t]); + a2 = mul_float2(twiddles[k+block_size], smem[x+2*t]); + + a3 = smem[x2]; + a4 = mul_float2(twiddles[k2], smem[x2+t]); + a5 = mul_float2(twiddles[k2+block_size], smem[x2+2*t]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < (t+1)/2) + { + int dst_ind = ((x - k) * 3) + k; + + float2 b1 = a1 + a2; + a2 = twiddle(sin_120*(a1 - a2)); + float2 b0 = a0 - (float2)(0.5f)*b1; + + smem[dst_ind] = a0 + b1; + smem[dst_ind + block_size] = b0 + a2; + smem[dst_ind + 2*block_size] = b0 - a2; + + dst_ind = ((x2 - k2) * 3) + k2; + + b1 = a4 + a5; + a5 = twiddle(sin_120*(a4 - a5)); + b0 = a3 - (float2)(0.5f)*b1; + + smem[dst_ind] = a3 + b1; + smem[dst_ind + block_size] = b0 + a5; + smem[dst_ind + 2*block_size] = b0 - a5; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + __attribute__((always_inline)) void fft_radix5(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { @@ -196,8 +256,6 @@ void fft_radix5(__local float2* smem, __constant const float2* twiddles, const i if (x < t) { - int tw_ind = block_size / 5; - a0 = smem[x]; a1 = mul_float2(twiddles[k], smem[x + t]); a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); @@ -223,8 +281,8 @@ void fft_radix5(__local float2* smem, __constant const float2* twiddles, const i a2 = b1 + a4; b0 = a0 - (float2)0.25f * a2; - b1 = (float2)fft5_2 * (b1 - a4); - a4 = (float2)fft5_3 * (float2)(-a1.y - a3.y, a1.x + a3.x); + b1 = fft5_2 * (b1 - a4); + a4 = fft5_3 * (float2)(-a1.y - a3.y, a1.x + a3.x); b5 = (float2)(a4.x - fft5_5 * a1.y, a4.y + fft5_5 * a1.x); a4.x += fft5_4 * a3.y; @@ -243,9 +301,9 @@ void fft_radix5(__local float2* smem, __constant const float2* twiddles, const i barrier(CLK_LOCAL_MEM_FENCE); } -__kernel void fft_multi_radix(__global const uchar* src_ptr, int src_step, int src_offset, - __global uchar* dst_ptr, int dst_step, int dst_offset, - __constant float2 * twiddles_ptr, const int t, const int nz) +__kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, int src_offset, int src_rows, int src_cols, + __global uchar* dst_ptr, int dst_step, int dst_offset, int dst_rows, int dst_cols, + __constant float2 * twiddles_ptr, const int t, const int nz) { const int x = get_global_id(0); const int y = get_group_id(1); @@ -253,14 +311,60 @@ __kernel void fft_multi_radix(__global const uchar* src_ptr, int src_step, int s if (y < nz) { __local float2 smem[LOCAL_SIZE]; + __constant const float2* twiddles = (__constant float2*) twiddles_ptr; + const int ind = x; + const int block_size = LOCAL_SIZE/kercn; + +#ifndef REAL_INPUT __global const float2* src = (__global const float2*)(src_ptr + mad24(y, src_step, mad24(x, (int)(sizeof(float)*2), src_offset))); + #pragma unroll + for (int i=0; i Date: Thu, 17 Jul 2014 12:31:41 +0400 Subject: [PATCH 097/136] Added packing to CCS format --- modules/core/src/dxt.cpp | 117 +++++++---------------------- modules/core/src/opencl/fft.cl | 48 ++++++++++-- modules/core/test/ocl/test_dft.cpp | 18 +++-- 3 files changed, 82 insertions(+), 101 deletions(-) diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index a3df694364..69ec2c9efe 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2083,20 +2083,19 @@ struct OCL_FftPlan int dft_size; int flags; - - OCL_FftPlan(int _size, int _flags): dft_size(_size), flags(_flags) + bool status; + OCL_FftPlan(int _size, int _flags): dft_size(_size), flags(_flags), status(true) { int min_radix = INT_MAX; std::vector radixes, blocks; ocl_getRadixes(dft_size, radixes, blocks, min_radix); thread_count = (dft_size + min_radix-1) / min_radix; - printf("cols: %d - ", dft_size); - for (int i=0; i ocl::Device::getDefault().maxWorkGroupSize()) { - printf("%d ", radixes[i]); + status = false; + return; } - printf("min radix - %d\n", min_radix); // generate string with radix calls String radix_processing; @@ -2142,6 +2141,9 @@ struct OCL_FftPlan bool enqueueTransform(InputArray _src, OutputArray _dst, int dft_size, int flags, bool rows = true) const { + if (!status) + return false; + UMat src = _src.getUMat(); UMat dst = _dst.getUMat(); @@ -2162,11 +2164,14 @@ struct OCL_FftPlan kernel_name = "fft_multi_radix_cols"; } + bool is1d = (flags & DFT_ROWS) != 0 || dft_size == 1; String options = buildOptions; if (src.channels() == 1) options += " -D REAL_INPUT"; if (dst.channels() == 1) options += " -D CCS_OUTPUT"; + if ((is1d && src.channels() == 1) || (rows && (flags & DFT_REAL_OUTPUT))) + options += " -D NO_CONJUGATE"; ocl::Kernel k(kernel_name.c_str(), ocl::core::fft_oclsrc, options); if (k.empty()) @@ -2219,61 +2224,16 @@ protected: std::vector planStorage; }; -static bool ocl_packToCCS(InputArray _src, OutputArray _dst, int flags) -{ - UMat src = _src.getUMat(); - _dst.create(src.size(), CV_32F); - UMat dst = _dst.getUMat(); - - src = src.reshape(1); - if ((flags & DFT_ROWS) == 0 && src.rows > 1) - { - // pack to CCS by rows - if (dst.cols > 2) - src.colRange(2, dst.cols + (dst.cols % 2)).copyTo(dst.colRange(1, dst.cols-1 + (dst.cols % 2))); - - Mat dst_mat = dst.getMat(ACCESS_WRITE); - Mat buffer_mat = src.getMat(ACCESS_READ); - - dst_mat.at(0,0) = buffer_mat.at(0,0); - dst_mat.at(dst_mat.rows-1,0) = buffer_mat.at(src.rows/2,0); - for (int i=1; i(i,0) = buffer_mat.at((i+1)/2,0); - dst_mat.at(i+1,0) = buffer_mat.at((i+1)/2,1); - } - - if (dst_mat.cols % 2 == 0) - { - dst_mat.at(0,dst_mat.cols-1) = buffer_mat.at(0,src.cols/2); - dst_mat.at(dst_mat.rows-1,dst_mat.cols-1) = buffer_mat.at(src.rows/2,src.cols/2); - - for (int i=1; i(i,dst_mat.cols-1) = buffer_mat.at((i+1)/2,src.cols/2); - dst_mat.at(i+1,dst_mat.cols-1) = buffer_mat.at((i+1)/2,src.cols/2+1); - } - } - } - else - { - // pack to CCS each row - src.colRange(0,1).copyTo(dst.colRange(0,1)); - src.colRange(2, (dst.cols+1)).copyTo(dst.colRange(1, dst.cols)); - } - return true; -} - static bool ocl_dft_C2C_rows(InputArray _src, OutputArray _dst, int nonzero_rows, int flags) { const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.cols(), flags); return plan->enqueueTransform(_src, _dst, nonzero_rows, flags, true); } -static bool ocl_dft_C2C_cols(InputArray _src, OutputArray _dst, int flags) +static bool ocl_dft_C2C_cols(InputArray _src, OutputArray _dst, int nonzero_cols, int flags) { const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.rows(), flags); - return plan->enqueueTransform(_src, _dst, _src.cols(), flags, false); + return plan->enqueueTransform(_src, _dst, nonzero_cols, flags, false); } static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_rows) @@ -2315,6 +2275,8 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro // Forward Complex to CCS not supported if (complex_input && real_output && !inv) { + flags ^= DFT_REAL_OUTPUT; + flags |= DFT_COMPLEX_OUTPUT; real_output = 0; complex_output = 1; } @@ -2344,23 +2306,21 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro if (complex_output) { - if (real_input && is1d && !inv) - output.create(src.size(), CV_32FC2); - else - { - _dst.create(src.size(), CV_32FC2); - output = _dst.getUMat(); - } - } else + _dst.create(src.size(), CV_32FC2); + output = _dst.getUMat(); + } + else { - // CCS if (is1d) { _dst.create(src.size(), CV_32FC1); output = _dst.getUMat(); } else + { + _dst.create(src.size(), CV_32FC1); output.create(src.size(), CV_32FC2); + } } if (!ocl_dft_C2C_rows(input, output, nonzero_rows, flags)) @@ -2368,32 +2328,13 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro if (!is1d) { - if (!ocl_dft_C2C_cols(output, output, flags)) + int nonzero_cols = real_input && real_output ? output.cols/2 + 1 : output.cols; + if (!ocl_dft_C2C_cols(output, _dst, nonzero_cols, flags)) return false; - } - - if (complex_output) + } else { - if (real_input && is1d && !inv) - _dst.assign(output.colRange(0, output.cols/2+1)); - else - _dst.assign(output); + _dst.assign(output); } - else - { - if (!inv) - { - if (!is1d) - ocl_packToCCS(output, _dst, flags); - else - _dst.assign(output); - } - else - { - // copy real part to dst - } - } - //printf("OCL!\n"); return true; } @@ -2435,7 +2376,6 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) int elem_size = (int)src.elemSize1(), complex_elem_size = elem_size*2; int factors[34]; bool inplace_transform = false; - bool is1d = (flags & DFT_ROWS) != 0 || src.rows == 1; #ifdef USE_IPP_DFT AutoBuffer ippbuf; int ipp_norm_flag = !(flags & DFT_SCALE) ? 8 : inv ? 2 : 1; @@ -2444,10 +2384,7 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) CV_Assert( type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2 ); if( !inv && src.channels() == 1 && (flags & DFT_COMPLEX_OUTPUT) ) - if (!is1d) - _dst.create( src.size(), CV_MAKETYPE(depth, 2) ); - else - _dst.create( Size(src.cols/2+1, src.rows), CV_MAKETYPE(depth, 2) ); + _dst.create( src.size(), CV_MAKETYPE(depth, 2) ); else if( inv && src.channels() == 2 && (flags & DFT_REAL_OUTPUT) ) _dst.create( src.size(), depth ); else diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index 7803cdbc21..a778d59f22 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -331,10 +331,17 @@ __kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, RADIX_PROCESS; #ifndef CCS_OUTPUT - __global float2* dst = (__global float2*)(dst_ptr + mad24(y, dst_step, mad24(x, (int)(sizeof(float)*2), dst_offset))); +#ifdef NO_CONJUGATE + // copy result without complex conjugate + const int cols = dst_cols/2 + 1; +#else + const int cols = dst_cols; +#endif + + __global float2* dst = (__global float2*)(dst_ptr + mad24(y, dst_step, dst_offset)); #pragma unroll - for (int i=0; i(df) << std::endl; double eps = src.size().area() * 1e-4; EXPECT_MAT_NEAR(dst, udst, eps); @@ -181,9 +189,9 @@ OCL_TEST_P(MulSpectrums, Mat) OCL_INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MulSpectrums, testing::Combine(Bool(), Bool())); -OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(6, 1), cv::Size(5, 8), cv::Size(30, 20), +OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(6, 4), cv::Size(5, 8), cv::Size(6, 6), cv::Size(512, 1), cv::Size(1280, 768)), - Values((OCL_FFT_TYPE) R2C, (OCL_FFT_TYPE) C2C, (OCL_FFT_TYPE) R2R/*, (OCL_FFT_TYPE) C2R*/), + Values((OCL_FFT_TYPE) R2C, (OCL_FFT_TYPE) C2C, (OCL_FFT_TYPE) R2R, (OCL_FFT_TYPE) C2R), Bool(), // DFT_ROWS Bool() // inplace ) From b17bf031f696f1bc89b871466360d675f5a1b3fb Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Thu, 17 Jul 2014 16:20:04 +0400 Subject: [PATCH 098/136] Added DFT_SCALE for forward transforms --- modules/core/src/dxt.cpp | 13 ++++-- modules/core/src/opencl/fft.cl | 31 ++++++++++---- modules/core/test/ocl/test_dft.cpp | 22 +++++----- samples/cpp/dft.cpp | 69 +++--------------------------- 4 files changed, 49 insertions(+), 86 deletions(-) diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 69ec2c9efe..449e19db4b 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2151,27 +2151,34 @@ struct OCL_FftPlan size_t localsize[2]; String kernel_name; + bool is1d = (flags & DFT_ROWS) != 0 || dft_size == 1; + String options = buildOptions; + if (rows) { globalsize[0] = thread_count; globalsize[1] = dft_size; localsize[0] = thread_count; localsize[1] = 1; kernel_name = "fft_multi_radix_rows"; + if (is1d && (flags & DFT_SCALE)) + options += " -D DFT_SCALE"; } else { globalsize[0] = dft_size; globalsize[1] = thread_count; localsize[0] = 1; localsize[1] = thread_count; kernel_name = "fft_multi_radix_cols"; + if (flags & DFT_SCALE) + options += " -D DFT_SCALE"; } - - bool is1d = (flags & DFT_ROWS) != 0 || dft_size == 1; - String options = buildOptions; + if (src.channels() == 1) options += " -D REAL_INPUT"; if (dst.channels() == 1) options += " -D CCS_OUTPUT"; if ((is1d && src.channels() == 1) || (rows && (flags & DFT_REAL_OUTPUT))) options += " -D NO_CONJUGATE"; + if (is1d) + options += " -D IS_1D"; ocl::Kernel k(kernel_name.c_str(), ocl::core::fft_oclsrc, options); if (k.empty()) diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index a778d59f22..d59e0d9b48 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -301,6 +301,12 @@ void fft_radix5(__local float2* smem, __constant const float2* twiddles, const i barrier(CLK_LOCAL_MEM_FENCE); } +#ifdef DFT_SCALE +#define VAL(x, scale) x*scale +#else +#define VAL(x, scale) x +#endif + __kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, int src_offset, int src_rows, int src_cols, __global uchar* dst_ptr, int dst_step, int dst_offset, int dst_rows, int dst_cols, __constant float2 * twiddles_ptr, const int t, const int nz) @@ -314,6 +320,11 @@ __kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, __constant const float2* twiddles = (__constant float2*) twiddles_ptr; const int ind = x; const int block_size = LOCAL_SIZE/kercn; +#ifdef IS_1D + float scale = 1.f/dst_cols; +#else + float scale = 1.f/(dst_cols*dst_rows); +#endif #ifndef REAL_INPUT __global const float2* src = (__global const float2*)(src_ptr + mad24(y, src_step, mad24(x, (int)(sizeof(float)*2), src_offset))); @@ -341,15 +352,15 @@ __kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, __global float2* dst = (__global float2*)(dst_ptr + mad24(y, dst_step, dst_offset)); #pragma unroll for (int i=x; i -#include -#include using namespace cv; using namespace std; @@ -26,31 +24,6 @@ const char* keys = int main(int argc, const char ** argv) { - //int cols = 4; - //int rows = 768; - //srand(0); - //Mat input(Size(cols, rows), CV_32FC2); - //for (int i=0; i(j,i) = Vec2f((float) rand() / RAND_MAX, (float) rand() / RAND_MAX); - //Mat dst; - // - //UMat gpu_input, gpu_dst; - //input.copyTo(gpu_input); - //auto start = std::chrono::system_clock::now(); - //dft(input, dst, DFT_ROWS); - //auto cpu_duration = chrono::duration_cast(chrono::system_clock::now() - start); - // - //start = std::chrono::system_clock::now(); - //dft(gpu_input, gpu_dst, DFT_ROWS); - //auto gpu_duration = chrono::duration_cast(chrono::system_clock::now() - start); - - //double n = norm(dst, gpu_dst); - //cout << "norm = " << n << endl; - //cout << "CPU time: " << cpu_duration.count() << "ms" << endl; - //cout << "GPU time: " << gpu_duration.count() << "ms" << endl; - - help(); CommandLineParser parser(argc, argv, keys); string filename = parser.get(0); @@ -62,46 +35,16 @@ int main(int argc, const char ** argv) printf("Cannot read image file: %s\n", filename.c_str()); return -1; } - - Mat small_img = img(Rect(0,0,6,6)); - - int M = getOptimalDFTSize( small_img.rows ); - int N = getOptimalDFTSize( small_img.cols ); + int M = getOptimalDFTSize( img.rows ); + int N = getOptimalDFTSize( img.cols ); Mat padded; - copyMakeBorder(small_img, padded, 0, M - small_img.rows, 0, N - small_img.cols, BORDER_CONSTANT, Scalar::all(0)); + copyMakeBorder(img, padded, 0, M - img.rows, 0, N - img.cols, BORDER_CONSTANT, Scalar::all(0)); - Mat planes[] = {Mat_(padded), Mat::ones(padded.size(), CV_32F)}; - Mat complexImg, complexImg1, complexInput; + Mat planes[] = {Mat_(padded), Mat::zeros(padded.size(), CV_32F)}; + Mat complexImg; merge(planes, 2, complexImg); - Mat realInput; - padded.convertTo(realInput, CV_32F); - complexInput = complexImg; - //cout << complexImg << endl; - //dft(complexImg, complexImg, DFT_REAL_OUTPUT); - //cout << "Complex to Complex" << endl; - //cout << complexImg << endl; - cout << "Complex input" << endl << complexInput << endl; - cout << "Real input" << endl << realInput << endl; - - dft(complexInput, complexImg1, DFT_COMPLEX_OUTPUT); - cout << "Complex to Complex image: " << endl; - cout << endl << complexImg1 << endl; - - Mat realImg1; - dft(complexInput, realImg1, DFT_REAL_OUTPUT); - cout << "Complex to Real image: " << endl; - cout << endl << realImg1 << endl; - - Mat realOut; - dft(complexImg1, realOut, DFT_INVERSE | DFT_COMPLEX_OUTPUT); - cout << "Complex to Complex (inverse):" << endl; - cout << realOut << endl; - - Mat complexOut; - dft(realImg1, complexOut, DFT_INVERSE | DFT_REAL_OUTPUT | DFT_SCALE); - cout << "Complex to Real (inverse):" << endl; - cout << complexOut << endl; + dft(complexImg, complexImg); // compute log(1 + sqrt(Re(DFT(img))**2 + Im(DFT(img))**2)) split(complexImg, planes); From 2b9e5560556541b5331e41413be17c0cca98af52 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Fri, 18 Jul 2014 13:41:57 +0400 Subject: [PATCH 099/136] Added Elena's changes with implemented DFT_INVERSE C2C mode. --- modules/core/perf/opencl/perf_dxt.cpp | 2 +- modules/core/src/dxt.cpp | 40 +++------ modules/core/src/opencl/fft.cl | 113 ++++++++++++++++++++++++++ modules/core/test/ocl/test_dft.cpp | 11 +-- 4 files changed, 131 insertions(+), 35 deletions(-) diff --git a/modules/core/perf/opencl/perf_dxt.cpp b/modules/core/perf/opencl/perf_dxt.cpp index edeeda7f0c..3980a191fa 100644 --- a/modules/core/perf/opencl/perf_dxt.cpp +++ b/modules/core/perf/opencl/perf_dxt.cpp @@ -67,7 +67,7 @@ typedef TestBaseWithParam DftFixture; OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(C2C, R2R, C2R, R2C), Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(1024, 1024), Size(512, 512), Size(2048, 2048)), - Values((int)DFT_ROWS, (int) 0/*, (int)DFT_SCALE, (int)DFT_INVERSE, + Values((int)DFT_ROWS, (int) 0, (int)DFT_SCALE/*, (int)DFT_INVERSE, (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE*/))) { const DftParams params = GetParam(); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 449e19db4b..879a70613f 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2129,8 +2129,8 @@ struct OCL_FftPlan for (int k=0; k<(n/radix); k++) { - ptr[ptr_index++] = cos(k*theta); - ptr[ptr_index++] = sin(k*theta); + ptr[ptr_index++] = (float) cos(k*theta); + ptr[ptr_index++] = (float) sin(k*theta); } } } @@ -2152,13 +2152,14 @@ struct OCL_FftPlan String kernel_name; bool is1d = (flags & DFT_ROWS) != 0 || dft_size == 1; + bool inv = (flags & DFT_INVERSE) != 0; String options = buildOptions; if (rows) { globalsize[0] = thread_count; globalsize[1] = dft_size; localsize[0] = thread_count; localsize[1] = 1; - kernel_name = "fft_multi_radix_rows"; + kernel_name = !inv ? "fft_multi_radix_rows" : "ifft_multi_radix_rows"; if (is1d && (flags & DFT_SCALE)) options += " -D DFT_SCALE"; } @@ -2166,7 +2167,7 @@ struct OCL_FftPlan { globalsize[0] = dft_size; globalsize[1] = thread_count; localsize[0] = 1; localsize[1] = thread_count; - kernel_name = "fft_multi_radix_cols"; + kernel_name = !inv ? "fft_multi_radix_cols" : "ifft_multi_radix_cols"; if (flags & DFT_SCALE) options += " -D DFT_SCALE"; } @@ -2270,13 +2271,10 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro // if output format is not specified if (complex_output + real_output == 0) { - if (!inv) - { - if (real_input) - real_output = 1; - else - complex_output = 1; - } + if (real_input) + real_output = 1; + else + complex_output = 1; } // Forward Complex to CCS not supported @@ -2294,23 +2292,7 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro real_output = 1; } - UMat input, output; - if (complex_input) - { - input = src; - } - else - { - if (!inv) - { - input = src; - } - else - { - // TODO: unpack from CCS format - } - } - + UMat output; if (complex_output) { _dst.create(src.size(), CV_32FC2); @@ -2330,7 +2312,7 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro } } - if (!ocl_dft_C2C_rows(input, output, nonzero_rows, flags)) + if (!ocl_dft_C2C_rows(src, output, nonzero_rows, flags)) return false; if (!is1d) diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index d59e0d9b48..8aecfc056a 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -424,4 +424,117 @@ __kernel void fft_multi_radix_cols(__global const uchar* src_ptr, int src_step, } #endif } +} + +__kernel void ifft_multi_radix_rows(__global const uchar* src_ptr, int src_step, int src_offset, int src_rows, int src_cols, + __global uchar* dst_ptr, int dst_step, int dst_offset, int dst_rows, int dst_cols, + __constant float2 * twiddles_ptr, const int t, const int nz) +{ + const int x = get_global_id(0); + const int y = get_group_id(1); + + if (y < nz) + { + __local float2 smem[LOCAL_SIZE]; + __constant const float2* twiddles = (__constant float2*) twiddles_ptr; + const int ind = x; + const int block_size = LOCAL_SIZE/kercn; +#ifdef IS_1D + float scale = 1.f/dst_cols; +#else + float scale = 1.f/(dst_cols*dst_rows); +#endif + +#ifndef REAL_INPUT + __global const float2* src = (__global const float2*)(src_ptr + mad24(y, src_step, mad24(x, (int)(sizeof(float)*2), src_offset))); + #pragma unroll + for (int i=0; i Date: Mon, 21 Jul 2014 10:42:56 +0400 Subject: [PATCH 100/136] Added multi-block scheme --- modules/core/perf/opencl/perf_dxt.cpp | 6 +- modules/core/src/dxt.cpp | 49 +++-- modules/core/src/opencl/fft.cl | 282 +++++++++++++++++++++++++- modules/core/test/ocl/test_dft.cpp | 14 +- 4 files changed, 321 insertions(+), 30 deletions(-) diff --git a/modules/core/perf/opencl/perf_dxt.cpp b/modules/core/perf/opencl/perf_dxt.cpp index 3980a191fa..f4b6b49a9f 100644 --- a/modules/core/perf/opencl/perf_dxt.cpp +++ b/modules/core/perf/opencl/perf_dxt.cpp @@ -65,10 +65,10 @@ enum OCL_FFT_TYPE typedef tuple DftParams; typedef TestBaseWithParam DftFixture; -OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(C2C, R2R, C2R, R2C), +OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(C2C/*, R2R, C2R, R2C*/), Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(1024, 1024), Size(512, 512), Size(2048, 2048)), - Values((int)DFT_ROWS, (int) 0, (int)DFT_SCALE/*, (int)DFT_INVERSE, - (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE*/))) + Values((int) 0, (int)DFT_ROWS, (int)DFT_SCALE, (int)DFT_INVERSE, + /*(int)DFT_INVERSE | DFT_SCALE,*/ (int)DFT_ROWS | DFT_INVERSE))) { const DftParams params = GetParam(); const int dft_type = get<0>(params); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 879a70613f..d5b1cb383d 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2041,23 +2041,33 @@ static std::vector ocl_getRadixes(int cols, std::vector& radixes, std: int n = 1; int factor_index = 0; + min_radix = INT_MAX; // 2^n transforms if ( (factors[factor_index] & 1) == 0 ) { for( ; n < factors[factor_index]; ) { - int radix = 2; + int radix = 2, block = 1; if (8*n <= factors[0]) radix = 8; else if (4*n <= factors[0]) + { radix = 4; + if (cols % 8 == 0) + block = 2; + } + else + { + if (cols % 8 == 0) + block = 4; + else if (cols % 4 == 0) + block = 2; + } radixes.push_back(radix); - if (radix == 2 && cols % 4 == 0) - min_radix = min(min_radix, 2*radix); - else - min_radix = min(min_radix, radix); + blocks.push_back(block); + min_radix = min(min_radix, block*radix); n *= radix; } factor_index++; @@ -2066,11 +2076,22 @@ static std::vector ocl_getRadixes(int cols, std::vector& radixes, std: // all the other transforms for( ; factor_index < nf; factor_index++ ) { - radixes.push_back(factors[factor_index]); - if (factors[factor_index] == 3 && cols % 6 == 0) - min_radix = min(min_radix, 2*factors[factor_index]); - else - min_radix = min(min_radix, factors[factor_index]); + int radix = factors[factor_index], block = 1; + if (radix == 3) + { + if (cols % 12 == 0) + block = 4; + else if (cols % 6 == 0) + block = 2; + } + else if (radix == 5) + { + if (cols % 10 == 0) + block = 2; + } + radixes.push_back(radix); + blocks.push_back(block); + min_radix = min(min_radix, block*radix); } return radixes; } @@ -2086,7 +2107,7 @@ struct OCL_FftPlan bool status; OCL_FftPlan(int _size, int _flags): dft_size(_size), flags(_flags), status(true) { - int min_radix = INT_MAX; + int min_radix; std::vector radixes, blocks; ocl_getRadixes(dft_size, radixes, blocks, min_radix); thread_count = (dft_size + min_radix-1) / min_radix; @@ -2102,9 +2123,9 @@ struct OCL_FftPlan int n = 1, twiddle_size = 0; for (size_t i=0; i 1) + radix_processing += format("fft_radix%d_B%d(smem,twiddles+%d,ind,%d,%d);", radix, block, twiddle_size, n, dft_size/radix); else radix_processing += format("fft_radix%d(smem,twiddles+%d,ind,%d,%d);", radix, twiddle_size, n, dft_size/radix); twiddle_size += (radix-1)*n; diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index 8aecfc056a..fdbad19ad0 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -44,11 +44,11 @@ __attribute__((always_inline)) void fft_radix2_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { const int k1 = x & (block_size - 1); - const int x2 = x + (t+1)/2; + const int x2 = x + t/2; const int k2 = x2 & (block_size - 1); float2 a0, a1, a2, a3; - if (x < (t+1)/2) + if (x < t/2) { a0 = smem[x]; a1 = mul_float2(twiddles[k1],smem[x+t]); @@ -58,7 +58,7 @@ void fft_radix2_B2(__local float2* smem, __constant const float2* twiddles, cons barrier(CLK_LOCAL_MEM_FENCE); - if (x < (t+1)/2) + if (x < t/2) { int dst_ind = (x << 1) - k1; smem[dst_ind] = a0 + a1; @@ -72,6 +72,55 @@ void fft_radix2_B2(__local float2* smem, __constant const float2* twiddles, cons barrier(CLK_LOCAL_MEM_FENCE); } +__attribute__((always_inline)) +void fft_radix2_B4(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +{ + const int thread_block = t/4; + const int k1 = x & (block_size - 1); + const int x2 = x + thread_block; + const int k2 = x2 & (block_size - 1); + const int x3 = x + 2*thread_block; + const int k3 = x3 & (block_size - 1); + const int x4 = x + 3*thread_block; + const int k4 = x4 & (block_size - 1); + float2 a0, a1, a2, a3, a4, a5, a6, a7; + + if (x < t/4) + { + a0 = smem[x]; + a1 = mul_float2(twiddles[k1],smem[x+t]); + a2 = smem[x2]; + a3 = mul_float2(twiddles[k2],smem[x2+t]); + a4 = smem[x3]; + a5 = mul_float2(twiddles[k3],smem[x3+t]); + a6 = smem[x4]; + a7 = mul_float2(twiddles[k4],smem[x4+t]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t/4) + { + int dst_ind = (x << 1) - k1; + smem[dst_ind] = a0 + a1; + smem[dst_ind+block_size] = a0 - a1; + + dst_ind = (x2 << 1) - k2; + smem[dst_ind] = a2 + a3; + smem[dst_ind+block_size] = a2 - a3; + + dst_ind = (x3 << 1) - k3; + smem[dst_ind] = a4 + a5; + smem[dst_ind+block_size] = a4 - a5; + + dst_ind = (x4 << 1) - k4; + smem[dst_ind] = a6 + a7; + smem[dst_ind+block_size] = a6 - a7; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + __attribute__((always_inline)) void fft_radix4(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { @@ -107,6 +156,58 @@ void fft_radix4(__local float2* smem, __constant const float2* twiddles, const i barrier(CLK_LOCAL_MEM_FENCE); } +__attribute__((always_inline)) +void fft_radix4_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +{ + const int k = x & (block_size - 1); + const int x2 = x + t/2; + const int k2 = x2 & (block_size - 1); + float2 a0, a1, a2, a3, a4, a5, a6, a7; + + if (x < t/2) + { + a0 = smem[x]; + a1 = mul_float2(twiddles[k], smem[x+t]); + a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); + a3 = mul_float2(twiddles[k + 2*block_size],smem[x+3*t]); + + a4 = smem[x2]; + a5 = mul_float2(twiddles[k2], smem[x2+t]); + a6 = mul_float2(twiddles[k2 + block_size],smem[x2+2*t]); + a7 = mul_float2(twiddles[k2 + 2*block_size],smem[x2+3*t]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t/2) + { + int dst_ind = ((x - k) << 2) + k; + + float2 b0 = a0 + a2; + a2 = a0 - a2; + float2 b1 = a1 + a3; + a3 = twiddle(a1 - a3); + + smem[dst_ind] = b0 + b1; + smem[dst_ind + block_size] = a2 + a3; + smem[dst_ind + 2*block_size] = b0 - b1; + smem[dst_ind + 3*block_size] = a2 - a3; + + dst_ind = ((x2 - k2) << 2) + k2; + b0 = a4 + a6; + a6 = a4 - a6; + b1 = a5 + a7; + a7 = twiddle(a5 - a7); + + smem[dst_ind] = b0 + b1; + smem[dst_ind + block_size] = a6 + a7; + smem[dst_ind + 2*block_size] = b0 - b1; + smem[dst_ind + 3*block_size] = a6 - a7; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + __attribute__((always_inline)) void fft_radix8(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { @@ -205,11 +306,11 @@ __attribute__((always_inline)) void fft_radix3_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { const int k = x % block_size; - const int x2 = x + (t+1)/2; + const int x2 = x + t/2; const int k2 = x2 % block_size; float2 a0, a1, a2, a3, a4, a5; - if (x < (t+1)/2) + if (x < t/2) { a0 = smem[x]; a1 = mul_float2(twiddles[k], smem[x+t]); @@ -222,7 +323,7 @@ void fft_radix3_B2(__local float2* smem, __constant const float2* twiddles, cons barrier(CLK_LOCAL_MEM_FENCE); - if (x < (t+1)/2) + if (x < t/2) { int dst_ind = ((x - k) * 3) + k; @@ -248,6 +349,86 @@ void fft_radix3_B2(__local float2* smem, __constant const float2* twiddles, cons barrier(CLK_LOCAL_MEM_FENCE); } +__attribute__((always_inline)) +void fft_radix3_B4(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +{ + const int thread_block = t/4; + const int k = x % block_size; + const int x2 = x + thread_block; + const int k2 = x2 % block_size; + const int x3 = x + 2*thread_block; + const int k3 = x3 % block_size; + const int x4 = x + 3*thread_block; + const int k4 = x4 % block_size; + float2 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11; + + if (x < t/4) + { + a0 = smem[x]; + a1 = mul_float2(twiddles[k], smem[x+t]); + a2 = mul_float2(twiddles[k+block_size], smem[x+2*t]); + + a3 = smem[x2]; + a4 = mul_float2(twiddles[k2], smem[x2+t]); + a5 = mul_float2(twiddles[k2+block_size], smem[x2+2*t]); + + a6 = smem[x3]; + a7 = mul_float2(twiddles[k3], smem[x3+t]); + a8 = mul_float2(twiddles[k3+block_size], smem[x3+2*t]); + + a9 = smem[x4]; + a10 = mul_float2(twiddles[k4], smem[x4+t]); + a11 = mul_float2(twiddles[k4+block_size], smem[x4+2*t]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t/4) + { + int dst_ind = ((x - k) * 3) + k; + + float2 b1 = a1 + a2; + a2 = twiddle(sin_120*(a1 - a2)); + float2 b0 = a0 - (float2)(0.5f)*b1; + + smem[dst_ind] = a0 + b1; + smem[dst_ind + block_size] = b0 + a2; + smem[dst_ind + 2*block_size] = b0 - a2; + + dst_ind = ((x2 - k2) * 3) + k2; + + b1 = a4 + a5; + a5 = twiddle(sin_120*(a4 - a5)); + b0 = a3 - (float2)(0.5f)*b1; + + smem[dst_ind] = a3 + b1; + smem[dst_ind + block_size] = b0 + a5; + smem[dst_ind + 2*block_size] = b0 - a5; + + dst_ind = ((x3 - k3) * 3) + k3; + + b1 = a7 + a8; + a8 = twiddle(sin_120*(a7 - a8)); + b0 = a6 - (float2)(0.5f)*b1; + + smem[dst_ind] = a6 + b1; + smem[dst_ind + block_size] = b0 + a8; + smem[dst_ind + 2*block_size] = b0 - a8; + + dst_ind = ((x4 - k4) * 3) + k4; + + b1 = a10 + a11; + a11 = twiddle(sin_120*(a10 - a11)); + b0 = a9 - (float2)(0.5f)*b1; + + smem[dst_ind] = a9 + b1; + smem[dst_ind + block_size] = b0 + a11; + smem[dst_ind + 2*block_size] = b0 - a11; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + __attribute__((always_inline)) void fft_radix5(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { @@ -301,6 +482,95 @@ void fft_radix5(__local float2* smem, __constant const float2* twiddles, const i barrier(CLK_LOCAL_MEM_FENCE); } +__attribute__((always_inline)) +void fft_radix5_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +{ + const int k = x % block_size; + const int x2 = x+t/2; + const int k2 = x2 % block_size; + float2 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9; + + if (x < t/2) + { + a0 = smem[x]; + a1 = mul_float2(twiddles[k], smem[x + t]); + a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); + a3 = mul_float2(twiddles[k+2*block_size],smem[x+3*t]); + a4 = mul_float2(twiddles[k+3*block_size],smem[x+4*t]); + + a5 = smem[x2]; + a6 = mul_float2(twiddles[k2], smem[x2 + t]); + a7 = mul_float2(twiddles[k2 + block_size],smem[x2+2*t]); + a8 = mul_float2(twiddles[k2+2*block_size],smem[x2+3*t]); + a9 = mul_float2(twiddles[k2+3*block_size],smem[x2+4*t]); + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x < t/2) + { + int dst_ind = ((x - k) * 5) + k; + __local float2* dst = smem + dst_ind; + + float2 b0, b1, b5; + + b1 = a1 + a4; + a1 -= a4; + + a4 = a3 + a2; + a3 -= a2; + + a2 = b1 + a4; + b0 = a0 - (float2)0.25f * a2; + + b1 = fft5_2 * (b1 - a4); + a4 = fft5_3 * (float2)(-a1.y - a3.y, a1.x + a3.x); + b5 = (float2)(a4.x - fft5_5 * a1.y, a4.y + fft5_5 * a1.x); + + a4.x += fft5_4 * a3.y; + a4.y -= fft5_4 * a3.x; + + a1 = b0 + b1; + b0 -= b1; + + dst[0] = a0 + a2; + dst[block_size] = a1 + a4; + dst[2 * block_size] = b0 + b5; + dst[3 * block_size] = b0 - b5; + dst[4 * block_size] = a1 - a4; + + dst_ind = ((x2 - k2) * 5) + k2; + dst = smem + dst_ind; + + b1 = a6 + a9; + a6 -= a9; + + a9 = a8 + a7; + a8 -= a7; + + a7 = b1 + a9; + b0 = a5 - (float2)0.25f * a7; + + b1 = fft5_2 * (b1 - a9); + a9 = fft5_3 * (float2)(-a6.y - a8.y, a6.x + a8.x); + b5 = (float2)(a9.x - fft5_5 * a6.y, a9.y + fft5_5 * a6.x); + + a9.x += fft5_4 * a8.y; + a9.y -= fft5_4 * a8.x; + + a6 = b0 + b1; + b0 -= b1; + + dst[0] = a5 + a7; + dst[block_size] = a6 + a9; + dst[2 * block_size] = b0 + b5; + dst[3 * block_size] = b0 - b5; + dst[4 * block_size] = a6 - a9; + } + + barrier(CLK_LOCAL_MEM_FENCE); +} + #ifdef DFT_SCALE #define VAL(x, scale) x*scale #else diff --git a/modules/core/test/ocl/test_dft.cpp b/modules/core/test/ocl/test_dft.cpp index 64f6c63843..1fa03ae472 100644 --- a/modules/core/test/ocl/test_dft.cpp +++ b/modules/core/test/ocl/test_dft.cpp @@ -62,7 +62,7 @@ namespace ocl { //////////////////////////////////////////////////////////////////////////// // Dft -PARAM_TEST_CASE(Dft, cv::Size, OCL_FFT_TYPE, bool, bool, bool, bool) +PARAM_TEST_CASE(Dft, cv::Size, OCL_FFT_TYPE, bool, bool, bool) { cv::Size dft_size; int dft_flags, depth, cn, dft_type; @@ -91,9 +91,9 @@ PARAM_TEST_CASE(Dft, cv::Size, OCL_FFT_TYPE, bool, bool, bool, bool) dft_flags |= cv::DFT_ROWS; if (GET_PARAM(3)) dft_flags |= cv::DFT_SCALE; - if (GET_PARAM(4)) - dft_flags |= cv::DFT_INVERSE; - inplace = GET_PARAM(5); + /*if (GET_PARAM(4)) + dft_flags |= cv::DFT_INVERSE;*/ + inplace = GET_PARAM(4); is1d = (dft_flags & DFT_ROWS) != 0 || dft_size.height == 1; @@ -188,12 +188,12 @@ OCL_TEST_P(MulSpectrums, Mat) OCL_INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MulSpectrums, testing::Combine(Bool(), Bool())); -OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(6, 4), cv::Size(5, 8), cv::Size(6, 6), +OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(16, 4), cv::Size(5, 8), cv::Size(6, 6), cv::Size(512, 1), cv::Size(1280, 768)), - Values(/*(OCL_FFT_TYPE) R2C, */(OCL_FFT_TYPE) C2C/*, (OCL_FFT_TYPE) R2R, (OCL_FFT_TYPE) C2R*/), + Values((OCL_FFT_TYPE) R2C, (OCL_FFT_TYPE) C2C, (OCL_FFT_TYPE) R2R, (OCL_FFT_TYPE) C2R), Bool(), // DFT_ROWS Bool(), // DFT_SCALE - Bool(), // DFT_INVERSE + //Bool(), // DFT_INVERSE Bool() // inplace ) ); From 52f76a32838019b4eb8e3f889dd25623a5983c74 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Tue, 22 Jul 2014 11:24:19 +0400 Subject: [PATCH 101/136] Added rest Elena's changes --- modules/core/perf/opencl/perf_dxt.cpp | 6 +- modules/core/src/dxt.cpp | 131 +++-- modules/core/src/opencl/fft.cl | 692 +++++++++++++------------- modules/core/test/ocl/test_dft.cpp | 32 +- 4 files changed, 457 insertions(+), 404 deletions(-) diff --git a/modules/core/perf/opencl/perf_dxt.cpp b/modules/core/perf/opencl/perf_dxt.cpp index f4b6b49a9f..797b2c5334 100644 --- a/modules/core/perf/opencl/perf_dxt.cpp +++ b/modules/core/perf/opencl/perf_dxt.cpp @@ -65,10 +65,10 @@ enum OCL_FFT_TYPE typedef tuple DftParams; typedef TestBaseWithParam DftFixture; -OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(C2C/*, R2R, C2R, R2C*/), +OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(C2C, R2R, C2R, R2C), Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(1024, 1024), Size(512, 512), Size(2048, 2048)), - Values((int) 0, (int)DFT_ROWS, (int)DFT_SCALE, (int)DFT_INVERSE, - /*(int)DFT_INVERSE | DFT_SCALE,*/ (int)DFT_ROWS | DFT_INVERSE))) + Values((int) 0, (int)DFT_ROWS, (int)DFT_SCALE/*, (int)DFT_INVERSE, + (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE*/))) { const DftParams params = GetParam(); const int dft_type = get<0>(params); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index d5b1cb383d..eaef53ad23 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -1791,14 +1791,6 @@ namespace cv { CV_Assert(s == CLFFT_SUCCESS); \ } -enum FftType -{ - R2R = 0, // real to real - C2R = 1, // opencl HERMITIAN_INTERLEAVED to real - R2C = 2, // real to opencl HERMITIAN_INTERLEAVED - C2C = 3 // complex to complex -}; - class PlanCache { struct FftPlan @@ -2034,6 +2026,14 @@ namespace cv #ifdef HAVE_OPENCL +enum FftType +{ + R2R = 0, + C2R = 1, + R2C = 2, + C2C = 3 +}; + static std::vector ocl_getRadixes(int cols, std::vector& radixes, std::vector& blocks, int& min_radix) { int factors[34]; @@ -2054,13 +2054,19 @@ static std::vector ocl_getRadixes(int cols, std::vector& radixes, std: else if (4*n <= factors[0]) { radix = 4; - if (cols % 8 == 0) + if (cols % 12 == 0) + block = 3; + else if (cols % 8 == 0) block = 2; } else { - if (cols % 8 == 0) + if (cols % 10 == 0) + block = 5; + else if (cols % 8 == 0) block = 4; + else if (cols % 6 == 0) + block = 3; else if (cols % 4 == 0) block = 2; } @@ -2081,6 +2087,8 @@ static std::vector ocl_getRadixes(int cols, std::vector& radixes, std: { if (cols % 12 == 0) block = 4; + else if (cols % 9 == 0) + block = 3; else if (cols % 6 == 0) block = 2; } @@ -2142,7 +2150,6 @@ struct OCL_FftPlan { int radix = radixes[i]; n *= radix; - for (int j=1; j planStorage; }; -static bool ocl_dft_C2C_rows(InputArray _src, OutputArray _dst, int nonzero_rows, int flags) +static bool ocl_dft_C2C_rows(InputArray _src, OutputArray _dst, int nonzero_rows, int flags, int fftType) { const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.cols(), flags); - return plan->enqueueTransform(_src, _dst, nonzero_rows, flags, true); + return plan->enqueueTransform(_src, _dst, nonzero_rows, flags, fftType, true); } -static bool ocl_dft_C2C_cols(InputArray _src, OutputArray _dst, int nonzero_cols, int flags) +static bool ocl_dft_C2C_cols(InputArray _src, OutputArray _dst, int nonzero_cols, int flags, int fftType) { const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.rows(), flags); - return plan->enqueueTransform(_src, _dst, nonzero_cols, flags, false); + return plan->enqueueTransform(_src, _dst, nonzero_cols, flags, fftType, false); } static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_rows) @@ -2298,29 +2318,26 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro complex_output = 1; } + FftType fftType = (FftType)(complex_input << 0 | complex_output << 1); + // Forward Complex to CCS not supported - if (complex_input && real_output && !inv) - { - flags ^= DFT_REAL_OUTPUT; - flags |= DFT_COMPLEX_OUTPUT; - real_output = 0; - complex_output = 1; - } + if (fftType == C2R && !inv) + fftType = C2C; + // Inverse CCS to Complex not supported - if (real_input && complex_output && inv) - { - complex_output = 0; - real_output = 1; - } + if (fftType == R2C && inv) + fftType = R2R; UMat output; - if (complex_output) + if (fftType == C2C || fftType == R2C) { + // complex output _dst.create(src.size(), CV_32FC2); output = _dst.getUMat(); - } + } else { + // real output if (is1d) { _dst.create(src.size(), CV_32FC1); @@ -2333,17 +2350,49 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro } } - if (!ocl_dft_C2C_rows(src, output, nonzero_rows, flags)) - return false; - - if (!is1d) + if (!inv) { - int nonzero_cols = real_input && real_output ? output.cols/2 + 1 : output.cols; - if (!ocl_dft_C2C_cols(output, _dst, nonzero_cols, flags)) + if (!ocl_dft_C2C_rows(src, output, nonzero_rows, flags, fftType)) return false; - } else + + if (!is1d) + { + int nonzero_cols = fftType == R2R ? output.cols/2 + 1 : output.cols; + if (!ocl_dft_C2C_cols(output, _dst, nonzero_cols, flags, fftType)) + return false; + } + } + else { - _dst.assign(output); + if (fftType == C2C) + { + // complex output + if (!ocl_dft_C2C_rows(src, output, nonzero_rows, flags, fftType)) + return false; + + if (!is1d) + { + if (!ocl_dft_C2C_cols(output, output, output.cols, flags, fftType)) + return false; + } + } + else + { + if (is1d) + { + if (!ocl_dft_C2C_rows(src, output, nonzero_rows, flags, fftType)) + return false; + } + else + { + int nonzero_cols = src.cols/2 + 1;// : src.cols; + if (!ocl_dft_C2C_cols(src, output, nonzero_cols, flags, fftType)) + return false; + + if (!ocl_dft_C2C_rows(output, _dst, nonzero_rows, flags, fftType)) + return false; + } + } } return true; } diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index fdbad19ad0..dd8ff59850 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -16,106 +16,224 @@ float2 twiddle(float2 a) { } __attribute__((always_inline)) -void fft_radix2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void butterfly2(float2 a0, float2 a1, __local float2* smem, __constant const float2* twiddles, + const int x, const int block_size) +{ + const int k = x & (block_size - 1); + a1 = mul_float2(twiddles[k], a1); + const int dst_ind = (x << 1) - k; + + smem[dst_ind] = a0 + a1; + smem[dst_ind+block_size] = a0 - a1; +} + +__attribute__((always_inline)) +void butterfly4(float2 a0, float2 a1, float2 a2, float2 a3, __local float2* smem, __constant const float2* twiddles, + const int x, const int block_size) { const int k = x & (block_size - 1); + a1 = mul_float2(twiddles[k], a1); + a2 = mul_float2(twiddles[k + block_size], a2); + a3 = mul_float2(twiddles[k + 2*block_size], a3); + + const int dst_ind = ((x - k) << 2) + k; + + float2 b0 = a0 + a2; + a2 = a0 - a2; + float2 b1 = a1 + a3; + a3 = twiddle(a1 - a3); + + smem[dst_ind] = b0 + b1; + smem[dst_ind + block_size] = a2 + a3; + smem[dst_ind + 2*block_size] = b0 - b1; + smem[dst_ind + 3*block_size] = a2 - a3; +} + +__attribute__((always_inline)) +void butterfly3(float2 a0, float2 a1, float2 a2, __local float2* smem, __constant const float2* twiddles, + const int x, const int block_size) +{ + const int k = x & (block_size - 1); + a1 = mul_float2(twiddles[k], a1); + a2 = mul_float2(twiddles[k+block_size], a2); + const int dst_ind = ((x - k) * 3) + k; + + float2 b1 = a1 + a2; + a2 = twiddle(sin_120*(a1 - a2)); + float2 b0 = a0 - (float2)(0.5f)*b1; + + smem[dst_ind] = a0 + b1; + smem[dst_ind + block_size] = b0 + a2; + smem[dst_ind + 2*block_size] = b0 - a2; +} + +__attribute__((always_inline)) +void butterfly5(float2 a0, float2 a1, float2 a2, float2 a3, float2 a4, __local float2* smem, __constant const float2* twiddles, + const int x, const int block_size) +{ + const int k = x & (block_size - 1); + a1 = mul_float2(twiddles[k], a1); + a2 = mul_float2(twiddles[k + block_size], a2); + a3 = mul_float2(twiddles[k+2*block_size], a3); + a4 = mul_float2(twiddles[k+3*block_size], a4); + + const int dst_ind = ((x - k) * 5) + k; + __local float2* dst = smem + dst_ind; + + float2 b0, b1, b5; + + b1 = a1 + a4; + a1 -= a4; + + a4 = a3 + a2; + a3 -= a2; + + a2 = b1 + a4; + b0 = a0 - (float2)0.25f * a2; + + b1 = fft5_2 * (b1 - a4); + a4 = fft5_3 * (float2)(-a1.y - a3.y, a1.x + a3.x); + b5 = (float2)(a4.x - fft5_5 * a1.y, a4.y + fft5_5 * a1.x); + + a4.x += fft5_4 * a3.y; + a4.y -= fft5_4 * a3.x; + + a1 = b0 + b1; + b0 -= b1; + + dst[0] = a0 + a2; + dst[block_size] = a1 + a4; + dst[2 * block_size] = b0 + b5; + dst[3 * block_size] = b0 - b5; + dst[4 * block_size] = a1 - a4; +} + +__attribute__((always_inline)) +void fft_radix2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +{ float2 a0, a1; if (x < t) { a0 = smem[x]; - a1 = mul_float2(twiddles[k],smem[x+t]); + a1 = smem[x+t]; } barrier(CLK_LOCAL_MEM_FENCE); if (x < t) - { - const int dst_ind = (x << 1) - k; - - smem[dst_ind] = a0 + a1; - smem[dst_ind+block_size] = a0 - a1; - } + butterfly2(a0, a1, smem, twiddles, x, block_size); barrier(CLK_LOCAL_MEM_FENCE); } __attribute__((always_inline)) -void fft_radix2_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix2_B2(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) { - const int k1 = x & (block_size - 1); - const int x2 = x + t/2; - const int k2 = x2 & (block_size - 1); + const int x2 = x1 + t/2; float2 a0, a1, a2, a3; - if (x < t/2) + if (x1 < t/2) { - a0 = smem[x]; - a1 = mul_float2(twiddles[k1],smem[x+t]); - a2 = smem[x2]; - a3 = mul_float2(twiddles[k2],smem[x2+t]); + a0 = smem[x1]; a1 = smem[x1+t]; + a2 = smem[x2]; a3 = smem[x2+t]; } barrier(CLK_LOCAL_MEM_FENCE); - if (x < t/2) + if (x1 < t/2) { - int dst_ind = (x << 1) - k1; - smem[dst_ind] = a0 + a1; - smem[dst_ind+block_size] = a0 - a1; + butterfly2(a0, a1, smem, twiddles, x1, block_size); + butterfly2(a2, a3, smem, twiddles, x2, block_size); + } - dst_ind = (x2 << 1) - k2; - smem[dst_ind] = a2 + a3; - smem[dst_ind+block_size] = a2 - a3; + barrier(CLK_LOCAL_MEM_FENCE); +} + +__attribute__((always_inline)) +void fft_radix2_B3(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +{ + const int x2 = x1 + t/3; + const int x3 = x1 + 2*t/3; + float2 a0, a1, a2, a3, a4, a5; + + if (x1 < t/3) + { + a0 = smem[x1]; a1 = smem[x1+t]; + a2 = smem[x2]; a3 = smem[x2+t]; + a4 = smem[x3]; a5 = smem[x3+t]; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x1 < t/3) + { + butterfly2(a0, a1, smem, twiddles, x1, block_size); + butterfly2(a2, a3, smem, twiddles, x2, block_size); + butterfly2(a4, a5, smem, twiddles, x3, block_size); } barrier(CLK_LOCAL_MEM_FENCE); } __attribute__((always_inline)) -void fft_radix2_B4(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix2_B4(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) { const int thread_block = t/4; - const int k1 = x & (block_size - 1); - const int x2 = x + thread_block; - const int k2 = x2 & (block_size - 1); - const int x3 = x + 2*thread_block; - const int k3 = x3 & (block_size - 1); - const int x4 = x + 3*thread_block; - const int k4 = x4 & (block_size - 1); + const int x2 = x1 + thread_block; + const int x3 = x1 + 2*thread_block; + const int x4 = x1 + 3*thread_block; float2 a0, a1, a2, a3, a4, a5, a6, a7; - if (x < t/4) + if (x1 < t/4) { - a0 = smem[x]; - a1 = mul_float2(twiddles[k1],smem[x+t]); - a2 = smem[x2]; - a3 = mul_float2(twiddles[k2],smem[x2+t]); - a4 = smem[x3]; - a5 = mul_float2(twiddles[k3],smem[x3+t]); - a6 = smem[x4]; - a7 = mul_float2(twiddles[k4],smem[x4+t]); + a0 = smem[x1]; a1 = smem[x1+t]; + a2 = smem[x2]; a3 = smem[x2+t]; + a4 = smem[x3]; a5 = smem[x3+t]; + a6 = smem[x4]; a7 = smem[x4+t]; } barrier(CLK_LOCAL_MEM_FENCE); - if (x < t/4) + if (x1 < t/4) { - int dst_ind = (x << 1) - k1; - smem[dst_ind] = a0 + a1; - smem[dst_ind+block_size] = a0 - a1; + butterfly2(a0, a1, smem, twiddles, x1, block_size); + butterfly2(a2, a3, smem, twiddles, x2, block_size); + butterfly2(a4, a5, smem, twiddles, x3, block_size); + butterfly2(a6, a7, smem, twiddles, x4, block_size); + } - dst_ind = (x2 << 1) - k2; - smem[dst_ind] = a2 + a3; - smem[dst_ind+block_size] = a2 - a3; + barrier(CLK_LOCAL_MEM_FENCE); +} - dst_ind = (x3 << 1) - k3; - smem[dst_ind] = a4 + a5; - smem[dst_ind+block_size] = a4 - a5; +__attribute__((always_inline)) +void fft_radix2_B5(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +{ + const int thread_block = t/5; + const int x2 = x1 + thread_block; + const int x3 = x1 + 2*thread_block; + const int x4 = x1 + 3*thread_block; + const int x5 = x1 + 4*thread_block; + float2 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9; - dst_ind = (x4 << 1) - k4; - smem[dst_ind] = a6 + a7; - smem[dst_ind+block_size] = a6 - a7; + if (x1 < t/5) + { + a0 = smem[x1]; a1 = smem[x1+t]; + a2 = smem[x2]; a3 = smem[x2+t]; + a4 = smem[x3]; a5 = smem[x3+t]; + a6 = smem[x4]; a7 = smem[x4+t]; + a8 = smem[x5]; a9 = smem[x5+t]; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x1 < t/5) + { + butterfly2(a0, a1, smem, twiddles, x1, block_size); + butterfly2(a2, a3, smem, twiddles, x2, block_size); + butterfly2(a4, a5, smem, twiddles, x3, block_size); + butterfly2(a6, a7, smem, twiddles, x4, block_size); + butterfly2(a8, a9, smem, twiddles, x5, block_size); } barrier(CLK_LOCAL_MEM_FENCE); @@ -124,85 +242,65 @@ void fft_radix2_B4(__local float2* smem, __constant const float2* twiddles, cons __attribute__((always_inline)) void fft_radix4(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { - const int k = x & (block_size - 1); float2 a0, a1, a2, a3; if (x < t) { - const int twiddle_block = block_size / 4; - a0 = smem[x]; - a1 = mul_float2(twiddles[k],smem[x+t]); - a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); - a3 = mul_float2(twiddles[k + 2*block_size],smem[x+3*t]); + a0 = smem[x]; a1 = smem[x+t]; a2 = smem[x+2*t]; a3 = smem[x+3*t]; } barrier(CLK_LOCAL_MEM_FENCE); if (x < t) + butterfly4(a0, a1, a2, a3, smem, twiddles, x, block_size); + + barrier(CLK_LOCAL_MEM_FENCE); +} + +__attribute__((always_inline)) +void fft_radix4_B2(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +{ + const int x2 = x1 + t/2; + float2 a0, a1, a2, a3, a4, a5, a6, a7; + + if (x1 < t/2) { - const int dst_ind = ((x - k) << 2) + k; + a0 = smem[x1]; a1 = smem[x1+t]; a2 = smem[x1+2*t]; a3 = smem[x1+3*t]; + a4 = smem[x2]; a5 = smem[x2+t]; a6 = smem[x2+2*t]; a7 = smem[x2+3*t]; + } - float2 b0 = a0 + a2; - a2 = a0 - a2; - float2 b1 = a1 + a3; - a3 = twiddle(a1 - a3); + barrier(CLK_LOCAL_MEM_FENCE); - smem[dst_ind] = b0 + b1; - smem[dst_ind + block_size] = a2 + a3; - smem[dst_ind + 2*block_size] = b0 - b1; - smem[dst_ind + 3*block_size] = a2 - a3; + if (x1 < t/2) + { + butterfly4(a0, a1, a2, a3, smem, twiddles, x1, block_size); + butterfly4(a4, a5, a6, a7, smem, twiddles, x2, block_size); } barrier(CLK_LOCAL_MEM_FENCE); } __attribute__((always_inline)) -void fft_radix4_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix4_B3(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) { - const int k = x & (block_size - 1); - const int x2 = x + t/2; - const int k2 = x2 & (block_size - 1); - float2 a0, a1, a2, a3, a4, a5, a6, a7; + const int x2 = x1 + t/3; + const int x3 = x2 + t/3; + float2 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11; - if (x < t/2) + if (x1 < t/3) { - a0 = smem[x]; - a1 = mul_float2(twiddles[k], smem[x+t]); - a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); - a3 = mul_float2(twiddles[k + 2*block_size],smem[x+3*t]); - - a4 = smem[x2]; - a5 = mul_float2(twiddles[k2], smem[x2+t]); - a6 = mul_float2(twiddles[k2 + block_size],smem[x2+2*t]); - a7 = mul_float2(twiddles[k2 + 2*block_size],smem[x2+3*t]); + a0 = smem[x1]; a1 = smem[x1+t]; a2 = smem[x1+2*t]; a3 = smem[x1+3*t]; + a4 = smem[x2]; a5 = smem[x2+t]; a6 = smem[x2+2*t]; a7 = smem[x2+3*t]; + a8 = smem[x3]; a9 = smem[x3+t]; a10 = smem[x3+2*t]; a11 = smem[x3+3*t]; } barrier(CLK_LOCAL_MEM_FENCE); - if (x < t/2) + if (x1 < t/3) { - int dst_ind = ((x - k) << 2) + k; - - float2 b0 = a0 + a2; - a2 = a0 - a2; - float2 b1 = a1 + a3; - a3 = twiddle(a1 - a3); - - smem[dst_ind] = b0 + b1; - smem[dst_ind + block_size] = a2 + a3; - smem[dst_ind + 2*block_size] = b0 - b1; - smem[dst_ind + 3*block_size] = a2 - a3; - - dst_ind = ((x2 - k2) << 2) + k2; - b0 = a4 + a6; - a6 = a4 - a6; - b1 = a5 + a7; - a7 = twiddle(a5 - a7); - - smem[dst_ind] = b0 + b1; - smem[dst_ind + block_size] = a6 + a7; - smem[dst_ind + 2*block_size] = b0 - b1; - smem[dst_ind + 3*block_size] = a6 - a7; + butterfly4(a0, a1, a2, a3, smem, twiddles, x1, block_size); + butterfly4(a4, a5, a6, a7, smem, twiddles, x2, block_size); + butterfly4(a8, a9, a10, a11, smem, twiddles, x3, block_size); } barrier(CLK_LOCAL_MEM_FENCE); @@ -274,156 +372,95 @@ void fft_radix8(__local float2* smem, __constant const float2* twiddles, const i __attribute__((always_inline)) void fft_radix3(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) { - const int k = x % block_size; float2 a0, a1, a2; if (x < t) { - a0 = smem[x]; - a1 = mul_float2(twiddles[k], smem[x+t]); - a2 = mul_float2(twiddles[k+block_size], smem[x+2*t]); + a0 = smem[x]; a1 = smem[x+t]; a2 = smem[x+2*t]; } barrier(CLK_LOCAL_MEM_FENCE); if (x < t) - { - const int dst_ind = ((x - k) * 3) + k; - - float2 b1 = a1 + a2; - a2 = twiddle(sin_120*(a1 - a2)); - float2 b0 = a0 - (float2)(0.5f)*b1; - - smem[dst_ind] = a0 + b1; - smem[dst_ind + block_size] = b0 + a2; - smem[dst_ind + 2*block_size] = b0 - a2; - } + butterfly3(a0, a1, a2, smem, twiddles, x, block_size); barrier(CLK_LOCAL_MEM_FENCE); } __attribute__((always_inline)) -void fft_radix3_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix3_B2(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) { - const int k = x % block_size; - const int x2 = x + t/2; - const int k2 = x2 % block_size; + const int x2 = x1 + t/2; float2 a0, a1, a2, a3, a4, a5; - if (x < t/2) + if (x1 < t/2) { - a0 = smem[x]; - a1 = mul_float2(twiddles[k], smem[x+t]); - a2 = mul_float2(twiddles[k+block_size], smem[x+2*t]); - - a3 = smem[x2]; - a4 = mul_float2(twiddles[k2], smem[x2+t]); - a5 = mul_float2(twiddles[k2+block_size], smem[x2+2*t]); + a0 = smem[x1]; a1 = smem[x1+t]; a2 = smem[x1+2*t]; + a3 = smem[x2]; a4 = smem[x2+t]; a5 = smem[x2+2*t]; } barrier(CLK_LOCAL_MEM_FENCE); - if (x < t/2) + if (x1 < t/2) { - int dst_ind = ((x - k) * 3) + k; + butterfly3(a0, a1, a2, smem, twiddles, x1, block_size); + butterfly3(a3, a4, a5, smem, twiddles, x2, block_size); + } - float2 b1 = a1 + a2; - a2 = twiddle(sin_120*(a1 - a2)); - float2 b0 = a0 - (float2)(0.5f)*b1; + barrier(CLK_LOCAL_MEM_FENCE); +} - smem[dst_ind] = a0 + b1; - smem[dst_ind + block_size] = b0 + a2; - smem[dst_ind + 2*block_size] = b0 - a2; +__attribute__((always_inline)) +void fft_radix3_B3(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +{ + const int x2 = x1 + t/3; + const int x3 = x2 + t/3; + float2 a0, a1, a2, a3, a4, a5, a6, a7, a8; - dst_ind = ((x2 - k2) * 3) + k2; + if (x1 < t/2) + { + a0 = smem[x1]; a1 = smem[x1+t]; a2 = smem[x1+2*t]; + a3 = smem[x2]; a4 = smem[x2+t]; a5 = smem[x2+2*t]; + a6 = smem[x3]; a7 = smem[x3+t]; a8 = smem[x3+2*t]; + } - b1 = a4 + a5; - a5 = twiddle(sin_120*(a4 - a5)); - b0 = a3 - (float2)(0.5f)*b1; + barrier(CLK_LOCAL_MEM_FENCE); - smem[dst_ind] = a3 + b1; - smem[dst_ind + block_size] = b0 + a5; - smem[dst_ind + 2*block_size] = b0 - a5; + if (x1 < t/2) + { + butterfly3(a0, a1, a2, smem, twiddles, x1, block_size); + butterfly3(a3, a4, a5, smem, twiddles, x2, block_size); + butterfly3(a6, a7, a8, smem, twiddles, x3, block_size); } barrier(CLK_LOCAL_MEM_FENCE); } __attribute__((always_inline)) -void fft_radix3_B4(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix3_B4(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) { const int thread_block = t/4; - const int k = x % block_size; - const int x2 = x + thread_block; - const int k2 = x2 % block_size; - const int x3 = x + 2*thread_block; - const int k3 = x3 % block_size; - const int x4 = x + 3*thread_block; - const int k4 = x4 % block_size; + const int x2 = x1 + thread_block; + const int x3 = x1 + 2*thread_block; + const int x4 = x1 + 3*thread_block; float2 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11; - if (x < t/4) + if (x1 < t/4) { - a0 = smem[x]; - a1 = mul_float2(twiddles[k], smem[x+t]); - a2 = mul_float2(twiddles[k+block_size], smem[x+2*t]); - - a3 = smem[x2]; - a4 = mul_float2(twiddles[k2], smem[x2+t]); - a5 = mul_float2(twiddles[k2+block_size], smem[x2+2*t]); - - a6 = smem[x3]; - a7 = mul_float2(twiddles[k3], smem[x3+t]); - a8 = mul_float2(twiddles[k3+block_size], smem[x3+2*t]); - - a9 = smem[x4]; - a10 = mul_float2(twiddles[k4], smem[x4+t]); - a11 = mul_float2(twiddles[k4+block_size], smem[x4+2*t]); + a0 = smem[x1]; a1 = smem[x1+t]; a2 = smem[x1+2*t]; + a3 = smem[x2]; a4 = smem[x2+t]; a5 = smem[x2+2*t]; + a6 = smem[x3]; a7 = smem[x3+t]; a8 = smem[x3+2*t]; + a9 = smem[x4]; a10 = smem[x4+t]; a11 = smem[x4+2*t]; } barrier(CLK_LOCAL_MEM_FENCE); - if (x < t/4) + if (x1 < t/4) { - int dst_ind = ((x - k) * 3) + k; - - float2 b1 = a1 + a2; - a2 = twiddle(sin_120*(a1 - a2)); - float2 b0 = a0 - (float2)(0.5f)*b1; - - smem[dst_ind] = a0 + b1; - smem[dst_ind + block_size] = b0 + a2; - smem[dst_ind + 2*block_size] = b0 - a2; - - dst_ind = ((x2 - k2) * 3) + k2; - - b1 = a4 + a5; - a5 = twiddle(sin_120*(a4 - a5)); - b0 = a3 - (float2)(0.5f)*b1; - - smem[dst_ind] = a3 + b1; - smem[dst_ind + block_size] = b0 + a5; - smem[dst_ind + 2*block_size] = b0 - a5; - - dst_ind = ((x3 - k3) * 3) + k3; - - b1 = a7 + a8; - a8 = twiddle(sin_120*(a7 - a8)); - b0 = a6 - (float2)(0.5f)*b1; - - smem[dst_ind] = a6 + b1; - smem[dst_ind + block_size] = b0 + a8; - smem[dst_ind + 2*block_size] = b0 - a8; - - dst_ind = ((x4 - k4) * 3) + k4; - - b1 = a10 + a11; - a11 = twiddle(sin_120*(a10 - a11)); - b0 = a9 - (float2)(0.5f)*b1; - - smem[dst_ind] = a9 + b1; - smem[dst_ind + block_size] = b0 + a11; - smem[dst_ind + 2*block_size] = b0 - a11; + butterfly3(a0, a1, a2, smem, twiddles, x1, block_size); + butterfly3(a3, a4, a5, smem, twiddles, x2, block_size); + butterfly3(a6, a7, a8, smem, twiddles, x3, block_size); + butterfly3(a9, a10, a11, smem, twiddles, x4, block_size); } barrier(CLK_LOCAL_MEM_FENCE); @@ -437,135 +474,35 @@ void fft_radix5(__local float2* smem, __constant const float2* twiddles, const i if (x < t) { - a0 = smem[x]; - a1 = mul_float2(twiddles[k], smem[x + t]); - a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); - a3 = mul_float2(twiddles[k+2*block_size],smem[x+3*t]); - a4 = mul_float2(twiddles[k+3*block_size],smem[x+4*t]); + a0 = smem[x]; a1 = smem[x + t]; a2 = smem[x+2*t]; a3 = smem[x+3*t]; a4 = smem[x+4*t]; } barrier(CLK_LOCAL_MEM_FENCE); if (x < t) - { - const int dst_ind = ((x - k) * 5) + k; - __local float2* dst = smem + dst_ind; - - float2 b0, b1, b5; - - b1 = a1 + a4; - a1 -= a4; - - a4 = a3 + a2; - a3 -= a2; - - a2 = b1 + a4; - b0 = a0 - (float2)0.25f * a2; - - b1 = fft5_2 * (b1 - a4); - a4 = fft5_3 * (float2)(-a1.y - a3.y, a1.x + a3.x); - b5 = (float2)(a4.x - fft5_5 * a1.y, a4.y + fft5_5 * a1.x); - - a4.x += fft5_4 * a3.y; - a4.y -= fft5_4 * a3.x; - - a1 = b0 + b1; - b0 -= b1; - - dst[0] = a0 + a2; - dst[block_size] = a1 + a4; - dst[2 * block_size] = b0 + b5; - dst[3 * block_size] = b0 - b5; - dst[4 * block_size] = a1 - a4; - } + butterfly5(a0, a1, a2, a3, a4, smem, twiddles, x, block_size); barrier(CLK_LOCAL_MEM_FENCE); } __attribute__((always_inline)) -void fft_radix5_B2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix5_B2(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) { - const int k = x % block_size; - const int x2 = x+t/2; - const int k2 = x2 % block_size; + const int x2 = x1+t/2; float2 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9; - if (x < t/2) + if (x1 < t/2) { - a0 = smem[x]; - a1 = mul_float2(twiddles[k], smem[x + t]); - a2 = mul_float2(twiddles[k + block_size],smem[x+2*t]); - a3 = mul_float2(twiddles[k+2*block_size],smem[x+3*t]); - a4 = mul_float2(twiddles[k+3*block_size],smem[x+4*t]); - - a5 = smem[x2]; - a6 = mul_float2(twiddles[k2], smem[x2 + t]); - a7 = mul_float2(twiddles[k2 + block_size],smem[x2+2*t]); - a8 = mul_float2(twiddles[k2+2*block_size],smem[x2+3*t]); - a9 = mul_float2(twiddles[k2+3*block_size],smem[x2+4*t]); + a0 = smem[x1]; a1 = smem[x1 + t]; a2 = smem[x1+2*t]; a3 = smem[x1+3*t]; a4 = smem[x1+4*t]; + a5 = smem[x2]; a6 = smem[x2 + t]; a7 = smem[x2+2*t]; a8 = smem[x2+3*t]; a9 = smem[x2+4*t]; } barrier(CLK_LOCAL_MEM_FENCE); - if (x < t/2) + if (x1 < t/2) { - int dst_ind = ((x - k) * 5) + k; - __local float2* dst = smem + dst_ind; - - float2 b0, b1, b5; - - b1 = a1 + a4; - a1 -= a4; - - a4 = a3 + a2; - a3 -= a2; - - a2 = b1 + a4; - b0 = a0 - (float2)0.25f * a2; - - b1 = fft5_2 * (b1 - a4); - a4 = fft5_3 * (float2)(-a1.y - a3.y, a1.x + a3.x); - b5 = (float2)(a4.x - fft5_5 * a1.y, a4.y + fft5_5 * a1.x); - - a4.x += fft5_4 * a3.y; - a4.y -= fft5_4 * a3.x; - - a1 = b0 + b1; - b0 -= b1; - - dst[0] = a0 + a2; - dst[block_size] = a1 + a4; - dst[2 * block_size] = b0 + b5; - dst[3 * block_size] = b0 - b5; - dst[4 * block_size] = a1 - a4; - - dst_ind = ((x2 - k2) * 5) + k2; - dst = smem + dst_ind; - - b1 = a6 + a9; - a6 -= a9; - - a9 = a8 + a7; - a8 -= a7; - - a7 = b1 + a9; - b0 = a5 - (float2)0.25f * a7; - - b1 = fft5_2 * (b1 - a9); - a9 = fft5_3 * (float2)(-a6.y - a8.y, a6.x + a8.x); - b5 = (float2)(a9.x - fft5_5 * a6.y, a9.y + fft5_5 * a6.x); - - a9.x += fft5_4 * a8.y; - a9.y -= fft5_4 * a8.x; - - a6 = b0 + b1; - b0 -= b1; - - dst[0] = a5 + a7; - dst[block_size] = a6 + a9; - dst[2 * block_size] = b0 + b5; - dst[3 * block_size] = b0 - b5; - dst[4 * block_size] = a6 - a9; + butterfly5(a0, a1, a2, a3, a4, smem, twiddles, x1, block_size); + butterfly5(a5, a6, a7, a8, a9, smem, twiddles, x2, block_size); } barrier(CLK_LOCAL_MEM_FENCE); @@ -611,7 +548,7 @@ __kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, RADIX_PROCESS; -#ifndef CCS_OUTPUT +#ifndef REAL_OUTPUT #ifdef NO_CONJUGATE // copy result without complex conjugate const int cols = dst_cols/2 + 1; @@ -659,7 +596,7 @@ __kernel void fft_multi_radix_cols(__global const uchar* src_ptr, int src_step, RADIX_PROCESS; -#ifndef CCS_OUTPUT +#ifndef REAL_OUTPUT __global uchar* dst = dst_ptr + mad24(y, dst_step, mad24(x, (int)(sizeof(float)*2), dst_offset)); #pragma unroll for (int i=0; i Date: Tue, 22 Jul 2014 14:54:38 +0400 Subject: [PATCH 102/136] Added nonzero_rows support --- modules/core/src/dxt.cpp | 49 +++++------- modules/core/src/ocl.cpp | 8 +- modules/core/src/opencl/fft.cl | 120 +++++++++++++++++------------ modules/core/test/ocl/test_dft.cpp | 32 ++++---- 4 files changed, 109 insertions(+), 100 deletions(-) diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index eaef53ad23..869409f50d 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2034,19 +2034,19 @@ enum FftType C2C = 3 }; -static std::vector ocl_getRadixes(int cols, std::vector& radixes, std::vector& blocks, int& min_radix) +static void ocl_getRadixes(int cols, std::vector& radixes, std::vector& blocks, int& min_radix) { int factors[34]; - int nf = DFTFactorize( cols, factors ); + int nf = DFTFactorize(cols, factors); int n = 1; int factor_index = 0; min_radix = INT_MAX; // 2^n transforms - if ( (factors[factor_index] & 1) == 0 ) + if ((factors[factor_index] & 1) == 0) { - for( ; n < factors[factor_index]; ) + for( ; n < factors[factor_index];) { int radix = 2, block = 1; if (8*n <= factors[0]) @@ -2080,7 +2080,7 @@ static std::vector ocl_getRadixes(int cols, std::vector& radixes, std: } // all the other transforms - for( ; factor_index < nf; factor_index++ ) + for( ; factor_index < nf; factor_index++) { int radix = factors[factor_index], block = 1; if (radix == 3) @@ -2101,7 +2101,6 @@ static std::vector ocl_getRadixes(int cols, std::vector& radixes, std: blocks.push_back(block); min_radix = min(min_radix, block*radix); } - return radixes; } struct OCL_FftPlan @@ -2111,14 +2110,13 @@ struct OCL_FftPlan int thread_count; int dft_size; - int flags; bool status; - OCL_FftPlan(int _size, int _flags): dft_size(_size), flags(_flags), status(true) + OCL_FftPlan(int _size): dft_size(_size), status(true) { int min_radix; std::vector radixes, blocks; ocl_getRadixes(dft_size, radixes, blocks, min_radix); - thread_count = (dft_size + min_radix-1) / min_radix; + thread_count = dft_size / min_radix; if (thread_count > ocl::Device::getDefault().maxWorkGroupSize()) { @@ -2140,8 +2138,7 @@ struct OCL_FftPlan n *= radix; } - twiddles.create(1, twiddle_size, CV_32FC2); - Mat tw = twiddles.getMat(ACCESS_WRITE); + Mat tw(1, twiddle_size, CV_32FC2); float* ptr = tw.ptr(); int ptr_index = 0; @@ -2162,6 +2159,7 @@ struct OCL_FftPlan } } } + twiddles = tw.getUMat(ACCESS_READ); buildOptions = format("-D LOCAL_SIZE=%d -D kercn=%d -D RADIX_PROCESS=%s", dft_size, dft_size/thread_count, radix_processing.c_str()); @@ -2185,10 +2183,10 @@ struct OCL_FftPlan if (rows) { - globalsize[0] = thread_count; globalsize[1] = dft_size; + globalsize[0] = thread_count; globalsize[1] = src.rows; localsize[0] = thread_count; localsize[1] = 1; kernel_name = !inv ? "fft_multi_radix_rows" : "ifft_multi_radix_rows"; - if (is1d && (flags & DFT_SCALE)) + if ((is1d || inv) && (flags & DFT_SCALE)) options += " -D DFT_SCALE"; } else @@ -2200,14 +2198,9 @@ struct OCL_FftPlan options += " -D DFT_SCALE"; } - if (src.channels() == 1) - options += " -D REAL_INPUT"; - else - options += " -D COMPLEX_INPUT"; - if (dst.channels() == 1) - options += " -D REAL_OUTPUT"; - if (is1d) - options += " -D IS_1D"; + options += src.channels() == 1 ? " -D REAL_INPUT" : " -D COMPLEX_INPUT"; + options += dst.channels() == 1 ? " -D REAL_OUTPUT" : " -D COMPLEX_OUTPUT"; + options += is1d ? " -D IS_1D" : ""; if (!inv) { @@ -2216,10 +2209,10 @@ struct OCL_FftPlan } else { - if (is1d && fftType == C2R || (rows && fftType == R2R)) + if (rows && (fftType == C2R || fftType == R2R)) options += " -D NO_CONJUGATE"; if (dst.cols % 2 == 0) - options += " -D EVEN"; + options += " -D EVEN"; } ocl::Kernel k(kernel_name.c_str(), ocl::core::fft_oclsrc, options); @@ -2240,7 +2233,7 @@ public: return planCache; } - OCL_FftPlan* getFftPlan(int dft_size, int flags) + OCL_FftPlan* getFftPlan(int dft_size) { for (size_t i = 0, size = planStorage.size(); i < size; ++i) { @@ -2252,7 +2245,7 @@ public: } } - OCL_FftPlan * newPlan = new OCL_FftPlan(dft_size, flags); + OCL_FftPlan * newPlan = new OCL_FftPlan(dft_size); planStorage.push_back(newPlan); return newPlan; } @@ -2275,13 +2268,13 @@ protected: static bool ocl_dft_C2C_rows(InputArray _src, OutputArray _dst, int nonzero_rows, int flags, int fftType) { - const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.cols(), flags); + const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.cols()); return plan->enqueueTransform(_src, _dst, nonzero_rows, flags, fftType, true); } static bool ocl_dft_C2C_cols(InputArray _src, OutputArray _dst, int nonzero_cols, int flags, int fftType) { - const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.rows(), flags); + const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.rows()); return plan->enqueueTransform(_src, _dst, nonzero_cols, flags, fftType, false); } @@ -2385,7 +2378,7 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro } else { - int nonzero_cols = src.cols/2 + 1;// : src.cols; + int nonzero_cols = src.cols/2 + 1; if (!ocl_dft_C2C_cols(src, output, nonzero_cols, flags, fftType)) return false; diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 32db8c91b4..a2110f6cc2 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3002,7 +3002,8 @@ bool Kernel::run(int dims, size_t _globalsize[], size_t _localsize[], sync ? 0 : &p->e); if( sync || retval != CL_SUCCESS ) { - CV_OclDbgAssert(clFinish(qq) == CL_SUCCESS); + int a = clFinish(qq); + CV_OclDbgAssert(a == CL_SUCCESS); p->cleanupUMats(); } else @@ -3898,8 +3899,9 @@ public: if( (accessFlags & ACCESS_READ) != 0 && u->hostCopyObsolete() ) { AlignedDataPtr alignedPtr(u->data, u->size, CV_OPENCL_DATA_PTR_ALIGNMENT); - CV_Assert( clEnqueueReadBuffer(q, (cl_mem)u->handle, CL_TRUE, 0, - u->size, alignedPtr.getAlignedPtr(), 0, 0, 0) == CL_SUCCESS ); + int a = clEnqueueReadBuffer(q, (cl_mem)u->handle, CL_TRUE, 0, + u->size, alignedPtr.getAlignedPtr(), 0, 0, 0); + CV_Assert( a == CL_SUCCESS ); u->markHostCopyObsolete(false); } } diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index dd8ff59850..b8d2c6716d 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -16,7 +16,7 @@ float2 twiddle(float2 a) { } __attribute__((always_inline)) -void butterfly2(float2 a0, float2 a1, __local float2* smem, __constant const float2* twiddles, +void butterfly2(float2 a0, float2 a1, __local float2* smem, __global const float2* twiddles, const int x, const int block_size) { const int k = x & (block_size - 1); @@ -28,7 +28,7 @@ void butterfly2(float2 a0, float2 a1, __local float2* smem, __constant const flo } __attribute__((always_inline)) -void butterfly4(float2 a0, float2 a1, float2 a2, float2 a3, __local float2* smem, __constant const float2* twiddles, +void butterfly4(float2 a0, float2 a1, float2 a2, float2 a3, __local float2* smem, __global const float2* twiddles, const int x, const int block_size) { const int k = x & (block_size - 1); @@ -50,10 +50,10 @@ void butterfly4(float2 a0, float2 a1, float2 a2, float2 a3, __local float2* smem } __attribute__((always_inline)) -void butterfly3(float2 a0, float2 a1, float2 a2, __local float2* smem, __constant const float2* twiddles, +void butterfly3(float2 a0, float2 a1, float2 a2, __local float2* smem, __global const float2* twiddles, const int x, const int block_size) { - const int k = x & (block_size - 1); + const int k = x % block_size; a1 = mul_float2(twiddles[k], a1); a2 = mul_float2(twiddles[k+block_size], a2); const int dst_ind = ((x - k) * 3) + k; @@ -68,10 +68,10 @@ void butterfly3(float2 a0, float2 a1, float2 a2, __local float2* smem, __constan } __attribute__((always_inline)) -void butterfly5(float2 a0, float2 a1, float2 a2, float2 a3, float2 a4, __local float2* smem, __constant const float2* twiddles, +void butterfly5(float2 a0, float2 a1, float2 a2, float2 a3, float2 a4, __local float2* smem, __global const float2* twiddles, const int x, const int block_size) { - const int k = x & (block_size - 1); + const int k = x % block_size; a1 = mul_float2(twiddles[k], a1); a2 = mul_float2(twiddles[k + block_size], a2); a3 = mul_float2(twiddles[k+2*block_size], a3); @@ -109,7 +109,7 @@ void butterfly5(float2 a0, float2 a1, float2 a2, float2 a3, float2 a4, __local f } __attribute__((always_inline)) -void fft_radix2(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix2(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { float2 a0, a1; @@ -128,7 +128,7 @@ void fft_radix2(__local float2* smem, __constant const float2* twiddles, const i } __attribute__((always_inline)) -void fft_radix2_B2(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix2_B2(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int x2 = x1 + t/2; float2 a0, a1, a2, a3; @@ -151,7 +151,7 @@ void fft_radix2_B2(__local float2* smem, __constant const float2* twiddles, cons } __attribute__((always_inline)) -void fft_radix2_B3(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix2_B3(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int x2 = x1 + t/3; const int x3 = x1 + 2*t/3; @@ -177,7 +177,7 @@ void fft_radix2_B3(__local float2* smem, __constant const float2* twiddles, cons } __attribute__((always_inline)) -void fft_radix2_B4(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix2_B4(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int thread_block = t/4; const int x2 = x1 + thread_block; @@ -207,7 +207,7 @@ void fft_radix2_B4(__local float2* smem, __constant const float2* twiddles, cons } __attribute__((always_inline)) -void fft_radix2_B5(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix2_B5(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int thread_block = t/5; const int x2 = x1 + thread_block; @@ -240,7 +240,7 @@ void fft_radix2_B5(__local float2* smem, __constant const float2* twiddles, cons } __attribute__((always_inline)) -void fft_radix4(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix4(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { float2 a0, a1, a2, a3; @@ -258,7 +258,7 @@ void fft_radix4(__local float2* smem, __constant const float2* twiddles, const i } __attribute__((always_inline)) -void fft_radix4_B2(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix4_B2(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int x2 = x1 + t/2; float2 a0, a1, a2, a3, a4, a5, a6, a7; @@ -281,7 +281,7 @@ void fft_radix4_B2(__local float2* smem, __constant const float2* twiddles, cons } __attribute__((always_inline)) -void fft_radix4_B3(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix4_B3(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int x2 = x1 + t/3; const int x3 = x2 + t/3; @@ -307,7 +307,7 @@ void fft_radix4_B3(__local float2* smem, __constant const float2* twiddles, cons } __attribute__((always_inline)) -void fft_radix8(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix8(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { const int k = x % block_size; float2 a0, a1, a2, a3, a4, a5, a6, a7; @@ -370,7 +370,7 @@ void fft_radix8(__local float2* smem, __constant const float2* twiddles, const i } __attribute__((always_inline)) -void fft_radix3(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix3(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { float2 a0, a1, a2; @@ -388,7 +388,7 @@ void fft_radix3(__local float2* smem, __constant const float2* twiddles, const i } __attribute__((always_inline)) -void fft_radix3_B2(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix3_B2(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int x2 = x1 + t/2; float2 a0, a1, a2, a3, a4, a5; @@ -411,7 +411,7 @@ void fft_radix3_B2(__local float2* smem, __constant const float2* twiddles, cons } __attribute__((always_inline)) -void fft_radix3_B3(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix3_B3(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int x2 = x1 + t/3; const int x3 = x2 + t/3; @@ -437,7 +437,7 @@ void fft_radix3_B3(__local float2* smem, __constant const float2* twiddles, cons } __attribute__((always_inline)) -void fft_radix3_B4(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix3_B4(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int thread_block = t/4; const int x2 = x1 + thread_block; @@ -467,7 +467,7 @@ void fft_radix3_B4(__local float2* smem, __constant const float2* twiddles, cons } __attribute__((always_inline)) -void fft_radix5(__local float2* smem, __constant const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix5(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { const int k = x % block_size; float2 a0, a1, a2, a3, a4; @@ -486,7 +486,7 @@ void fft_radix5(__local float2* smem, __constant const float2* twiddles, const i } __attribute__((always_inline)) -void fft_radix5_B2(__local float2* smem, __constant const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix5_B2(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int x2 = x1+t/2; float2 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9; @@ -516,24 +516,23 @@ void fft_radix5_B2(__local float2* smem, __constant const float2* twiddles, cons __kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, int src_offset, int src_rows, int src_cols, __global uchar* dst_ptr, int dst_step, int dst_offset, int dst_rows, int dst_cols, - __constant float2 * twiddles_ptr, const int t, const int nz) + __global float2* twiddles_ptr, const int t, const int nz) { const int x = get_global_id(0); const int y = get_group_id(1); - + const int block_size = LOCAL_SIZE/kercn; if (y < nz) { __local float2 smem[LOCAL_SIZE]; - __constant const float2* twiddles = (__constant float2*) twiddles_ptr; + __global const float2* twiddles = (__global float2*) twiddles_ptr; const int ind = x; - const int block_size = LOCAL_SIZE/kercn; #ifdef IS_1D float scale = 1.f/dst_cols; #else float scale = 1.f/(dst_cols*dst_rows); #endif -#ifndef REAL_INPUT +#ifdef COMPLEX_INPUT __global const float2* src = (__global const float2*)(src_ptr + mad24(y, src_step, mad24(x, (int)(sizeof(float)*2), src_offset))); #pragma unroll for (int i=0; i(df) << std::endl; double eps = src.size().area() * 1e-4; @@ -188,13 +185,12 @@ OCL_TEST_P(MulSpectrums, Mat) OCL_INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MulSpectrums, testing::Combine(Bool(), Bool())); -OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(4, 1), cv::Size(5, 8), cv::Size(6, 6), - cv::Size(512, 1), cv::Size(1280, 768)), - Values((OCL_FFT_TYPE) R2C, (OCL_FFT_TYPE) C2C, (OCL_FFT_TYPE) R2R, (OCL_FFT_TYPE) C2R), +OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(10, 10), cv::Size(36, 36), cv::Size(512, 1), cv::Size(1280, 768)), + Values((OCL_FFT_TYPE) R2C, (OCL_FFT_TYPE) C2C, (OCL_FFT_TYPE) R2R, (OCL_FFT_TYPE) C2R), Bool(), // DFT_INVERSE Bool(), // DFT_ROWS Bool(), // DFT_SCALE - Bool() // inplace + Bool() // hint ) ); From 4fdd6de8e8f93df567736f71be1391f7ec2534c5 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Wed, 23 Jul 2014 13:39:31 +0400 Subject: [PATCH 103/136] Fixed ippiDFT call --- modules/core/src/dxt.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 2a08899167..d3327940db 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -2080,32 +2080,32 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) { if ((flags & DFT_ROWS) == 0) { - if (!real_transform) + if (src.channels() == 2 && !(inv && (flags & DFT_REAL_OUTPUT))) { - if (ippi_DFT_C_32F(src,dst, inv, ipp_norm_flag)) + if (ippi_DFT_C_32F(src, dst, inv, ipp_norm_flag)) return; setIppErrorStatus(); } - else if (inv || !(flags & DFT_COMPLEX_OUTPUT)) + if (src.channels() == 1 && (inv || !(flags & DFT_COMPLEX_OUTPUT))) { - if (ippi_DFT_R_32F(src,dst, inv, ipp_norm_flag)) + if (ippi_DFT_R_32F(src, dst, inv, ipp_norm_flag)) return; setIppErrorStatus(); } } else { - if (!real_transform) + if (src.channels() == 2 && !(inv && (flags & DFT_REAL_OUTPUT))) { ippiDFT_C_Func ippiFunc = inv ? (ippiDFT_C_Func)ippiDFTInv_CToC_32fc_C1R : (ippiDFT_C_Func)ippiDFTFwd_CToC_32fc_C1R; - if (Dft_C_IPPLoop(src,dst, IPPDFT_C_Functor(ippiFunc),ipp_norm_flag)) + if (Dft_C_IPPLoop(src, dst, IPPDFT_C_Functor(ippiFunc),ipp_norm_flag)) return; setIppErrorStatus(); } - else if (inv || !(flags & DFT_COMPLEX_OUTPUT)) + if (src.channels() == 1 && (inv || !(flags & DFT_COMPLEX_OUTPUT))) { ippiDFT_R_Func ippiFunc = inv ? (ippiDFT_R_Func)ippiDFTInv_PackToR_32f_C1R : (ippiDFT_R_Func)ippiDFTFwd_RToPack_32f_C1R; - if (Dft_R_IPPLoop(src,dst, IPPDFT_R_Functor(ippiFunc),ipp_norm_flag)) + if (Dft_R_IPPLoop(src, dst, IPPDFT_R_Functor(ippiFunc),ipp_norm_flag)) return; setIppErrorStatus(); } From 6a769c92b3b6bcfb6c312fe4df9dd908fd354ae2 Mon Sep 17 00:00:00 2001 From: Ernest Galbrun Date: Wed, 23 Jul 2014 14:16:53 +0200 Subject: [PATCH 104/136] modified default stream initialization to allow concurrent calls modified cuda surf.cuda.cpp to allow concurrent call --- modules/core/src/cuda_buffer_pool.cpp | 31 +++++++++++++++++++++------ modules/core/src/cuda_stream.cpp | 16 ++++++++++++-- modules/nonfree/src/surf.cuda.cpp | 8 ++++++- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/modules/core/src/cuda_buffer_pool.cpp b/modules/core/src/cuda_buffer_pool.cpp index ea060a7c20..e5caf6ef25 100644 --- a/modules/core/src/cuda_buffer_pool.cpp +++ b/modules/core/src/cuda_buffer_pool.cpp @@ -207,7 +207,6 @@ namespace MemoryStack* MemoryPool::getFreeMemStack() { AutoLock lock(mtx_); - if (!initialized_) initilizeImpl(); @@ -256,22 +255,31 @@ namespace namespace { + Mutex mtx_; + bool memory_pool_manager_initialized; + class MemoryPoolManager { public: MemoryPoolManager(); ~MemoryPoolManager(); + void Init(); MemoryPool* getPool(int deviceId); private: std::vector pools_; - }; + } manager; + + //MemoryPoolManager ; MemoryPoolManager::MemoryPoolManager() { - int deviceCount = getCudaEnabledDeviceCount(); + } + void MemoryPoolManager::Init() + { + int deviceCount = getCudaEnabledDeviceCount(); if (deviceCount > 0) pools_.resize(deviceCount); } @@ -280,7 +288,7 @@ namespace { for (size_t i = 0; i < pools_.size(); ++i) { - cudaSetDevice(i); + cudaSetDevice(static_cast(i)); pools_[i].release(); } } @@ -293,7 +301,14 @@ namespace MemoryPool* memPool(int deviceId) { - static MemoryPoolManager manager; + { + AutoLock lock(mtx_); + if (!memory_pool_manager_initialized) + { + memory_pool_manager_initialized = true; + manager.Init(); + } + } return manager.getPool(deviceId); } } @@ -311,8 +326,10 @@ cv::cuda::StackAllocator::StackAllocator(cudaStream_t stream) : stream_(stream), if (enableMemoryPool) { const int deviceId = getDevice(); - memStack_ = memPool(deviceId)->getFreeMemStack(); - + { + AutoLock lock(mtx_); + memStack_ = memPool(deviceId)->getFreeMemStack(); + } DeviceInfo devInfo(deviceId); alignment_ = devInfo.textureAlignment(); } diff --git a/modules/core/src/cuda_stream.cpp b/modules/core/src/cuda_stream.cpp index 9f190c3fab..1f73a8e5a5 100644 --- a/modules/core/src/cuda_stream.cpp +++ b/modules/core/src/cuda_stream.cpp @@ -190,10 +190,22 @@ void cv::cuda::Stream::enqueueHostCallback(StreamCallback callback, void* userDa #endif } +namespace +{ + bool default_stream_is_initialized; + Mutex mtx; + Ptr default_stream; +} + Stream& cv::cuda::Stream::Null() { - static Stream s(Ptr(new Impl(0))); - return s; + AutoLock lock(mtx); + if (!default_stream_is_initialized) + { + default_stream = Ptr(new Stream(Ptr(new Impl(0)))); + default_stream_is_initialized = true; + } + return *default_stream; } cv::cuda::Stream::operator bool_type() const diff --git a/modules/nonfree/src/surf.cuda.cpp b/modules/nonfree/src/surf.cuda.cpp index 4089b506b3..461ba0f7ef 100644 --- a/modules/nonfree/src/surf.cuda.cpp +++ b/modules/nonfree/src/surf.cuda.cpp @@ -93,6 +93,8 @@ using namespace ::cv::cuda::device::surf; namespace { + Mutex mtx; + int calcSize(int octave, int layer) { /* Wavelet size at first layer of first octave. */ @@ -166,7 +168,6 @@ namespace { const int layer_rows = img_rows >> octave; const int layer_cols = img_cols >> octave; - loadOctaveConstants(octave, layer_rows, layer_cols); icvCalcLayerDetAndTrace_gpu(surf_.det, surf_.trace, img_rows, img_cols, octave, surf_.nOctaveLayers); @@ -354,6 +355,7 @@ void cv::cuda::SURF_CUDA::downloadDescriptors(const GpuMat& descriptorsGPU, std: void cv::cuda::SURF_CUDA::operator()(const GpuMat& img, const GpuMat& mask, GpuMat& keypoints) { + AutoLock lock(mtx); if (!img.empty()) { SURF_CUDA_Invoker surf(*this, img, mask); @@ -365,6 +367,7 @@ void cv::cuda::SURF_CUDA::operator()(const GpuMat& img, const GpuMat& mask, GpuM void cv::cuda::SURF_CUDA::operator()(const GpuMat& img, const GpuMat& mask, GpuMat& keypoints, GpuMat& descriptors, bool useProvidedKeypoints) { + AutoLock lock(mtx); if (!img.empty()) { SURF_CUDA_Invoker surf(*this, img, mask); @@ -382,6 +385,7 @@ void cv::cuda::SURF_CUDA::operator()(const GpuMat& img, const GpuMat& mask, GpuM void cv::cuda::SURF_CUDA::operator()(const GpuMat& img, const GpuMat& mask, std::vector& keypoints) { + AutoLock lock(mtx); GpuMat keypointsGPU; (*this)(img, mask, keypointsGPU); @@ -392,6 +396,7 @@ void cv::cuda::SURF_CUDA::operator()(const GpuMat& img, const GpuMat& mask, std: void cv::cuda::SURF_CUDA::operator()(const GpuMat& img, const GpuMat& mask, std::vector& keypoints, GpuMat& descriptors, bool useProvidedKeypoints) { + AutoLock lock(mtx); GpuMat keypointsGPU; if (useProvidedKeypoints) @@ -405,6 +410,7 @@ void cv::cuda::SURF_CUDA::operator()(const GpuMat& img, const GpuMat& mask, std: void cv::cuda::SURF_CUDA::operator()(const GpuMat& img, const GpuMat& mask, std::vector& keypoints, std::vector& descriptors, bool useProvidedKeypoints) { + AutoLock lock(mtx); GpuMat descriptorsGPU; (*this)(img, mask, keypoints, descriptorsGPU, useProvidedKeypoints); From 551ab83cf21c727a67151a9316cbfa2fdeccca44 Mon Sep 17 00:00:00 2001 From: Ernest Galbrun Date: Wed, 23 Jul 2014 14:34:22 +0200 Subject: [PATCH 105/136] trailing whitespace --- modules/core/src/cuda_stream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/cuda_stream.cpp b/modules/core/src/cuda_stream.cpp index 1f73a8e5a5..98a29df19b 100644 --- a/modules/core/src/cuda_stream.cpp +++ b/modules/core/src/cuda_stream.cpp @@ -190,7 +190,7 @@ void cv::cuda::Stream::enqueueHostCallback(StreamCallback callback, void* userDa #endif } -namespace +namespace { bool default_stream_is_initialized; Mutex mtx; From f8442da945361ef229e0ad503fb573c5968ef772 Mon Sep 17 00:00:00 2001 From: Sander Mathijs van Veen Date: Mon, 21 Jul 2014 10:12:25 +0200 Subject: [PATCH 106/136] Initialize all pointers of CvCapture_GStreamer correctly --- modules/videoio/src/cap_gstreamer.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/videoio/src/cap_gstreamer.cpp b/modules/videoio/src/cap_gstreamer.cpp index 00562aa41c..c5a78a0273 100644 --- a/modules/videoio/src/cap_gstreamer.cpp +++ b/modules/videoio/src/cap_gstreamer.cpp @@ -160,13 +160,17 @@ protected: void CvCapture_GStreamer::init() { pipeline = NULL; - frame = NULL; - buffer = NULL; - buffer_caps = NULL; + uridecodebin = NULL; + color = NULL; + sink = NULL; #if GST_VERSION_MAJOR > 0 sample = NULL; info = new GstMapInfo; #endif + buffer = NULL; + caps = NULL; + buffer_caps = NULL; + frame = NULL; } /*! From facb2f9a810b61e7d1e9c242fb1588effb0af5e3 Mon Sep 17 00:00:00 2001 From: Sander Mathijs van Veen Date: Wed, 23 Jul 2014 19:15:16 +0200 Subject: [PATCH 107/136] Reset class members to NULL after gst_*_unref() --- modules/videoio/src/cap_gstreamer.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_gstreamer.cpp b/modules/videoio/src/cap_gstreamer.cpp index c5a78a0273..fea148f91f 100644 --- a/modules/videoio/src/cap_gstreamer.cpp +++ b/modules/videoio/src/cap_gstreamer.cpp @@ -185,31 +185,41 @@ void CvCapture_GStreamer::close() if(pipeline) { gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL); gst_object_unref(GST_OBJECT(pipeline)); + pipeline = NULL; } if(uridecodebin){ gst_object_unref(GST_OBJECT(uridecodebin)); + uridecodebin = NULL; } if(color){ gst_object_unref(GST_OBJECT(color)); + color = NULL; } if(sink){ gst_object_unref(GST_OBJECT(sink)); + sink = NULL; } - if(buffer) + if(buffer) { gst_buffer_unref(buffer); + buffer = NULL; + } if(frame) { frame->imageData = 0; cvReleaseImage(&frame); + frame = NULL; } if(caps){ gst_caps_unref(caps); + caps = NULL; } if(buffer_caps){ gst_caps_unref(buffer_caps); + buffer_caps = NULL; } #if GST_VERSION_MAJOR > 0 if(sample){ gst_sample_unref(sample); + sample = NULL; } #endif From 16a82b17475fad26a45b76e8e18a886a6c50aa9e Mon Sep 17 00:00:00 2001 From: Joan Puigcerver Date: Wed, 23 Jul 2014 22:47:51 +0200 Subject: [PATCH 108/136] Added an option to traincascade program to select the maximum number of threads to use during training --- apps/traincascade/traincascade.cpp | 7 +++++++ doc/user_guide/ug_traincascade.rst | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/apps/traincascade/traincascade.cpp b/apps/traincascade/traincascade.cpp index e6e16ba896..52bacc8083 100644 --- a/apps/traincascade/traincascade.cpp +++ b/apps/traincascade/traincascade.cpp @@ -13,6 +13,7 @@ int main( int argc, char* argv[] ) int numPos = 2000; int numNeg = 1000; int numStages = 20; + int numThreads = getNumThreads(); int precalcValBufSize = 256, precalcIdxBufSize = 256; bool baseFormatSave = false; @@ -36,6 +37,7 @@ int main( int argc, char* argv[] ) cout << " [-precalcValBufSize ]" << endl; cout << " [-precalcIdxBufSize ]" << endl; cout << " [-baseFormatSave]" << endl; + cout << " [-numThreads ]" << endl; cascadeParams.printDefaults(); stageParams.printDefaults(); for( int fi = 0; fi < fc; fi++ ) @@ -82,6 +84,10 @@ int main( int argc, char* argv[] ) { baseFormatSave = true; } + else if( !strcmp( argv[i], "-numThreads" ) ) + { + numThreads = atoi(argv[++i]); + } else if ( cascadeParams.scanAttr( argv[i], argv[i+1] ) ) { i++; } else if ( stageParams.scanAttr( argv[i], argv[i+1] ) ) { i++; } else if ( !set ) @@ -98,6 +104,7 @@ int main( int argc, char* argv[] ) } } + setNumThreads( numThreads ); classifier.train( cascadeDirName, vecName, bgName, diff --git a/doc/user_guide/ug_traincascade.rst b/doc/user_guide/ug_traincascade.rst index 601f504382..20c1b1683d 100644 --- a/doc/user_guide/ug_traincascade.rst +++ b/doc/user_guide/ug_traincascade.rst @@ -200,6 +200,12 @@ Command line arguments of ``opencv_traincascade`` application grouped by purpose This argument is actual in case of Haar-like features. If it is specified, the cascade will be saved in the old format. + * ``-numThreads `` + + Maximum number of threads to use during training. Notice that + the actual number of used threads may be lower, depending on + your machine and compilation options. + #. Cascade parameters: From 66ac46214d4bb7685b78d0b3aed4c67b5cdb76a7 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Wed, 23 Jul 2014 12:13:09 +0400 Subject: [PATCH 109/136] Final refactoring, fixes --- modules/core/perf/opencl/perf_arithm.cpp | 2 +- modules/core/perf/opencl/perf_dxt.cpp | 37 +- modules/core/src/dxt.cpp | 513 +++++++++++------------ modules/core/src/ocl.cpp | 8 +- modules/core/src/opencl/fft.cl | 105 +++-- modules/core/test/ocl/test_dft.cpp | 75 +--- 6 files changed, 352 insertions(+), 388 deletions(-) diff --git a/modules/core/perf/opencl/perf_arithm.cpp b/modules/core/perf/opencl/perf_arithm.cpp index ba808b494f..17badca765 100644 --- a/modules/core/perf/opencl/perf_arithm.cpp +++ b/modules/core/perf/opencl/perf_arithm.cpp @@ -292,7 +292,7 @@ OCL_PERF_TEST_P(MagnitudeFixture, Magnitude, ::testing::Combine( typedef Size_MatType TransposeFixture; OCL_PERF_TEST_P(TransposeFixture, Transpose, ::testing::Combine( - OCL_TEST_SIZES, Values(CV_8UC1, CV_32FC1, CV_8UC2, CV_32FC2, CV_8UC4, CV_32FC4))) + OCL_TEST_SIZES, OCL_TEST_TYPES_134)) { const Size_MatType_t params = GetParam(); const Size srcSize = get<0>(params); diff --git a/modules/core/perf/opencl/perf_dxt.cpp b/modules/core/perf/opencl/perf_dxt.cpp index 797b2c5334..d0219913b5 100644 --- a/modules/core/perf/opencl/perf_dxt.cpp +++ b/modules/core/perf/opencl/perf_dxt.cpp @@ -54,40 +54,21 @@ namespace ocl { ///////////// dft //////////////////////// -enum OCL_FFT_TYPE -{ - R2R = 0, // real to real (CCS) - C2R = 1, // complex to real - R2C = 2, // real to complex - C2C = 3 // complex to complex -}; - -typedef tuple DftParams; +typedef tuple DftParams; typedef TestBaseWithParam DftFixture; -OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(C2C, R2R, C2R, R2C), - Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(1024, 1024), Size(512, 512), Size(2048, 2048)), - Values((int) 0, (int)DFT_ROWS, (int)DFT_SCALE/*, (int)DFT_INVERSE, - (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE*/))) +OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), + Values((int)DFT_ROWS, (int)DFT_SCALE, (int)DFT_INVERSE, + (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE))) { const DftParams params = GetParam(); - const int dft_type = get<0>(params); - const Size srcSize = get<1>(params); - int flags = get<2>(params); - - int in_cn, out_cn; - switch (dft_type) - { - case R2R: flags |= cv::DFT_REAL_OUTPUT; in_cn = 1; out_cn = 1; break; - case C2R: flags |= cv::DFT_REAL_OUTPUT; in_cn = 2; out_cn = 2; break; - case R2C: flags |= cv::DFT_COMPLEX_OUTPUT; in_cn = 1; out_cn = 2; break; - case C2C: flags |= cv::DFT_COMPLEX_OUTPUT; in_cn = 2; out_cn = 2; break; - } - - UMat src(srcSize, CV_MAKE_TYPE(CV_32F, in_cn)), dst(srcSize, CV_MAKE_TYPE(CV_32F, out_cn)); + const Size srcSize = get<0>(params); + const int flags = get<1>(params); + + UMat src(srcSize, CV_32FC2), dst(srcSize, CV_32FC2); declare.in(src, WARMUP_RNG).out(dst); - OCL_TEST_CYCLE() cv::dft(src, dst, flags); + OCL_TEST_CYCLE() cv::dft(src, dst, flags | DFT_COMPLEX_OUTPUT); SANITY_CHECK(dst, 1e-3); } diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 869409f50d..cb0b118bca 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -1781,251 +1781,11 @@ static bool ippi_DFT_R_32F(const Mat& src, Mat& dst, bool inv, int norm_flag) #endif } -#ifdef HAVE_CLAMDFFT - -namespace cv { - -#define CLAMDDFT_Assert(func) \ - { \ - clAmdFftStatus s = (func); \ - CV_Assert(s == CLFFT_SUCCESS); \ - } - -class PlanCache -{ - struct FftPlan - { - FftPlan(const Size & _dft_size, int _src_step, int _dst_step, bool _doubleFP, bool _inplace, int _flags, FftType _fftType) : - dft_size(_dft_size), src_step(_src_step), dst_step(_dst_step), - doubleFP(_doubleFP), inplace(_inplace), flags(_flags), fftType(_fftType), - context((cl_context)ocl::Context::getDefault().ptr()), plHandle(0) - { - bool dft_inverse = (flags & DFT_INVERSE) != 0; - bool dft_scale = (flags & DFT_SCALE) != 0; - bool dft_rows = (flags & DFT_ROWS) != 0; - - clAmdFftLayout inLayout = CLFFT_REAL, outLayout = CLFFT_REAL; - clAmdFftDim dim = dft_size.height == 1 || dft_rows ? CLFFT_1D : CLFFT_2D; - - size_t batchSize = dft_rows ? dft_size.height : 1; - size_t clLengthsIn[3] = { dft_size.width, dft_rows ? 1 : dft_size.height, 1 }; - size_t clStridesIn[3] = { 1, 1, 1 }; - size_t clStridesOut[3] = { 1, 1, 1 }; - int elemSize = doubleFP ? sizeof(double) : sizeof(float); - - switch (fftType) - { - case C2C: - inLayout = CLFFT_COMPLEX_INTERLEAVED; - outLayout = CLFFT_COMPLEX_INTERLEAVED; - clStridesIn[1] = src_step / (elemSize << 1); - clStridesOut[1] = dst_step / (elemSize << 1); - break; - case R2C: - inLayout = CLFFT_REAL; - outLayout = CLFFT_HERMITIAN_INTERLEAVED; - clStridesIn[1] = src_step / elemSize; - clStridesOut[1] = dst_step / (elemSize << 1); - break; - case C2R: - inLayout = CLFFT_HERMITIAN_INTERLEAVED; - outLayout = CLFFT_REAL; - clStridesIn[1] = src_step / (elemSize << 1); - clStridesOut[1] = dst_step / elemSize; - break; - case R2R: - default: - CV_Error(Error::StsNotImplemented, "AMD Fft does not support this type"); - break; - } - - clStridesIn[2] = dft_rows ? clStridesIn[1] : dft_size.width * clStridesIn[1]; - clStridesOut[2] = dft_rows ? clStridesOut[1] : dft_size.width * clStridesOut[1]; - - CLAMDDFT_Assert(clAmdFftCreateDefaultPlan(&plHandle, (cl_context)ocl::Context::getDefault().ptr(), dim, clLengthsIn)) - - // setting plan properties - CLAMDDFT_Assert(clAmdFftSetPlanPrecision(plHandle, doubleFP ? CLFFT_DOUBLE : CLFFT_SINGLE)); - CLAMDDFT_Assert(clAmdFftSetResultLocation(plHandle, inplace ? CLFFT_INPLACE : CLFFT_OUTOFPLACE)) - CLAMDDFT_Assert(clAmdFftSetLayout(plHandle, inLayout, outLayout)) - CLAMDDFT_Assert(clAmdFftSetPlanBatchSize(plHandle, batchSize)) - CLAMDDFT_Assert(clAmdFftSetPlanInStride(plHandle, dim, clStridesIn)) - CLAMDDFT_Assert(clAmdFftSetPlanOutStride(plHandle, dim, clStridesOut)) - CLAMDDFT_Assert(clAmdFftSetPlanDistance(plHandle, clStridesIn[dim], clStridesOut[dim])) - - float scale = dft_scale ? 1.0f / (dft_rows ? dft_size.width : dft_size.area()) : 1.0f; - CLAMDDFT_Assert(clAmdFftSetPlanScale(plHandle, dft_inverse ? CLFFT_BACKWARD : CLFFT_FORWARD, scale)) - - // ready to bake - cl_command_queue queue = (cl_command_queue)ocl::Queue::getDefault().ptr(); - CLAMDDFT_Assert(clAmdFftBakePlan(plHandle, 1, &queue, NULL, NULL)) - } - - ~FftPlan() - { -// clAmdFftDestroyPlan(&plHandle); - } - - friend class PlanCache; - - private: - Size dft_size; - int src_step, dst_step; - bool doubleFP; - bool inplace; - int flags; - FftType fftType; - - cl_context context; - clAmdFftPlanHandle plHandle; - }; - -public: - static PlanCache & getInstance() - { - static PlanCache planCache; - return planCache; - } - - clAmdFftPlanHandle getPlanHandle(const Size & dft_size, int src_step, int dst_step, bool doubleFP, - bool inplace, int flags, FftType fftType) - { - cl_context currentContext = (cl_context)ocl::Context::getDefault().ptr(); - - for (size_t i = 0, size = planStorage.size(); i < size; ++i) - { - const FftPlan * const plan = planStorage[i]; - - if (plan->dft_size == dft_size && - plan->flags == flags && - plan->src_step == src_step && - plan->dst_step == dst_step && - plan->doubleFP == doubleFP && - plan->fftType == fftType && - plan->inplace == inplace) - { - if (plan->context != currentContext) - { - planStorage.erase(planStorage.begin() + i); - break; - } - - return plan->plHandle; - } - } - - // no baked plan is found, so let's create a new one - FftPlan * newPlan = new FftPlan(dft_size, src_step, dst_step, doubleFP, inplace, flags, fftType); - planStorage.push_back(newPlan); - - return newPlan->plHandle; - } - - ~PlanCache() - { - for (std::vector::iterator i = planStorage.begin(), end = planStorage.end(); i != end; ++i) - delete (*i); - planStorage.clear(); - } - -protected: - PlanCache() : - planStorage() - { - } - - std::vector planStorage; -}; - -extern "C" { - -static void CL_CALLBACK oclCleanupCallback(cl_event e, cl_int, void *p) -{ - UMatData * u = (UMatData *)p; - - if( u && CV_XADD(&u->urefcount, -1) == 1 ) - u->currAllocator->deallocate(u); - u = 0; - - clReleaseEvent(e), e = 0; -} - -} - -static bool ocl_dft_amdfft(InputArray _src, OutputArray _dst, int flags) -{ - int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - Size ssize = _src.size(); - - bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - if ( (!doubleSupport && depth == CV_64F) || - !(type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2) || - _src.offset() != 0) - return false; - - // if is not a multiplication of prime numbers { 2, 3, 5 } - if (ssize.area() != getOptimalDFTSize(ssize.area())) - return false; - - int dst_complex_input = cn == 2 ? 1 : 0; - bool dft_inverse = (flags & DFT_INVERSE) != 0 ? 1 : 0; - int dft_complex_output = (flags & DFT_COMPLEX_OUTPUT) != 0; - bool dft_real_output = (flags & DFT_REAL_OUTPUT) != 0; - - CV_Assert(dft_complex_output + dft_real_output < 2); - FftType fftType = (FftType)(dst_complex_input << 0 | dft_complex_output << 1); - - switch (fftType) - { - case C2C: - _dst.create(ssize.height, ssize.width, CV_MAKE_TYPE(depth, 2)); - break; - case R2C: // TODO implement it if possible - case C2R: // TODO implement it if possible - case R2R: // AMD Fft does not support this type - default: - return false; - } - - UMat src = _src.getUMat(), dst = _dst.getUMat(); - bool inplace = src.u == dst.u; - - clAmdFftPlanHandle plHandle = PlanCache::getInstance(). - getPlanHandle(ssize, (int)src.step, (int)dst.step, - depth == CV_64F, inplace, flags, fftType); - - // get the bufferSize - size_t bufferSize = 0; - CLAMDDFT_Assert(clAmdFftGetTmpBufSize(plHandle, &bufferSize)) - UMat tmpBuffer(1, (int)bufferSize, CV_8UC1); - - cl_mem srcarg = (cl_mem)src.handle(ACCESS_READ); - cl_mem dstarg = (cl_mem)dst.handle(ACCESS_RW); - - cl_command_queue queue = (cl_command_queue)ocl::Queue::getDefault().ptr(); - cl_event e = 0; - - CLAMDDFT_Assert(clAmdFftEnqueueTransform(plHandle, dft_inverse ? CLFFT_BACKWARD : CLFFT_FORWARD, - 1, &queue, 0, NULL, &e, - &srcarg, &dstarg, (cl_mem)tmpBuffer.handle(ACCESS_RW))) - - tmpBuffer.addref(); - clSetEventCallback(e, CL_COMPLETE, oclCleanupCallback, tmpBuffer.u); - - return true; -} - -#undef DFT_ASSERT - -} - -#endif // HAVE_CLAMDFFT +#ifdef HAVE_OPENCL namespace cv { -#ifdef HAVE_OPENCL - enum FftType { R2R = 0, @@ -2038,7 +1798,7 @@ static void ocl_getRadixes(int cols, std::vector& radixes, std::vector { int factors[34]; int nf = DFTFactorize(cols, factors); - + int n = 1; int factor_index = 0; min_radix = INT_MAX; @@ -2118,7 +1878,7 @@ struct OCL_FftPlan ocl_getRadixes(dft_size, radixes, blocks, min_radix); thread_count = dft_size / min_radix; - if (thread_count > ocl::Device::getDefault().maxWorkGroupSize()) + if (thread_count > (int) ocl::Device::getDefault().maxWorkGroupSize()) { status = false; return; @@ -2141,13 +1901,13 @@ struct OCL_FftPlan Mat tw(1, twiddle_size, CV_32FC2); float* ptr = tw.ptr(); int ptr_index = 0; - + n = 1; for (size_t i=0; i 0; - if ( (!doubleSupport && depth == CV_64F) || - !(type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2)) + if ( !(type == CV_32FC1 || type == CV_32FC2) ) return false; // if is not a multiplication of prime numbers { 2, 3, 5 } @@ -2325,7 +2083,7 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro if (fftType == C2C || fftType == R2C) { // complex output - _dst.create(src.size(), CV_32FC2); + _dst.create(src.size(), CV_32FC2); output = _dst.getUMat(); } else @@ -2381,7 +2139,7 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro int nonzero_cols = src.cols/2 + 1; if (!ocl_dft_C2C_cols(src, output, nonzero_cols, flags, fftType)) return false; - + if (!ocl_dft_C2C_rows(output, _dst, nonzero_rows, flags, fftType)) return false; } @@ -2390,11 +2148,248 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro return true; } +} // namespace cv; + #endif -} // namespace cv; +#ifdef HAVE_CLAMDFFT + +namespace cv { + +#define CLAMDDFT_Assert(func) \ + { \ + clAmdFftStatus s = (func); \ + CV_Assert(s == CLFFT_SUCCESS); \ + } + +class PlanCache +{ + struct FftPlan + { + FftPlan(const Size & _dft_size, int _src_step, int _dst_step, bool _doubleFP, bool _inplace, int _flags, FftType _fftType) : + dft_size(_dft_size), src_step(_src_step), dst_step(_dst_step), + doubleFP(_doubleFP), inplace(_inplace), flags(_flags), fftType(_fftType), + context((cl_context)ocl::Context::getDefault().ptr()), plHandle(0) + { + bool dft_inverse = (flags & DFT_INVERSE) != 0; + bool dft_scale = (flags & DFT_SCALE) != 0; + bool dft_rows = (flags & DFT_ROWS) != 0; + clAmdFftLayout inLayout = CLFFT_REAL, outLayout = CLFFT_REAL; + clAmdFftDim dim = dft_size.height == 1 || dft_rows ? CLFFT_1D : CLFFT_2D; + + size_t batchSize = dft_rows ? dft_size.height : 1; + size_t clLengthsIn[3] = { dft_size.width, dft_rows ? 1 : dft_size.height, 1 }; + size_t clStridesIn[3] = { 1, 1, 1 }; + size_t clStridesOut[3] = { 1, 1, 1 }; + int elemSize = doubleFP ? sizeof(double) : sizeof(float); + switch (fftType) + { + case C2C: + inLayout = CLFFT_COMPLEX_INTERLEAVED; + outLayout = CLFFT_COMPLEX_INTERLEAVED; + clStridesIn[1] = src_step / (elemSize << 1); + clStridesOut[1] = dst_step / (elemSize << 1); + break; + case R2C: + inLayout = CLFFT_REAL; + outLayout = CLFFT_HERMITIAN_INTERLEAVED; + clStridesIn[1] = src_step / elemSize; + clStridesOut[1] = dst_step / (elemSize << 1); + break; + case C2R: + inLayout = CLFFT_HERMITIAN_INTERLEAVED; + outLayout = CLFFT_REAL; + clStridesIn[1] = src_step / (elemSize << 1); + clStridesOut[1] = dst_step / elemSize; + break; + case R2R: + default: + CV_Error(Error::StsNotImplemented, "AMD Fft does not support this type"); + break; + } + + clStridesIn[2] = dft_rows ? clStridesIn[1] : dft_size.width * clStridesIn[1]; + clStridesOut[2] = dft_rows ? clStridesOut[1] : dft_size.width * clStridesOut[1]; + + CLAMDDFT_Assert(clAmdFftCreateDefaultPlan(&plHandle, (cl_context)ocl::Context::getDefault().ptr(), dim, clLengthsIn)) + + // setting plan properties + CLAMDDFT_Assert(clAmdFftSetPlanPrecision(plHandle, doubleFP ? CLFFT_DOUBLE : CLFFT_SINGLE)); + CLAMDDFT_Assert(clAmdFftSetResultLocation(plHandle, inplace ? CLFFT_INPLACE : CLFFT_OUTOFPLACE)) + CLAMDDFT_Assert(clAmdFftSetLayout(plHandle, inLayout, outLayout)) + CLAMDDFT_Assert(clAmdFftSetPlanBatchSize(plHandle, batchSize)) + CLAMDDFT_Assert(clAmdFftSetPlanInStride(plHandle, dim, clStridesIn)) + CLAMDDFT_Assert(clAmdFftSetPlanOutStride(plHandle, dim, clStridesOut)) + CLAMDDFT_Assert(clAmdFftSetPlanDistance(plHandle, clStridesIn[dim], clStridesOut[dim])) + + float scale = dft_scale ? 1.0f / (dft_rows ? dft_size.width : dft_size.area()) : 1.0f; + CLAMDDFT_Assert(clAmdFftSetPlanScale(plHandle, dft_inverse ? CLFFT_BACKWARD : CLFFT_FORWARD, scale)) + + // ready to bake + cl_command_queue queue = (cl_command_queue)ocl::Queue::getDefault().ptr(); + CLAMDDFT_Assert(clAmdFftBakePlan(plHandle, 1, &queue, NULL, NULL)) + } + + ~FftPlan() + { +// clAmdFftDestroyPlan(&plHandle); + } + + friend class PlanCache; + + private: + Size dft_size; + int src_step, dst_step; + bool doubleFP; + bool inplace; + int flags; + FftType fftType; + + cl_context context; + clAmdFftPlanHandle plHandle; + }; + +public: + static PlanCache & getInstance() + { + static PlanCache planCache; + return planCache; + } + + clAmdFftPlanHandle getPlanHandle(const Size & dft_size, int src_step, int dst_step, bool doubleFP, + bool inplace, int flags, FftType fftType) + { + cl_context currentContext = (cl_context)ocl::Context::getDefault().ptr(); + + for (size_t i = 0, size = planStorage.size(); i < size; ++i) + { + const FftPlan * const plan = planStorage[i]; + + if (plan->dft_size == dft_size && + plan->flags == flags && + plan->src_step == src_step && + plan->dst_step == dst_step && + plan->doubleFP == doubleFP && + plan->fftType == fftType && + plan->inplace == inplace) + { + if (plan->context != currentContext) + { + planStorage.erase(planStorage.begin() + i); + break; + } + + return plan->plHandle; + } + } + + // no baked plan is found, so let's create a new one + FftPlan * newPlan = new FftPlan(dft_size, src_step, dst_step, doubleFP, inplace, flags, fftType); + planStorage.push_back(newPlan); + + return newPlan->plHandle; + } + + ~PlanCache() + { + for (std::vector::iterator i = planStorage.begin(), end = planStorage.end(); i != end; ++i) + delete (*i); + planStorage.clear(); + } + +protected: + PlanCache() : + planStorage() + { + } + + std::vector planStorage; +}; + +extern "C" { + +static void CL_CALLBACK oclCleanupCallback(cl_event e, cl_int, void *p) +{ + UMatData * u = (UMatData *)p; + + if( u && CV_XADD(&u->urefcount, -1) == 1 ) + u->currAllocator->deallocate(u); + u = 0; + + clReleaseEvent(e), e = 0; +} + +} + +static bool ocl_dft_amdfft(InputArray _src, OutputArray _dst, int flags) +{ + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + Size ssize = _src.size(); + + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + if ( (!doubleSupport && depth == CV_64F) || + !(type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2) || + _src.offset() != 0) + return false; + + // if is not a multiplication of prime numbers { 2, 3, 5 } + if (ssize.area() != getOptimalDFTSize(ssize.area())) + return false; + + int dst_complex_input = cn == 2 ? 1 : 0; + bool dft_inverse = (flags & DFT_INVERSE) != 0 ? 1 : 0; + int dft_complex_output = (flags & DFT_COMPLEX_OUTPUT) != 0; + bool dft_real_output = (flags & DFT_REAL_OUTPUT) != 0; + + CV_Assert(dft_complex_output + dft_real_output < 2); + FftType fftType = (FftType)(dst_complex_input << 0 | dft_complex_output << 1); + + switch (fftType) + { + case C2C: + _dst.create(ssize.height, ssize.width, CV_MAKE_TYPE(depth, 2)); + break; + case R2C: // TODO implement it if possible + case C2R: // TODO implement it if possible + case R2R: // AMD Fft does not support this type + default: + return false; + } + + UMat src = _src.getUMat(), dst = _dst.getUMat(); + bool inplace = src.u == dst.u; + + clAmdFftPlanHandle plHandle = PlanCache::getInstance(). + getPlanHandle(ssize, (int)src.step, (int)dst.step, + depth == CV_64F, inplace, flags, fftType); + + // get the bufferSize + size_t bufferSize = 0; + CLAMDDFT_Assert(clAmdFftGetTmpBufSize(plHandle, &bufferSize)) + UMat tmpBuffer(1, (int)bufferSize, CV_8UC1); + + cl_mem srcarg = (cl_mem)src.handle(ACCESS_READ); + cl_mem dstarg = (cl_mem)dst.handle(ACCESS_RW); + + cl_command_queue queue = (cl_command_queue)ocl::Queue::getDefault().ptr(); + cl_event e = 0; + + CLAMDDFT_Assert(clAmdFftEnqueueTransform(plHandle, dft_inverse ? CLFFT_BACKWARD : CLFFT_FORWARD, + 1, &queue, 0, NULL, &e, + &srcarg, &dstarg, (cl_mem)tmpBuffer.handle(ACCESS_RW))) + + tmpBuffer.addref(); + clSetEventCallback(e, CL_COMPLETE, oclCleanupCallback, tmpBuffer.u); + return true; +} + +#undef DFT_ASSERT + +} + +#endif // HAVE_CLAMDFFT void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) { diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index a2110f6cc2..32db8c91b4 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3002,8 +3002,7 @@ bool Kernel::run(int dims, size_t _globalsize[], size_t _localsize[], sync ? 0 : &p->e); if( sync || retval != CL_SUCCESS ) { - int a = clFinish(qq); - CV_OclDbgAssert(a == CL_SUCCESS); + CV_OclDbgAssert(clFinish(qq) == CL_SUCCESS); p->cleanupUMats(); } else @@ -3899,9 +3898,8 @@ public: if( (accessFlags & ACCESS_READ) != 0 && u->hostCopyObsolete() ) { AlignedDataPtr alignedPtr(u->data, u->size, CV_OPENCL_DATA_PTR_ALIGNMENT); - int a = clEnqueueReadBuffer(q, (cl_mem)u->handle, CL_TRUE, 0, - u->size, alignedPtr.getAlignedPtr(), 0, 0, 0); - CV_Assert( a == CL_SUCCESS ); + CV_Assert( clEnqueueReadBuffer(q, (cl_mem)u->handle, CL_TRUE, 0, + u->size, alignedPtr.getAlignedPtr(), 0, 0, 0) == CL_SUCCESS ); u->markHostCopyObsolete(false); } } diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index b8d2c6716d..1cb2278c0d 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -6,36 +6,36 @@ #define fft5_5 0.363271264002f __attribute__((always_inline)) -float2 mul_float2(float2 a, float2 b) { - return (float2)(fma(a.x, b.x, -a.y * b.y), fma(a.x, b.y, a.y * b.x)); +float2 mul_float2(float2 a, float2 b) { + return (float2)(fma(a.x, b.x, -a.y * b.y), fma(a.x, b.y, a.y * b.x)); } __attribute__((always_inline)) -float2 twiddle(float2 a) { - return (float2)(a.y, -a.x); +float2 twiddle(float2 a) { + return (float2)(a.y, -a.x); } __attribute__((always_inline)) -void butterfly2(float2 a0, float2 a1, __local float2* smem, __global const float2* twiddles, - const int x, const int block_size) -{ +void butterfly2(float2 a0, float2 a1, __local float2* smem, __global const float2* twiddles, + const int x, const int block_size) +{ const int k = x & (block_size - 1); a1 = mul_float2(twiddles[k], a1); const int dst_ind = (x << 1) - k; - + smem[dst_ind] = a0 + a1; smem[dst_ind+block_size] = a0 - a1; } __attribute__((always_inline)) -void butterfly4(float2 a0, float2 a1, float2 a2, float2 a3, __local float2* smem, __global const float2* twiddles, - const int x, const int block_size) +void butterfly4(float2 a0, float2 a1, float2 a2, float2 a3, __local float2* smem, __global const float2* twiddles, + const int x, const int block_size) { const int k = x & (block_size - 1); a1 = mul_float2(twiddles[k], a1); a2 = mul_float2(twiddles[k + block_size], a2); a3 = mul_float2(twiddles[k + 2*block_size], a3); - + const int dst_ind = ((x - k) << 2) + k; float2 b0 = a0 + a2; @@ -50,9 +50,9 @@ void butterfly4(float2 a0, float2 a1, float2 a2, float2 a3, __local float2* smem } __attribute__((always_inline)) -void butterfly3(float2 a0, float2 a1, float2 a2, __local float2* smem, __global const float2* twiddles, - const int x, const int block_size) -{ +void butterfly3(float2 a0, float2 a1, float2 a2, __local float2* smem, __global const float2* twiddles, + const int x, const int block_size) +{ const int k = x % block_size; a1 = mul_float2(twiddles[k], a1); a2 = mul_float2(twiddles[k+block_size], a2); @@ -69,8 +69,8 @@ void butterfly3(float2 a0, float2 a1, float2 a2, __local float2* smem, __global __attribute__((always_inline)) void butterfly5(float2 a0, float2 a1, float2 a2, float2 a3, float2 a4, __local float2* smem, __global const float2* twiddles, - const int x, const int block_size) -{ + const int x, const int block_size) +{ const int k = x % block_size; a1 = mul_float2(twiddles[k], a1); a2 = mul_float2(twiddles[k + block_size], a2); @@ -95,7 +95,7 @@ void butterfly5(float2 a0, float2 a1, float2 a2, float2 a3, float2 a4, __local f a4 = fft5_3 * (float2)(-a1.y - a3.y, a1.x + a3.x); b5 = (float2)(a4.x - fft5_5 * a1.y, a4.y + fft5_5 * a1.x); - a4.x += fft5_4 * a3.y; + a4.x += fft5_4 * a3.y; a4.y -= fft5_4 * a3.x; a1 = b0 + b1; @@ -109,7 +109,7 @@ void butterfly5(float2 a0, float2 a1, float2 a2, float2 a3, float2 a4, __local f } __attribute__((always_inline)) -void fft_radix2(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) +void fft_radix2(__local float2* smem, __global const float2* twiddles, const int x, const int block_size, const int t) { float2 a0, a1; @@ -122,13 +122,13 @@ void fft_radix2(__local float2* smem, __global const float2* twiddles, const int barrier(CLK_LOCAL_MEM_FENCE); if (x < t) - butterfly2(a0, a1, smem, twiddles, x, block_size); + butterfly2(a0, a1, smem, twiddles, x, block_size); barrier(CLK_LOCAL_MEM_FENCE); } __attribute__((always_inline)) -void fft_radix2_B2(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix2_B2(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int x2 = x1 + t/2; float2 a0, a1, a2, a3; @@ -151,7 +151,7 @@ void fft_radix2_B2(__local float2* smem, __global const float2* twiddles, const } __attribute__((always_inline)) -void fft_radix2_B3(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix2_B3(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int x2 = x1 + t/3; const int x3 = x1 + 2*t/3; @@ -177,7 +177,7 @@ void fft_radix2_B3(__local float2* smem, __global const float2* twiddles, const } __attribute__((always_inline)) -void fft_radix2_B4(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix2_B4(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int thread_block = t/4; const int x2 = x1 + thread_block; @@ -207,7 +207,7 @@ void fft_radix2_B4(__local float2* smem, __global const float2* twiddles, const } __attribute__((always_inline)) -void fft_radix2_B5(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) +void fft_radix2_B5(__local float2* smem, __global const float2* twiddles, const int x1, const int block_size, const int t) { const int thread_block = t/5; const int x2 = x1 + thread_block; @@ -326,7 +326,7 @@ void fft_radix8(__local float2* smem, __global const float2* twiddles, const int a7 = mul_float2(twiddles[k+6*block_size],smem[x+7*t]); float2 b0, b1, b6, b7; - + b0 = a0 + a4; a4 = a0 - a4; b1 = a1 + a5; @@ -335,7 +335,7 @@ void fft_radix8(__local float2* smem, __global const float2* twiddles, const int b6 = twiddle(a2 - a6); a2 = a2 + a6; b7 = a3 - a7; - b7 = (float2)(SQRT_2) * (float2)(-b7.x + b7.y, -b7.x - b7.y); + b7 = (float2)(SQRT_2) * (float2)(-b7.x + b7.y, -b7.x - b7.y); a3 = a3 + a7; a0 = b0 + a2; @@ -571,10 +571,15 @@ __kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, } else { + // fill with zero other rows +#ifdef COMPLEX_OUTPUT __global float2* dst = (__global float2*)(dst_ptr + mad24(y, dst_step, dst_offset)); +#else + __global float* dst = (__global float*)(dst_ptr + mad24(y, dst_step, dst_offset)); +#endif #pragma unroll for (int i=x; i(df) << std::endl; + OCL_OFF(cv::dft(src, dst, dft_flags | cv::DFT_COMPLEX_OUTPUT)); + OCL_ON(cv::dft(usrc, udst, dft_flags | cv::DFT_COMPLEX_OUTPUT)); double eps = src.size().area() * 1e-4; EXPECT_MAT_NEAR(dst, udst, eps); @@ -185,15 +150,15 @@ OCL_TEST_P(MulSpectrums, Mat) OCL_INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MulSpectrums, testing::Combine(Bool(), Bool())); -OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(10, 10), cv::Size(36, 36), cv::Size(512, 1), cv::Size(1280, 768)), - Values((OCL_FFT_TYPE) R2C, (OCL_FFT_TYPE) C2C, (OCL_FFT_TYPE) R2R, (OCL_FFT_TYPE) C2R), - Bool(), // DFT_INVERSE +OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(2, 3), cv::Size(5, 4), cv::Size(25, 20), + cv::Size(512, 1), cv::Size(1024, 768)), + Values(CV_32F, CV_64F), + Bool(), // inplace Bool(), // DFT_ROWS Bool(), // DFT_SCALE - Bool() // hint - ) + Bool()) // DFT_INVERSE ); } } // namespace cvtest::ocl -#endif // HAVE_OPENCL \ No newline at end of file +#endif // HAVE_OPENCL From e51c0810b6bd6e5cdd934d172feb8b983bf7a407 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Thu, 24 Jul 2014 13:11:58 +0400 Subject: [PATCH 110/136] Added accuracy and performance tests for DFT all modes. --- modules/core/perf/opencl/perf_dxt.cpp | 39 +++++++++++----- modules/core/test/ocl/test_dft.cpp | 65 ++++++++++++++++++--------- 2 files changed, 74 insertions(+), 30 deletions(-) diff --git a/modules/core/perf/opencl/perf_dxt.cpp b/modules/core/perf/opencl/perf_dxt.cpp index d0219913b5..c0e41485e4 100644 --- a/modules/core/perf/opencl/perf_dxt.cpp +++ b/modules/core/perf/opencl/perf_dxt.cpp @@ -54,23 +54,42 @@ namespace ocl { ///////////// dft //////////////////////// -typedef tuple DftParams; +enum OCL_FFT_TYPE +{ + R2R = 0, + C2R = 1, + R2C = 2, + C2C = 3 +}; + +typedef tuple DftParams; typedef TestBaseWithParam DftFixture; -OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), - Values((int)DFT_ROWS, (int)DFT_SCALE, (int)DFT_INVERSE, - (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE))) +OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(C2C, R2R, C2R, R2C), + Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(512, 512), Size(1024, 1024), Size(2048, 2048)), + Values((int) 0, (int)DFT_ROWS, (int)DFT_SCALE, (int)DFT_INVERSE, + (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE))) { const DftParams params = GetParam(); - const Size srcSize = get<0>(params); - const int flags = get<1>(params); - - UMat src(srcSize, CV_32FC2), dst(srcSize, CV_32FC2); + const int dft_type = get<0>(params); + const Size srcSize = get<1>(params); + int flags = get<2>(params); + + int in_cn, out_cn; + switch (dft_type) + { + case R2R: flags |= cv::DFT_REAL_OUTPUT; in_cn = 1; out_cn = 1; break; + case C2R: flags |= cv::DFT_REAL_OUTPUT; in_cn = 2; out_cn = 2; break; + case R2C: flags |= cv::DFT_COMPLEX_OUTPUT; in_cn = 1; out_cn = 2; break; + case C2C: flags |= cv::DFT_COMPLEX_OUTPUT; in_cn = 2; out_cn = 2; break; + } + + UMat src(srcSize, CV_MAKE_TYPE(CV_32F, in_cn)), dst(srcSize, CV_MAKE_TYPE(CV_32F, out_cn)); declare.in(src, WARMUP_RNG).out(dst); - OCL_TEST_CYCLE() cv::dft(src, dst, flags | DFT_COMPLEX_OUTPUT); + OCL_TEST_CYCLE() cv::dft(src, dst, flags); - SANITY_CHECK(dst, 1e-3); + SANITY_CHECK(dst, 1e-5, ERROR_RELATIVE); } ///////////// MulSpectrums //////////////////////// diff --git a/modules/core/test/ocl/test_dft.cpp b/modules/core/test/ocl/test_dft.cpp index 1f0e43b20e..cd0c1f07d0 100644 --- a/modules/core/test/ocl/test_dft.cpp +++ b/modules/core/test/ocl/test_dft.cpp @@ -48,17 +48,26 @@ #ifdef HAVE_OPENCL +enum OCL_FFT_TYPE +{ + R2R = 0, + C2R = 1, + R2C = 2, + C2C = 3 +}; + namespace cvtest { namespace ocl { //////////////////////////////////////////////////////////////////////////// // Dft -PARAM_TEST_CASE(Dft, cv::Size, MatDepth, bool, bool, bool, bool) +PARAM_TEST_CASE(Dft, cv::Size, OCL_FFT_TYPE, bool, bool, bool, bool) { cv::Size dft_size; - int dft_flags, depth; - bool inplace; + int dft_flags, depth, cn, dft_type; + bool hint; + bool is1d; TEST_DECLARE_INPUT_PARAMETER(src); TEST_DECLARE_OUTPUT_PARAMETER(dst); @@ -66,34 +75,50 @@ PARAM_TEST_CASE(Dft, cv::Size, MatDepth, bool, bool, bool, bool) virtual void SetUp() { dft_size = GET_PARAM(0); - depth = GET_PARAM(1); - inplace = GET_PARAM(2); + dft_type = GET_PARAM(1); + depth = CV_32F; dft_flags = 0; + switch (dft_type) + { + case R2R: dft_flags |= cv::DFT_REAL_OUTPUT; cn = 1; break; + case C2R: dft_flags |= cv::DFT_REAL_OUTPUT; cn = 2; break; + case R2C: dft_flags |= cv::DFT_COMPLEX_OUTPUT; cn = 1; break; + case C2C: dft_flags |= cv::DFT_COMPLEX_OUTPUT; cn = 2; break; + } + + if (GET_PARAM(2)) + dft_flags |= cv::DFT_INVERSE; if (GET_PARAM(3)) dft_flags |= cv::DFT_ROWS; if (GET_PARAM(4)) dft_flags |= cv::DFT_SCALE; - if (GET_PARAM(5)) - dft_flags |= cv::DFT_INVERSE; + hint = GET_PARAM(5); + is1d = (dft_flags & DFT_ROWS) != 0 || dft_size.height == 1; } - void generateTestData(int cn = 2) + void generateTestData() { src = randomMat(dft_size, CV_MAKE_TYPE(depth, cn), 0.0, 100.0); usrc = src.getUMat(ACCESS_READ); - - if (inplace) - dst = src, udst = usrc; } }; -OCL_TEST_P(Dft, C2C) +OCL_TEST_P(Dft, Mat) { generateTestData(); - OCL_OFF(cv::dft(src, dst, dft_flags | cv::DFT_COMPLEX_OUTPUT)); - OCL_ON(cv::dft(usrc, udst, dft_flags | cv::DFT_COMPLEX_OUTPUT)); + int nonzero_rows = hint ? src.cols - randomInt(1, src.rows-1) : 0; + OCL_OFF(cv::dft(src, dst, dft_flags, nonzero_rows)); + OCL_ON(cv::dft(usrc, udst, dft_flags, nonzero_rows)); + + // In case forward R2C 1d tranform dst contains only half of output + // without complex conjugate + if (dft_type == R2C && is1d && (dft_flags & cv::DFT_INVERSE) == 0) + { + dst = dst(cv::Range(0, dst.rows), cv::Range(0, dst.cols/2 + 1)); + udst = udst(cv::Range(0, udst.rows), cv::Range(0, udst.cols/2 + 1)); + } double eps = src.size().area() * 1e-4; EXPECT_MAT_NEAR(dst, udst, eps); @@ -150,15 +175,15 @@ OCL_TEST_P(MulSpectrums, Mat) OCL_INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MulSpectrums, testing::Combine(Bool(), Bool())); -OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(2, 3), cv::Size(5, 4), cv::Size(25, 20), - cv::Size(512, 1), cv::Size(1024, 768)), - Values(CV_32F, CV_64F), - Bool(), // inplace +OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(10, 10), cv::Size(36, 36), cv::Size(512, 1), cv::Size(1280, 768)), + Values((OCL_FFT_TYPE) R2C, (OCL_FFT_TYPE) C2C, (OCL_FFT_TYPE) R2R, (OCL_FFT_TYPE) C2R), + Bool(), // DFT_INVERSE Bool(), // DFT_ROWS Bool(), // DFT_SCALE - Bool()) // DFT_INVERSE + Bool() // hint + ) ); } } // namespace cvtest::ocl -#endif // HAVE_OPENCL +#endif // HAVE_OPENCL \ No newline at end of file From a98ce86ca32eef38037c9efa17c25ee9b0afa9fa Mon Sep 17 00:00:00 2001 From: Adrian Stratulat Date: Wed, 2 Oct 2013 19:23:42 +0000 Subject: [PATCH 111/136] Add NEON intrinsics to core/src/arithm.cpp --- modules/core/src/arithm.cpp | 109 ++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index b98bf830e4..29501a0715 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -54,21 +54,23 @@ namespace cv struct NOP {}; -#if CV_SSE2 +#if CV_SSE2 || CV_NEON #define FUNCTOR_TEMPLATE(name) \ template struct name {} FUNCTOR_TEMPLATE(VLoadStore128); +#if CV_SSE2 FUNCTOR_TEMPLATE(VLoadStore64); FUNCTOR_TEMPLATE(VLoadStore128Aligned); +#endif #endif template void vBinOp(const T* src1, size_t step1, const T* src2, size_t step2, T* dst, size_t step, Size sz) { -#if CV_SSE2 +#if CV_SSE2 || CV_NEON VOp vop; #endif Op op; @@ -79,9 +81,11 @@ void vBinOp(const T* src1, size_t step1, const T* src2, size_t step2, T* dst, si { int x = 0; +#if CV_NEON || CV_SSE2 #if CV_SSE2 if( USE_SSE2 ) { +#endif for( ; x <= sz.width - 32/(int)sizeof(T); x += 32/sizeof(T) ) { typename VLoadStore128::reg_type r0 = VLoadStore128::load(src1 + x ); @@ -91,8 +95,10 @@ void vBinOp(const T* src1, size_t step1, const T* src2, size_t step2, T* dst, si VLoadStore128::store(dst + x , r0); VLoadStore128::store(dst + x + 16/sizeof(T), r1); } +#if CV_SSE2 } #endif +#endif #if CV_SSE2 if( USE_SSE2 ) { @@ -125,7 +131,7 @@ template void vBinOp32(const T* src1, size_t step1, const T* src2, size_t step2, T* dst, size_t step, Size sz) { -#if CV_SSE2 +#if CV_SSE2 || CV_NEON Op32 op32; #endif Op op; @@ -153,9 +159,11 @@ void vBinOp32(const T* src1, size_t step1, const T* src2, size_t step2, } } #endif +#if CV_NEON || CV_SSE2 #if CV_SSE2 if( USE_SSE2 ) { +#endif for( ; x <= sz.width - 8; x += 8 ) { typename VLoadStore128::reg_type r0 = VLoadStore128::load(src1 + x ); @@ -165,8 +173,10 @@ void vBinOp32(const T* src1, size_t step1, const T* src2, size_t step2, VLoadStore128::store(dst + x , r0); VLoadStore128::store(dst + x + 4, r1); } +#if CV_SSE2 } #endif +#endif #if CV_ENABLE_UNROLLED for( ; x <= sz.width - 4; x += 4 ) { @@ -383,7 +393,98 @@ FUNCTOR_TEMPLATE(VNot); FUNCTOR_CLOSURE_1arg(VNot, uchar, return _mm_xor_si128(_mm_set1_epi32(-1), a)); #endif -#if CV_SSE2 +#if CV_NEON + +#define FUNCTOR_LOADSTORE(name, template_arg, register_type, load_body, store_body)\ + template <> \ + struct name{ \ + typedef register_type reg_type; \ + static reg_type load(const template_arg * p) { return load_body (p);}; \ + static void store(template_arg * p, reg_type v) { store_body (p, v);}; \ + } + +#define FUNCTOR_CLOSURE_2arg(name, template_arg, body)\ + template<> \ + struct name \ + { \ + VLoadStore128::reg_type operator()( \ + VLoadStore128::reg_type a, \ + VLoadStore128::reg_type b) const \ + { \ + return body; \ + }; \ + } + +#define FUNCTOR_CLOSURE_1arg(name, template_arg, body)\ + template<> \ + struct name \ + { \ + VLoadStore128::reg_type operator()( \ + VLoadStore128::reg_type a, \ + VLoadStore128::reg_type ) const \ + { \ + return body; \ + }; \ + } + +FUNCTOR_LOADSTORE(VLoadStore128, uchar, uint8x16_t, vld1q_u8 , vst1q_u8 ); +FUNCTOR_LOADSTORE(VLoadStore128, schar, int8x16_t, vld1q_s8 , vst1q_s8 ); +FUNCTOR_LOADSTORE(VLoadStore128, ushort, uint16x8_t, vld1q_u16, vst1q_u16); +FUNCTOR_LOADSTORE(VLoadStore128, short, int16x8_t, vld1q_s16, vst1q_s16); +FUNCTOR_LOADSTORE(VLoadStore128, int, int32x4_t, vld1q_s32, vst1q_s32); +FUNCTOR_LOADSTORE(VLoadStore128, float, float32x4_t, vld1q_f32, vst1q_f32); + +FUNCTOR_TEMPLATE(VAdd); +FUNCTOR_CLOSURE_2arg(VAdd, uchar, vqaddq_u8 (a, b)); +FUNCTOR_CLOSURE_2arg(VAdd, schar, vqaddq_s8 (a, b)); +FUNCTOR_CLOSURE_2arg(VAdd, ushort, vqaddq_u16(a, b)); +FUNCTOR_CLOSURE_2arg(VAdd, short, vqaddq_s16(a, b)); +FUNCTOR_CLOSURE_2arg(VAdd, int, vaddq_s32 (a, b)); +FUNCTOR_CLOSURE_2arg(VAdd, float, vaddq_f32 (a, b)); + +FUNCTOR_TEMPLATE(VSub); +FUNCTOR_CLOSURE_2arg(VSub, uchar, vqsubq_u8 (a, b)); +FUNCTOR_CLOSURE_2arg(VSub, schar, vqsubq_s8 (a, b)); +FUNCTOR_CLOSURE_2arg(VSub, ushort, vqsubq_u16(a, b)); +FUNCTOR_CLOSURE_2arg(VSub, short, vqsubq_s16(a, b)); +FUNCTOR_CLOSURE_2arg(VSub, int, vsubq_s32 (a, b)); +FUNCTOR_CLOSURE_2arg(VSub, float, vsubq_f32 (a, b)); + +FUNCTOR_TEMPLATE(VMin); +FUNCTOR_CLOSURE_2arg(VMin, uchar, vminq_u8 (a, b)); +FUNCTOR_CLOSURE_2arg(VMin, schar, vminq_s8 (a, b)); +FUNCTOR_CLOSURE_2arg(VMin, ushort, vminq_u16(a, b)); +FUNCTOR_CLOSURE_2arg(VMin, short, vminq_s16(a, b)); +FUNCTOR_CLOSURE_2arg(VMin, int, vminq_s32(a, b)); +FUNCTOR_CLOSURE_2arg(VMin, float, vminq_f32(a, b)); + +FUNCTOR_TEMPLATE(VMax); +FUNCTOR_CLOSURE_2arg(VMax, uchar, vmaxq_u8 (a, b)); +FUNCTOR_CLOSURE_2arg(VMax, schar, vmaxq_s8 (a, b)); +FUNCTOR_CLOSURE_2arg(VMax, ushort, vmaxq_u16(a, b)); +FUNCTOR_CLOSURE_2arg(VMax, short, vmaxq_s16(a, b)); +FUNCTOR_CLOSURE_2arg(VMax, int, vmaxq_s32(a, b)); +FUNCTOR_CLOSURE_2arg(VMax, float, vmaxq_f32(a, b)); + +FUNCTOR_TEMPLATE(VAbsDiff); +FUNCTOR_CLOSURE_2arg(VAbsDiff, uchar, vabdq_u8 (a, b)); +FUNCTOR_CLOSURE_2arg(VAbsDiff, schar, vqabsq_s8 (vqsubq_s8(a, b))); +FUNCTOR_CLOSURE_2arg(VAbsDiff, ushort, vabdq_u16 (a, b)); +FUNCTOR_CLOSURE_2arg(VAbsDiff, short, vqabsq_s16(vqsubq_s16(a, b))); +FUNCTOR_CLOSURE_2arg(VAbsDiff, int, vabdq_s32 (a, b)); +FUNCTOR_CLOSURE_2arg(VAbsDiff, float, vabdq_f32 (a, b)); + +FUNCTOR_TEMPLATE(VAnd); +FUNCTOR_CLOSURE_2arg(VAnd, uchar, vandq_u8(a, b)); +FUNCTOR_TEMPLATE(VOr); +FUNCTOR_CLOSURE_2arg(VOr , uchar, vorrq_u8(a, b)); +FUNCTOR_TEMPLATE(VXor); +FUNCTOR_CLOSURE_2arg(VXor, uchar, veorq_u8(a, b)); +FUNCTOR_TEMPLATE(VNot); +FUNCTOR_CLOSURE_1arg(VNot, uchar, vmvnq_u8(a )); +#endif + +#if CV_SSE2 || CV_NEON #define IF_SIMD(op) op #else #define IF_SIMD(op) NOP From 37d01e2d27b6ed6eac7f9f179796a7574d43ae71 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Fri, 25 Jul 2014 13:11:35 +0400 Subject: [PATCH 112/136] Added license header, using cv::Ptr, small fixes. --- modules/core/include/opencv2/core/cvdef.h | 2 +- modules/core/src/dxt.cpp | 195 +++++++++++----------- modules/core/src/opencl/fft.cl | 47 +++--- 3 files changed, 125 insertions(+), 119 deletions(-) diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 765c54cbe1..1f64cd2ace 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -244,7 +244,7 @@ typedef signed char schar; /* fundamental constants */ #define CV_PI 3.1415926535897932384626433832795 -#define CV_TWO_PI 6.283185307179586476925286766559 +#define CV_2PI 6.283185307179586476925286766559 #define CV_LOG2 0.69314718055994530941723212145818 /****************************************************************************************\ diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index cb0b118bca..b57e4e8cc0 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -1788,89 +1788,23 @@ namespace cv enum FftType { - R2R = 0, - C2R = 1, - R2C = 2, - C2C = 3 + R2R = 0, // real to CCS in case forward transform, CCS to real otherwise + C2R = 1, // complex to real in case inverse transform + R2C = 2, // real to complex in case forward transform + C2C = 3 // complex to complex }; -static void ocl_getRadixes(int cols, std::vector& radixes, std::vector& blocks, int& min_radix) -{ - int factors[34]; - int nf = DFTFactorize(cols, factors); - - int n = 1; - int factor_index = 0; - min_radix = INT_MAX; - - // 2^n transforms - if ((factors[factor_index] & 1) == 0) - { - for( ; n < factors[factor_index];) - { - int radix = 2, block = 1; - if (8*n <= factors[0]) - radix = 8; - else if (4*n <= factors[0]) - { - radix = 4; - if (cols % 12 == 0) - block = 3; - else if (cols % 8 == 0) - block = 2; - } - else - { - if (cols % 10 == 0) - block = 5; - else if (cols % 8 == 0) - block = 4; - else if (cols % 6 == 0) - block = 3; - else if (cols % 4 == 0) - block = 2; - } - - radixes.push_back(radix); - blocks.push_back(block); - min_radix = min(min_radix, block*radix); - n *= radix; - } - factor_index++; - } - - // all the other transforms - for( ; factor_index < nf; factor_index++) - { - int radix = factors[factor_index], block = 1; - if (radix == 3) - { - if (cols % 12 == 0) - block = 4; - else if (cols % 9 == 0) - block = 3; - else if (cols % 6 == 0) - block = 2; - } - else if (radix == 5) - { - if (cols % 10 == 0) - block = 2; - } - radixes.push_back(radix); - blocks.push_back(block); - min_radix = min(min_radix, block*radix); - } -} - struct OCL_FftPlan { +private: UMat twiddles; String buildOptions; int thread_count; + bool status; +public: int dft_size; - bool status; + OCL_FftPlan(int _size): dft_size(_size), status(true) { int min_radix; @@ -1910,7 +1844,7 @@ struct OCL_FftPlan for (int j=1; j& radixes, std::vector& blocks, int& min_radix) + { + int factors[34]; + int nf = DFTFactorize(cols, factors); + + int n = 1; + int factor_index = 0; + min_radix = INT_MAX; + + // 2^n transforms + if ((factors[factor_index] & 1) == 0) + { + for( ; n < factors[factor_index];) + { + int radix = 2, block = 1; + if (8*n <= factors[0]) + radix = 8; + else if (4*n <= factors[0]) + { + radix = 4; + if (cols % 12 == 0) + block = 3; + else if (cols % 8 == 0) + block = 2; + } + else + { + if (cols % 10 == 0) + block = 5; + else if (cols % 8 == 0) + block = 4; + else if (cols % 6 == 0) + block = 3; + else if (cols % 4 == 0) + block = 2; + } + + radixes.push_back(radix); + blocks.push_back(block); + min_radix = min(min_radix, block*radix); + n *= radix; + } + factor_index++; + } + + // all the other transforms + for( ; factor_index < nf; factor_index++) + { + int radix = factors[factor_index], block = 1; + if (radix == 3) + { + if (cols % 12 == 0) + block = 4; + else if (cols % 9 == 0) + block = 3; + else if (cols % 6 == 0) + block = 2; + } + else if (radix == 5) + { + if (cols % 10 == 0) + block = 2; + } + radixes.push_back(radix); + blocks.push_back(block); + min_radix = min(min_radix, block*radix); + } + } }; class OCL_FftPlanCache @@ -1993,27 +1997,24 @@ public: return planCache; } - OCL_FftPlan* getFftPlan(int dft_size) + Ptr getFftPlan(int dft_size) { for (size_t i = 0, size = planStorage.size(); i < size; ++i) { - OCL_FftPlan * const plan = planStorage[i]; - + Ptr plan = planStorage[i]; if (plan->dft_size == dft_size) { return plan; } } - OCL_FftPlan * newPlan = new OCL_FftPlan(dft_size); + Ptr newPlan = Ptr(new OCL_FftPlan(dft_size)); planStorage.push_back(newPlan); return newPlan; } ~OCL_FftPlanCache() { - for (std::vector::iterator i = planStorage.begin(), end = planStorage.end(); i != end; ++i) - delete (*i); planStorage.clear(); } @@ -2023,18 +2024,18 @@ protected: { } - std::vector planStorage; + std::vector > planStorage; }; -static bool ocl_dft_C2C_rows(InputArray _src, OutputArray _dst, int nonzero_rows, int flags, int fftType) +static bool ocl_dft_rows(InputArray _src, OutputArray _dst, int nonzero_rows, int flags, int fftType) { - const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.cols()); + Ptr plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.cols()); return plan->enqueueTransform(_src, _dst, nonzero_rows, flags, fftType, true); } -static bool ocl_dft_C2C_cols(InputArray _src, OutputArray _dst, int nonzero_cols, int flags, int fftType) +static bool ocl_dft_cols(InputArray _src, OutputArray _dst, int nonzero_cols, int flags, int fftType) { - const OCL_FftPlan* plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.rows()); + Ptr plan = OCL_FftPlanCache::getInstance().getFftPlan(_src.rows()); return plan->enqueueTransform(_src, _dst, nonzero_cols, flags, fftType, false); } @@ -2103,13 +2104,13 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro if (!inv) { - if (!ocl_dft_C2C_rows(src, output, nonzero_rows, flags, fftType)) + if (!ocl_dft_rows(src, output, nonzero_rows, flags, fftType)) return false; if (!is1d) { int nonzero_cols = fftType == R2R ? output.cols/2 + 1 : output.cols; - if (!ocl_dft_C2C_cols(output, _dst, nonzero_cols, flags, fftType)) + if (!ocl_dft_cols(output, _dst, nonzero_cols, flags, fftType)) return false; } } @@ -2118,12 +2119,12 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro if (fftType == C2C) { // complex output - if (!ocl_dft_C2C_rows(src, output, nonzero_rows, flags, fftType)) + if (!ocl_dft_rows(src, output, nonzero_rows, flags, fftType)) return false; if (!is1d) { - if (!ocl_dft_C2C_cols(output, output, output.cols, flags, fftType)) + if (!ocl_dft_cols(output, output, output.cols, flags, fftType)) return false; } } @@ -2131,16 +2132,16 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro { if (is1d) { - if (!ocl_dft_C2C_rows(src, output, nonzero_rows, flags, fftType)) + if (!ocl_dft_rows(src, output, nonzero_rows, flags, fftType)) return false; } else { int nonzero_cols = src.cols/2 + 1; - if (!ocl_dft_C2C_cols(src, output, nonzero_cols, flags, fftType)) + if (!ocl_dft_cols(src, output, nonzero_cols, flags, fftType)) return false; - if (!ocl_dft_C2C_rows(output, _dst, nonzero_rows, flags, fftType)) + if (!ocl_dft_rows(output, _dst, nonzero_rows, flags, fftType)) return false; } } @@ -2286,7 +2287,7 @@ public: } // no baked plan is found, so let's create a new one - FftPlan * newPlan = new FftPlan(dft_size, src_step, dst_step, doubleFP, inplace, flags, fftType); + Ptr newPlan = Ptr(new FftPlan(dft_size, src_step, dst_step, doubleFP, inplace, flags, fftType)); planStorage.push_back(newPlan); return newPlan->plHandle; @@ -2294,8 +2295,6 @@ public: ~PlanCache() { - for (std::vector::iterator i = planStorage.begin(), end = planStorage.end(); i != end; ++i) - delete (*i); planStorage.clear(); } @@ -2305,7 +2304,7 @@ protected: { } - std::vector planStorage; + std::vector > planStorage; }; extern "C" { diff --git a/modules/core/src/opencl/fft.cl b/modules/core/src/opencl/fft.cl index 1cb2278c0d..1268c4d6e4 100644 --- a/modules/core/src/opencl/fft.cl +++ b/modules/core/src/opencl/fft.cl @@ -1,3 +1,10 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// Copyright (C) 2014, Itseez, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. + #define SQRT_2 0.707106781188f #define sin_120 0.866025403784f #define fft5_2 0.559016994374f @@ -509,9 +516,9 @@ void fft_radix5_B2(__local float2* smem, __global const float2* twiddles, const } #ifdef DFT_SCALE -#define VAL(x, scale) x*scale +#define SCALE_VAL(x, scale) x*scale #else -#define VAL(x, scale) x +#define SCALE_VAL(x, scale) x #endif __kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, int src_offset, int src_rows, int src_cols, @@ -558,15 +565,15 @@ __kernel void fft_multi_radix_rows(__global const uchar* src_ptr, int src_step, __global float2* dst = (__global float2*)(dst_ptr + mad24(y, dst_step, dst_offset)); #pragma unroll for (int i=x; i Date: Fri, 25 Jul 2014 14:51:30 +0400 Subject: [PATCH 113/136] Fixed bug in reduce.cl --- modules/core/src/opencl/reduce.cl | 2 +- modules/core/src/stat.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/core/src/opencl/reduce.cl b/modules/core/src/opencl/reduce.cl index f16a742e54..c89f1cf005 100644 --- a/modules/core/src/opencl/reduce.cl +++ b/modules/core/src/opencl/reduce.cl @@ -379,7 +379,7 @@ #define REDUCE_GLOBAL \ dstTK temp = convertToDT(loadpix(srcptr + src_index)); \ dstTK temp2 = convertToDT(loadpix(src2ptr + src2_index)); \ - temp = SUM_ABS2(temp, temp2)); \ + temp = SUM_ABS2(temp, temp2); \ FUNC(accumulator, temp.s0); \ FUNC(accumulator, temp.s1); \ FUNC(accumulator, temp.s2); \ diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 48d85900d9..60c8dc89bb 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -482,6 +482,7 @@ static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask kercn = cn == 1 && !haveMask ? ocl::predictOptimalVectorWidth(_src) : 1, mcn = std::max(cn, kercn); CV_Assert(!haveSrc2 || _src2.type() == type); + int convert_cn = haveSrc2 ? mcn : cn; if ( (!doubleSupport && depth == CV_64F) || cn > 4 ) return false; @@ -513,7 +514,7 @@ static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask haveMask && _mask.isContinuous() ? " -D HAVE_MASK_CONT" : "", kercn, haveSrc2 ? " -D HAVE_SRC2" : "", calc2 ? " -D OP_CALC2" : "", haveSrc2 && _src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "", - depth <= CV_32S && ddepth == CV_32S ? ocl::convertTypeStr(CV_8U, ddepth, mcn, cvt[1]) : "noconvert"); + depth <= CV_32S && ddepth == CV_32S ? ocl::convertTypeStr(CV_8U, ddepth, convert_cn, cvt[1]) : "noconvert"); ocl::Kernel k("reduce", ocl::core::reduce_oclsrc, opts); if (k.empty()) From d25770ee76ddfb82b15998d39604fa34324b3482 Mon Sep 17 00:00:00 2001 From: Sander Mathijs van Veen Date: Sat, 26 Jul 2014 16:40:09 +0200 Subject: [PATCH 114/136] Fix Python 2 bindings for findContours The sanity check prevents Python 2 from calling findContours, because the Python 2 bindings pass an empty matrix for `_contours`. If `_contours` is not empty, the channel and depth check should determine whether the matrix is of the correct type and size. Note: the Python 2 bindings passes a matrix of type `STD_VECTOR_MAT` to parameters of the type `OutputArrayOfArrays`. --- modules/imgproc/src/contours.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/contours.cpp b/modules/imgproc/src/contours.cpp index 5ea4a07c61..ee7f21ac88 100644 --- a/modules/imgproc/src/contours.cpp +++ b/modules/imgproc/src/contours.cpp @@ -1704,8 +1704,10 @@ void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours, OutputArray _hierarchy, int mode, int method, Point offset ) { // Sanity check: output must be of type vector> - CV_Assert( _contours.kind() == _InputArray::STD_VECTOR_VECTOR && - _contours.channels() == 2 && _contours.depth() == CV_32S ); + CV_Assert((_contours.kind() == _InputArray::STD_VECTOR_VECTOR || _contours.kind() == _InputArray::STD_VECTOR_MAT || + _contours.kind() == _InputArray::STD_VECTOR_UMAT)); + + CV_Assert(_contours.empty() || (_contours.channels() == 2 && _contours.depth() == CV_32S)); Mat image = _image.getMat(); MemStorage storage(cvCreateMemStorage()); From 1d1bfd3d7d305339342bf2b0c752c18aae9694d8 Mon Sep 17 00:00:00 2001 From: Alexander Mordvintsev Date: Tue, 22 Jul 2014 12:36:36 +0400 Subject: [PATCH 115/136] automatic search for headers for python wrapper generation --- modules/python/CMakeLists.txt | 41 +++++++++++++++-------------------- modules/python/src2/gen2.py | 4 +++- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index af062cebc7..4eaa885254 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -19,31 +19,24 @@ ocv_module_include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/src2" ) -set(opencv_hdrs - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/base.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/types.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/persistence.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/utility.hpp" - "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/ocl.hpp" - "${OPENCV_MODULE_opencv_flann_LOCATION}/include/opencv2/flann/miniflann.hpp" - "${OPENCV_MODULE_opencv_imgproc_LOCATION}/include/opencv2/imgproc.hpp" - "${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/background_segm.hpp" - "${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/tracking.hpp" - "${OPENCV_MODULE_opencv_photo_LOCATION}/include/opencv2/photo.hpp" - "${OPENCV_MODULE_opencv_imgcodecs_LOCATION}/include/opencv2/imgcodecs.hpp" - "${OPENCV_MODULE_opencv_videoio_LOCATION}/include/opencv2/videoio.hpp" - "${OPENCV_MODULE_opencv_highgui_LOCATION}/include/opencv2/highgui.hpp" - "${OPENCV_MODULE_opencv_ml_LOCATION}/include/opencv2/ml.hpp" - "${OPENCV_MODULE_opencv_features2d_LOCATION}/include/opencv2/features2d.hpp" - "${OPENCV_MODULE_opencv_calib3d_LOCATION}/include/opencv2/calib3d.hpp" - "${OPENCV_MODULE_opencv_objdetect_LOCATION}/include/opencv2/objdetect.hpp" - ) -if(HAVE_opencv_nonfree) - list(APPEND opencv_hdrs "${OPENCV_MODULE_opencv_nonfree_LOCATION}/include/opencv2/nonfree/features2d.hpp" - "${OPENCV_MODULE_opencv_nonfree_LOCATION}/include/opencv2/nonfree.hpp") -endif() +set(opencv_hdrs_raw) +foreach(mod_name IN LISTS OPENCV_MODULE_opencv_python_DEPS) + list(APPEND opencv_hdrs_raw "${OPENCV_MODULE_${mod_name}_HEADERS}") +endforeach(mod_name) + +# remove problematic headers +set(opencv_hdrs) +foreach(hdr IN LISTS opencv_hdrs_raw) + if(NOT ${hdr} MATCHES ".h$") + if(NOT ${hdr} MATCHES "opencv2/core/cuda") + if(NOT ${hdr} MATCHES "opencv2/objdetect/detection_based_tracker.hpp") + list(APPEND opencv_hdrs ${hdr}) + endif() + endif() + endif() +endforeach(hdr) + set(cv2_generated_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h" diff --git a/modules/python/src2/gen2.py b/modules/python/src2/gen2.py index b613ccd4ac..5666355bb6 100755 --- a/modules/python/src2/gen2.py +++ b/modules/python/src2/gen2.py @@ -831,8 +831,10 @@ class PythonWrapperGenerator(object): # step 1: scan the headers and build more descriptive maps of classes, consts, functions for hdr in srcfiles: - self.code_include.write( '#include "{}"\n'.format(hdr[hdr.rindex('opencv2/'):]) ) decls = parser.parse(hdr) + if len(decls) == 0: + continue + self.code_include.write( '#include "{}"\n'.format(hdr[hdr.rindex('opencv2/'):]) ) for decl in decls: name = decl[0] if name.startswith("struct") or name.startswith("class"): From 964657a155899f40ad5fedd7c3afd248566d860d Mon Sep 17 00:00:00 2001 From: Alexander Mordvintsev Date: Tue, 22 Jul 2014 14:22:46 +0400 Subject: [PATCH 116/136] glob for python module dependences --- modules/python/CMakeLists.txt | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index 4eaa885254..3da937fccc 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -11,7 +11,26 @@ if(ANDROID OR IOS OR NOT PYTHONLIBS_FOUND OR NOT PYTHON_NUMPY_INCLUDE_DIRS) endif() set(the_description "The python bindings") -ocv_add_module(python BINDINGS opencv_core opencv_flann opencv_imgproc opencv_video opencv_ml opencv_features2d opencv_imgcodecs opencv_videoio opencv_highgui opencv_calib3d opencv_photo opencv_objdetect OPTIONAL opencv_nonfree) + +set(candidate_deps_raw) +foreach(mp ${OPENCV_MODULES_PATH} ${OPENCV_EXTRA_MODULES_PATH}) + file(GLOB names "${mp}/*") + list(APPEND candidate_deps_raw ${names}) +endforeach(mp) + +set(candidate_deps) +foreach(m IN LISTS candidate_deps_raw) + if(IS_DIRECTORY ${m}) + get_filename_component(m ${m} NAME) + if (NOT ${m} MATCHES "^cud(a|ev)") + if (NOT ${m} MATCHES "optim") # unless we handle namespaces + list(APPEND candidate_deps "opencv_${m}") + endif() + endif() + endif() +endforeach(m) + +ocv_add_module(python BINDINGS OPTIONAL ${candidate_deps}) ocv_module_include_directories( "${PYTHON_INCLUDE_PATH}" @@ -21,9 +40,9 @@ ocv_module_include_directories( set(opencv_hdrs_raw) -foreach(mod_name IN LISTS OPENCV_MODULE_opencv_python_DEPS) - list(APPEND opencv_hdrs_raw "${OPENCV_MODULE_${mod_name}_HEADERS}") -endforeach(mod_name) +foreach(m IN LISTS OPENCV_MODULE_opencv_python_DEPS) + list(APPEND opencv_hdrs_raw "${OPENCV_MODULE_${m}_HEADERS}") +endforeach(m) # remove problematic headers set(opencv_hdrs) From 42ecfc5538b3da27f3ec4c0d5cd3c214547f8a6b Mon Sep 17 00:00:00 2001 From: Alexander Mordvintsev Date: Wed, 23 Jul 2014 14:54:04 +0400 Subject: [PATCH 117/136] fixed parsing enums with tailing comma gen2.py reports headers it processes cmake file restructured --- modules/python/CMakeLists.txt | 56 +++++++++++++++---------------- modules/python/src2/gen2.py | 1 + modules/python/src2/hdr_parser.py | 2 ++ 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index 3da937fccc..cccf0c3915 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -12,23 +12,18 @@ endif() set(the_description "The python bindings") -set(candidate_deps_raw) +set(candidate_deps) foreach(mp ${OPENCV_MODULES_PATH} ${OPENCV_EXTRA_MODULES_PATH}) file(GLOB names "${mp}/*") - list(APPEND candidate_deps_raw ${names}) -endforeach(mp) - -set(candidate_deps) -foreach(m IN LISTS candidate_deps_raw) - if(IS_DIRECTORY ${m}) - get_filename_component(m ${m} NAME) - if (NOT ${m} MATCHES "^cud(a|ev)") - if (NOT ${m} MATCHES "optim") # unless we handle namespaces - list(APPEND candidate_deps "opencv_${m}") + foreach(m IN LISTS names) + if(IS_DIRECTORY ${m}) + get_filename_component(m ${m} NAME) + if (NOT ${m} MATCHES "^cud(a|ev)") + list(APPEND candidate_deps "opencv_${m}") + endif() endif() - endif() - endif() -endforeach(m) + endforeach(m) +endforeach(mp) ocv_add_module(python BINDINGS OPTIONAL ${candidate_deps}) @@ -39,23 +34,26 @@ ocv_module_include_directories( ) -set(opencv_hdrs_raw) -foreach(m IN LISTS OPENCV_MODULE_opencv_python_DEPS) - list(APPEND opencv_hdrs_raw "${OPENCV_MODULE_${m}_HEADERS}") -endforeach(m) +set(opencv_hdrs_blacklist + ".h$" + "opencv2/core/cuda" + "opencv2/objdetect/detection_based_tracker.hpp" + "opencv2/optim.hpp") -# remove problematic headers set(opencv_hdrs) -foreach(hdr IN LISTS opencv_hdrs_raw) - if(NOT ${hdr} MATCHES ".h$") - if(NOT ${hdr} MATCHES "opencv2/core/cuda") - if(NOT ${hdr} MATCHES "opencv2/objdetect/detection_based_tracker.hpp") - list(APPEND opencv_hdrs ${hdr}) - endif() - endif() - endif() -endforeach(hdr) - +foreach(m IN LISTS OPENCV_MODULE_opencv_python_DEPS) + foreach(hdr IN LISTS OPENCV_MODULE_${m}_HEADERS) + set(good TRUE) + foreach(s IN LISTS opencv_hdrs_blacklist) + if (${hdr} MATCHES ${s}) + set(good FALSE) + endif() + endforeach(s) + if(${good}) + list(APPEND opencv_hdrs ${hdr}) + endif() + endforeach(hdr) +endforeach(m) set(cv2_generated_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h" diff --git a/modules/python/src2/gen2.py b/modules/python/src2/gen2.py index 5666355bb6..9488107715 100755 --- a/modules/python/src2/gen2.py +++ b/modules/python/src2/gen2.py @@ -831,6 +831,7 @@ class PythonWrapperGenerator(object): # step 1: scan the headers and build more descriptive maps of classes, consts, functions for hdr in srcfiles: + print(hdr) decls = parser.parse(hdr) if len(decls) == 0: continue diff --git a/modules/python/src2/hdr_parser.py b/modules/python/src2/hdr_parser.py index 92f1b7347c..eb9100928f 100755 --- a/modules/python/src2/hdr_parser.py +++ b/modules/python/src2/hdr_parser.py @@ -206,6 +206,8 @@ class CppHeaderParser(object): def parse_enum(self, decl_str): l = decl_str ll = l.split(",") + if ll[-1].strip() == "": + ll = ll[:-1] prev_val = "" prev_val_delta = -1 decl = [] From 9ab3b89c53aa0153111398b08f880f68bb7e497d Mon Sep 17 00:00:00 2001 From: Alexander Mordvintsev Date: Sun, 27 Jul 2014 16:35:35 +0400 Subject: [PATCH 118/136] pass header list to gen2.py by a text file (avoid command line length limit on windows) --- modules/python/CMakeLists.txt | 36 +++++++++++++---------------------- modules/python/src2/gen2.py | 3 +-- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index cccf0c3915..57a8ed7b4f 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -12,18 +12,17 @@ endif() set(the_description "The python bindings") -set(candidate_deps) +set(candidate_deps "") foreach(mp ${OPENCV_MODULES_PATH} ${OPENCV_EXTRA_MODULES_PATH}) file(GLOB names "${mp}/*") foreach(m IN LISTS names) if(IS_DIRECTORY ${m}) get_filename_component(m ${m} NAME) - if (NOT ${m} MATCHES "^cud(a|ev)") - list(APPEND candidate_deps "opencv_${m}") - endif() + list(APPEND candidate_deps "opencv_${m}") endif() endforeach(m) endforeach(mp) +ocv_list_filterout(candidate_deps "^opencv_cud(a|ev)") ocv_add_module(python BINDINGS OPTIONAL ${candidate_deps}) @@ -34,27 +33,16 @@ ocv_module_include_directories( ) -set(opencv_hdrs_blacklist - ".h$" - "opencv2/core/cuda" - "opencv2/objdetect/detection_based_tracker.hpp" - "opencv2/optim.hpp") - -set(opencv_hdrs) +set(opencv_hdrs "") foreach(m IN LISTS OPENCV_MODULE_opencv_python_DEPS) - foreach(hdr IN LISTS OPENCV_MODULE_${m}_HEADERS) - set(good TRUE) - foreach(s IN LISTS opencv_hdrs_blacklist) - if (${hdr} MATCHES ${s}) - set(good FALSE) - endif() - endforeach(s) - if(${good}) - list(APPEND opencv_hdrs ${hdr}) - endif() - endforeach(hdr) + list(APPEND opencv_hdrs ${OPENCV_MODULE_${m}_HEADERS}) endforeach(m) +ocv_list_filterout(opencv_hdrs ".h$") +ocv_list_filterout(opencv_hdrs "opencv2/core/cuda") +ocv_list_filterout(opencv_hdrs "opencv2/objdetect/detection_based_tracker.hpp") +ocv_list_filterout(opencv_hdrs "opencv2/optim.hpp") + set(cv2_generated_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h" "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_funcs.h" @@ -63,11 +51,13 @@ set(cv2_generated_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_type_reg.h" "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_const_reg.h") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}") add_custom_command( OUTPUT ${cv2_generated_hdrs} - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} ${opencv_hdrs} + COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src2/gen2.py DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src2/hdr_parser.py + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txt DEPENDS ${opencv_hdrs}) add_library(${the_module} SHARED src2/cv2.cpp ${cv2_generated_hdrs}) diff --git a/modules/python/src2/gen2.py b/modules/python/src2/gen2.py index 9488107715..684b80f4e8 100755 --- a/modules/python/src2/gen2.py +++ b/modules/python/src2/gen2.py @@ -831,7 +831,6 @@ class PythonWrapperGenerator(object): # step 1: scan the headers and build more descriptive maps of classes, consts, functions for hdr in srcfiles: - print(hdr) decls = parser.parse(hdr) if len(decls) == 0: continue @@ -904,6 +903,6 @@ if __name__ == "__main__": if len(sys.argv) > 1: dstdir = sys.argv[1] if len(sys.argv) > 2: - srcfiles = sys.argv[2:] + srcfiles = open(sys.argv[2], 'r').read().split(';') generator = PythonWrapperGenerator() generator.gen(srcfiles, dstdir) From a2ae1db31c8a831c254952550786b3c589319285 Mon Sep 17 00:00:00 2001 From: Alexander Mordvintsev Date: Sun, 27 Jul 2014 17:41:12 +0400 Subject: [PATCH 119/136] 'adas' extra module doesn't produce .lib on windows (causes link error) --- modules/python/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index 57a8ed7b4f..c41d19a3f9 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -23,6 +23,8 @@ foreach(mp ${OPENCV_MODULES_PATH} ${OPENCV_EXTRA_MODULES_PATH}) endforeach(m) endforeach(mp) ocv_list_filterout(candidate_deps "^opencv_cud(a|ev)") +ocv_list_filterout(candidate_deps "^opencv_adas$") + ocv_add_module(python BINDINGS OPTIONAL ${candidate_deps}) From 5f47f70183612d6a1228e5dd3d97529230fa4b23 Mon Sep 17 00:00:00 2001 From: Alexander Mordvintsev Date: Sun, 27 Jul 2014 18:03:27 +0400 Subject: [PATCH 120/136] module blacklist --- modules/python/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index c41d19a3f9..66ac1addd6 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -22,8 +22,11 @@ foreach(mp ${OPENCV_MODULES_PATH} ${OPENCV_EXTRA_MODULES_PATH}) endif() endforeach(m) endforeach(mp) + +# module blacklist ocv_list_filterout(candidate_deps "^opencv_cud(a|ev)") ocv_list_filterout(candidate_deps "^opencv_adas$") +ocv_list_filterout(candidate_deps "^opencv_tracking$") ocv_add_module(python BINDINGS OPTIONAL ${candidate_deps}) @@ -40,6 +43,7 @@ foreach(m IN LISTS OPENCV_MODULE_opencv_python_DEPS) list(APPEND opencv_hdrs ${OPENCV_MODULE_${m}_HEADERS}) endforeach(m) +# header blacklist ocv_list_filterout(opencv_hdrs ".h$") ocv_list_filterout(opencv_hdrs "opencv2/core/cuda") ocv_list_filterout(opencv_hdrs "opencv2/objdetect/detection_based_tracker.hpp") From fc8f0e341b2b33d8f116e215b180b8474c7fb537 Mon Sep 17 00:00:00 2001 From: Kobi Gurkan Date: Sun, 27 Jul 2014 17:09:05 +0300 Subject: [PATCH 121/136] adding support for 16-bit 4 channel tiffs - when IMREAD_UNCHANGED is set in flags, the tiff is read with 4 channels - adding test for read/write --- modules/imgcodecs/src/grfmt_tiff.cpp | 17 ++++++++++++++++- modules/imgcodecs/test/test_grfmt.cpp | 6 ++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_tiff.cpp b/modules/imgcodecs/src/grfmt_tiff.cpp index 9013c39d11..3ec68c8669 100644 --- a/modules/imgcodecs/src/grfmt_tiff.cpp +++ b/modules/imgcodecs/src/grfmt_tiff.cpp @@ -158,7 +158,7 @@ bool TiffDecoder::readHeader() m_type = CV_MAKETYPE(CV_8U, photometric > 1 ? wanted_channels : 1); break; case 16: - m_type = CV_MAKETYPE(CV_16U, photometric > 1 ? 3 : 1); + m_type = CV_MAKETYPE(CV_16U, photometric > 1 ? wanted_channels : 1); break; case 32: @@ -326,6 +326,21 @@ bool TiffDecoder::readData( Mat& img ) (ushort*)(data + img.step*i) + x*3, 0, cvSize(tile_width,1) ); } + else if (ncn == 4) + { + if (wanted_channels == 4) + { + icvCvt_BGRA2RGBA_16u_C4R(buffer16 + i*tile_width0*ncn, 0, + (ushort*)(data + img.step*i) + x * 4, 0, + cvSize(tile_width, 1)); + } + else + { + icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width0*ncn, 0, + (ushort*)(data + img.step*i) + x * 3, 0, + cvSize(tile_width, 1), 2); + } + } else { icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width0*ncn, 0, diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index 9b06c5744c..37c9bf879c 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -139,9 +139,6 @@ public: string filename = cv::tempfile(".jpg"); imwrite(filename, img); - img = imread(filename, IMREAD_UNCHANGED); - - filename = string(ts->get_data_path() + "readwrite/test_" + char(k + 48) + "_c" + char(num_channels + 48) + ".jpg"); ts->printf(ts->LOG, "reading test image : %s\n", filename.c_str()); Mat img_test = imread(filename, IMREAD_UNCHANGED); @@ -160,8 +157,9 @@ public: #endif #ifdef HAVE_TIFF - for (int num_channels = 1; num_channels <= 3; num_channels+=2) + for (int num_channels = 1; num_channels <= 4; num_channels++) { + if (num_channels == 2) continue; // tiff ts->printf(ts->LOG, "image type depth:%d channels:%d ext: %s\n", CV_16U, num_channels, ".tiff"); Mat img(img_r * k, img_c * k, CV_MAKETYPE(CV_16U, num_channels), Scalar::all(0)); From 6cac76bfe4400c56bcdc622d15fb4cb3f3f50f36 Mon Sep 17 00:00:00 2001 From: Kobi Gurkan Date: Sun, 27 Jul 2014 17:14:54 +0300 Subject: [PATCH 122/136] fixes tab indentation - replacing with 4 spaces --- modules/imgcodecs/src/grfmt_tiff.cpp | 32 +++++++++++++-------------- modules/imgcodecs/test/test_grfmt.cpp | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_tiff.cpp b/modules/imgcodecs/src/grfmt_tiff.cpp index 3ec68c8669..06b2ab6a15 100644 --- a/modules/imgcodecs/src/grfmt_tiff.cpp +++ b/modules/imgcodecs/src/grfmt_tiff.cpp @@ -158,7 +158,7 @@ bool TiffDecoder::readHeader() m_type = CV_MAKETYPE(CV_8U, photometric > 1 ? wanted_channels : 1); break; case 16: - m_type = CV_MAKETYPE(CV_16U, photometric > 1 ? wanted_channels : 1); + m_type = CV_MAKETYPE(CV_16U, photometric > 1 ? wanted_channels : 1); break; case 32: @@ -326,21 +326,21 @@ bool TiffDecoder::readData( Mat& img ) (ushort*)(data + img.step*i) + x*3, 0, cvSize(tile_width,1) ); } - else if (ncn == 4) - { - if (wanted_channels == 4) - { - icvCvt_BGRA2RGBA_16u_C4R(buffer16 + i*tile_width0*ncn, 0, - (ushort*)(data + img.step*i) + x * 4, 0, - cvSize(tile_width, 1)); - } - else - { - icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width0*ncn, 0, - (ushort*)(data + img.step*i) + x * 3, 0, - cvSize(tile_width, 1), 2); - } - } + else if (ncn == 4) + { + if (wanted_channels == 4) + { + icvCvt_BGRA2RGBA_16u_C4R(buffer16 + i*tile_width0*ncn, 0, + (ushort*)(data + img.step*i) + x * 4, 0, + cvSize(tile_width, 1)); + } + else + { + icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width0*ncn, 0, + (ushort*)(data + img.step*i) + x * 3, 0, + cvSize(tile_width, 1), 2); + } + } else { icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width0*ncn, 0, diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index 37c9bf879c..02e84d67f5 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -159,7 +159,7 @@ public: #ifdef HAVE_TIFF for (int num_channels = 1; num_channels <= 4; num_channels++) { - if (num_channels == 2) continue; + if (num_channels == 2) continue; // tiff ts->printf(ts->LOG, "image type depth:%d channels:%d ext: %s\n", CV_16U, num_channels, ".tiff"); Mat img(img_r * k, img_c * k, CV_MAKETYPE(CV_16U, num_channels), Scalar::all(0)); From 586ace1873fbf2f588b2edce29e6917c73c06e67 Mon Sep 17 00:00:00 2001 From: Alexander Mordvintsev Date: Sun, 27 Jul 2014 18:25:42 +0400 Subject: [PATCH 123/136] double to float cast warning fix --- modules/shape/include/opencv2/shape/hist_cost.hpp | 8 ++++---- modules/shape/include/opencv2/shape/shape_distance.hpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/shape/include/opencv2/shape/hist_cost.hpp b/modules/shape/include/opencv2/shape/hist_cost.hpp index 9ca3825fda..0ff3573eea 100644 --- a/modules/shape/include/opencv2/shape/hist_cost.hpp +++ b/modules/shape/include/opencv2/shape/hist_cost.hpp @@ -73,7 +73,7 @@ public: }; CV_EXPORTS_W Ptr - createNormHistogramCostExtractor(int flag=DIST_L2, int nDummies=25, float defaultCost=0.2); + createNormHistogramCostExtractor(int flag=DIST_L2, int nDummies=25, float defaultCost=0.2f); /*! */ class CV_EXPORTS_W EMDHistogramCostExtractor : public HistogramCostExtractor @@ -84,20 +84,20 @@ public: }; CV_EXPORTS_W Ptr - createEMDHistogramCostExtractor(int flag=DIST_L2, int nDummies=25, float defaultCost=0.2); + createEMDHistogramCostExtractor(int flag=DIST_L2, int nDummies=25, float defaultCost=0.2f); /*! */ class CV_EXPORTS_W ChiHistogramCostExtractor : public HistogramCostExtractor {}; -CV_EXPORTS_W Ptr createChiHistogramCostExtractor(int nDummies=25, float defaultCost=0.2); +CV_EXPORTS_W Ptr createChiHistogramCostExtractor(int nDummies=25, float defaultCost=0.2f); /*! */ class CV_EXPORTS_W EMDL1HistogramCostExtractor : public HistogramCostExtractor {}; CV_EXPORTS_W Ptr - createEMDL1HistogramCostExtractor(int nDummies=25, float defaultCost=0.2); + createEMDL1HistogramCostExtractor(int nDummies=25, float defaultCost=0.2f); } // cv #endif diff --git a/modules/shape/include/opencv2/shape/shape_distance.hpp b/modules/shape/include/opencv2/shape/shape_distance.hpp index 55e21aaa4a..acdb6e5f6e 100644 --- a/modules/shape/include/opencv2/shape/shape_distance.hpp +++ b/modules/shape/include/opencv2/shape/shape_distance.hpp @@ -116,7 +116,7 @@ public: /* Complete constructor */ CV_EXPORTS_W Ptr createShapeContextDistanceExtractor(int nAngularBins=12, int nRadialBins=4, - float innerRadius=0.2, float outerRadius=2, int iterations=3, + float innerRadius=0.2f, float outerRadius=2, int iterations=3, const Ptr &comparer = createChiHistogramCostExtractor(), const Ptr &transformer = createThinPlateSplineShapeTransformer()); @@ -137,7 +137,7 @@ public: }; /* Constructor */ -CV_EXPORTS_W Ptr createHausdorffDistanceExtractor(int distanceFlag=cv::NORM_L2, float rankProp=0.6); +CV_EXPORTS_W Ptr createHausdorffDistanceExtractor(int distanceFlag=cv::NORM_L2, float rankProp=0.6f); } // cv #endif From ba706177cbc0ffd48f6bfc32352cb3046f0d9f57 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Mon, 28 Jul 2014 12:13:52 +0400 Subject: [PATCH 124/136] fix cudacodec module dependecies --- modules/cudacodec/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cudacodec/CMakeLists.txt b/modules/cudacodec/CMakeLists.txt index ca62995505..5d8f7327c0 100644 --- a/modules/cudacodec/CMakeLists.txt +++ b/modules/cudacodec/CMakeLists.txt @@ -6,7 +6,7 @@ set(the_description "CUDA-accelerated Video Encoding/Decoding") ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127 /wd4324 /wd4512 -Wundef) -ocv_add_module(cudacodec OPTIONAL opencv_cudev) +ocv_add_module(cudacodec opencv_core opencv_videoio OPTIONAL opencv_cudev) ocv_module_include_directories() ocv_glob_module_sources() From 27d97aa231b9b936298a57c16ac2d9528cd30ddc Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Mon, 28 Jul 2014 12:21:00 +0400 Subject: [PATCH 125/136] fixed --- modules/core/src/stat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 60c8dc89bb..a26d3345c3 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -479,7 +479,7 @@ static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask haveMask = _mask.kind() != _InputArray::NONE, haveSrc2 = _src2.kind() != _InputArray::NONE; int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), - kercn = cn == 1 && !haveMask ? ocl::predictOptimalVectorWidth(_src) : 1, + kercn = cn == 1 && !haveMask ? ocl::predictOptimalVectorWidth(_src, _src2) : 1, mcn = std::max(cn, kercn); CV_Assert(!haveSrc2 || _src2.type() == type); int convert_cn = haveSrc2 ? mcn : cn; From fecfaf4092fec486aa7c6ea2f4e3121500180afe Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Sun, 27 Jul 2014 13:31:46 +0400 Subject: [PATCH 126/136] Using std::map in PlanCache --- modules/core/src/dxt.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index b57e4e8cc0..69cac1a0fc 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -43,6 +43,7 @@ #include "opencv2/core/opencl/runtime/opencl_clamdfft.hpp" #include "opencv2/core/opencl/runtime/opencl_core.hpp" #include "opencl_kernels.hpp" +#include namespace cv { @@ -1801,10 +1802,9 @@ private: String buildOptions; int thread_count; bool status; - -public: int dft_size; +public: OCL_FftPlan(int _size): dft_size(_size), status(true) { int min_radix; @@ -1999,18 +1999,17 @@ public: Ptr getFftPlan(int dft_size) { - for (size_t i = 0, size = planStorage.size(); i < size; ++i) + std::map >::iterator f = planStorage.find(dft_size); + if (f != planStorage.end()) { - Ptr plan = planStorage[i]; - if (plan->dft_size == dft_size) - { - return plan; - } + return f->second; + } + else + { + Ptr newPlan = Ptr(new OCL_FftPlan(dft_size)); + planStorage[dft_size] = newPlan; + return newPlan; } - - Ptr newPlan = Ptr(new OCL_FftPlan(dft_size)); - planStorage.push_back(newPlan); - return newPlan; } ~OCL_FftPlanCache() @@ -2023,8 +2022,7 @@ protected: planStorage() { } - - std::vector > planStorage; + std::map > planStorage; }; static bool ocl_dft_rows(InputArray _src, OutputArray _dst, int nonzero_rows, int flags, int fftType) From f42bb0bd6528c7e77a2872158a0577b7e713cd63 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Mon, 28 Jul 2014 15:45:54 +0400 Subject: [PATCH 127/136] disable OpenCL difference norms with mask, since some of the tests fail --- modules/core/src/stat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index a26d3345c3..a1415652cc 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -2540,7 +2540,7 @@ static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, InputArr normType &= ~NORM_RELATIVE; bool normsum = normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR; - if ( !(normType == NORM_INF || normsum) ) + if ( !(normType == NORM_INF || normsum) || !_mask.empty() ) return false; if (normsum) From 1ad9827fc4ede1b9c42515569fcc5d8d1106a4ea Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Mon, 28 Jul 2014 16:48:53 +0400 Subject: [PATCH 128/136] removed ERFilter (to be moved to opencv_contrib/modules/text) and lineMOD (to be moved to opencv_contrib/modules/rgbd) --- modules/objdetect/doc/erfilter.rst | 211 -- modules/objdetect/doc/latent_svm.rst | 262 -- modules/objdetect/doc/objdetect.rst | 1 - modules/objdetect/doc/pics/component_tree.png | Bin 108183 -> 0 bytes .../objdetect/include/opencv2/objdetect.hpp | 2 - .../include/opencv2/objdetect/erfilter.hpp | 266 -- .../include/opencv2/objdetect/linemod.hpp | 455 --- modules/objdetect/src/erfilter.cpp | 3187 ----------------- modules/objdetect/src/linemod.cpp | 1844 ---------- modules/objdetect/src/normal_lut.i | 4 - .../MacOSX/FaceTracker/FaceTracker-Info.plist | 20 - samples/MacOSX/FaceTracker/FaceTracker.cpp | 86 - .../FaceTracker.xcodeproj/project.pbxproj | 262 -- samples/MacOSX/FaceTracker/README.txt | 35 - samples/cpp/linemod.cpp | 705 ---- samples/cpp/scenetext01.jpg | Bin 97100 -> 0 bytes samples/cpp/scenetext02.jpg | Bin 95135 -> 0 bytes samples/cpp/scenetext03.jpg | Bin 60751 -> 0 bytes samples/cpp/scenetext04.jpg | Bin 99487 -> 0 bytes samples/cpp/scenetext05.jpg | Bin 113689 -> 0 bytes samples/cpp/scenetext06.jpg | Bin 70430 -> 0 bytes samples/cpp/textdetection.cpp | 128 - 22 files changed, 7468 deletions(-) delete mode 100644 modules/objdetect/doc/erfilter.rst delete mode 100644 modules/objdetect/doc/latent_svm.rst delete mode 100644 modules/objdetect/doc/pics/component_tree.png delete mode 100644 modules/objdetect/include/opencv2/objdetect/erfilter.hpp delete mode 100644 modules/objdetect/include/opencv2/objdetect/linemod.hpp delete mode 100644 modules/objdetect/src/erfilter.cpp delete mode 100644 modules/objdetect/src/linemod.cpp delete mode 100644 modules/objdetect/src/normal_lut.i delete mode 100644 samples/MacOSX/FaceTracker/FaceTracker-Info.plist delete mode 100644 samples/MacOSX/FaceTracker/FaceTracker.cpp delete mode 100644 samples/MacOSX/FaceTracker/FaceTracker.xcodeproj/project.pbxproj delete mode 100644 samples/MacOSX/FaceTracker/README.txt delete mode 100644 samples/cpp/linemod.cpp delete mode 100644 samples/cpp/scenetext01.jpg delete mode 100644 samples/cpp/scenetext02.jpg delete mode 100644 samples/cpp/scenetext03.jpg delete mode 100644 samples/cpp/scenetext04.jpg delete mode 100644 samples/cpp/scenetext05.jpg delete mode 100644 samples/cpp/scenetext06.jpg delete mode 100644 samples/cpp/textdetection.cpp diff --git a/modules/objdetect/doc/erfilter.rst b/modules/objdetect/doc/erfilter.rst deleted file mode 100644 index 85d6bcc7fe..0000000000 --- a/modules/objdetect/doc/erfilter.rst +++ /dev/null @@ -1,211 +0,0 @@ -Scene Text Detection -==================== - -.. highlight:: cpp - -Class-specific Extremal Regions for Scene Text Detection --------------------------------------------------------- - -The scene text detection algorithm described below has been initially proposed by Lukás Neumann & Jiri Matas [Neumann12]. The main idea behind Class-specific Extremal Regions is similar to the MSER in that suitable Extremal Regions (ERs) are selected from the whole component tree of the image. However, this technique differs from MSER in that selection of suitable ERs is done by a sequential classifier trained for character detection, i.e. dropping the stability requirement of MSERs and selecting class-specific (not necessarily stable) regions. - -The component tree of an image is constructed by thresholding by an increasing value step-by-step from 0 to 255 and then linking the obtained connected components from successive levels in a hierarchy by their inclusion relation: - -.. image:: pics/component_tree.png - :width: 100% - -The component tree may conatain a huge number of regions even for a very simple image as shown in the previous image. This number can easily reach the order of 1 x 10^6 regions for an average 1 Megapixel image. In order to efficiently select suitable regions among all the ERs the algorithm make use of a sequential classifier with two differentiated stages. - -In the first stage incrementally computable descriptors (area, perimeter, bounding box, and euler number) are computed (in O(1)) for each region r and used as features for a classifier which estimates the class-conditional probability p(r|character). Only the ERs which correspond to local maximum of the probability p(r|character) are selected (if their probability is above a global limit p_min and the difference between local maximum and local minimum is greater than a \delta_min value). - -In the second stage, the ERs that passed the first stage are classified into character and non-character classes using more informative but also more computationally expensive features. (Hole area ratio, convex hull ratio, and the number of outer boundary inflexion points). - -This ER filtering process is done in different single-channel projections of the input image in order to increase the character localization recall. - -After the ER filtering is done on each input channel, character candidates must be grouped in high-level text blocks (i.e. words, text lines, paragraphs, ...). The grouping algorithm used in this implementation has been proposed by Lluis Gomez and Dimosthenis Karatzas in [Gomez13] and basically consist in finding meaningful groups of regions using a perceptual organization based clustering analisys (see :ocv:func:`erGrouping`). - - -To see the text detector at work, have a look at the textdetection demo: https://github.com/Itseez/opencv/blob/master/samples/cpp/textdetection.cpp - - -.. [Neumann12] Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012. The paper is available online at http://cmp.felk.cvut.cz/~neumalu1/neumann-cvpr2012.pdf - -.. [Gomez13] Gomez L. and Karatzas D.: Multi-script Text Extraction from Natural Scenes, ICDAR 2013. The paper is available online at http://158.109.8.37/files/GoK2013.pdf - - -ERStat ------- -.. ocv:struct:: ERStat - -The ERStat structure represents a class-specific Extremal Region (ER). - -An ER is a 4-connected set of pixels with all its grey-level values smaller than the values in its outer boundary. A class-specific ER is selected (using a classifier) from all the ER's in the component tree of the image. :: - - struct CV_EXPORTS ERStat - { - public: - //! Constructor - explicit ERStat(int level = 256, int pixel = 0, int x = 0, int y = 0); - //! Destructor - ~ERStat() { } - - //! seed point and threshold (max grey-level value) - int pixel; - int level; - - //! incrementally computable features - int area; - int perimeter; - int euler; //!< euler number - Rect rect; //!< bounding box - double raw_moments[2]; //!< order 1 raw moments to derive the centroid - double central_moments[3]; //!< order 2 central moments to construct the covariance matrix - std::deque *crossings;//!< horizontal crossings - float med_crossings; //!< median of the crossings at three different height levels - - //! 2nd stage features - float hole_area_ratio; - float convex_hull_ratio; - float num_inflexion_points; - - //! probability that the ER belongs to the class we are looking for - double probability; - - //! pointers preserving the tree structure of the component tree - ERStat* parent; - ERStat* child; - ERStat* next; - ERStat* prev; - }; - -computeNMChannels ------------------ -Compute the different channels to be processed independently in the N&M algorithm [Neumann12]. - -.. ocv:function:: void computeNMChannels(InputArray _src, OutputArrayOfArrays _channels, int _mode = ERFILTER_NM_RGBLGrad) - - :param _src: Source image. Must be RGB ``CV_8UC3``. - :param _channels: Output vector where computed channels are stored. - :param _mode: Mode of operation. Currently the only available options are: **ERFILTER_NM_RGBLGrad** (used by default) and **ERFILTER_NM_IHSGrad**. - -In N&M algorithm, the combination of intensity (I), hue (H), saturation (S), and gradient magnitude channels (Grad) are used in order to obtain high localization recall. This implementation also provides an alternative combination of red (R), green (G), blue (B), lightness (L), and gradient magnitude (Grad). - - -ERFilter --------- -.. ocv:class:: ERFilter : public Algorithm - -Base class for 1st and 2nd stages of Neumann and Matas scene text detection algorithm [Neumann12]. :: - - class CV_EXPORTS ERFilter : public Algorithm - { - public: - - //! callback with the classifier is made a class. - //! By doing it we hide SVM, Boost etc. Developers can provide their own classifiers - class CV_EXPORTS Callback - { - public: - virtual ~Callback() { } - //! The classifier must return probability measure for the region. - virtual double eval(const ERStat& stat) = 0; - }; - - /*! - the key method. Takes image on input and returns the selected regions in a vector of ERStat - only distinctive ERs which correspond to characters are selected by a sequential classifier - */ - virtual void run( InputArray image, std::vector& regions ) = 0; - - (...) - - }; - - - -ERFilter::Callback ------------------- -Callback with the classifier is made a class. By doing it we hide SVM, Boost etc. Developers can provide their own classifiers to the ERFilter algorithm. - -.. ocv:class:: ERFilter::Callback - -ERFilter::Callback::eval ------------------------- -The classifier must return probability measure for the region. - -.. ocv:function:: double ERFilter::Callback::eval(const ERStat& stat) - - :param stat: The region to be classified - -ERFilter::run -------------- -The key method of ERFilter algorithm. Takes image on input and returns the selected regions in a vector of ERStat only distinctive ERs which correspond to characters are selected by a sequential classifier - -.. ocv:function:: void ERFilter::run( InputArray image, std::vector& regions ) - - :param image: Sinle channel image ``CV_8UC1`` - :param regions: Output for the 1st stage and Input/Output for the 2nd. The selected Extremal Regions are stored here. - -Extracts the component tree (if needed) and filter the extremal regions (ER's) by using a given classifier. - -createERFilterNM1 ------------------ -Create an Extremal Region Filter for the 1st stage classifier of N&M algorithm [Neumann12]. - -.. ocv:function:: Ptr createERFilterNM1( const Ptr& cb, int thresholdDelta = 1, float minArea = 0.00025, float maxArea = 0.13, float minProbability = 0.4, bool nonMaxSuppression = true, float minProbabilityDiff = 0.1 ) - - :param cb: Callback with the classifier. Default classifier can be implicitly load with function :ocv:func:`loadClassifierNM1`, e.g. from file in samples/cpp/trained_classifierNM1.xml - :param thresholdDelta: Threshold step in subsequent thresholds when extracting the component tree - :param minArea: The minimum area (% of image size) allowed for retreived ER's - :param minArea: The maximum area (% of image size) allowed for retreived ER's - :param minProbability: The minimum probability P(er|character) allowed for retreived ER's - :param nonMaxSuppression: Whenever non-maximum suppression is done over the branch probabilities - :param minProbability: The minimum probability difference between local maxima and local minima ERs - -The component tree of the image is extracted by a threshold increased step by step from 0 to 255, incrementally computable descriptors (aspect_ratio, compactness, number of holes, and number of horizontal crossings) are computed for each ER and used as features for a classifier which estimates the class-conditional probability P(er|character). The value of P(er|character) is tracked using the inclusion relation of ER across all thresholds and only the ERs which correspond to local maximum of the probability P(er|character) are selected (if the local maximum of the probability is above a global limit pmin and the difference between local maximum and local minimum is greater than minProbabilityDiff). - -createERFilterNM2 ------------------ -Create an Extremal Region Filter for the 2nd stage classifier of N&M algorithm [Neumann12]. - -.. ocv:function:: Ptr createERFilterNM2( const Ptr& cb, float minProbability = 0.3 ) - - :param cb: Callback with the classifier. Default classifier can be implicitly load with function :ocv:func:`loadClassifierNM2`, e.g. from file in samples/cpp/trained_classifierNM2.xml - :param minProbability: The minimum probability P(er|character) allowed for retreived ER's - -In the second stage, the ERs that passed the first stage are classified into character and non-character classes using more informative but also more computationally expensive features. The classifier uses all the features calculated in the first stage and the following additional features: hole area ratio, convex hull ratio, and number of outer inflexion points. - -loadClassifierNM1 ------------------ -Allow to implicitly load the default classifier when creating an ERFilter object. - -.. ocv:function:: Ptr loadClassifierNM1(const std::string& filename) - - :param filename: The XML or YAML file with the classifier model (e.g. trained_classifierNM1.xml) - -returns a pointer to ERFilter::Callback. - -loadClassifierNM2 ------------------ -Allow to implicitly load the default classifier when creating an ERFilter object. - -.. ocv:function:: Ptr loadClassifierNM2(const std::string& filename) - - :param filename: The XML or YAML file with the classifier model (e.g. trained_classifierNM2.xml) - -returns a pointer to ERFilter::Callback. - -erGrouping ----------- -Find groups of Extremal Regions that are organized as text blocks. - -.. ocv:function:: void erGrouping( InputArrayOfArrays src, std::vector > ®ions, const std::string& filename, float minProbablity, std::vector &groups) - - :param src: Vector of sinle channel images CV_8UC1 from wich the regions were extracted - :param regions: Vector of ER's retreived from the ERFilter algorithm from each channel - :param filename: The XML or YAML file with the classifier model (e.g. trained_classifier_erGrouping.xml) - :param minProbability: The minimum probability for accepting a group - :param groups: The output of the algorithm are stored in this parameter as list of rectangles. - -This function implements the grouping algorithm described in [Gomez13]. Notice that this implementation constrains the results to horizontally-aligned text and latin script (since ERFilter classifiers are trained only for latin script detection). - -The algorithm combines two different clustering techniques in a single parameter-free procedure to detect groups of regions organized as text. The maximally meaningful groups are fist detected in several feature spaces, where each feature space is a combination of proximity information (x,y coordinates) and a similarity measure (intensity, color, size, gradient magnitude, etc.), thus providing a set of hypotheses of text groups. Evidence Accumulation framework is used to combine all these hypotheses to get the final estimate. Each of the resulting groups are finally validated using a classifier in order to assess if they form a valid horizontally-aligned text block. diff --git a/modules/objdetect/doc/latent_svm.rst b/modules/objdetect/doc/latent_svm.rst deleted file mode 100644 index 4b4ff117fa..0000000000 --- a/modules/objdetect/doc/latent_svm.rst +++ /dev/null @@ -1,262 +0,0 @@ -Latent SVM -=============================================================== - -Discriminatively Trained Part Based Models for Object Detection ---------------------------------------------------------------- - -The object detector described below has been initially proposed by -P.F. Felzenszwalb in [Felzenszwalb2010]_. It is based on a -Dalal-Triggs detector that uses a single filter on histogram of -oriented gradients (HOG) features to represent an object category. -This detector uses a sliding window approach, where a filter is -applied at all positions and scales of an image. The first -innovation is enriching the Dalal-Triggs model using a -star-structured part-based model defined by a "root" filter -(analogous to the Dalal-Triggs filter) plus a set of parts filters -and associated deformation models. The score of one of star models -at a particular position and scale within an image is the score of -the root filter at the given location plus the sum over parts of the -maximum, over placements of that part, of the part filter score on -its location minus a deformation cost easuring the deviation of the -part from its ideal location relative to the root. Both root and -part filter scores are defined by the dot product between a filter -(a set of weights) and a subwindow of a feature pyramid computed -from the input image. Another improvement is a representation of the -class of models by a mixture of star models. The score of a mixture -model at a particular position and scale is the maximum over -components, of the score of that component model at the given -location. - -In OpenCV there are C implementation of Latent SVM and C++ wrapper of it. -C version is the structure :ocv:struct:`CvObjectDetection` and a set of functions -working with this structure (see :ocv:func:`cvLoadLatentSvmDetector`, -:ocv:func:`cvReleaseLatentSvmDetector`, :ocv:func:`cvLatentSvmDetectObjects`). -C++ version is the class :ocv:class:`LatentSvmDetector` and has slightly different -functionality in contrast with C version - it supports loading and detection -of several models. - -There are two examples of Latent SVM usage: ``samples/c/latentsvmdetect.cpp`` -and ``samples/cpp/latentsvm_multidetect.cpp``. - -.. highlight:: c - - -CvLSVMFilterPosition --------------------- -.. ocv:struct:: CvLSVMFilterPosition - - Structure describes the position of the filter in the feature pyramid. - - .. ocv:member:: unsigned int l - - level in the feature pyramid - - .. ocv:member:: unsigned int x - - x-coordinate in level l - - .. ocv:member:: unsigned int y - - y-coordinate in level l - - -CvLSVMFilterObject ------------------- -.. ocv:struct:: CvLSVMFilterObject - - Description of the filter, which corresponds to the part of the object. - - .. ocv:member:: CvLSVMFilterPosition V - - ideal (penalty = 0) position of the partial filter - from the root filter position (V_i in the paper) - - .. ocv:member:: float fineFunction[4] - - vector describes penalty function (d_i in the paper) - pf[0] * x + pf[1] * y + pf[2] * x^2 + pf[3] * y^2 - - .. ocv:member:: int sizeX - .. ocv:member:: int sizeY - - Rectangular map (sizeX x sizeY), - every cell stores feature vector (dimension = p) - - .. ocv:member:: int numFeatures - - number of features - - .. ocv:member:: float *H - - matrix of feature vectors to set and get - feature vectors (i,j) used formula H[(j * sizeX + i) * p + k], - where k - component of feature vector in cell (i, j) - -CvLatentSvmDetector -------------------- -.. ocv:struct:: CvLatentSvmDetector - - Structure contains internal representation of trained Latent SVM detector. - - .. ocv:member:: int num_filters - - total number of filters (root plus part) in model - - .. ocv:member:: int num_components - - number of components in model - - .. ocv:member:: int* num_part_filters - - array containing number of part filters for each component - - .. ocv:member:: CvLSVMFilterObject** filters - - root and part filters for all model components - - .. ocv:member:: float* b - - biases for all model components - - .. ocv:member:: float score_threshold - - confidence level threshold - - -CvObjectDetection ------------------ -.. ocv:struct:: CvObjectDetection - - Structure contains the bounding box and confidence level for detected object. - - .. ocv:member:: CvRect rect - - bounding box for a detected object - - .. ocv:member:: float score - - confidence level - - -cvLoadLatentSvmDetector ------------------------ -Loads trained detector from a file. - -.. ocv:function:: CvLatentSvmDetector* cvLoadLatentSvmDetector(const char* filename) - - :param filename: Name of the file containing the description of a trained detector - - -cvReleaseLatentSvmDetector --------------------------- -Release memory allocated for CvLatentSvmDetector structure. - -.. ocv:function:: void cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector) - - :param detector: CvLatentSvmDetector structure to be released - - -cvLatentSvmDetectObjects ------------------------- -Find rectangular regions in the given image that are likely to contain objects -and corresponding confidence levels. - -.. ocv:function:: CvSeq* cvLatentSvmDetectObjects( IplImage* image, CvLatentSvmDetector* detector, CvMemStorage* storage, float overlap_threshold=0.5f, int numThreads=-1 ) - - :param image: image - :param detector: LatentSVM detector in internal representation - :param storage: Memory storage to store the resultant sequence of the object candidate rectangles - :param overlap_threshold: Threshold for the non-maximum suppression algorithm - :param numThreads: Number of threads used in parallel version of the algorithm - -.. highlight:: cpp - -LatentSvmDetector ------------------ -.. ocv:class:: LatentSvmDetector - -This is a C++ wrapping class of Latent SVM. It contains internal representation of several -trained Latent SVM detectors (models) and a set of methods to load the detectors and detect objects -using them. - -LatentSvmDetector::ObjectDetection ----------------------------------- -.. ocv:struct:: LatentSvmDetector::ObjectDetection - - Structure contains the detection information. - - .. ocv:member:: Rect rect - - bounding box for a detected object - - .. ocv:member:: float score - - confidence level - - .. ocv:member:: int classID - - class (model or detector) ID that detect an object - - -LatentSvmDetector::LatentSvmDetector ------------------------------------- -Two types of constructors. - -.. ocv:function:: LatentSvmDetector::LatentSvmDetector() - -.. ocv:function:: LatentSvmDetector::LatentSvmDetector(const vector& filenames, const vector& classNames=vector()) - - - - :param filenames: A set of filenames storing the trained detectors (models). Each file contains one model. See examples of such files here /opencv_extra/testdata/cv/latentsvmdetector/models_VOC2007/. - - :param classNames: A set of trained models names. If it's empty then the name of each model will be constructed from the name of file containing the model. E.g. the model stored in "/home/user/cat.xml" will get the name "cat". - -LatentSvmDetector::~LatentSvmDetector -------------------------------------- -Destructor. - -.. ocv:function:: LatentSvmDetector::~LatentSvmDetector() - -LatentSvmDetector::~clear -------------------------- -Clear all trained models and their names stored in an class object. - -.. ocv:function:: void LatentSvmDetector::clear() - -LatentSvmDetector::load ------------------------ -Load the trained models from given ``.xml`` files and return ``true`` if at least one model was loaded. - -.. ocv:function:: bool LatentSvmDetector::load( const vector& filenames, const vector& classNames=vector() ) - - :param filenames: A set of filenames storing the trained detectors (models). Each file contains one model. See examples of such files here /opencv_extra/testdata/cv/latentsvmdetector/models_VOC2007/. - - :param classNames: A set of trained models names. If it's empty then the name of each model will be constructed from the name of file containing the model. E.g. the model stored in "/home/user/cat.xml" will get the name "cat". - -LatentSvmDetector::detect -------------------------- -Find rectangular regions in the given image that are likely to contain objects of loaded classes (models) -and corresponding confidence levels. - -.. ocv:function:: void LatentSvmDetector::detect( const Mat& image, vector& objectDetections, float overlapThreshold=0.5f, int numThreads=-1 ) - - :param image: An image. - :param objectDetections: The detections: rectangulars, scores and class IDs. - :param overlapThreshold: Threshold for the non-maximum suppression algorithm. - :param numThreads: Number of threads used in parallel version of the algorithm. - -LatentSvmDetector::getClassNames --------------------------------- -Return the class (model) names that were passed in constructor or method ``load`` or extracted from models filenames in those methods. - -.. ocv:function:: const vector& LatentSvmDetector::getClassNames() const - -LatentSvmDetector::getClassCount --------------------------------- -Return a count of loaded models (classes). - -.. ocv:function:: size_t LatentSvmDetector::getClassCount() const - - -.. [Felzenszwalb2010] Felzenszwalb, P. F. and Girshick, R. B. and McAllester, D. and Ramanan, D. *Object Detection with Discriminatively Trained Part Based Models*. PAMI, vol. 32, no. 9, pp. 1627-1645, September 2010 diff --git a/modules/objdetect/doc/objdetect.rst b/modules/objdetect/doc/objdetect.rst index 0cd8cf3ef9..bbd5d0e359 100644 --- a/modules/objdetect/doc/objdetect.rst +++ b/modules/objdetect/doc/objdetect.rst @@ -8,5 +8,4 @@ objdetect. Object Detection :maxdepth: 2 cascade_classification - latent_svm erfilter diff --git a/modules/objdetect/doc/pics/component_tree.png b/modules/objdetect/doc/pics/component_tree.png deleted file mode 100644 index 7391e2de62cefd33825884758ec3196964802109..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108183 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

vSyAJ+A;wNY8Bw(=)dJl8UC)8QE9jR0&R}pT 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 i@}`$l%x2GKVy zh~ohc{w)pu2ghWH2gY{CZ*L>q(rTznw1C!9|9_@f-`_hA*jr+iV_Y~0deV$B@85SO zn6*muH3eK~{LM!7L^TBND?-diO_WQC zPKzYXmQhht&CC7sYkR#_qzfY;rmM4oe()+3LQW4A+?yFBdho5kK6}4lKbJbE9m9wV zVaA{4(4W}+Nt-{%b3Dgy@6%G}zN6T&h;5iHEscoyi78&XdZIo@OJJAua`my+q__0Fl-n5aK!*FO&$0D4j>?eF|pNj(uSLJ z=w*)XH0en|Usf48PDsnc5<;nRIa(LKRd}rk+E=h!9)(#=Q^wTzI$4Ecr+T0Rq~HzQ z001BWNkl8VR?$-gWYY}|j8tDz#OmHT582l>e^nquKS z$>_$s2D(t0C}v<0@DGCDEez1tp2S?xJ+#*!K@|gBG~nF-K3q#0#@G$)7`8e9 z2GS3#;1ABZdGPG#lu0i8q4K@=@7j{g&=(93rL+1xy{zzA$@bNIw>&=~jASgkm}^(W zjmpcdx6aMF2;TTNt~M96kRFe)@9HMLK!u_}C?-@!pB~s-s`etf3j-G<$dHS{uHbH8 z@D3*2XV+-1Vk7waBa$FiZ=0~~E%28H+b1@Ej^}ue=lBQ48-WKP;w5KXgjtAy6t;a} z0~ihG%k}G6d=1dm+GZ0ASj#}M2%fG=fv=Hl1G)rrAO)$xjO!*c@rA3v2eot%>?XyZ!Rt~J5)f@=;kpTM^2M?2W(gPzJWMi>S2ETEH0Am;v!RwT( z111}nXeimgL7VH9Lyj?KAAW)HA3$Z<4nBN79~8o|!_E{tX4gQC7EwZ0LgT&q$xQ7|2W(nE*&s0z%|-+D*$L^x`Pic-3ehXOgpARX zMj3OvCq{}A^q~MDDTHVjcdh+0Y~F{y0CfZ@>N1+j)-MY|I*9H^$$}(E4lu-&Fi=F0 zB__+AYX9(wWHUO+d~J|o5nbrzWZ#@$eB4M42Q@1Kl9~ak!B6MwCOpR5=0kg%*d`_c zArs|V;RAf|Atg}xf0`m!zb%@r(tWyp8Qyv-v!WA7`;aRR@O*D7aq~{Sj)wg|v$%NAo#zsz+yg1^M_B}yBwI6GY5_Wh4ifrOC>RI9LU%f)i<+qszU_wpAbnO$^m!71D~W=vdw zuhSA&>bw(ebH!TCI$<6H;r8R|@tP>W2768G=0LxYlj;ZBlA|;wm4-SyV}gSXlA}_D zZ(sklXc6W>N3-^_g{jksAmYBlgCKJn!Lmk21D6+~QAOiu5}4_S75vp!@&ufT9Y@}f z7@B(?+%E#aWYBBMfFLe_@jC9eGOpiOp;aJOO5;+3MzMHG}16{>`EQ?^mz5;{P-CMr>V@CP(La+Nid~h>{dn))$A1& zh0i%}A5M5Pegt#m!odibU(yvM4Gc2$U=T88OsfCvg7n1ZPh9>S&+#1h5a0SI>Ez!_ z6C2RvYEsKa7q%}!=ylCa2P$L-N(1RsI@|EZsZ{&BC)A!BQxl1lM)T-1<;n3Q3*X<` z5W^nzbA#9ztpSmesHtZ9t1GJpNri;QT#&IkH3oE+|IEEsHYkL{MiDRjFbldsc$k&` zD^4JI#*RxeHy}Gfyo^@AaMc|TFNs0#a)UDF<_x1YR1W9)ccC&Lqm{i!T5QO&Q{c($ zc|sCCB%L$ZrvVddLjuuuM%CesNb808hNR?p+EOQMc5l6{K=_Sc1d-<>tid*6zSedI z2Z|io$kTo1{`x;=mqYP_F~b7U;lN&(@>bt1+zP0KY!+Tv2m}*M^5D9cCwK`(UMi?e zyhi}W_z^)_kuX;>)cvQg4 zw&Ovo-C@J>R&)?$=`7PP7dXk_io~;Am9Nw7Xk_`aD8#laV1vwyxB4zubfhxMvibz5 zb!Gz<7E^g-Y5mK^2~#iFP(5GvGAN5UpQQ6RN}orUq^>GxwdU2&p-FTzFF$MSzudOR z$H{gGf~K&aE-+L(3zzD_sRzioE93=GFGF>r_d+#+IkwlRa{d;lb_f8H&FJ!&ZI6*O zQQzq#SeyPp*MO``Ve2Uq2IYQq{aN6&pb$7sjT`LgnTl{Q>xu2@X+=7vs z8}?1e>C1XpnOiP+>0r#r5?)_kZeY!Dj&}?#L6_6a=xs6{*@&*M5vhWN`yV|rW<(Em zq3`cG?pv2alj*`FqDEatm^*=JtGrsxqjR)R7mzKO_~Y;O<(pH9&M!T3{+~ZlU48n` z2+p6p`9Cj?_}Axcc#h}zD@Q(jC#RcxITz-I%*CQxAqMtuAJD5kjm!8vC&=66c3C!I z`=2-rwvywQrZFpHx;1dpETEV0T`^O-Jl4)MTmk`YwSk8t0^@2kAs5n$~PP^h- z7JpUvQ`@*9T@W(0?KG5vn90yz0t{a9q=yh2#j`q4BjUd>;rs@3WppqR64g+Qiip|= z`Nx;xDj(4U3YCamxR7R2B-xsIpgJbY$O$3}DM0E{7;G8n-u@6t@f!{}#|{AlvD@>- z#R;+owLRXN|9Fk5tdzuXUoXNKG{5xC;iZn#@X+%9=~##)29E?!zj|ULG~Fj?k6EW8 zX5BQY{|#9Q3W`cQ#s$fV8iAY#Mex#T2Pi;=%yCKWaK={p0%7@sK_{^~P`yK@xUt%K zI0f^*snc6>%8zqHU@|HX+6mw2_M$hKUdD2; z{BpK)YqHJ=a~d_6A1^n4E+EE-ZHE9kW%GQwn5+!eP`>_Xm=s<6n4Q`20)wfHKPK@W@N~PrgT;~X)nHD6a-G-rA7U7Qd4YcJ+-pPS8^WL`Hh+%ic#h}z z?x2_R7eYviUQJcbkuV%6{-$$n-k3}Y9qa~(i@=>|!DN32_^s{hTD~7){zJJsOsgl) zUt0nkc5QDVNgcp4IC3T`fK_sZAmfLg8i)_oy^=6LWmFnW@XgLvAO#SS$;pZ8-Vw6Z zqa!uvw;HKdJdKQy!X#Uu6(CbvGB9&Tkl@48d2K2b2rn?y=rUq0wec15-n}fN0IjT; zI1OV0mDM6ZEr+>B3p>JeC0Je}7XUl#(U=>c{phi~dp{Z`+LfzEwCpI!d71P;p!dhY z>~h6Aqm~b_Sc46BY~IJIK`hGX&I56 z(CyC|?Rg`g-^5e|E+FB6Oqs~31Maup3S-%*=-5|ca(L!9v;v=M8Pw;N3(2u@1ZO?u z!$I_NcoORPCAkAP&8**hO#nvxAA>+J2EDxd?%8(ode;ODRMM>;K#fzS?{~2r8Bj+6 z!3hDo)h=xMAL5x*?#%O#f;9pPQ(k5r99Tz!i$XFvbnsq^P}j_3F*-@dqdbbvY1BZaO>Y&$rwqStTiS6W1^ z_NaZc5RWip{&-z@lJ_;CpN^w2O^o!wVZWX2Vy=+suQ;+5K&>g0;cB|;3fMIPrjd$K zwU*zNH~N6WN?3lQk~F2p%Q^hu7W0KJrmGn&%eV3R!>D+$39B)jZ`|N6%n_L&1X{)j zdg`#1tPVJ@x$L(HvRch>D;xFwnKBHN7-Rb7{AJ-(Xr|u`=EwO3Gn~>K^JCxy!Db9&0t~TNB6U)%n=}O$%zC3hpv9BDjpod;Alh^+y_G<~|VYf`CiG z`Q@>yr9zE(0@tT;WP$6Wv-irKBr<}P7zh)90 zf7Qh(MjzAn%a76eVeN&z+!@mfzEy`K(CYwG&6;m@z@vAAEh*SHZ<+II4E5!XT;@Pm z%aF&c_P6+K25eNw(WWNq&#ygy>TmyF)IS@v#mD*n&wl<-T>c!-@xPZjuhz^KjLzuk zrYqV9^2oO9(`VK}hbUmf@&~YM>XiX2Bi}S=;o^6fpF%k}Bl}2QhRc`@@}n*LeK0$K zP?#pr3eUkTY|9n}+PYJ{f4QxJ0P?G7PHb_)f6(eMYiTPrj}{KVl9h9E;epQbyx-Q{Pp8W@SfF49yup+k0}se zY(gv;txy?`L622`iEbuh^o2tvx}dF zIL9hzDAiVVp>A|t4_HueO7jq8ESDz39qa{|qy^`e=Z4E73I+??+wu20_rMa!-|-Tu z4tD)5L=p4d{C(H9&$^72mGq$DVsr4}V?<9>n;Z7wae3g2&R>A=AUa6YP>$H)oA-G0 zyj>w=VzkNceiz>wtGlWJu-+}L9`XxUQp5y=Dbn8{rYkV1$$eq~hS=Z8Rw}2$7W^{N z-(|B&7vNx;Y6gFC_Rwh7KilH^@hkApe*Vw#9MAFBmcqY4pCE>dI{|60P1JaDTC)N-#f&M!)#rgMl|wZie{**F{~x3@Yy@^gx|Ts?ty+Lr#&M z7g{@aK&jXhCv*nBGIb0lFy2+Pggc;sg!;4w-}}U&DN>HWq1o6v$V)FKF<-K8OQf1I z;SCLJF`d}u<-yp(-17i6)RdHh5g!pl;6z6ENIDbw+LPNP2>UR6gT+*%8Ow)E;|p-! z0o$083_*0T1L9f-+?*iJrOO1!>>0Sj+w6q!|G11k#tXBma>#n?`X3*~*iL7Ka;~qxP zd-sO@mN?mJkhrks8@4A^6M{vjw#g9IP0tOk7UCt)ekas6(EV=4dUMtkL9`=dc^9sE zx*65RL^JYz8TQ;oe}vK+iNd``Yub(zlaq_htrXg7e#u zncz}9o?2%9wB-EHXGKoAdwpU;g!pqn_hA{z{m>;MUk%LC|A_b8Ob+ z6pn<(ZyrjSVA4#4>E${6@23zGUJ-_?4eb%x97KtdeFbKYeVCeKj>gMwk1KbG2gfqt2|Ls2vzxNCMQjgf9u{ON|!zg5c&kpYGvC2uux&}N!So(->MmQ#UCU$ zUGQO!f2XQamq#n;0`uOw8N_9dj^ziMh(YeZ__)mB3cE)|*KU|wO0HSfFOD^GR9)Ds znR!q8Bq7*;n?eKz2zCk3-1?h1i@-3#u4Z9&AU5|6aLgUy{^uPL{~S`~x2lF;+BEX}A3of6za^mNuUJ{r zzxVw9v!DNSJjZkV?;_9vaF+Ly6?4QyVFnAk@cQ-qvez+*Q$)E!#oI6P?|v$djIAG{LjlzsSXKlWE&J)giF7jGXHy9$&BiuE9uG^AOec=3Mihy=i9 z$yQ@-#@#�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 diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index 79e213ee39..4ccb810703 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -315,8 +315,6 @@ public: } -#include "opencv2/objdetect/linemod.hpp" -#include "opencv2/objdetect/erfilter.hpp" #include "opencv2/objdetect/detection_based_tracker.hpp" #endif diff --git a/modules/objdetect/include/opencv2/objdetect/erfilter.hpp b/modules/objdetect/include/opencv2/objdetect/erfilter.hpp deleted file mode 100644 index d7e07d80d8..0000000000 --- a/modules/objdetect/include/opencv2/objdetect/erfilter.hpp +++ /dev/null @@ -1,266 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#ifndef __OPENCV_OBJDETECT_ERFILTER_HPP__ -#define __OPENCV_OBJDETECT_ERFILTER_HPP__ - -#include "opencv2/core.hpp" -#include -#include -#include - -namespace cv -{ - -/*! - Extremal Region Stat structure - - The ERStat structure represents a class-specific Extremal Region (ER). - - An ER is a 4-connected set of pixels with all its grey-level values smaller than the values - in its outer boundary. A class-specific ER is selected (using a classifier) from all the ER's - in the component tree of the image. -*/ -struct CV_EXPORTS ERStat -{ -public: - //! Constructor - explicit ERStat(int level = 256, int pixel = 0, int x = 0, int y = 0); - //! Destructor - ~ERStat() { } - - //! seed point and the threshold (max grey-level value) - int pixel; - int level; - - //! incrementally computable features - int area; - int perimeter; - int euler; //!< euler number - Rect rect; - double raw_moments[2]; //!< order 1 raw moments to derive the centroid - double central_moments[3]; //!< order 2 central moments to construct the covariance matrix - std::deque *crossings;//!< horizontal crossings - float med_crossings; //!< median of the crossings at three different height levels - - //! 2nd stage features - float hole_area_ratio; - float convex_hull_ratio; - float num_inflexion_points; - - // TODO Other features can be added (average color, standard deviation, and such) - - - // TODO shall we include the pixel list whenever available (i.e. after 2nd stage) ? - std::vector *pixels; - - //! probability that the ER belongs to the class we are looking for - double probability; - - //! pointers preserving the tree structure of the component tree - ERStat* parent; - ERStat* child; - ERStat* next; - ERStat* prev; - - //! wenever the regions is a local maxima of the probability - bool local_maxima; - ERStat* max_probability_ancestor; - ERStat* min_probability_ancestor; -}; - -/*! - Base class for 1st and 2nd stages of Neumann and Matas scene text detection algorithms - Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012 - - Extracts the component tree (if needed) and filter the extremal regions (ER's) by using a given classifier. -*/ -class CV_EXPORTS ERFilter : public Algorithm -{ -public: - - //! callback with the classifier is made a class. By doing it we hide SVM, Boost etc. - class CV_EXPORTS Callback - { - public: - virtual ~Callback() { } - //! The classifier must return probability measure for the region. - virtual double eval(const ERStat& stat) = 0; //const = 0; //TODO why cannot use const = 0 here? - }; - - /*! - the key method. Takes image on input and returns the selected regions in a vector of ERStat - only distinctive ERs which correspond to characters are selected by a sequential classifier - \param image is the input image - \param regions is output for the first stage, input/output for the second one. - */ - virtual void run( InputArray image, std::vector& regions ) = 0; - - - //! set/get methods to set the algorithm properties, - virtual void setCallback(const Ptr& cb) = 0; - virtual void setThresholdDelta(int thresholdDelta) = 0; - virtual void setMinArea(float minArea) = 0; - virtual void setMaxArea(float maxArea) = 0; - virtual void setMinProbability(float minProbability) = 0; - virtual void setMinProbabilityDiff(float minProbabilityDiff) = 0; - virtual void setNonMaxSuppression(bool nonMaxSuppression) = 0; - virtual int getNumRejected() = 0; -}; - - -/*! - Create an Extremal Region Filter for the 1st stage classifier of N&M algorithm - Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012 - - The component tree of the image is extracted by a threshold increased step by step - from 0 to 255, incrementally computable descriptors (aspect_ratio, compactness, - number of holes, and number of horizontal crossings) are computed for each ER - and used as features for a classifier which estimates the class-conditional - probability P(er|character). The value of P(er|character) is tracked using the inclusion - relation of ER across all thresholds and only the ERs which correspond to local maximum - of the probability P(er|character) are selected (if the local maximum of the - probability is above a global limit pmin and the difference between local maximum and - local minimum is greater than minProbabilityDiff). - - \param cb Callback with the classifier. - default classifier can be implicitly load with function loadClassifierNM1() - from file in samples/cpp/trained_classifierNM1.xml - \param thresholdDelta Threshold step in subsequent thresholds when extracting the component tree - \param minArea The minimum area (% of image size) allowed for retreived ER's - \param minArea The maximum area (% of image size) allowed for retreived ER's - \param minProbability The minimum probability P(er|character) allowed for retreived ER's - \param nonMaxSuppression Whenever non-maximum suppression is done over the branch probabilities - \param minProbability The minimum probability difference between local maxima and local minima ERs -*/ -CV_EXPORTS Ptr createERFilterNM1(const Ptr& cb, - int thresholdDelta = 1, float minArea = 0.00025, - float maxArea = 0.13, float minProbability = 0.4, - bool nonMaxSuppression = true, - float minProbabilityDiff = 0.1); - -/*! - Create an Extremal Region Filter for the 2nd stage classifier of N&M algorithm - Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012 - - In the second stage, the ERs that passed the first stage are classified into character - and non-character classes using more informative but also more computationally expensive - features. The classifier uses all the features calculated in the first stage and the following - additional features: hole area ratio, convex hull ratio, and number of outer inflexion points. - - \param cb Callback with the classifier - default classifier can be implicitly load with function loadClassifierNM2() - from file in samples/cpp/trained_classifierNM2.xml - \param minProbability The minimum probability P(er|character) allowed for retreived ER's -*/ -CV_EXPORTS Ptr createERFilterNM2(const Ptr& cb, - float minProbability = 0.3); - - -/*! - Allow to implicitly load the default classifier when creating an ERFilter object. - The function takes as parameter the XML or YAML file with the classifier model - (e.g. trained_classifierNM1.xml) returns a pointer to ERFilter::Callback. -*/ - -CV_EXPORTS Ptr loadClassifierNM1(const std::string& filename); - -/*! - Allow to implicitly load the default classifier when creating an ERFilter object. - The function takes as parameter the XML or YAML file with the classifier model - (e.g. trained_classifierNM1.xml) returns a pointer to ERFilter::Callback. -*/ - -CV_EXPORTS Ptr loadClassifierNM2(const std::string& filename); - - -// computeNMChannels operation modes -enum { ERFILTER_NM_RGBLGrad = 0, - ERFILTER_NM_IHSGrad = 1 - }; - -/*! - Compute the different channels to be processed independently in the N&M algorithm - Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012 - - In N&M algorithm, the combination of intensity (I), hue (H), saturation (S), and gradient - magnitude channels (Grad) are used in order to obtain high localization recall. - This implementation also provides an alternative combination of red (R), green (G), blue (B), - lightness (L), and gradient magnitude (Grad). - - \param _src Source image. Must be RGB CV_8UC3. - \param _channels Output vector where computed channels are stored. - \param _mode Mode of operation. Currently the only available options are - ERFILTER_NM_RGBLGrad (by default) and ERFILTER_NM_IHSGrad. - -*/ -CV_EXPORTS void computeNMChannels(InputArray _src, OutputArrayOfArrays _channels, int _mode = ERFILTER_NM_RGBLGrad); - - -/*! - Find groups of Extremal Regions that are organized as text blocks. This function implements - the grouping algorithm described in: - Gomez L. and Karatzas D.: Multi-script Text Extraction from Natural Scenes, ICDAR 2013. - Notice that this implementation constrains the results to horizontally-aligned text and - latin script (since ERFilter classifiers are trained only for latin script detection). - - The algorithm combines two different clustering techniques in a single parameter-free procedure - to detect groups of regions organized as text. The maximally meaningful groups are fist detected - in several feature spaces, where each feature space is a combination of proximity information - (x,y coordinates) and a similarity measure (intensity, color, size, gradient magnitude, etc.), - thus providing a set of hypotheses of text groups. Evidence Accumulation framework is used to - combine all these hypotheses to get the final estimate. Each of the resulting groups are finally - validated using a classifier in order to assest if they form a valid horizontally-aligned text block. - - \param src Vector of sinle channel images CV_8UC1 from wich the regions were extracted. - \param regions Vector of ER's retreived from the ERFilter algorithm from each channel - \param filename The XML or YAML file with the classifier model (e.g. trained_classifier_erGrouping.xml) - \param minProbability The minimum probability for accepting a group - \param groups The output of the algorithm are stored in this parameter as list of rectangles. -*/ -CV_EXPORTS void erGrouping(InputArrayOfArrays src, std::vector > ®ions, - const std::string& filename, float minProbablity, - std::vector &groups); - -} -#endif // _OPENCV_ERFILTER_HPP_ diff --git a/modules/objdetect/include/opencv2/objdetect/linemod.hpp b/modules/objdetect/include/opencv2/objdetect/linemod.hpp deleted file mode 100644 index 46d869926f..0000000000 --- a/modules/objdetect/include/opencv2/objdetect/linemod.hpp +++ /dev/null @@ -1,455 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Copyright (C) 2013, OpenCV Foundation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#ifndef __OPENCV_OBJDETECT_LINEMOD_HPP__ -#define __OPENCV_OBJDETECT_LINEMOD_HPP__ - -#include "opencv2/core.hpp" -#include - -/****************************************************************************************\ -* LINE-MOD * -\****************************************************************************************/ - -namespace cv { -namespace linemod { - -/// @todo Convert doxy comments to rst - -/** - * \brief Discriminant feature described by its location and label. - */ -struct CV_EXPORTS Feature -{ - int x; ///< x offset - int y; ///< y offset - int label; ///< Quantization - - Feature() : x(0), y(0), label(0) {} - Feature(int x, int y, int label); - - void read(const FileNode& fn); - void write(FileStorage& fs) const; -}; - -inline Feature::Feature(int _x, int _y, int _label) : x(_x), y(_y), label(_label) {} - -struct CV_EXPORTS Template -{ - int width; - int height; - int pyramid_level; - std::vector features; - - void read(const FileNode& fn); - void write(FileStorage& fs) const; -}; - -/** - * \brief Represents a modality operating over an image pyramid. - */ -class QuantizedPyramid -{ -public: - // Virtual destructor - virtual ~QuantizedPyramid() {} - - /** - * \brief Compute quantized image at current pyramid level for online detection. - * - * \param[out] dst The destination 8-bit image. For each pixel at most one bit is set, - * representing its classification. - */ - virtual void quantize(Mat& dst) const =0; - - /** - * \brief Extract most discriminant features at current pyramid level to form a new template. - * - * \param[out] templ The new template. - */ - virtual bool extractTemplate(Template& templ) const =0; - - /** - * \brief Go to the next pyramid level. - * - * \todo Allow pyramid scale factor other than 2 - */ - virtual void pyrDown() =0; - -protected: - /// Candidate feature with a score - struct Candidate - { - Candidate(int x, int y, int label, float score); - - /// Sort candidates with high score to the front - bool operator<(const Candidate& rhs) const - { - return score > rhs.score; - } - - Feature f; - float score; - }; - - /** - * \brief Choose candidate features so that they are not bunched together. - * - * \param[in] candidates Candidate features sorted by score. - * \param[out] features Destination vector of selected features. - * \param[in] num_features Number of candidates to select. - * \param[in] distance Hint for desired distance between features. - */ - static void selectScatteredFeatures(const std::vector& candidates, - std::vector& features, - size_t num_features, float distance); -}; - -inline QuantizedPyramid::Candidate::Candidate(int x, int y, int label, float _score) : f(x, y, label), score(_score) {} - -/** - * \brief Interface for modalities that plug into the LINE template matching representation. - * - * \todo Max response, to allow optimization of summing (255/MAX) features as uint8 - */ -class CV_EXPORTS Modality -{ -public: - // Virtual destructor - virtual ~Modality() {} - - /** - * \brief Form a quantized image pyramid from a source image. - * - * \param[in] src The source image. Type depends on the modality. - * \param[in] mask Optional mask. If not empty, unmasked pixels are set to zero - * in quantized image and cannot be extracted as features. - */ - Ptr process(const Mat& src, - const Mat& mask = Mat()) const - { - return processImpl(src, mask); - } - - virtual String name() const =0; - - virtual void read(const FileNode& fn) =0; - virtual void write(FileStorage& fs) const =0; - - /** - * \brief Create modality by name. - * - * The following modality types are supported: - * - "ColorGradient" - * - "DepthNormal" - */ - static Ptr create(const String& modality_type); - - /** - * \brief Load a modality from file. - */ - static Ptr create(const FileNode& fn); - -protected: - // Indirection is because process() has a default parameter. - virtual Ptr processImpl(const Mat& src, - const Mat& mask) const =0; -}; - -/** - * \brief Modality that computes quantized gradient orientations from a color image. - */ -class CV_EXPORTS ColorGradient : public Modality -{ -public: - /** - * \brief Default constructor. Uses reasonable default parameter values. - */ - ColorGradient(); - - /** - * \brief Constructor. - * - * \param weak_threshold When quantizing, discard gradients with magnitude less than this. - * \param num_features How many features a template must contain. - * \param strong_threshold Consider as candidate features only gradients whose norms are - * larger than this. - */ - ColorGradient(float weak_threshold, size_t num_features, float strong_threshold); - - virtual String name() const; - - virtual void read(const FileNode& fn); - virtual void write(FileStorage& fs) const; - - float weak_threshold; - size_t num_features; - float strong_threshold; - -protected: - virtual Ptr processImpl(const Mat& src, - const Mat& mask) const; -}; - -/** - * \brief Modality that computes quantized surface normals from a dense depth map. - */ -class CV_EXPORTS DepthNormal : public Modality -{ -public: - /** - * \brief Default constructor. Uses reasonable default parameter values. - */ - DepthNormal(); - - /** - * \brief Constructor. - * - * \param distance_threshold Ignore pixels beyond this distance. - * \param difference_threshold When computing normals, ignore contributions of pixels whose - * depth difference with the central pixel is above this threshold. - * \param num_features How many features a template must contain. - * \param extract_threshold Consider as candidate feature only if there are no differing - * orientations within a distance of extract_threshold. - */ - DepthNormal(int distance_threshold, int difference_threshold, size_t num_features, - int extract_threshold); - - virtual String name() const; - - virtual void read(const FileNode& fn); - virtual void write(FileStorage& fs) const; - - int distance_threshold; - int difference_threshold; - size_t num_features; - int extract_threshold; - -protected: - virtual Ptr processImpl(const Mat& src, - const Mat& mask) const; -}; - -/** - * \brief Debug function to colormap a quantized image for viewing. - */ -void colormap(const Mat& quantized, Mat& dst); - -/** - * \brief Represents a successful template match. - */ -struct CV_EXPORTS Match -{ - Match() - { - } - - Match(int x, int y, float similarity, const String& class_id, int template_id); - - /// Sort matches with high similarity to the front - bool operator<(const Match& rhs) const - { - // Secondarily sort on template_id for the sake of duplicate removal - if (similarity != rhs.similarity) - return similarity > rhs.similarity; - else - return template_id < rhs.template_id; - } - - bool operator==(const Match& rhs) const - { - return x == rhs.x && y == rhs.y && similarity == rhs.similarity && class_id == rhs.class_id; - } - - int x; - int y; - float similarity; - String class_id; - int template_id; -}; - -inline -Match::Match(int _x, int _y, float _similarity, const String& _class_id, int _template_id) - : x(_x), y(_y), similarity(_similarity), class_id(_class_id), template_id(_template_id) -{} - -/** - * \brief Object detector using the LINE template matching algorithm with any set of - * modalities. - */ -class CV_EXPORTS Detector -{ -public: - /** - * \brief Empty constructor, initialize with read(). - */ - Detector(); - - /** - * \brief Constructor. - * - * \param modalities Modalities to use (color gradients, depth normals, ...). - * \param T_pyramid Value of the sampling step T at each pyramid level. The - * number of pyramid levels is T_pyramid.size(). - */ - Detector(const std::vector< Ptr >& modalities, const std::vector& T_pyramid); - - /** - * \brief Detect objects by template matching. - * - * Matches globally at the lowest pyramid level, then refines locally stepping up the pyramid. - * - * \param sources Source images, one for each modality. - * \param threshold Similarity threshold, a percentage between 0 and 100. - * \param[out] matches Template matches, sorted by similarity score. - * \param class_ids If non-empty, only search for the desired object classes. - * \param[out] quantized_images Optionally return vector of quantized images. - * \param masks The masks for consideration during matching. The masks should be CV_8UC1 - * where 255 represents a valid pixel. If non-empty, the vector must be - * the same size as sources. Each element must be - * empty or the same size as its corresponding source. - */ - void match(const std::vector& sources, float threshold, std::vector& matches, - const std::vector& class_ids = std::vector(), - OutputArrayOfArrays quantized_images = noArray(), - const std::vector& masks = std::vector()) const; - - /** - * \brief Add new object template. - * - * \param sources Source images, one for each modality. - * \param class_id Object class ID. - * \param object_mask Mask separating object from background. - * \param[out] bounding_box Optionally return bounding box of the extracted features. - * - * \return Template ID, or -1 if failed to extract a valid template. - */ - int addTemplate(const std::vector& sources, const String& class_id, - const Mat& object_mask, Rect* bounding_box = NULL); - - /** - * \brief Add a new object template computed by external means. - */ - int addSyntheticTemplate(const std::vector