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

2024-04-21 08:08

本文主要是介绍cv::CascadeClassifier类在多次读取新版本xml模型时的错误及其修正,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    偶然机会,试了试opencv中自带的人脸检测器,自带的haar和hog分类器xml文件读入时都不会有错误,但是在用lbp文件时发生了类似于vector越界的问题,找到了相应的vector,的确是这个提示,但是由于xml文件读取时只有一句load含税,调用的dll也无法跟进去浸提函数,也没有怀疑过opencv会出现错误。因此换了台电脑想用侥幸的办法试试,依旧是相同的问题。之后又想可能是我的opencv300版本来自民间,不稳定,难免会有bug,因此从别处copy另一版本的(opencv247)的lbpcascade_frontalface.xml文件,还是同样的问题,文件是一样的。。。然后又用opencv247建了新的工程,相同问题。。。好吧,看来可能opencv还真有问题。于是乎网上搜索,看到了类似问题的帖子 :http://blog.sina.com.cn/s/blog_4298002e010153hn.html。原文如下:

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

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

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

CascadeClassifier *pClassifier = new CascadeClassifier;

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

Mat matImage;
vector<Rect> objs;
pClassifier->load("haarcascade_frontalface_default.xml");

pClassifier->detectMultiScale(matImage, objs, 1.1, 3);

pClassifier->load("lbpcascade_frontalface.xml");

pClassifier->detectMultiScale(matImage, objs, 1.1, 3);

pClassifier->load("haarcascade_frontalface_default.xml");

pClassifier->detectMultiScale(matImage, objs, 1.1, 3);

pClassifier->load("lbpcascade_frontalface.xml");

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()的调用而不断增加。其中影响最明显的成员变量是:

vector<Stage> CascadeClassifier::stages

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

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

 stages.clear();
 classifiers.clear();
 nodes.clear();
 leaves.clear();
 subsets.clear();
 feval.release();



   按照作者的思路,应当是需要把objdetect对应的文件夹中的源文件考到自己的工程中,然后,修改需要修改的部分,再与自己的程序一起编译即可。找了半天,终于找到了类似的地方,按照类似的方法改过,成功了。在文件cascadedetect.cpp中大概960行的位置,修改为:

bool CascadeClassifierImpl::load(const String& filename)
{oldCascade.release();data = Data();featureEvaluator.release();node.stages.clear();    //modify 20150505node.classifiers.clear();node.nodes.clear();node.leaves.clear();node.subsets.clear();FileStorage fs(filename, FileStorage::READ);if( !fs.isOpened() )return false;if( read_(fs.getFirstTopLevelNode()) )return true;fs.release();oldCascade.reset((CvHaarClassifierCascade*)cvLoad(filename.c_str(), 0, 0, 0));return !oldCascade.empty();
}


这篇关于cv::CascadeClassifier类在多次读取新版本xml模型时的错误及其修正的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/922573

相关文章

C#读取本地网络配置信息全攻略分享

《C#读取本地网络配置信息全攻略分享》在当今数字化时代,网络已深度融入我们生活与工作的方方面面,对于软件开发而言,掌握本地计算机的网络配置信息显得尤为关键,而在C#编程的世界里,我们又该如何巧妙地读取... 目录一、引言二、C# 读取本地网络配置信息的基础准备2.1 引入关键命名空间2.2 理解核心类与方法

解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题

《解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题》本文主要讲述了在使用MyBatis和MyBatis-Plus时遇到的绑定异常... 目录myBATis-plus-boot-starpythonter与mybatis-spring-b

SpringBoot使用Apache POI库读取Excel文件的操作详解

《SpringBoot使用ApachePOI库读取Excel文件的操作详解》在日常开发中,我们经常需要处理Excel文件中的数据,无论是从数据库导入数据、处理数据报表,还是批量生成数据,都可能会遇到... 目录项目背景依赖导入读取Excel模板的实现代码实现代码解析ExcelDemoInfoDTO 数据传输

你的华为手机升级了吗? 鸿蒙NEXT多连推5.0.123版本变化颇多

《你的华为手机升级了吗?鸿蒙NEXT多连推5.0.123版本变化颇多》现在的手机系统更新可不仅仅是修修补补那么简单了,华为手机的鸿蒙系统最近可是动作频频,给用户们带来了不少惊喜... 为了让用户的使用体验变得很好,华为手机不仅发布了一系列给力的新机,还在操作系统方面进行了疯狂的发力。尤其是近期,不仅鸿蒙O

什么是 Ubuntu LTS?Ubuntu LTS和普通版本区别对比

《什么是UbuntuLTS?UbuntuLTS和普通版本区别对比》UbuntuLTS是Ubuntu操作系统的一个特殊版本,旨在提供更长时间的支持和稳定性,与常规的Ubuntu版本相比,LTS版... 如果你正打算安装 Ubuntu 系统,可能会被「LTS 版本」和「普通版本」给搞得一头雾水吧?尤其是对于刚入

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

windows端python版本管理工具pyenv-win安装使用

《windows端python版本管理工具pyenv-win安装使用》:本文主要介绍如何通过git方式下载和配置pyenv-win,包括下载、克隆仓库、配置环境变量等步骤,同时还详细介绍了如何使用... 目录pyenv-win 下载配置环境变量使用 pyenv-win 管理 python 版本一、安装 和

Python读取TIF文件的两种方法实现

《Python读取TIF文件的两种方法实现》本文主要介绍了Python读取TIF文件的两种方法实现,包括使用tifffile库和Pillow库逐帧读取TIFF文件,具有一定的参考价值,感兴趣的可以了解... 目录方法 1:使用 tifffile 逐帧读取安装 tifffile:逐帧读取代码:方法 2:使用

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G