persistence.cpp:2197:ann.xml(1): There should be space between attributes in function icvXMLParseTag

本文详细记录了在将OpenCV 3.1.0移植到Ubuntu 16.04和ARM Linux开发板时遇到的XML解析错误。作者逐一排查了XML文件错误、ARM平台解析问题、编码问题、文件大小、路径问题、版本差异、交叉编译器问题以及编译opencv时的依赖库问题,但问题仍未解决。最终,作者使用了预编译的opencv库(版本2.4.5)和ffmpeg支持的库,成功运行了程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

August 3, 2016
作者:dengshuai_super
出处:http://blog.youkuaiyun.com/dengshuai_super/article/details/52069634
声明:转载请注明作者及出处。


注意⚠️:此问题还不算解决,只是暂时用了别人的库,以后解决了,会回来记录。因为我是做笔记,所以建议大家直接看文章最后。
Opencv3.1.0 , Ubuntu16.04 ,开发板Microzed和Zedboard都试过了,出现同样问题。


charVec size:101
file /home/ds/build/opencv-3.1.0/modules/core/src/persistence.cpp, line 2197 terminate called after throwing an instance of 'cv::Exception' 
what():/home/ds/build/opencv-3.1.0/modules/core/src/persistence.cpp:2197:error:(-212) /mnt/PRTest/resources/model/ann.xml(1):
There should be space between attributes in function icvXMLParseTag

http://www.th7.cn/Program/cp/201605/851893.shtml

/** @brief Loads algorithm from the file

     @param filename Name of the file to read.
     @param objname The optional name of the node to read (if empty, the first top-level node will be used)

     This is static template method of Algorithm. It's usage is following (in the case of SVM):
     @code
     Ptr<SVM> svm = Algorithm::load<SVM>("my_svm_model.xml");
     @endcode
     In order to make this method work, the derived class must overwrite Algorithm::read(const
     FileNode& fn).
*/

    template<typename _Tp> static Ptr<_Tp> load(const String& filename, const String& objname=String())
    {
        FileStorage fs(filename, FileStorage::READ);
        FileNode fn = objname.empty() ? fs.getFirstTopLevelNode() : fs[objname];
        Ptr<_Tp> obj = _Tp::create();
        obj->read(fn);
        return !obj->empty() ? obj : Ptr<_Tp>();
    }
  /** @brief Reads algorithm parameters from a file storage
    */
    virtual void read(const FileNode& fn) { (void)fn; }

    /** @brief Reads algorithm from the file node

     This is static template method of Algorithm. It's usage is following (in the case of SVM):
     @code
     Ptr<SVM> svm = Algorithm::read<SVM>(fn);
     @endcode
     In order to make this method work, the derived class must overwrite Algorithm::read(const
     FileNode& fn) and also have static create() method without parameters
     (or with all the optional parameters)
     */
    template<typename _Tp> static Ptr<_Tp> read(const FileNode& fn)
    {
        Ptr<_Tp> obj = _Tp::create();
        obj->read(fn);
        return !obj->empty() ? obj : Ptr<_Tp>();
    }

http://stackoverflow.com/questions/25831111/opencv-traincascade-build-intermediate-result/26301531#26301531

猜测一:xml本身出现了错误

Ubuntu 里面:/home/ds/桌面/EasyPR-master/resources/model/ann.xml

<?xml version="1.0"?>
<!opencv_storage>
<opencv_ml_ann_mlp>
  <format>3</format>
  <layer_sizes>120 40 65</layer_sizes>
  <activation_function>SIGMOID_SYM</activation_function>
  <f_param1>1.</f_param1>
  <f_param2>1.</f_param2>

我故意把第二行加了一个”!”,Ubuntu里运行程序:出现:

OpenCV Error: Parsing error (resources/model/ann.xml(2):
file /home/ds/opencv-3.1.0/modules/core/src/persistence.cpp, 
 line 2249 terminate called after throwing an instance of 'cv::Exception'
  what():  /home/ds/opencv-3.1.0/modules/core/src/persistence.cpp:2249: 
  error: (-212) resources/model/ann.xml(2): 
  <opencv_storage> tag is missing in function icvXMLParse

在已经做好opencv移植的arm linux里面运行,出现:

OpenCV Error: Parsing error (resources/model/ann.xml(1): 
There should be space between attributes) in icvXMLParseTag, 
file /home/ds/build/opencv-3.1.0/modules/core/src/persistence.cpp, line 2197 what():  
  /home/ds/build/opencv-3.1.0/modules/core/src/persistence.cpp:2197: error: (-212) resources/model/ann.xml(1):
   There should be space between attributes in function icvXMLParseTag

然后我只把ann.xml 的第一行改为
<?xml version !="1.0"?>
在arm linux 报错和Ubuntu 上一样:

OpenCV Error: Parsing error (resources/model/ann.xml(1): Attribute name should be followed by '=') in icvXMLParseTag, 
file /home/ds/build/opencv-3.1.0/modules/core/src/persistence.cpp, 
line 2149 terminate called after throwing an instance of 'cv::Exception' what():  
/home/ds/build/opencv-3.1.0/modules/core/src/persistence.cpp:2149: 
error: (-212) resources/model/ann.xml(1): Attribute name should be followed by '=' in function icvXMLParseTag

我把ann.xml 的第一行改为
<?xml version = "1.0" >
arm linux显示错误:

OpenCV Error: Parsing error (resources/model/ann.xml(1): 
There should be space between attributes) in icvXMLParseTag, 
file /home/ds/build/opencv-3.1.0/modules/core/src/persistence.cpp, 
line 2197 terminate called after throwing an instance of 'cv::Exception' what():  /home/ds/build/opencv-3.1.0/modules/core/src/persistence.cpp:2197: 
error: (-212) resources/model/ann.xml(1): 
There should be space between attributes in function icvXMLParseTag

结果arm上没检测出最右边?的问题,Ubuntu检测出来了。

于是我用opencv官方的例子人脸识别的那个(FaceDetection),在Ubuntu上可以顺利跑起来,移植到arm 上之后,出现了同样的问题:

WARNING: Could not load classifier cascade for nested objects OpenCV Error: 
There should be space between attributes) in icvXMLParseTag, 
file /home/ds/build/opencv3.1.0/modules/core/src/persistence.cpp, line 2197
terminate called after throwing an instance of 'cv::Exception'
    what():  /home/ds/build/opencv-3.1.0/modules/core/src/persistence.cpp:2197: error: (-212) haarcascade_frontalface_alt.xml(1): 
    There should be space between attributes in function icvXMLParseTag

Aborted

说明这是通性的问题,正确的在Ubuntu上可以用的xml,移植到开发板上的arm linux里面时,就会出现
There should be space between attributes in function icvXMLParseTag 的问题。

猜测二:是arm上解析出现问题

开始时我怀疑是缺少libxml2库的问题导致了解析失败:(其实后来发现opencv是用自己的解析函数来解析xml)
于是我用ldd命令看Ubuntu程序链接了哪些库:
其中发现了xml2

 ldd demo_linux_amd64 

打印出:

linux-vdso.so.1 =>  (0x00007ffdeb3b3000)
   `libopencv_world.so.3.1 => /usr/local/lib/libopencv_world.so.3.1 (0x00007f62e0ffe000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f62e0c61000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f62e0957000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f62e0741000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f62e0378000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f62e015d000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f62dff59000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f62dfd3c000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f62dfb33000)
    libpng12.so.0 => /lib/x86_64-linux-gnu/libpng12.so.0 (0x00007f62df90e000)`
    libgtk-3.so.0 => /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 (0x00007f62defdf000)
    libgdk-3.so.0 => /usr/lib/x86_64-linux-gnu/libgdk-3.so.0 (0x00007f62ded03000)
    libcairo.so.2 => /usr/lib/x86_64-linux-gnu/libcairo.so.2 (0x00007f62de9ef000)
    libgdk_pixbuf-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 (0x00007f62de7cd000)
    libgobject-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f62de579000)
    `libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f62de268000)`
    libavcodec-ffmpeg.so.56 => /usr/lib/x86_64-linux-gnu/libavcodec-ffmpeg.so.56 (0x00007f62dce3e000)
    libavformat-ffmpeg.so.56 => /usr/lib/x86_64-linux-gnu/libavformat-ffmpeg.so.56 (0x00007f62dca40000)
    libavutil-ffmpeg.so.54 => /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54 (0x00007f62dc7d1000)
    libswscale-ffmpeg.so.3 => /usr/lib/x86_64-linux-gnu/libswscale-ffmpeg.so.3 (0x00007f62dc542000)
    `/lib64/ld-linux-x86-64.so.2 (0x0000561e16755000)`
    libgmodule-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f62dc33d000)
    libpangocairo-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x00007f62dc130000)
    libX11.so.6 => /usr/lib/x86_6
<think>好的,我现在要解决用户遇到的关于OpenCV中cv::FileStorage无法打开文件的问题。用户提到错误信息是persistence.cpp 566行的cv::FileStorage::Impl::open无法打开文件,需要给出解决方案,特别是针对C++的OpenCV。 首先,我需要回忆一下OpenCV中FileStorage类的作用。这个类主要用于读写XML、YAML、JSON格式的文件。用户遇到的错误通常是文件路径不正确或者权限问题导致的。根据提供的引用,比如引用[1]和[2],错误信息指出无法以读取模式打开文件,可能原因包括文件不存在、路径错误或权限不足。引用[3]提到可能需要依赖正确的库,而引用[4]建议检查FileStorage的使用方法,比如是否需要连续使用getNode而不在函数中释放。 接下来,我应该列出可能的解决方案。首先检查文件路径是否正确,绝对路径还是相对路径。相对路径可能因为工作目录不同而找不到文件,所以建议使用绝对路径或者确认工作目录。然后检查文件是否存在,是否有读取权限。如果文件确实存在,可能需要检查文件是否被其他程序占用或者损坏。 然后是代码层面的检查,比如是否正确初始化了FileStorage对象,是否使用了正确的打开模式。例如,用户是否在读取时使用了cv::FileStorage::READ模式。另外,错误处理也很重要,比如检查isOpened()方法是否返回true,并在失败时输出更详细的错误信息。 另外,考虑文件格式是否正确。XML、YAML或JSON文件的结构是否符合OpenCV的要求,有没有语法错误。比如,节点名称是否正确,缩进是否正确,标签是否闭合等。有时候格式错误会导致文件无法正确解析。 还有一个可能的问题是OpenCV的版本问题,某些版本可能存在bug,或者对文件格式的支持不同。建议用户更新到最新版本或者稳定版本,并确保编译时包含了必要的模块。 此外,引用[4]提到,可能需要将FileStorage对象和getNode连续使用,避免在函数中提前释放。也就是说,如果在函数中创建FileStorage对象并立即读取,可能在函数返回时对象被销毁,导致节点无法访问。因此,需要确保对象的生命周期足够长,直到数据读取完毕。 最后,可能需要提供一些示例代码,展示正确的使用方式,比如如何正确打开文件,读取节点,并在出现错误时进行适当的处理。同时提醒用户处理异常情况,比如文件不存在时的错误提示。 总结一下,解决方案的步骤可能包括: 1. 检查文件路径和权限。 2. 确保文件存在且可读。 3. 使用绝对路径或调整工作目录。 4. 检查代码中的FileStorage初始化和模式是否正确。 5. 验证文件格式是否正确。 6. 确保FileStorage对象在读取数据前未释放。 7. 更新OpenCV版本或检查编译选项。 8. 添加错误处理逻辑,使用isOpened()检查。 在编写回答时,需要将这些步骤有条理地呈现,用中文简洁说明,并参考用户提供的引用信息来支持解决方案。例如,引用[4]中的建议可以对应到步骤6,确保对象不被提前释放。同时,示例代码可以帮助用户更直观地理解正确的使用方法。</think>### 解决 `cv::FileStorage` 无法打开文件的问题 #### 常见原因及解决方案 1. **文件路径错误** - 检查文件路径是否准确,建议使用**绝对路径**(如 `C:/data/file.xml`),避免因相对路径的当前工作目录不一致导致文件未找到[^1][^2]。 - **代码示例**: ```cpp cv::FileStorage fs("C:/opencv_data/config.xml", cv::FileStorage::READ); if (!fs.isOpened()) { std::cerr << "文件打开失败,请检查路径或权限!" << std::endl; } ``` 2. **文件不存在或权限不足** - 确保文件存在且可读。在代码中添加检查逻辑: ```cpp if (!fs.isOpened()) { std::cerr << "错误原因:" << cv::utils::getBuildInformation() << std::endl; // 查看OpenCV编译信息 } ``` 3. **文件格式或内容错误** - OpenCV要求文件符合XML/YAML/JSON格式规范。检查文件语法,例如: ```xml <!-- 正确示例 --> <opencv_storage> <matrix>1 2 3; 4 5 6</matrix> </opencv_storage> ``` 4. **对象生命周期问题** - 确保 `cv::FileStorage` 对象在读取数据前未被释放。避免将其定义在局部作用域中导致提前销毁[^4]: ```cpp cv::FileStorage fs; fs.open("data.yaml", cv::FileStorage::READ); cv::Mat params = fs["mat1"].mat(); fs.release(); // 读取完毕后再释放 ``` 5. **OpenCV库配置问题** - 确保编译OpenCV时启用了文件读写模块(默认开启)。通过以下代码检查功能支持: ```cpp std::cout << cv::getBuildInformation() << std::endl; ``` #### 调试建议 - 使用 `try-catch` 捕获异常(需启用OpenCV异常处理)。 - 打印当前工作目录确认路径基准: ```cpp #include <direct.h> char buf[256]; _getcwd(buf, sizeof(buf)); std::cout << "当前工作目录:" << buf << std::endl; ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值