之前的笔记也记,只不过是,不是记在所看文档上,就是记录在Word里,现在起打算把这些经验和记录放在这里,希望能与路过的朋友多多交流,共同提高,呵呵。
今天就讲讲reduce() 和 findContours()的使用陷阱。
首先介绍一下我所用的系统情况:VS2010+OpenCV2.3.1。在建立系统时选择了基于MFC的单文档类型,由于可能要将exe放到没装OpenCV的电脑上运行,选择了静态链接DLL,而这,竟然对使用函数findContours()埋下的祸根!
一,findContours()的使用陷阱
第一次使用函数findContours(),默认的方法,参照手册定义输入输出参数的类型,如法炮制地进行调用,结果竟然一运行完findContours()函数所在的程序块时就出现了如下问题:
直接运行exe的错误提示
PS:再反复调整项目配置的时候顺手试了一下,项目--属性--配置属性--C/C++--常规--多处理器编译--选择 是(/MP),果然能快不少,呵呵,原来我之前一直在无形地浪费着i5!
二,reduce() 的使用陷阱。
函数原型:void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype=-1)
对dtype采用默认值方式使用函数reduce(),出现了点异常问题,然后追加try-catch,发现输入输出的数据类型不匹配,于是就结合着reduce() 原代码做进一步分析,先是尝试着将输出创建为各种指定的格式,不行! 原因在于对下面这条语句没有理解好:
if( dtype < 0 )
dtype = _dst.fixedType() ? _dst.type() : stype;
上网、上Q,折腾许久,终于想到了要把 dtype指定一个初值! 由于输入的数据类型是8U,对于求和操作CV_REDUCE_SUM,那么输出是32S就可以,对应的 dtype=CV_32S 就行,此时输出的矩阵也就只需要定义一下就行,不必再进行其它操作。例如:
Mat matIn=imread(''lena.jpg",0);
Mat matOut;
reduce(matIn, matOut, 1, CV_REDUCE_SUM, CV_32S);
以下为函数reduce() 源码,方便对照学习。
- void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype)
- {
- Mat src = _src.getMat();
- CV_Assert( src.dims <= 2 );
- int op0 = op;
- int stype = src.type(), sdepth = src.depth(), cn = src.channels();
- if( dtype < 0 )
- dtype = _dst.fixedType() ? _dst.type() : stype;
- int ddepth = CV_MAT_DEPTH(dtype);
- _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1,
- CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn));
- Mat dst = _dst.getMat(), temp = dst;
- CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX ||
- op == CV_REDUCE_MIN || op == CV_REDUCE_AVG );
- CV_Assert( src.channels() == dst.channels() );
- if( op == CV_REDUCE_AVG )
- {
- op = CV_REDUCE_SUM;
- if( sdepth < CV_32S && ddepth < CV_32S )
- {
- temp.create(dst.rows, dst.cols, CV_32SC(cn));
- ddepth = CV_32S;
- }
- }
- ReduceFunc func = 0;
- if( dim == 0 )
- {
- if( op == CV_REDUCE_SUM )
- {
- if(sdepth == CV_8U && ddepth == CV_32S)
- func = reduceR_<uchar,int,OpAdd<int> >;
- else if(sdepth == CV_8U && ddepth == CV_32F)
- func = reduceR_<uchar,float,OpAdd<int> >;
- else if(sdepth == CV_8U && ddepth == CV_64F)
- func = reduceR_<uchar,double,OpAdd<int> >;
- else if(sdepth == CV_16U && ddepth == CV_32F)
- func = reduceR_<ushort,float,OpAdd<float> >;
- else if(sdepth == CV_16U && ddepth == CV_64F)
- func = reduceR_<ushort,double,OpAdd<double> >;
- else if(sdepth == CV_16S && ddepth == CV_32F)
- func = reduceR_<short,float,OpAdd<float> >;
- else if(sdepth == CV_16S && ddepth == CV_64F)
- func = reduceR_<short,double,OpAdd<double> >;
- else if(sdepth == CV_32F && ddepth == CV_32F)
- func = reduceR_<float,float,OpAdd<float> >;
- else if(sdepth == CV_32F && ddepth == CV_64F)
- func = reduceR_<float,double,OpAdd<double> >;
- else if(sdepth == CV_64F && ddepth == CV_64F)
- func = reduceR_<double,double,OpAdd<double> >;
- }
- else if(op == CV_REDUCE_MAX)
- {
- if(sdepth == CV_8U && ddepth == CV_8U)
- func = reduceR_<uchar, uchar, OpMax<uchar> >;
- else if(sdepth == CV_16U && ddepth == CV_16U)
- func = reduceR_<ushort, ushort, OpMax<ushort> >;
- else if(sdepth == CV_16S && ddepth == CV_16S)
- func = reduceR_<short, short, OpMax<short> >;
- else if(sdepth == CV_32F && ddepth == CV_32F)
- func = reduceR_<float, float, OpMax<float> >;
- else if(sdepth == CV_64F && ddepth == CV_64F)
- func = reduceR_<double, double, OpMax<double> >;
- }
- else if(op == CV_REDUCE_MIN)
- {
- if(sdepth == CV_8U && ddepth == CV_8U)
- func = reduceR_<uchar, uchar, OpMin<uchar> >;
- else if(sdepth == CV_16U && ddepth == CV_16U)
- func = reduceR_<ushort, ushort, OpMin<ushort> >;
- else if(sdepth == CV_16S && ddepth == CV_16S)
- func = reduceR_<short, short, OpMin<short> >;
- else if(sdepth == CV_32F && ddepth == CV_32F)
- func = reduceR_<float, float, OpMin<float> >;
- else if(sdepth == CV_64F && ddepth == CV_64F)
- func = reduceR_<double, double, OpMin<double> >;
- }
- }
- else
- {
- if(op == CV_REDUCE_SUM)
- {
- if(sdepth == CV_8U && ddepth == CV_32S)
- func = reduceC_<uchar,int,OpAdd<int> >;
- else if(sdepth == CV_8U && ddepth == CV_32F)
- func = reduceC_<uchar,float,OpAdd<int> >;
- else if(sdepth == CV_8U && ddepth == CV_64F)
- func = reduceC_<uchar,double,OpAdd<int> >;
- else if(sdepth == CV_16U && ddepth == CV_32F)
- func = reduceC_<ushort,float,OpAdd<float> >;
- else if(sdepth == CV_16U && ddepth == CV_64F)
- func = reduceC_<ushort,double,OpAdd<double> >;
- else if(sdepth == CV_16S && ddepth == CV_32F)
- func = reduceC_<short,float,OpAdd<float> >;
- else if(sdepth == CV_16S && ddepth == CV_64F)
- func = reduceC_<short,double,OpAdd<double> >;
- else if(sdepth == CV_32F && ddepth == CV_32F)
- func = reduceC_<float,float,OpAdd<float> >;
- else if(sdepth == CV_32F && ddepth == CV_64F)
- func = reduceC_<float,double,OpAdd<double> >;
- else if(sdepth == CV_64F && ddepth == CV_64F)
- func = reduceC_<double,double,OpAdd<double> >;
- }
- else if(op == CV_REDUCE_MAX)
- {
- if(sdepth == CV_8U && ddepth == CV_8U)
- func = reduceC_<uchar, uchar, OpMax<uchar> >;
- else if(sdepth == CV_16U && ddepth == CV_16U)
- func = reduceC_<ushort, ushort, OpMax<ushort> >;
- else if(sdepth == CV_16S && ddepth == CV_16S)
- func = reduceC_<short, short, OpMax<short> >;
- else if(sdepth == CV_32F && ddepth == CV_32F)
- func = reduceC_<float, float, OpMax<float> >;
- else if(sdepth == CV_64F && ddepth == CV_64F)
- func = reduceC_<double, double, OpMax<double> >;
- }
- else if(op == CV_REDUCE_MIN)
- {
- if(sdepth == CV_8U && ddepth == CV_8U)
- func = reduceC_<uchar, uchar, OpMin<uchar> >;
- else if(sdepth == CV_16U && ddepth == CV_16U)
- func = reduceC_<ushort, ushort, OpMin<ushort> >;
- else if(sdepth == CV_16S && ddepth == CV_16S)
- func = reduceC_<short, short, OpMin<short> >;
- else if(sdepth == CV_32F && ddepth == CV_32F)
- func = reduceC_<float, float, OpMin<float> >;
- else if(sdepth == CV_64F && ddepth == CV_64F)
- func = reduceC_<double, double, OpMin<double> >;
- }
- }
- if( !func )
- CV_Error( CV_StsUnsupportedFormat,
- "Unsupported combination of input and output array formats" );
- func( src, temp );
- if( op0 == CV_REDUCE_AVG )
- temp.convertTo(dst, dst.type(), 1./(dim == 0 ? src.rows : src.cols));
- }