用mask掩码处理图片,Mat::copyTo函数第一个用于输出的传入参数不能是原图片
来源:互联网 发布:破获特大网络售假药案 编辑:程序博客网 时间:2024/04/28 07:22
例如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);
于是现在需要返回去找copymask了(不得不说qtcreator真是一个比较完美的IDE):
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 voidcopyMask_(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]; }}
从这个函数里面我们能看到,这个函数会检测mask中相应位置是否为0,如果不为0是会把输入Mat相应位置的值直接复制到输出中的,但是,如果mask中相应位置为0呢,遇到为0的位置,copyMask函数并不会把相应的输出设置为0,而是不理它,让它维持原值,因此,如果我们Mat::copyTo的传入参数为源图像,那么mask中相应不为0的部分会原封不动输出,而相应为0的地方也会保持不变地输出!因此,这样使用并不能成功。
这些小打小闹且浪费时间的源代码分析虽然是有益的,但是对学习视觉分析个人认为没有太大必要,我还是得赶紧搞搞真正的算法才行。
- 用mask掩码处理图片,Mat::copyTo函数第一个用于输出的传入参数不能是原图片
- OpenCV中cvADDS()为啥第二个参数要是CvScalar类型?掩码mask=NULL又是何意?
- 一张图片与它的掩码 mask 蒙板
- Perl 对象是函数的第一个参数
- 接上面的拆分图片,这个是把刚才拆分的图片重新合成为原图片
- java中用Thumbnailator对图片各种处理的方法(可做到对原图片压缩仅改变大小)
- OpenCV中mat::copyto( )函数使用方法
- mybatis对于传入的多个参数的处理
- 如果函数的传入参数和返回值是对象
- 能向入口函数传入多个参数的 QueueUserWorkItem
- MyBatis传入多个参数,传入数组和列表数据的处理
- 编写一个函数。函数的3 个参数是一个字符和两个整数。字符参数是需要输 出的字符。第一个整数说明了在每行中该字符输出的个数,第二个整数指的是需 要输出的行数。编写一个调用该函数的程序
- 参数处理-Shell传入参数的处理
- shell--传入参数的处理
- shell--传入参数的处理
- shell--传入参数的处理
- shell--传入参数的处理
- shell--传入参数的处理
- orace 命令
- git blame
- 最原始网站回归网络
- Iphone应用开发之五: UIScrollView的详细讲解
- 图论学习-序列是否可图化(2)
- 用mask掩码处理图片,Mat::copyTo函数第一个用于输出的传入参数不能是原图片
- C++一些注意点之字符串与指针
- C++类构造和析构时代码的执行顺序
- 流程图简介
- c++ 操纵符
- WorldWideWeb浏览器
- 【NLP基础】基于LDA的Topic Model变形
- 7年一回首,流年似水
- (转)c#托管资源和非托管资源区别