例如src.copyTo(src,mask)是绝对不能成功的。原本只想把理由粗略说一下,但是后来想一想看一看源代码还是有好处的,于是去源代码里面看了看,怎么知道由于本人的过于才疏学浅,就这么一看就看了我好几个小时(包括看了恒大对山东的0:0),虽然还不是非常清楚,还是贴上来简单说说吧:
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 ) { 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); }
重点是这里:
copymask(data, step, mask.data, mask.step, dst.data, dst.step, sz, &esz);
BinaryFunc copymask = getCopyMaskFunc(esz);
BinaryFunc getCopyMaskFunc(size_t esz) { return esz <= 32 && copyMaskTab[esz] ? copyMaskTab[esz] : copyMaskGeneric; }
BinaryFunc copyMaskTab[] = { 0, copyMask8u, copyMask16u, copyMask8uC3, copyMask32s, 0, copyMask16uC3, 0, copyMask32sC2, 0, 0, 0, copyMask32sC3, 0, 0, 0, copyMask32sC4, 0, 0, 0, 0, 0, 0, 0, copyMask32sC6, 0, 0, 0, 0, 0, 0, 0, copyMask32sC8 };
重点来了,我搞了好久才发现原来copyMaskXXX(例如copyMask16uC3)是这样被定义以及使用的,这让我受益匪浅!!!:
#define DEF_COPY_MASK(suffix, type) \ static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \ uchar* dst, size_t dstep, Size size, void*) \ { \ copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \ } DEF_COPY_MASK(8u, uchar); DEF_COPY_MASK(16u, ushort); DEF_COPY_MASK(8uC3, Vec3b); DEF_COPY_MASK(32s, int); DEF_COPY_MASK(16uC3, Vec3s); DEF_COPY_MASK(32sC2, Vec2i); DEF_COPY_MASK(32sC3, Vec3i); DEF_COPY_MASK(32sC4, Vec4i); DEF_COPY_MASK(32sC6, Vec6i); DEF_COPY_MASK(32sC8, Vec8i);
因此,分析到这里,我们应该知道,我们真正需要分析的是这个函数:
template<typename T> static void copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size) { for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep ) { const T* src = (const T*)_src; T* dst = (T*)_dst; int x = 0; #if CV_ENABLE_UNROLLED 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]; } #endif for( ; x < size.width; x++ ) if( mask[x] ) dst[x] = src[x]; } }
这些小打小闹且浪费时间的源代码分析虽然是有益的,但是对学习视觉分析个人认为没有太大必要,我还是得赶紧搞搞真正的算法才行。