diff --git a/modules/core/src/hal_replacement.hpp b/modules/core/src/hal_replacement.hpp index 15149453c7..498cd63700 100644 --- a/modules/core/src/hal_replacement.hpp +++ b/modules/core/src/hal_replacement.hpp @@ -843,6 +843,27 @@ inline int hal_ni_minMaxIdx(const uchar* src_data, size_t src_step, int width, i #define cv_hal_minMaxIdx hal_ni_minMaxIdx //! @endcond +/** + @brief calculates the mean and the standard deviation of array elements independently for each channel + @param src_data Source image + @param src_step Source image + @param width Source image dimensions + @param height Source image dimensions + @param src_type Type of source image + @param mean_val Array of per-channel mean values. May be nullptr, if mean value is not required. + @param stddev_val Array of per-channel standard deviation values. May be nullptr, if stddev value is not required. + @param mask Specified array region. + @param mask_step Mask array step. + @sa meanStdDev +*/ +inline int hal_ni_meanStdDev(const uchar* src_data, size_t src_step, int width, int height, + int src_type, double* mean_val, double* stddev_val, uchar* mask, size_t mask_step) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_meanStdDev hal_ni_meanStdDev +//! @endcond + /** @brief hal_flip @param src_type source and destination image type diff --git a/modules/core/src/mean.dispatch.cpp b/modules/core/src/mean.dispatch.cpp index 0f94e5421a..b6ea926255 100644 --- a/modules/core/src/mean.dispatch.cpp +++ b/modules/core/src/mean.dispatch.cpp @@ -525,12 +525,55 @@ void meanStdDev(InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray Mat src = _src.getMat(), mask = _mask.getMat(); + CV_Assert(mask.empty() || src.size == mask.size); + CV_OVX_RUN(!ovx::skipSmallImages(src.cols, src.rows), openvx_meanStdDev(src, _mean, _sdv, mask)) CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_meanStdDev(src, _mean, _sdv, mask)); int k, cn = src.channels(), depth = src.depth(); + Mat mean_mat, stddev_mat; + + if(_mean.needed()) + { + if( !_mean.fixedSize() ) + _mean.create(cn, 1, CV_64F, -1, true); + + mean_mat = _mean.getMat(); + int dcn = (int)mean_mat.total(); + CV_Assert( mean_mat.type() == CV_64F && mean_mat.isContinuous() && + (mean_mat.cols == 1 || mean_mat.rows == 1) && dcn >= cn ); + } + + if (_sdv.needed()) + { + if( !_sdv.fixedSize() ) + _sdv.create(cn, 1, CV_64F, -1, true); + + stddev_mat = _sdv.getMat(); + int dcn = (int)stddev_mat.total(); + CV_Assert( stddev_mat.type() == CV_64F && stddev_mat.isContinuous() && + (stddev_mat.cols == 1 || stddev_mat.rows == 1) && dcn >= cn ); + } + + if (src.isContinuous() && mask.isContinuous()) + { + CALL_HAL(meanStdDev, cv_hal_meanStdDev, src.data, 0, (int)src.total(), 1, src.type(), + _mean.needed() ? mean_mat.ptr() : nullptr, + _sdv.needed() ? stddev_mat.ptr() : nullptr, + mask.data, 0); + } + else + { + if (src.dims <= 2) + { + CALL_HAL(meanStdDev, cv_hal_meanStdDev, src.data, src.step, src.cols, src.rows, src.type(), + _mean.needed() ? mean_mat.ptr() : nullptr, + _sdv.needed() ? stddev_mat.ptr() : nullptr, + mask.data, mask.step); + } + } SumSqrFunc func = getSumSqrFunc(depth); @@ -600,20 +643,22 @@ void meanStdDev(InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray sq[k] = std::sqrt(std::max(sq[k]*scale - s[k]*s[k], 0.)); } - for( j = 0; j < 2; j++ ) + if (_mean.needed()) { - const double* sptr = j == 0 ? s : sq; - _OutputArray _dst = j == 0 ? _mean : _sdv; - if( !_dst.needed() ) - continue; + const double* sptr = s; + int dcn = (int)mean_mat.total(); + double* dptr = mean_mat.ptr(); + for( k = 0; k < cn; k++ ) + dptr[k] = sptr[k]; + for( ; k < dcn; k++ ) + dptr[k] = 0; + } - if( !_dst.fixedSize() ) - _dst.create(cn, 1, CV_64F, -1, true); - Mat dst = _dst.getMat(); - int dcn = (int)dst.total(); - CV_Assert( dst.type() == CV_64F && dst.isContinuous() && - (dst.cols == 1 || dst.rows == 1) && dcn >= cn ); - double* dptr = dst.ptr(); + if (_sdv.needed()) + { + const double* sptr = sq; + int dcn = (int)stddev_mat.total(); + double* dptr = stddev_mat.ptr(); for( k = 0; k < cn; k++ ) dptr[k] = sptr[k]; for( ; k < dcn; k++ )