参考 文章1 文章2
CvSize CvReduce(//完毕由op指定的约简
const CvArr* src,//目标矩阵
CvArr* dst,//结果矩阵
int dim = -1,//因子系数,//1合并成行,0合并成列。-1转化成相应的dis
int op = CV_REDUCE_SUM,//指定约简法则
int dtype=-1// 如果结果矩阵没有初始化时输出数据类型
);
op的值 | 结果 |
CV_REDUCE_SUM | 计算全部向量的总和 |
CV_REDUCE_AVG | 计算全部向量的平均值 |
CV_REDUCE_MAX | 计算全部向量中的最大值 |
CV_REDUCE_MIN | 计算全部向量中的最小值 |
函数原型: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_ >;
else if(sdepth == CV_8U && ddepth == CV_32F)
func = reduceR_ >;
else if(sdepth == CV_8U && ddepth == CV_64F)
func = reduceR_ >;
else if(sdepth == CV_16U && ddepth == CV_32F)
func = reduceR_ >;
else if(sdepth == CV_16U && ddepth == CV_64F)
func = reduceR_ >;
else if(sdepth == CV_16S && ddepth == CV_32F)
func = reduceR_ >;
else if(sdepth == CV_16S && ddepth == CV_64F)
func = reduceR_ >;
else if(sdepth == CV_32F && ddepth == CV_32F)
func = reduceR_ >;
else if(sdepth == CV_32F && ddepth == CV_64F)
func = reduceR_ >;
else if(sdepth == CV_64F && ddepth == CV_64F)
func = reduceR_ >;
}
else if(op == CV_REDUCE_MAX)
{
if(sdepth == CV_8U && ddepth == CV_8U)
func = reduceR_ >;
else if(sdepth == CV_16U && ddepth == CV_16U)
func = reduceR_ >;
else if(sdepth == CV_16S && ddepth == CV_16S)
func = reduceR_ >;
else if(sdepth == CV_32F && ddepth == CV_32F)
func = reduceR_ >;
else if(sdepth == CV_64F && ddepth == CV_64F)
func = reduceR_ >;
}
else if(op == CV_REDUCE_MIN)
{
if(sdepth == CV_8U && ddepth == CV_8U)
func = reduceR_ >;
else if(sdepth == CV_16U && ddepth == CV_16U)
func = reduceR_ >;
else if(sdepth == CV_16S && ddepth == CV_16S)
func = reduceR_ >;
else if(sdepth == CV_32F && ddepth == CV_32F)
func = reduceR_ >;
else if(sdepth == CV_64F && ddepth == CV_64F)
func = reduceR_ >;
}
}
else
{
if(op == CV_REDUCE_SUM)
{
if(sdepth == CV_8U && ddepth == CV_32S)
func = reduceC_ >;
else if(sdepth == CV_8U && ddepth == CV_32F)
func = reduceC_ >;
else if(sdepth == CV_8U && ddepth == CV_64F)
func = reduceC_ >;
else if(sdepth == CV_16U && ddepth == CV_32F)
func = reduceC_ >;
else if(sdepth == CV_16U && ddepth == CV_64F)
func = reduceC_ >;
else if(sdepth == CV_16S && ddepth == CV_32F)
func = reduceC_ >;
else if(sdepth == CV_16S && ddepth == CV_64F)
func = reduceC_ >;
else if(sdepth == CV_32F && ddepth == CV_32F)
func = reduceC_ >;
else if(sdepth == CV_32F && ddepth == CV_64F)
func = reduceC_ >;
else if(sdepth == CV_64F && ddepth == CV_64F)
func = reduceC_ >;
}
else if(op == CV_REDUCE_MAX)
{
if(sdepth == CV_8U && ddepth == CV_8U)
func = reduceC_ >;
else if(sdepth == CV_16U && ddepth == CV_16U)
func = reduceC_ >;
else if(sdepth == CV_16S && ddepth == CV_16S)
func = reduceC_ >;
else if(sdepth == CV_32F && ddepth == CV_32F)
func = reduceC_ >;
else if(sdepth == CV_64F && ddepth == CV_64F)
func = reduceC_ >;
}
else if(op == CV_REDUCE_MIN)
{
if(sdepth == CV_8U && ddepth == CV_8U)
func = reduceC_ >;
else if(sdepth == CV_16U && ddepth == CV_16U)
func = reduceC_ >;
else if(sdepth == CV_16S && ddepth == CV_16S)
func = reduceC_ >;
else if(sdepth == CV_32F && ddepth == CV_32F)
func = reduceC_ >;
else if(sdepth == CV_64F && ddepth == CV_64F)
func = reduceC_ >;
}
}
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));
}