/* dst = src */ void Mat::copyTo( OutputArray _dst ) const { int dtype = _dst.type(); if( _dst.fixedType() && dtype != type() ) { CV_Assert( channels() == CV_MAT_CN(dtype) ); convertTo( _dst, dtype ); return; } if( empty() ) { _dst.release(); return; } if( dims <= 2 ) { _dst.create( rows, cols, type() ); Mat dst = _dst.getMat(); if( data == dst.data ) return; if( rows > 0 && cols > 0 ) { const uchar* sptr = data; uchar* dptr = dst.data; // to handle the copying 1xn matrix => nx1 std vector. Size sz = size() == dst.size() ? getContinuousSize(*this, dst) : getContinuousSize(*this); size_t len = sz.width*elemSize(); for( ; sz.height--; sptr += step, dptr += dst.step ) memcpy( dptr, sptr, len ); } return; } _dst.create( dims, size, type() ); Mat dst = _dst.getMat(); if( data == dst.data ) return; if( total() != 0 ) { const Mat* arrays[] = { this, &dst }; uchar* ptrs[2]; NAryMatIterator it(arrays, ptrs, 2); size_t sz = it.size*elemSize(); for( size_t i = 0; i < it.nplanes; i++, ++it ) memcpy(ptrs[1], ptrs[0], sz); } }
static double normDiff_(const Mat& srcmat1, const Mat& srcmat2) { ElemFunc f; UpdateFunc update; typedef typename UpdateFunc::rtype ST; assert(DataType<T>::depth == srcmat1.depth()); Size size = getContinuousSize(srcmat1, srcmat2, srcmat1.channels()); ST s = 0; for (int y = 0; y < size.height; y++) { const T* src1 = (const T*)(srcmat1.data + srcmat1.step * y); const T* src2 = (const T*)(srcmat2.data + srcmat2.step * y); int x = 0; for (; x <= size.width - 4; x += 4) { s = update(s, (ST)f(src1[x] - src2[x])); s = update(s, (ST)f(src1[x+1] - src2[x+1])); s = update(s, (ST)f(src1[x+2] - src2[x+2])); s = update(s, (ST)f(src1[x+3] - src2[x+3])); } for (; x < size.width; x++) { s = update(s, (ST)f(src1[x] - src2[x])); } } return s; }
static Scalar meanBlock_(const Mat& srcmat, const Mat& maskmat) { assert(DataType<T>::type == srcmat.type() && CV_8U == maskmat.type() && srcmat.size() == maskmat.size()); Size size = getContinuousSize(srcmat, maskmat); ST s0 = 0; WT s = 0; int y, remaining = BLOCK_SIZE, pix = 0; for (y = 0; y < size.height; y++) { const T* src = (const T*)(srcmat.data + srcmat.step * y); const uchar* mask = maskmat.data + maskmat.step * y; int x = 0; while (x < size.width) { int limit = std::min(remaining, size.width - x); remaining -= limit; limit += x; for (; x < limit; x++) if (mask[x]) { s += src[x], pix++; } if (remaining == 0 || (x == size.width && y == size.height - 1)) { s0 += s; s = 0; remaining = BLOCK_SIZE; } } } return rawToScalar(s0) * (1. / std::max(pix, 1)); }
template<typename T> static void minMaxIndx_(const Mat& srcmat, double* minVal, double* maxVal, int* minLoc, int* maxLoc) { assert(DataType<T>::type == srcmat.type()); const T* src = (const T*)srcmat.data; size_t step = srcmat.step / sizeof(src[0]); T min_val = src[0], max_val = min_val; int min_loc = 0, max_loc = 0; int x, loc = 0; Size size = getContinuousSize(srcmat); for (; size.height--; src += step, loc += size.width) { for (x = 0; x < size.width; x++) { T val = src[x]; if (val < min_val) { min_val = val; min_loc = loc + x; } else if (val > max_val) { max_val = val; max_loc = loc + x; } } } *minLoc = min_loc; *maxLoc = max_loc; *minVal = min_val; *maxVal = max_val; }
static Scalar sumBlock_(const Mat& srcmat) { assert(DataType<T>::type == srcmat.type()); Size size = getContinuousSize(srcmat); ST s0 = 0; WT s = 0; int y, remaining = BLOCK_SIZE; for (y = 0; y < size.height; y++) { const T* src = (const T*)(srcmat.data + srcmat.step * y); int x = 0; while (x < size.width) { int limit = std::min(remaining, size.width - x); remaining -= limit; limit += x; for (; x <= limit - 4; x += 4) { s += src[x]; s += src[x+1]; s += src[x+2]; s += src[x+3]; } for (; x < limit; x++) { s += src[x]; } if (remaining == 0 || (x == size.width && y == size.height - 1)) { s0 += s; s = 0; remaining = BLOCK_SIZE; } } } return rawToScalar(s0); }
template<class SqrOp> static void meanStdDevMask_(const Mat& srcmat, const Mat& maskmat, Scalar& _mean, Scalar& _stddev) { SqrOp sqr; typedef typename SqrOp::type1 T; typedef typename SqrOp::rtype ST; typedef typename DataType<ST>::channel_type ST1; assert(DataType<T>::type == srcmat.type() && CV_8U == maskmat.type() && srcmat.size() == maskmat.size()); Size size = getContinuousSize(srcmat, maskmat); ST s = 0, sq = 0; int pix = 0; for (int y = 0; y < size.height; y++) { const T* src = (const T*)(srcmat.data + srcmat.step * y); const uchar* mask = maskmat.data + maskmat.step * y; for (int x = 0; x < size.width; x++) if (mask[x]) { T v = src[x]; s += v; sq += sqr(v); pix++; } } _mean = _stddev = Scalar(); double scale = 1. / std::max(pix, 1); for (int i = 0; i < DataType<ST>::channels; i++) { double t = ((ST1*)&s)[i] * scale; _mean.val[i] = t; _stddev.val[i] = std::sqrt(std::max(((ST1*)&sq)[i] * scale - t * t, 0.)); } }
template<typename T> static void copyMask_(const Mat& srcmat, Mat& dstmat, const Mat& maskmat) { const uchar* mask = maskmat.data; size_t sstep = srcmat.step; size_t dstep = dstmat.step; size_t mstep = maskmat.step; Size size = getContinuousSize(srcmat, dstmat, maskmat); for( int y = 0; y < size.height; y++, mask += mstep ) { const T* src = (const T*)(srcmat.data + sstep*y); T* dst = (T*)(dstmat.data + dstep*y); int x = 0; for( ; x <= size.width - 4; x += 4 ) { if( mask[x] ) dst[x] = src[x]; if( mask[x+1] ) dst[x+1] = src[x+1]; if( mask[x+2] ) dst[x+2] = src[x+2]; if( mask[x+3] ) dst[x+3] = src[x+3]; } for( ; x < size.width; x++ ) if( mask[x] ) dst[x] = src[x]; } }
template<class Op> static void binarySOpCn_( const Mat& srcmat, Mat& dstmat, const Scalar& _scalar ) { Op op; typedef typename Op::type1 T; typedef typename Op::type2 WT; typedef typename Op::rtype DT; const T* src0 = (const T*)srcmat.data; DT* dst0 = (DT*)dstmat.data; size_t step1 = srcmat.step/sizeof(src0[0]); size_t step = dstmat.step/sizeof(dst0[0]); int cn = dstmat.channels(); Size size = getContinuousSize( srcmat, dstmat, cn ); WT scalar[12]; _scalar.convertTo(scalar, cn, 12); for( ; size.height--; src0 += step1, dst0 += step ) { int i, len = size.width; const T* src = src0; T* dst = dst0; for( ; (len -= 12) >= 0; dst += 12, src += 12 ) { DT t0 = op(src[0], scalar[0]); DT t1 = op(src[1], scalar[1]); dst[0] = t0; dst[1] = t1; t0 = op(src[2], scalar[2]); t1 = op(src[3], scalar[3]); dst[2] = t0; dst[3] = t1; t0 = op(src[4], scalar[4]); t1 = op(src[5], scalar[5]); dst[4] = t0; dst[5] = t1; t0 = op(src[6], scalar[6]); t1 = op(src[7], scalar[7]); dst[6] = t0; dst[7] = t1; t0 = op(src[8], scalar[8]); t1 = op(src[9], scalar[9]); dst[8] = t0; dst[9] = t1; t0 = op(src[10], scalar[10]); t1 = op(src[11], scalar[11]); dst[10] = t0; dst[11] = t1; } for( (len) += 12, i = 0; i < (len); i++ ) dst[i] = op((WT)src[i], scalar[i]); } }
static double normMaskBlock_(const Mat& srcmat, const Mat& maskmat) { ElemFunc f; UpdateFunc update; GlobUpdateFunc globUpdate; typedef typename ElemFunc::type1 T; typedef typename UpdateFunc::rtype WT; typedef typename GlobUpdateFunc::rtype ST; assert(DataType<T>::depth == srcmat.depth()); Size size = getContinuousSize(srcmat, maskmat); ST s0 = 0; WT s = 0; int y, remaining = BLOCK_SIZE; for (y = 0; y < size.height; y++) { const T* src = (const T*)(srcmat.data + srcmat.step * y); const uchar* mask = maskmat.data + maskmat.step * y; int x = 0; while (x < size.width) { int limit = std::min(remaining, size.width - x); remaining -= limit; limit += x; for (; x <= limit - 4; x += 4) { if (mask[x]) { s = update(s, (WT)f(src[x])); } if (mask[x+1]) { s = update(s, (WT)f(src[x+1])); } if (mask[x+2]) { s = update(s, (WT)f(src[x+2])); } if (mask[x+3]) { s = update(s, (WT)f(src[x+3])); } } for (; x < limit; x++) { if (mask[x]) { s = update(s, (WT)f(src[x])); } } if (remaining == 0 || (x == size.width && y == size.height - 1)) { s0 = globUpdate(s0, (ST)s); s = 0; remaining = BLOCK_SIZE; } } } return s0; }
template<typename T> static void minMaxIndxMask_(const Mat& srcmat, const Mat& maskmat, double* minVal, double* maxVal, int* minLoc, int* maxLoc) { assert(DataType<T>::type == srcmat.type() && CV_8U == maskmat.type() && srcmat.size() == maskmat.size()); const T* src = (const T*)srcmat.data; const uchar* mask = maskmat.data; size_t step = srcmat.step / sizeof(src[0]); size_t maskstep = maskmat.step; T min_val = 0, max_val = 0; int min_loc = -1, max_loc = -1; int x = 0, y, loc = 0; Size size = getContinuousSize(srcmat, maskmat); for (y = 0; y < size.height; y++, src += step, mask += maskstep, loc += size.width) { for (x = 0; x < size.width; x++) if (mask[x] != 0) { min_loc = max_loc = loc + x; min_val = max_val = src[x]; break; } if (x < size.width) { break; } } for (; y < size.height; x = 0, y++, src += step, mask += maskstep, loc += size.width) { for (; x < size.width; x++) { T val = src[x]; int m = mask[x]; if (val < min_val && m) { min_val = val; min_loc = loc + x; } else if (val > max_val && m) { max_val = val; max_loc = loc + x; } } } *minLoc = min_loc; *maxLoc = max_loc; *minVal = min_val; *maxVal = max_val; }
static Scalar mean_(const Mat& srcmat, const Mat& maskmat) { assert(DataType<T>::type == srcmat.type() && CV_8U == maskmat.type() && srcmat.size() == maskmat.size()); Size size = getContinuousSize(srcmat, maskmat); ST s = 0; int y, pix = 0; for (y = 0; y < size.height; y++) { const T* src = (const T*)(srcmat.data + srcmat.step * y); const uchar* mask = maskmat.data + maskmat.step * y; for (int x = 0; x < size.width; x++) if (mask[x]) { s += src[x], pix++; } } return rawToScalar(s) * (1. / std::max(pix, 1)); }
template<typename T> static void splitC2_( const Mat& srcmat, Mat* dstmat ) { Size size = getContinuousSize( srcmat, dstmat[0], dstmat[1] ); for( int y = 0; y < size.height; y++ ) { const T* src = (const T*)(srcmat.data + srcmat.step*y); T* dst0 = (T*)(dstmat[0].data + dstmat[0].step*y); T* dst1 = (T*)(dstmat[1].data + dstmat[1].step*y); for( int x = 0; x < size.width; x++ ) { T t0 = src[x*2], t1 = src[x*2+1]; dst0[x] = t0; dst1[x] = t1; } } }
static int countNonZero_(const Mat& srcmat) { //assert( DataType<T>::type == srcmat.type() ); const T* src = (const T*)srcmat.data; size_t step = srcmat.step / sizeof(src[0]); Size size = getContinuousSize(srcmat); int nz = 0; for (; size.height--; src += step) { int x = 0; for (; x <= size.width - 4; x += 4) { nz += (src[x] != 0) + (src[x+1] != 0) + (src[x+2] != 0) + (src[x+3] != 0); } for (; x < size.width; x++) { nz += src[x] != 0; } } return nz; }
template<class Op, class VecOp> static void binaryOpC1_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat ) { Op op; VecOp vecOp; typedef typename Op::type1 T1; typedef typename Op::type2 T2; typedef typename Op::rtype DT; const T1* src1 = (const T1*)srcmat1.data; const T2* src2 = (const T2*)srcmat2.data; DT* dst = (DT*)dstmat.data; size_t step1 = srcmat1.step/sizeof(src1[0]); size_t step2 = srcmat2.step/sizeof(src2[0]); size_t step = dstmat.step/sizeof(dst[0]); Size size = getContinuousSize( srcmat1, srcmat2, dstmat, dstmat.channels() ); if( size.width == 1 ) { for( ; size.height--; src1 += step1, src2 += step2, dst += step ) dst[0] = op( src1[0], src2[0] ); return; } for( ; size.height--; src1 += step1, src2 += step2, dst += step ) { int x = vecOp(src1, src2, dst, size.width); for( ; x <= size.width - 4; x += 4 ) { DT f0, f1; f0 = op( src1[x], src2[x] ); f1 = op( src1[x+1], src2[x+1] ); dst[x] = f0; dst[x+1] = f1; f0 = op(src1[x+2], src2[x+2]); f1 = op(src1[x+3], src2[x+3]); dst[x+2] = f0; dst[x+3] = f1; } for( ; x < size.width; x++ ) dst[x] = op( src1[x], src2[x] ); } }
static Scalar sum_(const Mat& srcmat) { assert(DataType<T>::type == srcmat.type()); Size size = getContinuousSize(srcmat); ST s = 0; for (int y = 0; y < size.height; y++) { const T* src = (const T*)(srcmat.data + srcmat.step * y); int x = 0; for (; x <= size.width - 4; x += 4) { s += src[x]; s += src[x+1]; s += src[x+2]; s += src[x+3]; } for (; x < size.width; x++) { s += src[x]; } } return rawToScalar(s); }
static double normDiffBlock_(const Mat& srcmat1, const Mat& srcmat2) { ElemFunc f; UpdateFunc update; GlobUpdateFunc globUpdate; typedef typename UpdateFunc::rtype WT; typedef typename GlobUpdateFunc::rtype ST; assert(DataType<T>::depth == srcmat1.depth()); Size size = getContinuousSize(srcmat1, srcmat2, srcmat1.channels()); ST s0 = 0; WT s = 0; int y, remaining = BLOCK_SIZE; for (y = 0; y < size.height; y++) { const T* src1 = (const T*)(srcmat1.data + srcmat1.step * y); const T* src2 = (const T*)(srcmat2.data + srcmat2.step * y); int x = 0; while (x < size.width) { int limit = std::min(remaining, size.width - x); remaining -= limit; limit += x; for (; x <= limit - 4; x += 4) { s = update(s, (WT)f(src1[x] - src2[x])); s = update(s, (WT)f(src1[x+1] - src2[x+1])); s = update(s, (WT)f(src1[x+2] - src2[x+2])); s = update(s, (WT)f(src1[x+3] - src2[x+3])); } for (; x < limit; x++) { s = update(s, (WT)f(src1[x] - src2[x])); } if (remaining == 0 || (x == size.width && y == size.height - 1)) { s0 = globUpdate(s0, (ST)s); s = 0; remaining = BLOCK_SIZE; } } } return s0; }
static double normBlock_(const Mat& srcmat) { ElemFunc f; UpdateFunc update; GlobUpdateFunc globUpdate; typedef typename ElemFunc::type1 T; typedef typename UpdateFunc::rtype WT; typedef typename GlobUpdateFunc::rtype ST; assert(DataType<T>::depth == srcmat.depth()); Size size = getContinuousSize(srcmat, srcmat.channels()); ST s0 = 0; // luckily, 0 is the correct starting value for both + and max update operations WT s = 0; int y, remaining = BLOCK_SIZE; for (y = 0; y < size.height; y++) { const T* src = (const T*)(srcmat.data + srcmat.step * y); int x = 0; while (x < size.width) { int limit = std::min(remaining, size.width - x); remaining -= limit; limit += x; for (; x <= limit - 4; x += 4) { s = update(s, (WT)f(src[x])); s = update(s, (WT)f(src[x+1])); s = update(s, (WT)f(src[x+2])); s = update(s, (WT)f(src[x+3])); } for (; x < limit; x++) { s = update(s, (WT)f(src[x])); } if (remaining == 0 || (x == size.width && y == size.height - 1)) { s0 = globUpdate(s0, (ST)s); s = 0; remaining = BLOCK_SIZE; } } } return s0; }
void Mat::copyTo( OutputArray _dst, InputArray _mask ) const { Mat mask = _mask.getMat(); if( !mask.data ) { copyTo(_dst); return; } int cn = channels(), mcn = mask.channels(); CV_Assert( mask.depth() == CV_8U && (mcn == 1 || mcn == cn) ); bool colorMask = mcn > 1; size_t esz = colorMask ? elemSize1() : elemSize(); BinaryFunc copymask = getCopyMaskFunc(esz); uchar* data0 = _dst.getMat().data; _dst.create( dims, size, type() ); Mat dst = _dst.getMat(); if( dst.data != data0 ) // do not leave dst uninitialized dst = Scalar(0); if( dims <= 2 ) { CV_Assert( size() == mask.size() ); Size sz = getContinuousSize(*this, dst, mask, mcn); copymask(data, step, mask.data, mask.step, dst.data, dst.step, sz, &esz); return; } const Mat* arrays[] = { this, &dst, &mask, 0 }; uchar* ptrs[3]; NAryMatIterator it(arrays, ptrs); Size sz((int)(it.size*mcn), 1); for( size_t i = 0; i < it.nplanes; i++, ++it ) copymask(ptrs[0], 0, ptrs[2], 0, ptrs[1], 0, sz, &esz); }
static double normMask_(const Mat& srcmat, const Mat& maskmat) { ElemFunc f; UpdateFunc update; typedef typename ElemFunc::type1 T; typedef typename UpdateFunc::rtype ST; assert(DataType<T>::depth == srcmat.depth()); Size size = getContinuousSize(srcmat, maskmat); ST s = 0; for (int y = 0; y < size.height; y++) { const T* src = (const T*)(srcmat.data + srcmat.step * y); const uchar* mask = maskmat.data + maskmat.step * y; int x = 0; for (; x <= size.width - 4; x += 4) { if (mask[x]) { s = update(s, (ST)f(src[x])); } if (mask[x+1]) { s = update(s, (ST)f(src[x+1])); } if (mask[x+2]) { s = update(s, (ST)f(src[x+2])); } if (mask[x+3]) { s = update(s, (ST)f(src[x+3])); } } for (; x < size.width; x++) { if (mask[x]) { s = update(s, (ST)f(src[x])); } } } return s; }
/* dst = src */ void Mat::copyTo( OutputArray _dst ) const { int dtype = _dst.type(); if( _dst.fixedType() && dtype != type() ) { CV_Assert( channels() == CV_MAT_CN(dtype) ); convertTo( _dst, dtype ); return; } if( empty() ) { _dst.release(); return; } if( _dst.isUMat() ) { _dst.create( dims, size.p, type() ); UMat dst = _dst.getUMat(); size_t i, sz[CV_MAX_DIM], dstofs[CV_MAX_DIM], esz = elemSize(); for( i = 0; i < (size_t)dims; i++ ) sz[i] = size.p[i]; sz[dims-1] *= esz; dst.ndoffset(dstofs); dstofs[dims-1] *= esz; dst.u->currAllocator->upload(dst.u, data, dims, sz, dstofs, dst.step.p, step.p); return; } if( dims <= 2 ) { _dst.create( rows, cols, type() ); Mat dst = _dst.getMat(); if( data == dst.data ) return; if( rows > 0 && cols > 0 ) { const uchar* sptr = data; uchar* dptr = dst.data; Size sz = getContinuousSize(*this, dst); size_t len = sz.width*elemSize(); for( ; sz.height--; sptr += step, dptr += dst.step ) memcpy( dptr, sptr, len ); } return; } _dst.create( dims, size, type() ); Mat dst = _dst.getMat(); if( data == dst.data ) return; if( total() != 0 ) { const Mat* arrays[] = { this, &dst }; uchar* ptrs[2]; NAryMatIterator it(arrays, ptrs, 2); size_t sz = it.size*elemSize(); for( size_t i = 0; i < it.nplanes; i++, ++it ) memcpy(ptrs[1], ptrs[0], sz); } }