`
king_c
  • 浏览: 222724 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

reduce() 和 findContours()的使用陷阱

 
阅读更多

        之前学习OpenCV时是从于老师的书本教材开始的,所以一直使用的接串口就全是其于C的,但越使用越觉得C接口不其方便,再者使用C++应当是大的趋势所向,所以,又只好对相应的C++接口进行学习和使用,真心烦燥! 浪费了一些时间不说,关键是c++接口中的一些函数的使用和要求,与C的有些出入,按之前C的方法去使用,有时会出些莫名的问题,解决起来老费劲!

        之前的笔记也记,只不过是,不是记在所看文档上,就是记录在Word里,现在起打算把这些经验和记录放在这里,希望能与路过的朋友多多交流,共同提高,呵呵。

        今天就讲讲reduce() 和 findContours()的使用陷阱。

        首先介绍一下我所用的系统情况:VS2010+OpenCV2.3.1。在建立系统时选择了基于MFC的单文档类型,由于可能要将exe放到没装OpenCV的电脑上运行,选择了静态链接DLL,而这,竟然对使用函数findContours()埋下的祸根!

 

       一,findContours()的使用陷阱

       第一次使用函数findContours(),默认的方法,参照手册定义输入输出参数的类型,如法炮制地进行调用,结果竟然一运行完findContours()函数所在的程序块时就出现了如下问题:

 

        按F5状态下的错误提示:
        直接运行exe的错误提示
 
         回头转去跟样例研究对比了半天,没有发现错漏。再去求助于百度,结果竟然还真有这类问题存在?! 难道把这么常用的一个函数升级得这么不稳定 ? 不应该呀!   尽管
http://code.opencv.org/issues里面有相应的解决办法,但都写得比较简略和抽象,估计是因为全是大牛,大体都是些编译器、动态库等方面的参数调整,俺等码农看了之后依然无从下手。 后来找到一中文简易版本的解决方法(http://giveuptech.com/post/opencv-findcontours-runtime-error-solution),说是“修改当前程序的vc运行库配置,问题解决。具体方法是:项目-属性-配置属性-C/C++-代码生成-运行库,将其改为“多线程调试(/MTd)”。”但仍然没有解决我的问题!
        幸好,我有加入两个超级大的OpenCV群,里面热心的高手相当多,这次我问题的解决就受助于 低调De盖子、极客等人的帮助,在此表示感谢!
         当一个DLL采用静态的方式链接到C运行时库时,会创建一个相对于该DLL的堆(Heap),而如果采用共享的方式链接到C运行时库的时候则使用的是应用程序的堆内存。而_CrtIsValidHeapPointer()在 DEBug模式下将确保传入的地址在本地的堆内存中。 因此就有理由相信,真有可能是静态链接的问题。
         所以,我立即尝试将:项目--属性--配置属性--常规--MFC的使用-- 选择 
在共享DLL中使用MFC 
;同时,项目--属性--配置属性--C/C++--代码生成--运行库--选择 
多线程DLL(/MD
)。
         然后,F5运行,无异常,竟然!激动ing....... 但做为好学上进的码农我,当然还需要看看它在Release情况下的表现啦,结果,结果,结果,它也正常! 爽!!! 只是它的exe文件要比Debug模式下要大出来好多。
         至此,函数findContours()的对编译环境的敏感问题就算是解决了,尽管就这小小问题忙活了大半天,但依然高兴,哈哈,^_^ 大笑

         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));
}

 

分享到:
评论

相关推荐

    【MapReduce篇06】MapReduce之MapJoin和ReduceJoin1

    在实际应用中,MapJoin 和 ReduceJoin 可以根据具体的业务需求和数据特点选择使用。例如,在订单表和公司名称表的关联分析中,可以使用 MapJoin 或 ReduceJoin 实现数据 Join 操作。 小结 MapReduce 之 MapJoin 和...

    使用Map-Reduce对大规模图进行排名和半监督分类

    标题中的“使用Map-Reduce对大规模图进行排名和半监督分类”是指利用MapReduce编程模型处理大规模图数据,实现图的排序(如PageRank)和半监督学习中的分类任务。MapReduce是由Google提出的一种分布式计算框架,适用...

    【JavaScript源代码】8个JS的reduce使用实例和reduce操作方式.docx

    8个JS的reduce使用实例和reduce操作方式  reduce方法是一个数组的迭代方法,和map、filter不同,reduce方法可缓存一个变量,迭代时我们可以操作这个变量,然后返回它。 这是我大白话的解释,可能还是不容易理解,...

    19、Join操作map side join 和 reduce side join

    在大数据处理领域,Hadoop MapReduce 是一种广泛使用的分布式计算框架。在处理涉及多数据集的任务时,Join 操作是必不可少的,它用于合并来自不同数据源的相关数据。本文主要探讨了两种 MapReduce 中的 Join 实现:...

    python reduce 函数使用详解

    `reduce()`函数接受三个参数:`function`、`sequence`和`initial`。 1. `function`: 这是一个需要两个参数的函数,用于处理序列中的元素。例如,可以是一个加法或乘法函数。 2. `sequence`: 这是可迭代对象,如元组...

    Map-Reduce原理体系架构和工作机制,eclipse与Hadoop集群连接

    - 使用Eclipse创建新的Map-Reduce项目。 - 编写Map和Reduce函数。 - 配置作业参数,如输入输出路径等。 **4. 提交和运行作业** - 将编写的Map-Reduce应用程序提交到Hadoop集群。 - 监控作业的执行进度和状态。 ##...

    cuda-使用cuda并行加速实现之reduce.zip

    在实际编程中,CUDA并行reduce还可以使用库函数如Thrust或者CUB来简化实现,这些库提供了高级接口,自动处理了并行化和归约过程的细节。 理解并掌握CUDA并行reduce的原理和实现方法,对于提升GPU计算性能至关重要,...

    使用map、reduce求平均值

    使用Spark算子map、reduce相结合求平均值

    js数组方法reduce经典用法代码分享

    ### Reduce方法的概念和用法 Reduce方法的核心概念是累加器(accumulator),它接受一个回调函数作为参数,该回调函数又接受四个参数:累加器(accumulator)、当前元素(currentValue)、当前索引(currentIndex)...

    noise reduce.rar_Reduce Noise _Reduce Noise v5_reduce noice_redu

    MATLAB是一种广泛使用的编程语言,特别适合进行数值计算和数据可视化,因此它是处理图像处理问题的理想工具。"Reduce Noise" 暗示了这个函数的目标是对输入图像进行噪声过滤,可能采用了高斯滤波器。高斯滤波器是一...

    a java map reduce framework

    MapReduce模型主要由两个主要阶段组成:Map阶段和Reduce阶段,以及一个可选的Shuffle和Sort阶段。Map阶段将输入数据拆分成键值对,并对其进行局部处理;Reduce阶段则对Map阶段的结果进行全局聚合,以生成最终的输出...

    hadoop map-reduce turorial

    **任务执行与环境**:Map-Reduce框架提供了丰富的API,允许用户监控任务的执行状态,包括任务进度、错误日志、内存使用情况等,有助于及时发现和解决执行过程中的问题。 **作业提交与监控**:用户可通过Hadoop...

    es6中reduce的基本使用方法

    第一种是使用排序和reduce方法联合使用,第二种则是结合了Set和Array.from方法。Set对象是ES6中新增的数据结构,它类似于数组,但是成员的值都是唯一的,利用这个特性可以帮助我们快速地去除数组中的重复元素。 ...

    Map/Reduce:大规模集群上的简化数据处理

    该模型的核心思想是将复杂的并行和分布式计算过程简化为两个主要步骤:Map 和 Reduce。Map 阶段将原始数据拆分成键值对,应用用户自定义的映射函数,生成中间键值对;Reduce 阶段则将具有相同中间键的值聚合,通过...

    JavaScript reduce和reduceRight详解

    需要注意的是,在使用reduce和reduceRight方法时,如果数组为空且没有提供initialValue,则会抛出TypeError异常。另外,若在回调函数中修改了正在迭代的数组,如添加或删除元素,其行为可能是不确定的,通常不推荐...

    18 - Day18 - Reduce、Map混合使用计算时分秒.rar

    这就是如何在JavaScript中使用`reduce()`和`map()`的混合使用来处理复杂的数据操作。通过这两个强大的工具,开发者可以灵活地处理数组数据,实现各种复杂的逻辑,如统计、转换和计算。在实际项目中,熟练掌握这两个...

Global site tag (gtag.js) - Google Analytics