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

来源:互联网 发布:php mvp 编辑:程序博客网 时间:2024/06/11 02:10
之前学习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() 源码,方便对照学习。

 

 

[cpp] view plaincopyprint?
  1. void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype)  
  2. {  
  3.     Mat src = _src.getMat();  
  4.     CV_Assert( src.dims <= 2 );  
  5.     int op0 = op;  
  6.     int stype = src.type(), sdepth = src.depth(), cn = src.channels();  
  7.     if( dtype < 0 )  
  8.         dtype = _dst.fixedType() ? _dst.type() : stype;  
  9.     int ddepth = CV_MAT_DEPTH(dtype);  
  10.   
  11.     _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1,  
  12.                 CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn));  
  13.     Mat dst = _dst.getMat(), temp = dst;  
  14.       
  15.     CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX ||  
  16.         op == CV_REDUCE_MIN || op == CV_REDUCE_AVG );  
  17.     CV_Assert( src.channels() == dst.channels() );  
  18.   
  19.     if( op == CV_REDUCE_AVG )  
  20.     {  
  21.         op = CV_REDUCE_SUM;  
  22.         if( sdepth < CV_32S && ddepth < CV_32S )  
  23.         {  
  24.             temp.create(dst.rows, dst.cols, CV_32SC(cn));  
  25.             ddepth = CV_32S;  
  26.         }  
  27.     }  
  28.   
  29.     ReduceFunc func = 0;  
  30.     if( dim == 0 )  
  31.     {  
  32.         if( op == CV_REDUCE_SUM )  
  33.         {  
  34.             if(sdepth == CV_8U && ddepth == CV_32S)  
  35.                 func = reduceR_<uchar,int,OpAdd<int> >;  
  36.             else if(sdepth == CV_8U && ddepth == CV_32F)  
  37.                 func = reduceR_<uchar,float,OpAdd<int> >;  
  38.             else if(sdepth == CV_8U && ddepth == CV_64F)  
  39.                 func = reduceR_<uchar,double,OpAdd<int> >;  
  40.             else if(sdepth == CV_16U && ddepth == CV_32F)  
  41.                 func = reduceR_<ushort,float,OpAdd<float> >;  
  42.             else if(sdepth == CV_16U && ddepth == CV_64F)  
  43.                 func = reduceR_<ushort,double,OpAdd<double> >;  
  44.             else if(sdepth == CV_16S && ddepth == CV_32F)  
  45.                 func = reduceR_<short,float,OpAdd<float> >;  
  46.             else if(sdepth == CV_16S && ddepth == CV_64F)  
  47.                 func = reduceR_<short,double,OpAdd<double> >;  
  48.             else if(sdepth == CV_32F && ddepth == CV_32F)  
  49.                 func = reduceR_<float,float,OpAdd<float> >;  
  50.             else if(sdepth == CV_32F && ddepth == CV_64F)  
  51.                 func = reduceR_<float,double,OpAdd<double> >;  
  52.             else if(sdepth == CV_64F && ddepth == CV_64F)  
  53.                 func = reduceR_<double,double,OpAdd<double> >;  
  54.         }  
  55.         else if(op == CV_REDUCE_MAX)  
  56.         {  
  57.             if(sdepth == CV_8U && ddepth == CV_8U)  
  58.                 func = reduceR_<uchar, uchar, OpMax<uchar> >;  
  59.             else if(sdepth == CV_16U && ddepth == CV_16U)  
  60.                 func = reduceR_<ushort, ushort, OpMax<ushort> >;  
  61.             else if(sdepth == CV_16S && ddepth == CV_16S)  
  62.                 func = reduceR_<shortshort, OpMax<short> >;  
  63.             else if(sdepth == CV_32F && ddepth == CV_32F)  
  64.                 func = reduceR_<floatfloat, OpMax<float> >;  
  65.             else if(sdepth == CV_64F && ddepth == CV_64F)  
  66.                 func = reduceR_<doubledouble, OpMax<double> >;  
  67.         }  
  68.         else if(op == CV_REDUCE_MIN)  
  69.         {  
  70.             if(sdepth == CV_8U && ddepth == CV_8U)  
  71.                 func = reduceR_<uchar, uchar, OpMin<uchar> >;  
  72.             else if(sdepth == CV_16U && ddepth == CV_16U)  
  73.                 func = reduceR_<ushort, ushort, OpMin<ushort> >;  
  74.             else if(sdepth == CV_16S && ddepth == CV_16S)  
  75.                 func = reduceR_<shortshort, OpMin<short> >;  
  76.             else if(sdepth == CV_32F && ddepth == CV_32F)  
  77.                 func = reduceR_<floatfloat, OpMin<float> >;  
  78.             else if(sdepth == CV_64F && ddepth == CV_64F)  
  79.                 func = reduceR_<doubledouble, OpMin<double> >;  
  80.         }  
  81.     }  
  82.     else  
  83.     {  
  84.         if(op == CV_REDUCE_SUM)  
  85.         {  
  86.             if(sdepth == CV_8U && ddepth == CV_32S)  
  87.                 func = reduceC_<uchar,int,OpAdd<int> >;  
  88.             else if(sdepth == CV_8U && ddepth == CV_32F)  
  89.                 func = reduceC_<uchar,float,OpAdd<int> >;  
  90.             else if(sdepth == CV_8U && ddepth == CV_64F)  
  91.                 func = reduceC_<uchar,double,OpAdd<int> >;  
  92.             else if(sdepth == CV_16U && ddepth == CV_32F)  
  93.                 func = reduceC_<ushort,float,OpAdd<float> >;  
  94.             else if(sdepth == CV_16U && ddepth == CV_64F)  
  95.                 func = reduceC_<ushort,double,OpAdd<double> >;  
  96.             else if(sdepth == CV_16S && ddepth == CV_32F)  
  97.                 func = reduceC_<short,float,OpAdd<float> >;  
  98.             else if(sdepth == CV_16S && ddepth == CV_64F)  
  99.                 func = reduceC_<short,double,OpAdd<double> >;  
  100.             else if(sdepth == CV_32F && ddepth == CV_32F)  
  101.                 func = reduceC_<float,float,OpAdd<float> >;  
  102.             else if(sdepth == CV_32F && ddepth == CV_64F)  
  103.                 func = reduceC_<float,double,OpAdd<double> >;  
  104.             else if(sdepth == CV_64F && ddepth == CV_64F)  
  105.                 func = reduceC_<double,double,OpAdd<double> >;  
  106.         }  
  107.         else if(op == CV_REDUCE_MAX)  
  108.         {  
  109.             if(sdepth == CV_8U && ddepth == CV_8U)  
  110.                 func = reduceC_<uchar, uchar, OpMax<uchar> >;  
  111.             else if(sdepth == CV_16U && ddepth == CV_16U)  
  112.                 func = reduceC_<ushort, ushort, OpMax<ushort> >;  
  113.             else if(sdepth == CV_16S && ddepth == CV_16S)  
  114.                 func = reduceC_<shortshort, OpMax<short> >;  
  115.             else if(sdepth == CV_32F && ddepth == CV_32F)  
  116.                 func = reduceC_<floatfloat, OpMax<float> >;  
  117.             else if(sdepth == CV_64F && ddepth == CV_64F)  
  118.                 func = reduceC_<doubledouble, OpMax<double> >;  
  119.         }  
  120.         else if(op == CV_REDUCE_MIN)  
  121.         {  
  122.             if(sdepth == CV_8U && ddepth == CV_8U)  
  123.                 func = reduceC_<uchar, uchar, OpMin<uchar> >;  
  124.             else if(sdepth == CV_16U && ddepth == CV_16U)  
  125.                 func = reduceC_<ushort, ushort, OpMin<ushort> >;  
  126.             else if(sdepth == CV_16S && ddepth == CV_16S)  
  127.                 func = reduceC_<shortshort, OpMin<short> >;  
  128.             else if(sdepth == CV_32F && ddepth == CV_32F)  
  129.                 func = reduceC_<floatfloat, OpMin<float> >;  
  130.             else if(sdepth == CV_64F && ddepth == CV_64F)  
  131.                 func = reduceC_<doubledouble, OpMin<double> >;  
  132.         }  
  133.     }  
  134.   
  135.     if( !func )  
  136.         CV_Error( CV_StsUnsupportedFormat,  
  137.         "Unsupported combination of input and output array formats" );  
  138.   
  139.     func( src, temp );  
  140.   
  141.     if( op0 == CV_REDUCE_AVG )  
  142.         temp.convertTo(dst, dst.type(), 1./(dim == 0 ? src.rows : src.cols));  
  143. }  
原创粉丝点击