织梦CMS - 轻松建站从此开始!

罗索

cv::CascadeClassifier类在多次读取新版本xml模型时的错误及其修

落鹤生 发布于 2014-02-10 16:26 点击:次 
在现在的OpenCV版本中,使用级联分类器做人脸检测的时候,有两种选择:一是使用老版本的CvHaarClassifierCascade,一是使用新版本的CascadeClassifier类。老版本的分类器只支持类Haar特征,而新版本的分类器既可以使用Haar,也可以使用LBP特征。
TAG: 分类器  haar  

在现在的OpenCV版本中,使用级联分类器做人脸检测的时候,有两种选择:一是使用老版本的CvHaarClassifierCascade,一是使用新版本的CascadeClassifier类。老版本的分类器只支持类Haar特征,而新版本的分类器既可以使用Haar,也可以使用LBP特征。

类CascadeClassifier中实际上封装了新旧两种分类器,对于老版本的xml模型文件,CascadeClassifier会用 CvHaarClassifierCascade去解析,并用cvHaarDetectObjects去检测。而对于新版本的xml文 件,CascadeClassifier会用自己的一套格式去解析。

在程序的实现上,CascadeClassifier对老版本的xml文件读取很简单,所以不会出什么问题。但是对新版本的xml文件的读取,其实现上有很多缺陷。如果你用下面代码创建了一个分类器:

CascadeClassifier *pClassifier = new CascadeClassifier;

若在程序的使用中,不释放该对象,只是来回在Haar特征和LBP特征之间切换,比较两种特征检测人脸的效果,如下:

  1. Mat matImage; 
  2. vector<Rect> objs; 
  3.  
  4. pClassifier->load("haarcascade_frontalface_default.xml"); 
  5. pClassifier->detectMultiScale(matImage, objs, 1.1, 3); 
  6. pClassifier->load("lbpcascade_frontalface.xml"); 
  7. pClassifier->detectMultiScale(matImage, objs, 1.1, 3); 
  8. pClassifier->load("haarcascade_frontalface_default.xml"); 
  9. pClassifier->detectMultiScale(matImage, objs, 1.1, 3); 
  10. pClassifier->load("lbpcascade_frontalface.xml"); 
  11. pClassifier->detectMultiScale(matImage, objs, 1.1, 3); 

那么程序会果断的崩溃,因为lbpcascade_frontalface.xml文件格式是新版本的。

对于老版本的xml文件是不存在这个问题的。因为读取老版本文件时,程序是不会调用CascadeClassifier::read(const FileNode &root)函数的。这个函数只会在读取新版本xml文件时,在load()中被调用。

read()函数之所以会导致程序崩溃,其原因是CascadeClassifier类有很多vector类型的成员变量,每次调用read()函数填充 这些变量时,都没有清空这些变量,而直接往这些变量里push_back元素。如此一来这些vector的长度会随着read()的调用而不断增加。其中 影响最明显的成员变量是:

  1. vector<Stage> CascadeClassifier::stages 

该变量的size决定了循环的次数。如果当前模型只有20个stage,但是上次读取xml时该变量没有清空,那么 CascadeClassifier::stages的长度可能会变成40。于是当前检测人脸的时候会循环40次,但是模型实际上只有20个stage, 循环次数超过20的时候,索引出来的其他变量可能就是无效的,从而导致下标越界,使程序崩溃。

要修正这个bug实际上很简单,只需要在read()函数的开头添加如下代码,清空上次的数据即可:

  1. stages.clear(); 
  2. classifiers.clear(); 
  3. nodes.clear(); 
  4. leaves.clear(); 
  5. subsets.clear(); 
  6. feval.release(); 

 

(seamusmore)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201402/16904.html]
本文出处:新浪博客 作者:seamusmore 原文
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容