C++ OpenCV中读取YAML文件的详解:定义、用途与实用示例

embedded/2024/12/26 7:51:51/

C++ OpenCV中读取YAML文件的详解:定义、用途与实用示例

在计算机视觉和图像处理领域,OpenCV(Open Source Computer Vision Library)是一个广泛使用的开源库。YAML(YAML Ain’t Markup Language)作为一种简洁且易于阅读的配置文件格式,在OpenCV中被广泛应用于存储和加载配置参数、校准数据、模型参数等。本文将详细解释在C++中如何使用OpenCV读取YAML文件,涵盖其定义、用途、使用方法以及实际示例。

目录
  1. YAML简介
  2. OpenCV中的YAML文件
  3. 使用OpenCV读取YAML文件的方法
  4. 示例解析
  5. 常见应用场景
  6. 编程规范与注意事项
  7. 总结

1. YAML简介
  • 定义:YAML是一种人类可读的数据序列化标准,常用于配置文件和数据交换。其语法简洁,支持复杂的数据结构,如映射(字典)、序列(列表)和标量(字符串、整数、浮点数等)。

  • 特点

    • 易读性高:结构清晰,缩进表示层级关系。
    • 支持多种数据类型:包括字符串、数值、布尔值、列表和字典等。
    • 灵活性强:可扩展,适用于多种应用场景。
2. OpenCV中的YAML文件

在OpenCV中,YAML文件常用于以下用途:

  • 配置参数存储:如相机内参、外参、图像处理参数等。
  • 模型参数保存:机器学习模型的权重和偏置等。
  • 校准数据记录:相机校准过程中得到的内外参数。

YAML文件的结构化特性使其成为存储和管理这些数据的理想选择。

3. 使用OpenCV读取YAML文件的方法

OpenCV提供了FileStorage类,用于读写XML、YAML和JSON格式的文件。以下是使用FileStorage读取YAML文件的基本步骤:

  1. 包含必要的头文件

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
  2. 创建FileStorage对象并打开YAML文件

    cv::FileStorage fs("config.yaml", cv::FileStorage::READ);
    if (!fs.isOpened()) {std::cerr << "无法打开文件" << std::endl;return -1;
    }
    
  3. 读取数据

    • 标量值

      int width, height;
      fs["image_width"] >> width;
      fs["image_height"] >> height;
      
    • 矩阵

      cv::Mat cameraMatrix;
      fs["camera_matrix"] >> cameraMatrix;
      
    • 序列或映射

      cv::FileNode features = fs["features"];
      for (auto it = features.begin(); it != features.end(); ++it) {std::string feature = (std::string)*it;std::cout << feature << std::endl;
      }
      
  4. 关闭文件

    fs.release();
    
4. 示例解析

以下通过一个具体的示例,展示如何在C++中使用OpenCV读取YAML文件。

4.1 示例YAML文件 (config.yaml)
%YAML:1.0
---
image_width: 1920
image_height: 1080
camera_matrix: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 1000.0, 0.0, 960.0,0.0, 1000.0, 540.0,0.0, 0.0, 1.0 ]
distortion_coefficients: [0.1, -0.25, 0.001, 0.0005, 0.0]
features:- SIFT- SURF- ORB
4.2 示例代码 (read_yaml.cpp)
#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 打开YAML文件进行读取cv::FileStorage fs("config.yaml", cv::FileStorage::READ);if (!fs.isOpened()) {std::cerr << "无法打开文件: config.yaml" << std::endl;return -1;}// 读取标量值int image_width, image_height;fs["image_width"] >> image_width;fs["image_height"] >> image_height;std::cout << "图像宽度: " << image_width << std::endl;std::cout << "图像高度: " << image_height << std::endl;// 读取矩阵cv::Mat cameraMatrix;fs["camera_matrix"] >> cameraMatrix;std::cout << "相机矩阵: " << std::endl << cameraMatrix << std::endl;// 读取数组std::vector<double> distortion_coefficients;fs["distortion_coefficients"] >> distortion_coefficients;std::cout << "畸变系数: ";for (const auto& coeff : distortion_coefficients) {std::cout << coeff << " ";}std::cout << std::endl;// 读取序列cv::FileNode features = fs["features"];std::cout << "特征检测算法: ";for (auto it = features.begin(); it != features.end(); ++it) {std::string feature = (std::string)*it;std::cout << feature << " ";}std::cout << std::endl;// 关闭文件fs.release();return 0;
}
4.3 编译与运行

使用以下命令编译示例代码:

g++ read_yaml.cpp -o read_yaml `pkg-config --cflags --libs opencv4`

运行程序:

./read_yaml
4.4 输出结果
图像宽度: 1920
图像高度: 1080
相机矩阵: 
[1000, 0, 960;0, 1000, 540;0, 0, 1]
畸变系数: 0.1 -0.25 0.001 0.0005 0 
特征检测算法: SIFT SURF ORB 

解释

  1. 读取标量值image_widthimage_height被读取并输出。
  2. 读取矩阵camera_matrix作为一个3x3的矩阵被读取并打印。
  3. 读取数组distortion_coefficients被读取为一个双精度浮点数的向量并输出。
  4. 读取序列features作为一个字符串序列被读取并依次输出。
5. 常见应用场景
  • 相机校准:存储和加载相机的内参、外参和畸变系数。
  • 配置管理:管理图像处理算法的参数,如滤波器的大小、阈值等。
  • 模型参数保存:保存机器学习模型的权重和偏置,以便在不同环境中加载和使用。
  • 数据交换:在不同模块或程序之间交换配置和参数数据。
6. 编程规范与注意事项
  • 包含防护:确保YAML文件格式正确,避免语法错误。
  • 数据类型匹配:确保读取的数据类型与YAML文件中定义的类型一致,避免类型转换错误。
  • 错误处理:在读取过程中,检查文件是否成功打开,以及各个节点是否存在,避免程序崩溃。
    if (!fs["camera_matrix"].isNone()) {fs["camera_matrix"] >> cameraMatrix;
    } else {std::cerr << "camera_matrix不存在" << std::endl;
    }
    
  • 文件路径:使用相对路径或绝对路径时,确保文件路径正确,避免路径错误导致文件无法打开。
  • 释放资源:读取完毕后,及时释放FileStorage对象以释放资源。
7. 总结

在C++中,利用OpenCV的FileStorage类读取YAML文件是一种高效且便捷的方法,适用于各种配置和数据存储需求。YAML文件的结构化和可读性使其成为管理复杂数据的理想选择。通过本文的详细解释和示例,读者可以掌握在C++中使用OpenCV读取YAML文件的基本方法,并将其应用于实际项目中,从而提高代码的可维护性和灵活性。

掌握YAML文件的读取和写入,不仅有助于简化配置管理,还能在不同模块之间实现高效的数据交换,进而推动项目的模块化和可扩展性发展。


http://www.ppmy.cn/embedded/148834.html

相关文章

Maxscript如何从对象中选择底边或者顶边?

在3dMax中&#xff0c;比如选择了一些墙对象&#xff0c;如何才能使用Maxscript脚本选择所有底部边缘&#xff1f; 有很多方法&#xff0c;我们看一下下面这段代码&#xff1a; if isKindOf $ Editable_Poly do (local minZ $.min.zlocal getEdgeV $.getEdgeVertexlocal bo…

【4 以太网RDMA优化--面向可靠传输】

4 面向可靠传输的优化 在RDMA应用于高性能计算&#xff08;high performance computing&#xff0c;HPC&#xff09;时&#xff0c;IB网络中使用专用网卡和交换机并通过基于信用的流控策略构建无损网络环境。 当RDMA迁移到基于以太网构建的的数据中心网络时&#xff0c;由于普…

【计算机视觉】轮廓检测

一、轮廓检测 在计算机视觉中&#xff0c;轮廓检测是另一个比较重要的任务&#xff0c;不单是用来检测图像或者视频帧中物体的轮廓&#xff0c;而且还有其他操作与轮廓检测相关。 以下代码展示了如何使用 OpenCV 进行 图像阈值处理、寻找图像轮廓 和 绘制轮廓 的完整流程&…

iPhone批量删除照片的方法

对于每一个iPhone用户来说&#xff0c;照片管理是一项日常而重要的任务。随着时间的积累&#xff0c;无数的照片快速填满了我们的存储空间&#xff0c;从美丽的风景到重要的家庭聚会&#xff0c;每一张照片都记录着我们生活中的瞬间。然而&#xff0c;当存储空间即将耗尽时&…

【stable diffusion】ComfyUI 使用 LoRA 极简工作流

ComfyUI的LoRA工作流相信大家都不陌生。开发者提供了大量基于默认节点功能搭建的工作流&#xff0c;其中就包括了如何使用LoRA。 仅仅使用一个LoRA也许还比较简单。只需要在基本工作流的基础上&#xff0c;再添加一个LoRA加载器的节点即可。如果要添加多个LoRA&#xff0c;就需…

基于 SOME/IP 的动态服务发现与调用:原理、实现与示例全解析

一、 SOME/IP 动态服务发现与调用例子代码 功能描述 服务发布程序: 提供两个远程服务,每个服务用唯一的 Service ID 和 Method ID 标识。根据客户端请求的 Service ID 和 Method ID 调用对应的处理函数。使用 Skeleton 实现服务的注册和响应。服务发现与调用程序: 动态发现…

SQL—leetcode—175. 组合两个表

175. 组合两个表 表: Person -------------------- | 列名 | 类型 | -------------------- | PersonId | int | | FirstName | varchar | | LastName | varchar | -------------------- personId 是该表的主键&#xff08;具有唯一值的列&#xff09;。 该表包含一些人的 ID 和…

探索Flink动态CEP:杭州银行的实战案例

摘要&#xff1a;本文撰写自杭州银行大数据工程师唐占峰、欧阳武林老师。将介绍 Flink 动态 CEP的定义与核心概念、应用场景、并深入探讨其技术实现并介绍使用方式。主要分为以下几个内容&#xff1a; Flink动态CEP简介 Flink动态CEP的应用场景 Flink动态CEP的技术实现 Flin…